Skip to content

Instantly share code, notes, and snippets.

@matthewjberger
Last active September 7, 2023 17:43
Show Gist options
  • Save matthewjberger/f369a26b30413a77f9cb67cb4719a904 to your computer and use it in GitHub Desktop.
Save matthewjberger/f369a26b30413a77f9cb67cb4719a904 to your computer and use it in GitHub Desktop.
#[derive(Default, Debug, Clone, Copy, PartialEq)]
struct Point {
x: f64,
y: f64,
}
impl Point {
fn lerp(self, other: Self, t: f64) -> Self {
Self {
x: (1.0 - t) * self.x + t * other.x,
y: (1.0 - t) * self.y + t * other.y,
}
}
}
struct BezierCurve {
control_points: Vec<Point>,
}
impl BezierCurve {
fn new(control_points: Vec<Point>) -> Self {
Self { control_points }
}
fn evaluate(&self, t: f64) -> Point {
let mut interpolated = self.control_points.clone();
for k in (1..interpolated.len()).rev() {
for i in 0..k {
interpolated[i] = interpolated[i].lerp(interpolated[i + 1], t);
}
}
interpolated[0]
}
}
#[cfg(test)]
mod tests {
use super::*;
fn approx_eq(a: f64, b: f64, tolerance: f64) -> bool {
(a - b).abs() < tolerance
}
#[test]
fn bezier_curve_evaluation() {
let curve = BezierCurve::new(vec![
Default::default(),
Point { x: 1.0, y: 2.0 },
Point { x: 2.0, y: 2.0 },
Point { x: 3.0, y: 0.0 },
]);
assert_eq!(curve.evaluate(0.0), Default::default());
assert_eq!(curve.evaluate(1.0), Point { x: 3.0, y: 0.0 });
assert!(approx_eq(curve.evaluate(0.5).x, 1.5, 1e-6));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment