5

Here is my approach, for an example surface function:

surface[x_, y_] := Sin[x y];

The normal vector of a point in the surface is computed as:

NormalVector[a_, b_] := {D[surface[xx, yy], xx], D[surface[xx, yy], yy],1} /. {xx -> a, yy -> b};

Then the plot is as follows:

Plot3D[surface[x, y], {x, 0, 3}, {y, 0, 3}, ColorFunction -> Function[{x, y, z}, 
RGBColor[0, 0, VectorAngle[NormalVector[x, y], {0, 0, 1}]]]]

However it fails, why?

novice
  • 2,325
  • 1
  • 24
  • 30

2 Answers2

9

Just for variety: Note also outward normal to surface $z=f(x,y)$: $\nabla(z-f(x,y))=<-f_x,-f_y,1>$ (inward negative)...not same as "NormalVector" function listed (apologies if I have misinterpreted or made error). I have rewritten taking into account:

f[x_, y_] := Sin[x y];
n[x_, y_] := {-D[f[a, b], a], -D[f[a, b], b], 1} /. {a -> x, b -> y};
va[x_, y_] := VectorAngle[n[x, y], {0, 0, 1}];
Manipulate[
 Show[Plot3D[f[x, y], {x, 0, 3}, {y, 0, 3}, 
   ColorFunction -> 
    Function[{x, y, z}, 
     ColorData["Rainbow"][Rescale[va[x, y], {0, 1.4}]]], 
   ColorFunctionScaling -> False, PlotRange -> {-2, 2}, 
   PerformanceGoal -> "Quality"], 
  Graphics3D[{Red, Thick, 
    Arrow[{{s[[1]], s[[2]], 
       f[s[[1]], s[[2]]]}, {s[[1]], s[[2]], f[s[[1]], s[[2]]]} + 
       Normalize@n[s[[1]], s[[2]]]}, 0.03]}],
  ContourPlot3D[{x - s[[1]], y - s[[2]], z - f[s[[1]], s[[2]]]}.n[
      s[[1]], s[[2]]] == 0, {x, s[[1]] - 0.2, 
    0.2 + s[[1]]}, {y, -0.2 + s[[2]], 0.2 + s[[2]]}, {z, -2, 2}, 
   Mesh -> False]], {s, {0.1, 0.1}, {3, 3}}]

The graphic illustrates color of surface based on angle between normal and $\vec{k}$ (which seems to be intended color function). I show the unit normal and tangent plane.

enter image description here

ubpdqn
  • 60,617
  • 3
  • 59
  • 148
8

To be honest, I'm not really sure why you need ColorFunctionScaling since there aren't any outlayers that could make the rest of the plot flat, nevertheless:

Plot3D[surface[x, y], {x, 0, 3}, {y, 0, 3}, ColorFunctionScaling -> False, 
          Lighting -> "Neutral", ColorFunction -> Function[{x, y, z}, 
          Blend[{Blue, White}, 2 #/Pi] &@ VectorAngle[NormalVector[x, y], {0, 0, 1}]]]

enter image description here

Update

Plot3D[surface[x, y], {x, 0, 3}, {y, 0, 3}, ColorFunctionScaling -> False, 
         ColorFunction -> Function[{x, y, z}, Blend["Rainbow", Rescale[#, {0, Pi/2}]
                                  ] & @ VectorAngle[NormalVector[x, y], {0, 0, 1}]], 
         PlotLegends -> BarLegend[{"Rainbow", {0, 90}},  ColorFunctionScaling -> True,  
                                  LegendLabel -> "normal vs zenith [\[Degree]]"]
      ]

enter image description here

Kuba
  • 136,707
  • 13
  • 279
  • 740