# Drawing normals to a curve

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];

• look at this related Q&A.
– Kuba
Commented Jul 7, 2013 at 16:32

## 4 Answers

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]


• Alternatively: normalArrows = Table[Arrow[TranslationTransform[{x[θ], y[θ]}] /@ {{0, 0}, - 0.1 Cross[Normalize[{x'[θ], y'[θ]}]]}], {θ, 0, 360 °, 4 °}]. Commented Oct 16, 2015 at 18:08
• Cool. With descriptive function names this makes things very instructive. Commented 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}]
ParametricPlot[
{x[th], y[th]},
{th, -Pi, Pi},
Epilog -> {
PointSize[Medium],
Point[{x[#], y[#]} & /@ points],
Arrow[{
{x[#], y[#]},
{x[#], y[#]} + 0.2 normal[#]
}] & /@ points
}, PlotRange -> .7
]


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.

• 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? Commented Jul 7, 2013 at 18:10
• 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. Commented Jul 7, 2013 at 19:17