circleSpline

fun List<Vector2>.circleSpline(closed: Boolean, tolerance: Double = 0.01, polarity: YPolarity = YPolarity.CW_NEGATIVE_Y): ShapeContour(source)

Converts this polyline into a circle spline through all points, after Séquin, Lee and Yen, "Fair, G2- and C2-continuous circle splines for the interpolation of sparse data points" (Computer-Aided Design, 2005).

Every segment from Pᵢ to Pᵢ₊₁ blends two circular arcs between those points: the arc of the circle through Pᵢ₋₁, Pᵢ and Pᵢ₊₁ and the arc of the circle through Pᵢ, Pᵢ₊₁ and Pᵢ₊₂. An arc from A to B is given by the angle θ between its tangent at A and the chord, and its point at fraction t of the way is A + rotate(chord direction, θ(1 - t)) times |AB|·sin(θt) / sin(θ). The segment takes θ from the first arc to the second with the weight sin²(πt / 2), in the angle space of the paper. Because the weight has zero derivative at both ends, every segment starts on the first circle and ends on the second with the same tangent and curvature: the spline is G2, its curvature at Pᵢ is that of the circle through Pᵢ and its neighbours, points on a circle give that circle and collinear points a straight line. The end segments of an open polyline are arcs of their one circle.

The blended arcs are drawn as cubic Béziers within tolerance.

Parameters

closed

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

tolerance

the largest distance between the cubic approximation and the spline

polarity

the polarity of the resulting contour