0
$\begingroup$

I have some data

Tinterspike200 = {3.01026957638`, 5.314505776636686`, 
   10.494223363285943`, 16.585365853657912`};
Tinterspike400 = {2.5609756097561167`, 3.940949935815186`, 
   6.103979460847167`, 8.921694480102463`, 12.50962772785579`, 
   17.092426187419257`, 22.13093709884531`};
Tinterspike600 = {2.3748395378690628`, 3.177150192554557`, 
   4.358151476251605`, 6.059050064184852`, 8.401797175866495`, 
   11.206675224646983`, 14.80744544287548`, 18.58793324775353`, 
   22.310654685494224`, 26.78433889602054`};
Tinterspike800 = {2.2657252888318355`, 2.7856225930680356`, 
   3.4403080872913994`, 4.2105263157894735`, 5.7124518613607185`, 
   8.318356867779203`, 11.59178433889602`, 14.441591784338895`, 
   17.77920410783055`, 21.059050064184852`, 25.532734274711167`};
Tinterspike1000 = {2.1822849807445444`, 2.593068035943517`, 
   3.0680359435173297`, 3.5879332477535297`, 4.255455712451861`, 
   5.423620025673941`, 8.164313222079588`, 11.07188703465982`, 
   13.49165596919127`, 16.084724005134788`, 19.17201540436457`, 
   22.35558408215661`, 25.84724005134788`};

Nspikes200 = {1, 2, 3, 4};
Nspikes400 = {1, 2, 3, 4, 5, 6, 7};
Nspikes600 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Nspikes800 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
Nspikes1000 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
Istim = {200, 400, 600, 800, 1000};

which I arrange in the following form

(*DATA*)
data1 = 
  Table[{Istim[[1]], Tinterspike200[[i]], Nspikes200[[i]]}, {i, 1, 4}];
data2 = Table[{Istim[[2]], Tinterspike400[[i]], Nspikes400[[i]]}, {i, 
    1, 7}];
data3 = Table[{Istim[[3]], Tinterspike600[[i]], Nspikes600[[i]]}, {i, 
    1, 10}];
data4 = Table[{Istim[[4]], Tinterspike800[[i]], Nspikes800[[i]]}, {i, 
    1, 11}];
data5 = Table[{Istim[[5]], Tinterspike1000[[i]], 
    Nspikes1000[[i]]}, {i, 1, 13}];
data = Join[data1, data2, data3, data4, data5];
lpp = ListPointPlot3D[data, PlotStyle -> {PointSize[Large], Red}];

I define the following boundary

(*BOUNDARY*)
p1 = {Istim[[1]], Tinterspike200[[4]], Nspikes200[[4]]};
p2 = {Istim[[2]], Tinterspike400[[7]], Nspikes400[[7]]};
p3 = {Istim[[3]], Tinterspike600[[10]], Nspikes600[[10]]};
p4 = {Istim[[4]], Tinterspike800[[11]], Nspikes800[[11]]};
p5 = {Istim[[5]], Tinterspike1000[[13]], Nspikes1000[[13]]};
boundary = 
  Graphics3D[{Dashed, Thick, Red, Line[{p1, p2, p3, p4, p5}]}];

Then I interpolate the data obtaining

(*INTERPOLATION*)
{xmin, xmax} = MinMax[data[[All, 1]]];
{ymin, ymax} = MinMax[data[[All, 2]]];
dataInterp = {Most@#, Last@#} & /@ data;
Istim3D = Interpolation[dataInterp, InterpolationOrder -> 1]
plIstim3D = 
  Plot3D[Istim3D[x, y], {x, xmin, xmax}, {y, ymin, ymax}, 
   PlotStyle -> Opacity[0.8], 
   AxesLabel -> {"\!\(\*SubscriptBox[\(I\), \(stim\)]\)", 
     "Tempi interspikes", "Numero di spikes"}, PlotRange -> All, 
   ImageSize -> 800];
Show[lpp, boundary, plIstim3D, ImageSize -> 800]

The plot that I obtain is the following enter image description here

Now my question is: I would like to cut the plot removing the part of surface, which goes beyond the red line, keeping the part of surface passing through my data. Is it possible to remove the part of the part of plot3d which goes beyond the dashed red line? If I have a curve defined by ParametricPlot3D, how can I achieve my objective?

Thank you very much for your help.

$\endgroup$
2
  • 2
    $\begingroup$ Off the top of my head, I think the easiest approach is to cut the plot by using the RegionFunction option of Plot3D. $\endgroup$
    – C. E.
    Nov 5, 2020 at 10:53
  • $\begingroup$ Thanks, I have tried with such an approach, but I do not know how to do it for a piecewise line. Could you please help me? $\endgroup$
    – VDF
    Nov 5, 2020 at 10:56

2 Answers 2

1
$\begingroup$
(*DATA*)data1 = 
  Table[{Istim[[1]], Tinterspike200[[i]], Nspikes200[[i]]}, {i, 1, 4}];
data2 = Table[{Istim[[2]], Tinterspike400[[i]], Nspikes400[[i]]}, {i, 
    1, 7}];
data3 = Table[{Istim[[3]], Tinterspike600[[i]], Nspikes600[[i]]}, {i, 
    1, 10}];
data4 = Table[{Istim[[4]], Tinterspike800[[i]], Nspikes800[[i]]}, {i, 
    1, 11}];
data5 = Table[{Istim[[5]], Tinterspike1000[[i]], 
    Nspikes1000[[i]]}, {i, 1, 13}];
data = Join[data1, data2, data3, data4, data5];
lpp = ListPointPlot3D[data, PlotStyle -> {PointSize[Large], Red}];

(*BOUNDARY*)p1 = {Istim[[1]], Tinterspike200[[4]], Nspikes200[[4]]};
p2 = {Istim[[2]], Tinterspike400[[7]], Nspikes400[[7]]};
p3 = {Istim[[3]], Tinterspike600[[10]], Nspikes600[[10]]};
p4 = {Istim[[4]], Tinterspike800[[11]], Nspikes800[[11]]};
p5 = {Istim[[5]], Tinterspike1000[[13]], Nspikes1000[[13]]};
ifun = Interpolation[{p1[[1 ;; 2]], p2[[1 ;; 2]], p3[[1 ;; 2]], 
   p4[[1 ;; 2]], p5[[1 ;; 2]]}, InterpolationOrder -> 1]
boundary = 
  Graphics3D[{Dashed, Thick, Red, Line[{p1, p2, p3, p4, p5}]}];

...

plIstim3D = 
  Plot3D[Istim3D[x, y], {x, xmin, xmax}, {y, ymin, ymax}, 
   PlotStyle -> Opacity[0.8], 
   AxesLabel -> {"\!\(\*SubscriptBox[\(I\), \(stim\)]\)", 
     "Tempi interspikes", "Numero di spikes"}, PlotRange -> All, 
   ImageSize -> 800, 
   RegionFunction -> 
    Function[{x, y, z}, ifun[x] > y > 0 && 200 < x && x < 1000]];
Show[lpp, boundary, plIstim3D, ImageSize -> 600]

RegionFunction

$\endgroup$
2
$\begingroup$

Perhaps the easiest way is to plot over {x, y} ∈ boundarypolygon, but due to the different scales in the x and y directions, the polygon is not meshed very well.

(*BOUNDARY*)
datasets = {data1, data2, data3, data4, data5};
pp = datasets[[All, -1]];
qq = datasets[[All, 1]];
bdycoord = Join[data1, pp[[2 ;; 4]], Reverse@data5, qq[[4 ;; 1 ;; -1]]];
boundary = Graphics3D[{Dashed, Thick, Red, Line[bdycoord]}];

Plot3D[Istim3D[x, y],
 {x, y} ∈ Polygon[Most /@ bdycoord],
 PlotStyle -> Opacity[0.8]]

enter image description here

It can be improved by setting PlotPoints -> {75, 1500}, but that seems excessive. A better result is obtained by rescale the polygon for meshing and then scaling back.

xc = Transpose[Most /@ bdycoord];
bdy = Polygon@Transpose[Rescale /@ xc];
bdymesh = ToElementMesh[bdy, MaxCellMeasure -> 1/1000];
bdymesh = ToElementMesh[
   "Coordinates" -> Transpose[
     MapThread[
      Rescale[#1, {0, 1}, #2] &,
       {Transpose@bdymesh@"Coordinates", MinMax /@ xc}]],
   "MeshElements" -> bdymesh@"MeshElements"
   ];
plIstim3D = Plot3D[Istim3D[x, y],
   {x, y} ∈ bdymesh,
   PlotStyle -> Opacity[0.8]];
Show[lpp, boundary, plIstim3D, PlotRange -> All]

enter image description here

Note the lower edge was trimmed, even though the OP did not ask for it. Adjust the definition of the polygon to set the lower edge as desired. (I thought trimming the domain so that there is no extrapolation would be more desirable, but I might be wrong.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.