extern crate plotters;
use plotters::prelude::*;
extern crate stroke;
use stroke::CubicBezier;
use stroke::PointN;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cpoints = vec![
(0f64, 1.77f64),
(1.1f64, -1f64),
(4.3f64, 3f64),
(3.2f64, -4f64),
];
let chull = vec![
(0f64, 1.77f64),
(1.1f64, -1f64),
(3.2f64, -4f64),
(4.3f64, 3f64),
(0f64, 1.77f64),
];
let bezier = CubicBezier::new(
PointN::new([0f64, 1.77f64]),
PointN::new([1.1f64, -1f64]),
PointN::new([4.3f64, 3f64]),
PointN::new([3.2f64, -4f64]),
);
let bounds = bezier.bounding_box();
let xmin = bounds[0].0;
let xmax = bounds[0].1;
let ymin = bounds[1].0;
let ymax = bounds[1].1;
let nsteps: usize = 1000;
let mut bezier_graph: Vec<(f64, f64)> = Vec::with_capacity(nsteps);
for t in 0..nsteps {
let t = t as f64 * 1f64 / (nsteps as f64);
let p = bezier.eval_casteljau(t);
bezier_graph.push((p[0], p[1]));
}
let root = BitMapBackend::new("cubic_bezier_bounding_box.png", (640, 480)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption("Cubic Bezier Curve", ("sans-serif", 21).into_font())
.margin(5)
.x_label_area_size(30)
.y_label_area_size(30)
.build_cartesian_2d(
(bounds[0].0 - 2.0)..(xmin + 6.0),
(ymin - 1.0)..(ymax + 3.0),
)?;
chart.configure_mesh().draw()?;
chart
.draw_series(PointSeries::of_element(
cpoints.clone(),
5,
&BLUE,
&|coord, size, style| {
EmptyElement::at(coord)
+ Circle::new((0, 0), size, style)
+ Text::new(
format!("{:?}", coord),
(0, 15),
("sans-serif", 15).into_font(),
)
},
))?
.label("Control Points of B(t)")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], BLUE));
chart
.draw_series(LineSeries::new(bezier_graph, &RED))?
.label("B(t)")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], RED));
chart
.draw_series(
AreaSeries::new(
vec![
(xmin, ymin),
(xmin, ymax),
(xmax, ymax),
(xmax, ymin),
(xmin, ymin),
],
0.0,
GREEN.mix(0.05),
)
.border_style(GREEN),
)?
.label("Bounding Box")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], GREEN));
chart
.draw_series(AreaSeries::new(chull, 0.0, BLUE.mix(0.0)).border_style(BLUE))?
.label("CH(control_points)")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], BLUE));
chart
.configure_series_labels()
.background_style(WHITE.mix(0.8))
.border_style(BLACK)
.draw()?;
Ok(())
}