# [metapost] workaround for turningnumber bug

Werner LEMBERG wl at gnu.org
Fri Jan 28 09:32:02 CET 2005

I've written a small function which computes the orientation of a
path, see below -- it is intended for use with mf2pt1.  It works
without problems (at least for the font outlines which I'm working on)
and gives reliable results in contrast to the buggy turningnumber'
function.

Since I'm a poor metapost programmer I wonder whether it can be

For your enjoyment I've also attached a (non-intersecting) curve where
metapost's turningnumber' reports -3 instead of the correct 1.

Werner

======================================================================

%% \begin{explaincode}
%%   Determine the direction of a closed curve.  \mfcomment
%    Returns |true| if the curve is clockwise, |false| if counterclockwise.
%%   Since the turningnumber' command in MetaPost is buggy, we compute
%%   the path orientation by ourselves.
%% \end{explaincode}

vardef Angle primary d =
if d <> (0, 0):
angle d
else:
0
fi
enddef;

vardef is_clockwise primary p =
save res, alpha, beta, gamma;

res := 0;

for t = 0 upto length p - 1:
alpha := Angle (postcontrol t of p - point t of p)
- Angle (point t of p - precontrol t of p);
if alpha > 180:
alpha := alpha - 360;
fi;
if alpha <= -180:
alpha := alpha + 360;
fi;

beta := Angle (precontrol t + 1 of p - postcontrol t of p)
- Angle (postcontrol t of p - point t of p);
if beta > 180:
beta := beta - 360;
fi;
if beta <= -180:
beta := beta + 360;
fi;

gamma := Angle (point t + 1 of p - precontrol t + 1 of p)
- Angle (precontrol t + 1 of p - postcontrol t of p);
if gamma > 180:
gamma := gamma - 360;
fi;
if gamma <= -180:
gamma := gamma + 360;
fi;

res := res + alpha + beta + gamma;
endfor;

res <= 0
enddef;
-------------- next part --------------
beginfig (0);
save bulb, p, radius, thin, inner_r, penh, pedalh, h, w;
path pat;

penh = 10;
pedalh = 100;
thin = 5;
w = 7/9 pedalh;
h = pedalh;

z0 = (1/2 w, h - 1/2 w);

bulb + 2 radius = w;
0.9 thin + bulb = (radius * 3.1415 * 2) / 8;

pickup pencircle scaled penh;

penpos1 (bulb, 180);
penpos2 (bulb, 0);
penpos3 (thin, 0);

z1 = z0 + (0, radius);
z2 = z1;

z4l = z0 + inner_r * dir (90 + 360/16);
z4r = z0 + inner_r * dir (90 - 360/16);

z4 = .5 [z4l, z4r];
z3 = .75 [z1, z4];

%	labels (0);
%	penlabels (1, 2, 3, 4);

pat := z3r{up}
.. z1l{up}
.. z2l{down}
.. z3l{down}
.. z4l{dir (180 + 360/16)};
for i = 1 upto 7:
pat := pat
.. ((z3r{up}
.. z1l{up}
.. z2l{down}
.. z3l{down}
.. z4l{dir (180 + 360/16)})
rotatedaround (z0, 360/8 i));
endfor;

pat := pat
.. cycle;

show turningnumber pat;

fill pat;
endfig;

end;
`