@@ 1,6 1,6 @@
//! Solver from cubic params to curve params.
-use druid::kurbo::{CubicBez, ParamCurveArclen, Point};
+use druid::kurbo::Point;
use crate::bezoid::CurveParams;
@@ 13,8 13,10 @@ impl Solver {
/// (1, 0).
pub fn solve(&self, p1: Point, p2: Point) -> CurveParams {
println!("({:.3}, {:.3}) ({:.3}, {:.3})", p1.x, p1.y, p2.x, p2.y);
- fn inv_arm_len(h: f64, chord: f64) -> f64 {
- let a = h * 3.0 * chord.powf(1.0);
+ fn inv_arm_len(h: f64, th: f64) -> f64 {
+ // This formula ensures that bezier parameters approximating
+ // a circular arc map to a bias of 1.0.
+ let a = h * 1.5 * (th.cos() + 1.0);
if a < 1.0 {
2.0 - a.powf(2.0)
} else {
@@ 23,16 25,14 @@ impl Solver {
}
let v1 = p1.to_vec2();
let v2 = Point::new(1.0, 0.0) - p2;
- let c = CubicBez::new(Point::ORIGIN, p1, p2, Point::new(1.0, 0.0));
let th0 = v1.atan2();
let th1 = -v2.atan2();
let mut dth = 0.0;
- let chord = 1.0 / c.arclen(1e-3);
let mut lastxy: Option<(f64, f64)> = None;
const N: usize = 10;
for i in 0..N {
- let bias0 = inv_arm_len(v1.hypot(), chord);
- let bias1 = inv_arm_len(v2.hypot(), chord);
+ let bias0 = inv_arm_len(v1.hypot(), th0);
+ let bias1 = inv_arm_len(v2.hypot(), th1);
let params = CurveParams {
k0: th0 + 0.5 * dth,
bias0,