57 lines
1.5 KiB
Rust
57 lines
1.5 KiB
Rust
//! Cubic Bézier curve example
|
|
//! <https://en.wikipedia.org/wiki/B%C3%A9zier_curve>
|
|
|
|
use turtle_lib::{turtle_main, vec2};
|
|
|
|
struct CubicBezier {
|
|
point0: (f32, f32),
|
|
point1: (f32, f32),
|
|
point2: (f32, f32),
|
|
point3: (f32, f32),
|
|
}
|
|
|
|
impl CubicBezier {
|
|
/// Returns the value of this curve at the given parameter t (0.0 to 1.0)
|
|
pub fn at(&self, t: f64) -> (f32, f32) {
|
|
let t = t as f32;
|
|
let mt = 1.0 - t; // (1 - t)
|
|
|
|
// Cubic Bézier formula from Wikipedia
|
|
let p0_weight = mt.powi(3);
|
|
let p1_weight = 3.0 * mt.powi(2) * t;
|
|
let p2_weight = 3.0 * mt * t.powi(2);
|
|
let p3_weight = t.powi(3);
|
|
|
|
(
|
|
self.point0.0 * p0_weight
|
|
+ self.point1.0 * p1_weight
|
|
+ self.point2.0 * p2_weight
|
|
+ self.point3.0 * p3_weight,
|
|
self.point0.1 * p0_weight
|
|
+ self.point1.1 * p1_weight
|
|
+ self.point2.1 * p2_weight
|
|
+ self.point3.1 * p3_weight,
|
|
)
|
|
}
|
|
}
|
|
|
|
#[turtle_main("Bézier Curve")]
|
|
fn draw(turtle: &mut TurtlePlan) {
|
|
let curve = CubicBezier {
|
|
point0: (-200.0, -100.0),
|
|
point1: (-100.0, 400.0),
|
|
point2: (100.0, -500.0),
|
|
point3: (300.0, 200.0),
|
|
};
|
|
|
|
let start = curve.at(0.0);
|
|
turtle.pen_up().go_to(vec2(start.0, start.1)).pen_down();
|
|
|
|
let samples = 100;
|
|
for i in 0..samples {
|
|
let t = f64::from(i) / f64::from(samples);
|
|
let point = curve.at(t);
|
|
turtle.go_to(vec2(point.0, point.1));
|
|
}
|
|
}
|