fitCubicBeziers

fun fitCubicBeziers(points: List<Vector2>, errorTolerance: Double = 1.0, maxDepth: Int = 10, minPointsToSplit: Int = 5, tangentWindow: Int = 1, preferLowCurvatureSplits: Boolean = true, curvatureSearchRadius: Int = 3, cornerAngle: Double? = null, closed: Boolean = false): List<Segment2D>(source)

Fits a polyline of points with one or more cubic Beziers, splitting wherever a single piece can't stay within errorTolerance, after Schneider, "An algorithm for automatically fitting digitized curves" (Graphics Gems, 1990):

  • Tangent directions are estimated once, globally, and pieces meeting at a shared point always use the same direction there - no visible kinks at split boundaries.

  • Every piece is fitted by least squares for the lengths of its handles, and while it misses the tolerance by not too much, the parameters of the points are moved towards their nearest points on the fit with Newton's method and the fit is repeated. That fits more points with fewer pieces.

  • The split location is chosen near the worst-fitting point, but biased toward the flattest (lowest local turn angle) point within curvatureSearchRadius of it - splitting where the data is already nearly straight makes any residual join even less noticeable.

  • With a cornerAngle, points where the polyline turns more sharply than that stay corners: the curve is split there first, and the pieces on either side follow the polyline into the corner instead of rounding it.

  • A closed polyline gives a closed loop of pieces, smooth at the first point unless that is a corner.

Parameters

points

the points to fit, in order along the curve

errorTolerance

max allowed distance between any input point and the fitted curve

maxDepth

recursion limit; caps output at 2^maxDepth pieces

minPointsToSplit

don't split a piece with fewer points than this

tangentWindow

how many neighbors on each side to use when estimating a point's tangent, and when measuring how sharply it turns for corner detection

preferLowCurvatureSplits

if true, nudges the split point toward lower local curvature

curvatureSearchRadius

how far (in points) to search for a flatter split point

cornerAngle

the turning angle in degrees above which a point is a corner, or null for no corners

closed

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