[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
made more elegant.

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;

	inner_r = .45 radius;

	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;


More information about the metapost mailing list