Pikchr

path-attribute
Login

A path-attribute is used provide the origin and direction of a line object (arc, arrow, line, move, or spline). It is an error to use a path-attribute on a block object (box, circle, cylinder, dot, ellipse, file, oval, or text).

There are seven forms:

The "from" attribute is used to assign the starting location of the line object (its ".start" value). The other six forms (collectively called "to" forms) assign intermediate vertexes or the end point (.end). If the "from" is omitted, then "from previous.end" is assumed, or if there is no previous object, "from (0,0)". If no "to" forms are provided then a single movement in the current layout direction by either the "linewid" or "lineht" (depending on layout direction) is used.

The "from" can occur either before or after the various "to" subclauses. That does not matter. But the order of the various "to" subclauses do matter, of course.

If there are two consecutive direction clauses (direction is always one of "right", "down", "left", or "right") then the two will be combined to specify a single line segment. Hence, the following are equivalent:

4cm 3cm 5cm 53.13°
leftmargin = 1cm
A1: arrow thick right 4cm up 3cm
dot at A1.start
X1: line thin color gray from (0,-3mm) down 0.4cm
X2: line same from (4cm,-3mm) down 0.4cm
arrow thin color gray from X1 to X2 "4cm" above
X3: line same from (4cm+3mm,0) right 0.4cm
X4: line same from (4cm+3mm,3cm) right .4cm
arrow thin color gray from X3 to X4 "3cm" aligned above
X5: line same from A1.start go 4mm heading 90+53.13010235
X6: line same from A1.end go 4mm heading 90+53.13010235
arrow thin color gray from X5 to X6 "5cm" below aligned
line same from (0,1cm) up 1cm
spline -> from 1.5cm heading 0 from A1.start \
   to 1.5cm heading 10 from A1.start \
   to 1.5cm heading 20 from A1.start \
   to 1.5cm heading 30 from A1.start \
   to 1.5cm heading 40 from A1.start \
   to 1.5cm heading 53.13 from A1.start \
   thin color gray "53.13°" aligned center small

If two separate movements are desired, one 4cm right and another 3cm up, then the "right" and "up" subphrases must be separated by the "then" keyword:

4cm 3cm
leftmargin = 1cm
A1: arrow thick right 4cm then up 3cm
dot at A1.start
X1: line thin color gray from (0,-3mm) down 0.4cm
X2: line same from (4cm,-3mm) down 0.4cm
arrow thin color gray from X1 to X2 "4cm" above
X3: line same from (4cm+3mm,0) right 0.4cm
X4: line same from (4cm+3mm,3cm) right .4cm
arrow thin color gray from X3 to X4 "3cm" aligned above

The "until even with" subclause

The "until even with" clause is a Pikchr extension (it does not exist in PIC) that makes it easier to specify paths that follow a "Manhattan geometry" (lines are axis-aligned) or that negotiate around obstacles. The phrase:

go direction until even with position

Means to continue the line in the specified direction until the coordinate being changed matches the corresponding coordinate in position If the line is going up or down, then it continues until the Y coordinate matches the Y coordinate of position. If the line is going left or right, then it continues until the X coordinate matches the X coordinate of position.

For example, suppose in the diagram below that we want to draw an arrow that begins on Origin.s and ends on Destination.s but goes around the Obstacle oval, clearing it by at least one centimeter.

Origin Destination Obstacle
box "Origin"
Obstacle: oval ht 300% wid 30% with .n at linewid right of Origin.ne;
box "Destination" with .nw at linewid right of Obstacle.n
line invis from 1st oval.s to 1st oval.n "Obstacle" aligned

The arrow might look like this:

   arrow from Origin.s \
      down until even with 1cm below Obstacle.s \
      then right until even with Destination.s \
      then to Destination.s

And we have (annotations added):

Origin Destination Obstacle down until even with 1cm below Obstacle.s right until even with Destination.s to Destination.s
box "Origin"
Obstacle: oval ht 300% wid 30% with .n at linewid right of Origin.ne;
box "Destination" with .nw at linewid right of Obstacle.n
line invis from 1st oval.s to 1st oval.n "Obstacle" aligned
X: \
   arrow from Origin.s \
      down until even with 1cm below Obstacle.s \
      then right until even with Destination.s \
      then to Destination.s

line invis color gray from X.start to 2nd vertex of X \
    "down until even with" aligned small \
    "1cm below Obstacle.s" aligned small
line invis color gray from 2nd vertex of X to 3rd vertex of X \
    "right until even with Destination.s" aligned small above
line invis color gray from 3nd vertex of X to 4rd vertex of X \
    "to Destination.s" aligned small above

# Evidence that the alternative arrow is equivalent:
assert( 2nd vertex of X == (Origin.s, 1cm below Obstacle.s) )
assert( 3nd vertex of X == (Destination.s, 1cm below Obstacle.s) )

The "( position , position )" syntax can be used in a similar way. The "( position , position )" syntax means a point whose X coordinate is taken from the first position and whose Y coordinate is taken from the second position. So the line around the obstacle could have been written like this:

   arrow from Origin.s \
     to (Origin.s, 1cm below Obstacle.s) \
     then to (Destination.s, 1cm below Obstacle.s) \
     then to Destination.s

However, we believe the "until even with" notation is easier.

The "close" subclause

The "close" attribute closes a multi-segment path so that it forms a polygon. When "close" is used, the ".end" point of the object is no longer the last vertex in the path but is instead one of ".e", ".s", ".w", or ".n" according to the current layout direction, as it would be for a block object.

The following diagram illustrates this behavior. The ".end" of each line is tagged with a red dot. The line that uses "close" has its end at the ".e" point of the bounding box since the layout direction is "right". The line without "close" has its ".end" at the last vertex of the line.

with 'close' without 'close'
line right 2cm then down .5cm then up 1cm right 1cm \
   then up 1cm left 1cm then down .5cm then left 2cm \
   close "with 'close'"
dot color red at last line.end

move to 2.5cm south of last line.start
line right 2cm then down .5cm then up 1cm right 1cm \
   then up 1cm left 1cm then down .5cm then left 2cm \
   then down 1cm "without 'close'"
dot color red at last line.end