# [metapost] workaround for turningnumber bug

Werner LEMBERG wl at gnu.org
Sun Jan 30 10:24:00 CET 2005

> When I try your algorithm on this path:
> path p;
> p := (0,0) ..controls (48,-18) and (24,-18).. (72,0)
>             ..controls (90,48) and (90,24).. (72,72)
>             ..controls (24,90) and (48,90).. (0,72)
>             ..controls (-18,24) and (-18,48).. cycle;
>
> it returns true (with res = -1080). But the path is clearly
> counterclockwise.

Thanks for the counterexample.  Is such a curve possible (this is,
with a reversed' order of the control points) in mpost if I don't
specify the control points explictly?

What are the constraints for a curve (P, P+, Q-, Q) so that there is a
self-intersection?  My algorithm can be improved by using only the
directions of P -> P+' and Q- -> Q' and assuring that no
self-intersection does happen.  Actually, I can drop the
self-intersection constraint, simply insisting that the curve doesn't
self-intersect (which must not happen in font outlines).

Are there any errors in my assumptions?

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 (point t + 1 of p - precontrol t + 1 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;

res := res + alpha + beta;
endfor;

res <= 0
enddef;