mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-12 13:33:19 +00:00
Width profiles: the edge fit stops once it is within tolerance (#3145)
This commit is contained in:
@@ -77,7 +77,7 @@ fn fit_through_rec(pts: &[Point], t0: Vec2, t1: Vec2, tol: f64, out: &mut Vec<Cu
|
||||
out.push(CubicBez::new(pts[0], pts[0] + t0 * d, pts[1] - t1 * d, pts[1]));
|
||||
return;
|
||||
}
|
||||
let (curve, err, split) = fit_single(pts, t0, t1);
|
||||
let (curve, err, split) = fit_single_tol(pts, t0, t1, tol);
|
||||
if err <= tol || depth >= MAX_SPLITS {
|
||||
out.push(curve);
|
||||
return;
|
||||
@@ -192,6 +192,32 @@ pub(crate) fn fit_single(pts: &[Point], t0: Vec2, t1: Vec2) -> (CubicBez, f64, u
|
||||
fit_single_from(pts, chord_params(pts), t0, t1)
|
||||
}
|
||||
|
||||
/// [`fit_single`] that stops reparameterising once the curve is within `tol` of its points: a
|
||||
/// curve already that close needs no better fit, and each Newton round reads every point.
|
||||
fn fit_single_tol(pts: &[Point], t0: Vec2, t1: Vec2, tol: f64) -> (CubicBez, f64, usize) {
|
||||
let mut u = chord_params(pts);
|
||||
let mut best = generate(pts, &u, t0, t1);
|
||||
let (mut best_err, mut best_split) = max_error(pts, &best, &u);
|
||||
for _ in 0..MAX_REPARAM {
|
||||
if best_err <= tol {
|
||||
break;
|
||||
}
|
||||
for (i, ui) in u.iter_mut().enumerate() {
|
||||
*ui = newton(&best, pts[i], *ui);
|
||||
}
|
||||
let c = generate(pts, &u, t0, t1);
|
||||
let (e, s) = max_error(pts, &c, &u);
|
||||
if e < best_err {
|
||||
best = c;
|
||||
best_err = e;
|
||||
best_split = s;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
(best, best_err, best_split)
|
||||
}
|
||||
|
||||
/// [`fit_single`] starting from the parameters `u` (one per point, 0 to 1) instead of the
|
||||
/// chord-length ones.
|
||||
pub(crate) fn fit_single_from(pts: &[Point], u: Vec<f64>, t0: Vec2, t1: Vec2) -> (CubicBez, f64, usize) {
|
||||
|
||||
Reference in New Issue
Block a user