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



More information about the metapost mailing list