# Cut an interpolating function

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

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.

• Off the top of my head, I think the easiest approach is to cut the plot by using the RegionFunction option of Plot3D. Commented Nov 5, 2020 at 10:53
• 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?
– VDF
Commented Nov 5, 2020 at 10:56

(*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]


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]]


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[
`