Pikchr

On arcs in PIC and pikchr
Login

On arcs in PIC and pikchr

(1.1) By Andreas Kupries (akupries) on 2020-09-16 17:39:39 edited from 1.0 [link] [source]

pikchr's current implementation of arc's is quite underdeveloped compared to what the legacy PIC processors provide.

As the first step in correcting this I decided to run both a recent GNU pic and a recent version of dPIC (Sep 1, 2020) through various examples, capture the drawing and then deduce what behaviour these black boxes implement.

My conclusions below are based on only 10 core examples at the moment, doubled for processing by looking at both clockwise and counter clockwise operation.

  1. arc
  2. arc from (0,2)
  3. arc to (0,2)
  4. arc to (1,2)
  5. arc to (2,2)
  6. arc to (4,2.5)
  7. arc to (4,2.5) rad 0.1
  8. arc to (4,2.5) rad 5
  9. arc from (4,2.5) to Here rad 5
  10. arc at (0,2)

I can provide an archive containing these examples, the processing scripts, and my results. I am unsure how to provide it here as links a reader can use.

Edit:

  • Zip archive holding the investigation data.
  • Table of commands and their diagrams.

Regardless, the conclusions I drew from the above are:

  1. GNU pic and dPIC are mostly identical in behaviour. They differ in how they resolve the ambiguity in legacy PIC regarding which center of an arc to use, when more than one is possible. More on that later.

  2. Arcs based on defaults or just a user-specified from position are always quarter turns beginning at the specified position, using the turn direction. In this case the layout direction after the arc is changed appropriately from the layout direction from before the arc.

  3. For arcs specifying a center via at (and of course having a from position, if only implied as Here) dPIC seg.faults on my example, and GNU pic draws something bogus.

    For pikchr I propose that we do not allow the setting of at for arcs. This is in line with what pikchr already does. In other words, I propose to keep the existing behaviour and to not expand pikchr into undefined (badly defined) territory.

    And we can always expand pikchr in the future when we find good definitions for this.

  4. For arcs specifying an end point, via to:

    1. The layout direction after the arc is the same as before the arc. The change of direction done by the quarter turns above is disabled.
    2. If the distance from start/end point to the mid point on the line between them is longer than the arc radius (implied or specified) it is technically not possible to draw an arc with that radius.

      In that case a half-turn arc (half-circle) is drawn, with the mid point as the center. In essence, the user's arc radius is ignored and the distance to the mid point is used as such. The turn direction then decides on which side of the line between start and end the arc is drawn.

      For clockwise on the left, for counter clockwise on the right.

      Left and right are defined by a person standing at the start point and looking towards the end point.

    3. If the distance to the mid point is however shorter than the desired arc radius then we can draw an arc with that radius.

      We then also have two possible locations for the center of the arc, the two intersection points of the two virtual circles around start and end point with the given radius.

      Which of the possible centers is chosen is where GNU pic and dPIC differ:

      • GNU pic chooses the center based on the turn direction, in the same manner as it chose the side for the half circle in the previous case.
      • dPIC ... I am not sure. The documentation claims that

        the interpreter will choose one by attempting to minimize the angle between the current direction and the initial arc tangent.

        I have trouble seeing that in the example inspected so far.

    4. I propose for pikchr to adopt GNU pic's behaviour, as something which is simple to explain and predict.

So, comments and opinions ?


Note, I have not talked about implementing this yet, nor how it would look in the SVG. This is purely investigation of the existing behaviour.

(2) By Stephan Beal (stephan) on 2020-09-16 02:44:55 in reply to 1.0 [link] [source]

I am unsure how to provide it here as links a reader can use.

If we only knew someone who could get you checkin access...

So, comments and opinions ?

The rest of it was way over my head, but i stand by my first statement ;).

(3) By Andreas Kupries (akupries) on 2020-09-16 03:14:38 in reply to 2 [link] [source]

If we only knew someone who could get you checkin access...

I have pinged @Richard now, in mail.

(4) By drh on 2020-09-19 19:50:55 in reply to 1.1 [link] [source]

Excellent information, Andreas!

However, as I set down to implement this, I quickly bogged down, especially with regard to adding arrows at the ends of arcs. And for that reason, I did a "fossil revert" and instead documented that arcs are really quadratic Bezier curves, and attempt to provide some justification for that choice.

If you would like to work up some code to implement "arc" as gpic and dpic do, I will be happy to consider including it. Or even if you want to improve upon my quadratic Bezier curve approximation, that would be great too. For example, perhaps it would be beneficial to translate an arc into a multi-segment spline that more closely approximates a true arc that my current crude approximation. This would mean that no new arrowhead adding logic would be required as the spline renderer already does that and the output would probably be close enough to a true arc that nobody will ever notice a difference. But I think I myself would rather focus on other issues.

As part of my rationalization of this choice, and to illustrate why I think arcs are not really required, I generated a Pikchr diagram with a cool-looking dimensional arc drawn using "spline":

C0 C1 C2 C4 C6 C3 30° distance C2 to C4
linewid *= 0.5
circle "C0" fit
circlerad = previous.radius
arrow
circle "C1"
arrow
circle "C2"
arrow
circle "C4"
arrow
circle "C6"
circle "C3" at dist(C2,C4) heading 30 from C2

d1 = dist(C2,C3.ne)+2mm
line thin color gray from d1 heading 30 from C2 \
   to d1+1cm heading 30 from C2
line thin color gray from d1 heading 0 from C2 \
   to d1+1cm heading 0 from C2
spline thin color gray <-> \
   from d1+8mm heading 0 from C2 \
   to d1+8mm heading 10 from C2 \
   to d1+8mm heading 20 from C2 \
   to d1+8mm heading 30 from C2 \
   "30&deg;" aligned above small

X1: line thin color gray from circlerad+1mm heading 300 from C3 \
        to circlerad+6mm heading 300 from C3
X2: line thin color gray from circlerad+1mm heading 300 from C2 \
        to circlerad+6mm heading 300 from C2
line thin color gray <-> from X2 to X1 "distance" aligned above small \
    "C2 to C4" aligned below small

(5) By Andreas Kupries (akupries) on 2020-09-19 20:13:51 in reply to 4 [source]

As nice as this graph looks, I still plan to do my own trial at PIC-legacy arc (without 'at" support). Not worked the courage up yet to fully go into the implementation.

Might try something simpler first, like the "angle" functions, and "intersect", or a "diamond" class (*). Thank you for doing "dist", btw.

(Ad *)

box wid 150% invis ; line from last.w to last.n to last.e to last.s close

pikchr