Proposals/Path data turtle graphics proposal

From SVG

ISSUE-2288

It is not trivial to author paths where a specific angle is needed between two adjacent path segments; the author must use trigonometry to compute the desired endpoint of the second path segment. This is not terribly difficult, but if the author wishes to animate the angle between the path segments using declarative animation, then this can only be done by specifying many points for the second path segment over the course of the animation, rather than a single angle value.

For example, for the following animation:

you would need to write the following:

<path>
  <animate attributeName="d"
           values="M10,40 L50,50 l0,40;
                   ...
                   M10,40 L50,50 l20,34.64;
                   ...
                   M10,40 L50,50 l34.64,20
                   ...
                   M10,40 L50,50 l40,0"/>
</path>

with as many animation values as desired to make the endpoint of the second path segment trace out a smooth arc.

Better would be if the angle between the two arc segments could be animated directly.

An initial proposal

At each point in the path, there is a current rotation, which starts off as 0deg. Like SVG transforms, 0deg is horizontal along the positive x axis and 90deg is vertical along the positive y axis. The current rotation for existing (SVG 1.1) path commands is already described for use by orient="auto" markers.

We introduce some new path commands:

  • R <angle> -- sets the current rotation to the given angle
  • r <angle> -- sets the current rotation the current rotation plus the given angle
  • f <length> or F <length> -- straight line from the current point, using the current rotation angle, for the given length

The rotation commands would not cause a marker to be rendered.

This allows the example above to written as:

<path>
  <animate attributeName="d"
           values="M10,40 L50,50 r90 f40;
                   M10,40 L50,50 r0 f40"/>
</path>

What about other path commands?

If a straight line current-rotation-aware path command is useful, then it seems that the other commands (move, curve, arc) would be too. But do we really want to duplicate all of those commands? Instead, we could consider introducing a modifier that causes the segment to be rotated around the current position by the current rotation.

So n alternative proposal:

  • We still introduce R and r to change the current rotation.
  • We introduce a prefix modifier ~ (character subject to bikeshedding) that causes the following command to be rotated.

Thus, to get a straight line forward segment like the f proposal, you would write ~h.

The example would be written as:

<path>
  <animate attributeName="d"
           values="M10,40 L50,50 r90 ~h40;
                   M10,40 L50,50 r0 ~h40"/>
</path>

Here, ~h wouldn't be a distinct path command from h. Instead we introduce a Boolean flag on SVGPathSeg (or perhaps each individual interface where ~ is sensible?) that indicates whether the segment is rotated:

interface SVGPathSeg {
  ...
  readonly attribute boolean rotated;
};

Here is a second example.

Without a rotate command, you would need to write the animation like so:

<path>
  <animate attributeName="d"
           values="M10,40 h40 c30,15 -30,30 0,45;
                   ...
                   M10,40 h40 c31.82,-10.61 -0,42.43 31.82,31.82;
                   ...
                   M10,40 h40 c15,-30 30,30 45,0"/>
</path>

with many entries in the values attribute to make the animation accurate.

With a rotate command, you could write the following:

<path>
  <animate attributeName="d"
           values="M10,40 h40 r0 ~c30,15 -30,30 0,45;
                   M10,40 h40 r-90 ~c30,15 -30,30 0,45"/>
</path>

Drawbacks

  • A minor issue is that the last two values of a rotated path command do not identify the new current point of the path, like all the other path commands do.