## ~raph/bezoid

8bfe25c0030d271103988ca2acb3364ce1964dac — Raph Levien 1 year, 2 months ago
```Simpler arm length formula

Make arm length ratio dependent on angle (matching circular arc bezier
approximation formula) rather than chord length.
```
```1 files changed, 7 insertions(+), 7 deletions(-)

M src/solve.rs
```
`M src/solve.rs => src/solve.rs +7 -7`
```@@ 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,

```