The question is pretty much in the title; I'm about to teach my multivariable calculus students about orientations on surfaces, and I would like to be able to show them pictures. Any ideas?


4 Answers 4


The easiest thing to do is differentiate the field and use VectorPlot3D and ContourPlot3D to show orthogonality of these. This is from Documentation Center. I will change this a bit from original to polish graphics for your lecture. These are not unit vectors though - do u really need unit ones? It can be done too if you need.

Use a contour plot to visualize the region of a vector plot:

scalarField = x^2 - y^2 - z;
vectorField = D[scalarField, {{x, y, z}}]

Plot a vector field over a particular region:

v = VectorPlot3D[vectorField, {x, -2, 2}, {y, -2, 2}, {z, -2, 2}, 
  VectorPoints -> 20, VectorScale -> {0.1, Scaled[0.5]}, 
  RegionFunction -> Function[{x, y, z}, -0.1 <= scalarField <= 0.1], 
  VectorStyle -> "Arrow3D", VectorColorFunction -> "Rainbow"]

Create a contour plot of the vector plot's region:

c = ContourPlot3D[
  scalarField == 0, {x, -2, 2}, {y, -2, 2}, {z, -2, 2}, Mesh -> 20, 
  MeshStyle -> Opacity[.1], 
  ContourStyle -> Directive[Green, Opacity[0.3], Specularity[White, 30]]]

Combine the vector and contour plots:

Show[v, c]

enter image description here

  • $\begingroup$ This is very helpful, thanks! Is there any way to modify your idea so that it works for surfaces described by parametric equations, rather than as level surfaces of functions of $x$, $y$, and $z$? $\endgroup$ Nov 6, 2012 at 21:39
  • $\begingroup$ @PaulSiegel I modified my answer to show a way to get vector field for surfaces on parametric form. $\endgroup$
    – ssch
    Nov 7, 2012 at 0:25
  • 1
    $\begingroup$ Nice start--but this is not a unit normal field. The lengths of the arrows come from extraneous, irrelevant information related to the function of which this surface is a zero. (The fix is fairly easy to make--but watch out for places where the gradient is zero!) $\endgroup$
    – whuber
    Nov 7, 2012 at 17:00
  • $\begingroup$ @whuber yes, I explicitly mentioned it in 1st paragraph. $\endgroup$ Nov 7, 2012 at 17:02
  • 2
    $\begingroup$ Sorry; I focused on the image and only skimmed the text! (+1). However, as I pointed out, the lengths of your vectors are extraneous to the problem, so in the intended application it likely is best to normalize them. You are also going to run into trouble where the gradient is zero (at the origin in your example) because you won't be able to calculate a nontrivial normal vector, even though it exists. $\endgroup$
    – whuber
    Nov 8, 2012 at 16:33

Let's start with a parametrized surface. Any one will do, but I guess being orientable helps in this case. Then calculate the unit normal, and then create a Manipulate object that lets you see how the normal behaves:

σ[u_, v_] := {(2 + Cos[v]) Cos[u], (2 + Cos[v]) Sin[u], Sin[v]}
n[u_, v_] := Evaluate[Normalize[
   Cross[D[σ[u, v], u], D[σ[u, v], v]]
surfacePlot = 
  ParametricPlot3D[σ[u, v], {u, -Pi, Pi}, {v, -Pi, Pi},
   PlotRangePadding -> 1];
normalPlot = 
  ParametricPlot3D[n[u, v], {u, -Pi, Pi}, {v, -Pi, Pi}, 
   PlotStyle -> Opacity[0.5]];

    Graphics3D[{Thick, Red, 
      Arrow[{σ @@ pt, σ @@ pt + n @@ pt}]}]
    Graphics3D[{Thick, Red, Arrow[{{0, 0, 0}, n @@ pt}]}]
 {pt, {-Pi, -Pi}, {Pi, Pi}}]

surface and normal

To show the entire vector field for a surface on parametric form you can use a bunch of Arrow's:

    Arrow[{σ[u, v], σ[u, v] + n[u, v]}],
    {u, -Pi, Pi, 0.4}, {v, -Pi, Pi, 0.4}]

vector field

As you can see, the arrows are equally spaced in the parameter space, which leads to uneven distribution of arrows on the surface; it might be worth transforming the parametrization into $f(x,y,z)=0$ form to get a nicer result.


It isn't too hard to roll your own routine, of course:

UnitNormalVector[f_, {u_, u0_}, {v_, v0_}] := Block[{f0, g0},
                 f0 = f /. {u -> u0, v -> v0};
                 g0 = Transpose[D[f, {{u, v}}] /. {u -> u0, v -> v0}];
                 Arrow[{f0, f0 + Normalize[Cross @@ g0]}]]

(* Möbius strip *)
mobius[u_, v_] :=
      {(3 + (1/2 - v) Cos[u/2]) Cos[u], (3 + (1/2 - v) Cos[u/2]) Sin[u], (1/2 - v) Sin[u/2]}

Show[ParametricPlot3D[mobius[u, v], {u, 0, 2 π}, {v, 0, 1},
                      Mesh -> False, PlotPoints -> 55],
     Graphics3D[Table[UnitNormalVector[mobius[u, v], {u, u0}, {v, v0}],
                      {u0, 0, 2 π, 2 π/20}, {v0, 0, 1, 1/5}]], PlotRange -> All]

Möbius strip with normals

It's not too hard to give the arrows depicting the normals some style:

% /. Arrow[stuff__] :> {Blue, Arrow[Tube[stuff, 0.05]]}

Möbius strip with dolled-up normals

  • 3
    $\begingroup$ Orienting a Möbius strip is pure heresy. Voting to inquisite. $\endgroup$ Nov 7, 2012 at 2:37
  • 1
    $\begingroup$ @bel, you weren't aware that I've always had a heretical streak? >:) $\endgroup$ Nov 7, 2012 at 2:44
  • $\begingroup$ I thought you were pretending $\endgroup$ Nov 7, 2012 at 2:48
  • 1
    $\begingroup$ +1. Seeing this normal field might help some people understand what's going on in the discussions about Möbius bands here. $\endgroup$
    – whuber
    Nov 7, 2012 at 16:58

Just adding this answer for completion seeing as there is an out-of-the-box solution for this hidden in the documentation.

Essentially the following function:

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

(that can easily be tweaked to subsample or use arrows instead of lines) works in the previously mentioned examples:

The c of Vitaly:

c // normalsShow

a surface with normals

the donut:

surfacePlot // normalsShow

torus with normals

and the Möbius band:

ParametricPlot3D[mobius[u, v], {u, 0, 2 π}, {v, 0, 1}, 
  Mesh -> False, PlotPoints -> 55] // normalsShow

Möbius strip with normals


Your Answer

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

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