arcer

fun List<Vector2>.arcer(closed: Boolean, startTangent: Vector2? = null, maxArcLength: Double = Double.POSITIVE_INFINITY, offset: Double = 0.0, polarity: YPolarity = YPolarity.CW_NEGATIVE_Y): ShapeContour(source)

Converts this polyline into a contour of tangent-continuous circular arcs that pass through all of its points, after surface-detail.com/posts/arc-plotter.

Every pair of consecutive points is joined by the unique circular arc that leaves the first point in the direction in which the previous arc arrived, the first arc leaves in startTangent. The exit direction of an arc is its entry direction mirrored in its chord, so the result is fully determined by the points and the start tangent. When the entry direction is parallel to the chord the arc degenerates into a straight segment.

When startTangent is null, open polylines start in the direction of the circle through the first three points. Closed polylines with an odd number of points start in the direction for which the last arc arrives back in that same direction, which gives a contour that is tangent-continuous everywhere. With an even number of points no such direction exists in general, the start then follows the circle through the last, first and second point and the contour has a kink at the first point.

When an arc is longer than maxArcLength, an extra point is inserted and the two arcs through it are tried instead, recursively. The point lies on the bisector of the entry direction and the chord, at half the chord length from the start. The first arc then arrives along the chord, turning half as far as the arc it replaces, and the second arc only corrects for the offset of the point from the chord, turning at most about 60 degrees. Both are shorter than the arc they replace, so long arcs straighten out towards their chords. Straight segments are not split. Splitting changes the direction in which an edge arrives, so it also changes the arcs that follow.

For closed polylines in which edges are split, the start direction for smooth closure is searched for numerically; when none exists the direction with the smallest kink at the first point is used.

With a non-zero offset the parallel curve at that distance is returned, which is exact because the offset of an arc is the concentric arc. Positive offsets lie on the side of the normal (-y, x) of the direction of travel, which is to the right in a y-down frame. Where an offset exceeds an arc's radius the offset arc passes through its center and reverses direction, as parallel curves do, leaving cusps at its ends. Contours at a range of offsets form the ribbons of the article.

Arcs are approximated with one cubic Bézier per 90 degrees of turn.

Parameters

closed

whether the polyline is closed, the last point should then not repeat the first

startTangent

the direction in which the first arc leaves the first point, or null for a default direction

maxArcLength

the length above which an arc is split in two, must be positive

offset

the signed distance of the returned parallel curve, 0.0 for the curve through the points

polarity

the polarity of the resulting contour