# How to plot a crossection of a ParametricPlot3D?

I'm plotting a surface using ParametricPlot3D. Ideally I would like to plot an intersection of the surface with a plane just as seen in another question (Cross Sections or slices of 3d figures - Mathematica). However in my case the parameters u and v are not equivalent to the spatial coordinates x,y. This is why i tried RegionPlot in place of CountourPlot to plot all pairs (x,y) that intersect the surface for a given value of z. This is not working somehow and I'm lost trying to look for alternatives.

Surface[u_, v_] = {Cos[u], Sin[u] + Cos[v], Sin[v]};

Row[{Show[{ParametricPlot3D[
Surface[u, v], {u, 0, 2Pi}, {v, -Pi, Pi},
PlotStyle -> Opacity[ 0.2]],
Graphics3D[{Blue, Opacity[0.4],
InfinitePlane[{0, 0, 0}, {{1, 0, 0}, {0, 1, 0}}]}]},
ImageSize -> 300],
RegionPlot[
Exists[{u, v}, Surface[u, v] == {x, y, 0}], {x, -1, 1}, {y, -1, 1},
ImageSize -> 300]}]


In reality my surface is a bit more complicated so I chose a simple one for posing this question. Also ideally I would like to be able to change around the normal vector of the plane later, checking out any angle of the crosssection I like, so please keep that in mind when thinking about the question. Thank you very much for any engagement in my problem!

You can use MeshFunctions + Mesh + MeshStyle to mark the intersection of the plane with the surface:

pp = ParametricPlot3D[Surface[u, v], {u, -Pi, Pi}, {v, -Pi, Pi},
PlotStyle -> Opacity[0.3],
PlotPoints -> 200,
MeshFunctions -> { #3 &},
Mesh -> {{{10^-6, Red}}}];

Show[pp, Graphics3D[{Blue, Opacity[0.4],
InfinitePlane[{0, 0, 0}, {{1, 0, 0}, {0, 1, 0}}]}]]


Extract the line primitives from pp and remove the last column of coordinates to get 2D lines to be used with Graphics:

Graphics[{Red, Thick,  Cases[Normal[pp], Line[x_] :> Line[x[[All, ;; 2]]], All]},
Frame -> True]


Use (1) MeshFunctions -> { #2 &} in ParametricPlot3D, (2) InfinitePlane[{0, 0, 0}, {{1, 0, 0}, {0,0,1}}] in Graphics3D and (3) Line[x[[All, {1,3}]]] in Cases to get

And MeshFunctions -> { #2-# &}, InfinitePlane[{0, 0, 0}, {{1, 1, 0}, {0,0,1}}], ] :> Line[x[[All, {1,3}]]] to get

Update: You can use any (not necessarily linear) function of 5 arguments ({x, y, z, u, v}) as the value of the MeshFunction option. Also you can use MeshShading to have different styles for mesh divisions:

pp = ParametricPlot3D[Surface[u, v], {u, -Pi, Pi}, {v, -Pi, Pi},
PlotStyle -> Opacity[0.3], PlotPoints -> 200,
MeshFunctions -> { -2 Pi # + #2 Sin[# + 3 #2] + Cos@#3 &},
Mesh -> {{{0, Directive[Thick, Red]}}},


Use ContourPlot3D with the mesh function as the first argument to get the separating surface and Show with pp:

cp = ContourPlot3D[-2 Pi x + y Sin[x + 3 y] + Cos@z == 0,
{x, -1, 1}, {y, -2, 2}, {z, -1, 1},
ContourStyle -> Opacity[.5, Red], Mesh -> None, BoundaryStyle -> None];

Show[pp, cp]


• I ended up using this, thanks a lot! – joe Jul 26 '19 at 15:26
• @joe, my pleasure. Welcome to mma.se. – kglr Jul 26 '19 at 15:31
• thank you. I adapted most of my stuff to your approach. just one last thing. i don't quite understand how I'm supposed to manipulate the part Cases[Normal[pp], Line[x_] :> Line[x[[All, ;; 2]]] when I change the direction of my plane. I have never used the functions Cases or Line before so I'm not quite sure, what the arguments do when you change them. I also haven't learned much from the documentation. Maybe you can give me a hint. – joe Jul 26 '19 at 16:55
• I figured something out Cases[Normal[pp], Line[x_] :> Line[Map[R2.R1.#1 &, x][[All, {1, 2}]]], All] where R2 and R1 are rotation matrices that turn {0,0,1} into the normal vector of the plane. Seems to be working. – joe Jul 26 '19 at 18:08

Here my solutionapproach

First define the plane e and n

n = {0, 0, 1}; (*normalvector of plane*)
e = {0, 0, 0}; (*point of plane*)


Condition of intersection is Surface[u, v] - e).n == 0 which can be visualized with

ContourPlot[(Surface[u, v] - e).n == 0, {u, 0, 2 Pi}, {v, -1.1 Pi ,1.1 Pi }, FrameLabel -> {u, v},PlotRange -> {{0, 2 Pi}, {-1.1 Pi, 1.1 Pi}}]


Obviously the intersection is defined by 0<u<2Pi ,v \[Element] {0, Pi} (which could be evaluated by NSolve[{(Surface[u, v] - e).n == 0,0 <= u <= 2 Pi, -Pi <= v <= Pi}, {u, v}, Reals]):

ParametricPlot3D[{Surface[u, 0], Surface[u, Pi]}, {u, 0, 2 Pi}]


It's not necessary to introduce new coordinates x,y.

2nd example:

n={0,1,0};
sol = NSolve[{(Surface[u, v] - e).n == 0,0 <= u <= 2 Pi, -Pi < v < Pi}, {u, v}, Reals]
ParametricPlot3D[Surface[u, v] /. sol, {u, 0, 2 Pi}]


• ok, thank you, I like the start of this. But what about the plane for n = {0, 1, 0}; though? The contour lines will not be constant in any coordinate u or v. So I can't just produce the second plot by putting constant numbers into the Surface function. – joe Jul 23 '19 at 12:57
• something I'm trying now to expand on your approach is the following uvlines = ImplicitRegion[(Surface[u, v] - e).n == 0, {u, v}] ParametricPlot3D[Surface[u, v], Element[{u, v}, uvlines]] but again, it's not working. – joe Jul 23 '19 at 13:05
• @joe NSolve gives you the parametric solution! You have to put the NSolve result into the ParametricPlot3D – Ulrich Neumann Jul 23 '19 at 13:08
• @joe I edited my answer... – Ulrich Neumann Jul 23 '19 at 13:10