[metapost] Re: workaround for turningnumber bug

Taco Hoekwater taco at elvenkind.com
Mon Jan 31 14:59:25 CET 2005


Larry Siebenmann wrote:

> Questions: Is 'buildcycle' or parts thereof involved in the
> triangular pen envelope construction? Or directiontime? Or
> 'intersectiontime'.  I still don't fully see what is going on at a
> low level.  Is Werner's approach involved at some level?

buildcycle is just a macro that uses intersectiontimes to find
points were (sub-)paths meet. 'low-level' turningnumber is pascal
code, and it consists of two parts:

a. run the envelope routine for the path, with an artificial pen.
    This is section 22 in mp.web, the routine offset_prep().

    JDH's comment says (slightly editted for simplicity by me):

    When MP has a path and a polygonal pen, it needs to express
    the desired shape in terms of things PS can understand.  The
    present task is to compute a new path that describes the region
    to be filled.  It is  convenient to define this as a two step
    process where the first step is  determining what offset to use
    for each segment of the path.

    Given a pointer c to a cyclic path, and a pointer h to the
    first knot of a pen polygon, the offset_prep routine changes
    the path into cubics that are associated with particular pen
    offsets. Thus if the cubic between p and q is associated with
    the k-th offset and the cubic between q and r has offset l,
    then info(q)=l-k.
    -- / end quote

    There is too much there for me to summarize it, just read
    mp.web yourself if you need more info.

b. use the resulting envelope spec to count pen offset delta's.
    This is done by the short routine called count_turns():

   function count_turns(c:pointer):scaled;
     var p:pointer; {a knot in envelope spec |c|}
         t:integer; {total pen offset changes counted}
     begin t:=0; p:=c;
     repeat t:=t+info(p)-zero_off;
     until p=c;
     count_turns:=(t div 3)*unity;

> One could start with Werner's code and introduce the following
> *initially optional* modifications:

certainly, but Werner's logic is not what I consider the hard
part of the algorithm.

> (1) politely refuse paths that mathematically speaking have no
> turning number. These are
>    (a) paths with a cusp, equivalently an interior point where the
> derivative is 0 (or within eps of 0).

How do I know this? That is the key problem, for me. Remember that
I have the 4 points (P, P+, Q-, Q) not the mathematical function
describing a path. That's why I raised the "triangle question" in
my other reply

>    (b) paths with an internal node at which the turning angle is
> angle is 180 degrees or within eps thereof. 

What is wrong with that? If this happens because of P+, it should
be fine as long as the Q- not likewise strange, right?

> (1*) optionally give warning in case a b'ezier segment 
> has a self intersection. Or a small loop?

What's the difference? And I think that a loop adds (or removes) 360
degrees to the turningnumber. Why should it not?

Greetings, Taco

More information about the metapost mailing list