use crate::geom::{LineSegment, CubicBezierSegment, QuadraticBezierSegment};
use crate::path::PathEvent;
use std::iter::IntoIterator;
pub fn approximate_length<Iter>(path: Iter, tolerance: f32) -> f32
where
Iter: IntoIterator<Item = PathEvent>
{
let tolerance = tolerance.max(1e-4);
let mut length = 0.0;
for evt in path.into_iter() {
match evt {
PathEvent::Line { from, to } => {
length += LineSegment { from, to }.length()
}
PathEvent::Quadratic { from, ctrl, to } => {
length += QuadraticBezierSegment { from, ctrl, to }.approximate_length(tolerance)
}
PathEvent::Cubic { from, ctrl1, ctrl2, to } => {
length += CubicBezierSegment { from, ctrl1, ctrl2, to }.approximate_length(tolerance)
}
PathEvent::End { last, first, close: true } => {
length += LineSegment { from: last, to: first }.length()
}
_ => {}
}
}
length
}
#[test]
fn approx_length() {
use crate::geom::point;
let mut builder = crate::path::Path::builder();
builder.begin(point(0.0, 0.0));
builder.line_to(point(1.0, 0.0));
builder.line_to(point(1.0, 1.0));
builder.line_to(point(0.0, 1.0));
builder.end(true);
let path = builder.build();
assert!((approximate_length(&path, 0.01) - 4.0).abs() < 0.0001);
}