# Plot of gradient over a surface

I have the following region:

curve = BSplineCurve[{{0, 0}, {1, -.5}, {2, .5}, {1, 2}, {0,
1}, {-1, .5}}, SplineClosed -> True];
reg = Region@BoundaryDiscretizeGraphics@curve;


and the function (over that region):

f[x_,y_]=Sin[x y+2];


How do I generate a 3D plot of the surface given by $$(x,y,f(x,y))$$ with a grid of unitary normal vectors, only on the region reg?

curve = BSplineCurve[{{0, 0}, {1, -.5}, {2, .5}, {1, 2}, {0,
1}, {-1, .5}}, SplineClosed -> True];

bdg = BoundaryDiscretizeGraphics[curve];

f[x_, y_] = Sin[x y + 2];

p3d = Plot3D[f[x, y], {x, y} ∈ bdg,
Mesh -> None, BoxRatios -> 1, PlotRangePadding -> Scaled[.15]]


You can post-process p3d to add

1. normal lines at the center of each polygon:

Normal[p3d] /. p : Polygon[c_, ___, VertexNormals -> vn_, ___] :>
{p, Black, Line[{Mean[c], Mean[c] + Mean[vn]/3}]}


2. normal lines at polygon vertices:

Normal[p3d] /. p : Polygon[c_, ___, VertexNormals -> vn_, ___] :>
{p, Black, MapThread[Line[{##}] &, {c, c + vn/3}]}


To compare the two methods use an input plot produced with MaxRecursion -> 0 and a small value for PlotPoints:

p3dB = Plot3D[f[x, y], {x, y} ∈ bdg, Mesh -> None,
BoxRatios -> 1, PlotPoints -> 1, MaxRecursion -> 0,
PlotStyle -> EdgeForm[{Gray, Thin}],

Row[Show[#, ImageSize -> 400] & /@
{Normal[p3dB] /. p : Polygon[c_, ___, VertexNormals -> vn_, ___] :>
{p, Black, Line[{Mean[c], Mean[c] + Mean[vn]/3}]},
Normal[p3dB] /. p : Polygon[c_, ___, VertexNormals -> vn_, ___] :>
{p, Black, MapThread[Line[{##}] &, {c, c + vn/3}]}}]


Alternatively, you can use the function normalsShow from VertexNormals >> Applications:

normalsShow[g_Graphics3D] :=  Module[{pl, vl, n},
{pl, vl} = First@Cases[g, GraphicsComplex[pl_, prims_, VertexNormals -> vl_,
opts___?OptionQ] :> {pl, vl}, Infinity];
n = Length[pl];
Show[g,
Graphics3D[GraphicsComplex @@ {Join[pl, pl + vl/3],
{Black, Line[Table[{i, i + n}, {i, n}]]}}]]
];

normalsShow @ p3d


• Thank you for your great answer, however when adding in the option ColorFunction -> "FallColors" in the p3d definition the normal vectors won't show up, do you know how to deal with this? Apr 20, 2020 at 19:41
• @Leonardo, try replacing Polygon[c_, VertexNormals -> vn_] with Polygon[c_, ___, VertexNormals -> vn_, ___]?
– kglr
Apr 20, 2020 at 19:49
• Solved, perfect. Apr 20, 2020 at 19:53
• @kglr I just asked a related question here: mathematica.stackexchange.com/questions/246462/…. Could you please tell me how to get a list of the normal vectors only along the boundary? And plot them as well (along with the surface).
– ap21
May 22, 2021 at 3:57