flo_curves
flo_curves copied to clipboard
A version of fit_curve_cubic that is gaurunteed to return only one curve.
pub fn fit_curve_cubic<Curve: BezierCurveFactory+BezierCurve>(points: &[Curve::Point], start_tangent: &Curve::Point, end_tangent: &Curve::Point, iterations: u32) -> Vec<Curve> {
if points.len() <= 2 {
// 2 points is a line (less than 2 points is an error here)
fit_line(&points[0], &points[1])
} else {
// Perform an initial estimate of the 't' values corresponding to the chords of the curve
let mut chords = chords_for_points(points);
// Use the least-squares method to fit against the initial set of chords
let mut curve = generate_bezier(points, &chords, start_tangent, end_tangent);
// Reparameterise the chords (which will probably be quite a bad estimate initially)
chords = reparameterize(points, &chords, &curve);
curve = generate_bezier(points, &chords, start_tangent, end_tangent);
// Estimate the error after the reparameterization
let (mut error, mut split_pos) = max_error_for_curve(points, &chords, &curve);
// Try iterating to improve the fit if we're not too far out
for _iteration in 1..iterations {
// Recompute the chords and the curve
chords = reparameterize(points, &chords, &curve);
curve = generate_bezier(points, &chords, start_tangent, end_tangent);
}
}
}
Would something like this work? The code above is completely untested napkin code. Right now I'm using fit_cubic_curve and just raising the max_error until it returns only one curve, but I'd rather be able to give it a static number of iterations and do less spinning.
I'm willing to work on this myself if you give me the greenlight.
I'm happy for you to work on this.
Yes, this would work: this section of the original does exactly what you want here. I think this would need to be a separate function, and it could potentially be re-used by the existing function if it didn't try to short-circuit the iterations when the error gets low enough (thinking about it, I'm not sure if short-circuiting actually saves any time given the need to calculate the error every iteration).
You might want to experiment to see if the iteration parameter is actually useful - the algorithm should minimize the error in the curve pretty quickly, so if the default value of 4 might be all that's required. It's quite hard to explain to a caller what values are a good choice for this parameter.