I want to draw a series of normals to a curve, where the curve has been parametrized by a single angle, i.e., the polar angle. The curve is actually sinusoidal perturbation of a circle of radius 1/2, and the magnitude of the perturbation is given by amp.

I have the normal function calculated in the code below already. I want to be able to draw normals to the curve at different points on the curve. How do I do this?

orad       = 1/2;
amp        = 0.05;
numpetals  = 7; 

(*Polar information of interface*)
r[th_]  := orad + amp * Sin[numpetals*th];
rp[th_] := amp*numpetals*Cos[numpetals*th];

(*Cartesian information of interface*)
x[th_]  := r[th]*Cos[th]; (*X-coordinate of the interface/*)
y[th_]  := r[th]*Sin[th]; (*Y-coordinate of the interface*)

(*Speeds of traveral*)
xp[th_] := rp[th]*Cos[th] - r[th]*Sin[th];
yp[th_] := rp[th]*Sin[th] + r[th]*Cos[th];

(*Outward unit normal to the curve*)
normal[th_] := {yp[th], -xp[th]}/Sqrt[xp[th]^2 + yp[th]^2];
  • $\begingroup$ look at this related Q&A. $\endgroup$
    – Kuba
    Jul 7, 2013 at 16:32

4 Answers 4


A solution using PolarPlot.

normalArrows = Table[Arrow[{{x[th], y[th]}, {x[th], y[th]} + 0.1 normal[th]}], {th,
 0, 360 \[Degree], 4 \[Degree]}];
PolarPlot[r[th], {th, 0, 360 \[Degree]}, Epilog -> normalArrows, PlotRange -> 0.65]

enter image description here

  • 1
    $\begingroup$ Alternatively: normalArrows = Table[Arrow[TranslationTransform[{x[θ], y[θ]}] /@ {{0, 0}, - 0.1 Cross[Normalize[{x'[θ], y'[θ]}]]}], {θ, 0, 360 °, 4 °}]. $\endgroup$ Oct 16, 2015 at 18:08
  • $\begingroup$ Cool. With descriptive function names this makes things very instructive. $\endgroup$ Oct 19, 2015 at 15:40

If I redefine normal, it is easy to plot the curve and its normals.

orad = 1/2;
amp = 0.05;
numpetals = 7;

r[th_] := orad + amp*Sin[numpetals*th]
rp[th_] := amp*numpetals*Cos[numpetals*th]

x[th_] := r[th]*Cos[th]; 
y[th_] := r[th]*Sin[th];

xp[th_] := rp[th]*Cos[th] - r[th]*Sin[th]
yp[th_] := rp[th]*Sin[th] + r[th]*Cos[th]

normal[th_] := Module[{unit, nx, ny},
  unit = Normalize@{xp[th], yp[th]};
  nx = unit[[2]]; ny = -unit[[1]];
  {{x[t], y[t]}, {x[t], y[t]} + {nx, ny}}]

Framed @ ParametricPlot[{x[u], y[u]}, {u, 0., 360 °},
  Epilog -> Table[Line[normal[t]], {t, 0., 360 °, 45 °}], 
  PlotRange -> 1.5]



Same approach (ParametricPlot, Epilog) as m_goldberg but with your definition for the normal.

points = Table[th, {th, -Pi, Pi, Pi/4}]
 {x[th], y[th]},
 {th, -Pi, Pi},
 Epilog -> {
   Point[{x[#], y[#]} & /@ points],
       {x[#], y[#]},
       {x[#], y[#]} + 0.2 normal[#]
       }] & /@ points
   }, PlotRange -> .7

enter image description here


Say you have this data points.

points = Table[{x[th], y[th]}, {th, 0, 2 Pi, Pi/100}];

And this is your line.

p1 = ListLinePlot[points];

And the normals will be simply lines joining these pair of points (as per your code).

norm = Table[{{x[th], y[th]}, normal[th]}, {th, 0, 2 Pi, Pi/10}];
(*I choose here 1/10th of total points or it will be too clumsy *) 

Then you can plot them if you wish

p2 = Graphics[{Table[Line[norm[[i]]], {i, Length[norm]}],
Point[Table[norm[[i]][[1]], {i, Length[norm]}]]}, Axes -> True];

And then you combine the both.

Show[{p2, p1}]

This will look something like

Grid[{{"Plot", "Normal", "Combine"}, {p1, p2, Show[{p2, p1}]}}, Frame -> All]


Please don't mind the aspect ratios. You can always fix them.

  • $\begingroup$ Thanks Sumit, but the indicated line segments don't look like normals to me, under the figure named combine, Is there some bug in your code? $\endgroup$ Jul 7, 2013 at 18:10
  • $\begingroup$ Thanks @smilingbuddha for the comment. It is because your code calculate normal at a point and it is made for a particular trajectory. When I choose only few points, the trajectory is not very clear and hence the normal doesn't appear to be 'normal'. It will be prominent when you take large number of points (what I have done now) and the normality will be more soothing to eye. $\endgroup$
    – Sumit
    Jul 7, 2013 at 19:17

Your Answer

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

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