1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use crate::path::{LinePathCommand, PathCommand};
use crate::geometry::QuadraticSegment;
use crate::internal_iter::InternalIterator;
pub trait PathIterator: InternalIterator<Item = PathCommand> {
fn linearize(self, epsilon: f64) -> Linearize<Self>
where
Self: Sized,
{
Linearize {
path: self,
epsilon,
}
}
}
impl<I> PathIterator for I where I: InternalIterator<Item = PathCommand> {}
#[derive(Clone, Debug)]
pub struct Linearize<P> {
path: P,
epsilon: f64,
}
impl<P> InternalIterator for Linearize<P>
where
P: PathIterator,
{
type Item = LinePathCommand;
fn for_each<F>(self, f: &mut F) -> bool
where
F: FnMut(LinePathCommand) -> bool,
{
let mut initial_point = None;
let mut current_point = None;
self.path.for_each({
let epsilon = self.epsilon;
&mut move |command| match command {
PathCommand::MoveTo(p) => {
initial_point = Some(p);
current_point = Some(p);
f(LinePathCommand::MoveTo(p))
}
PathCommand::LineTo(p) => {
current_point = Some(p);
f(LinePathCommand::LineTo(p))
}
PathCommand::QuadraticTo(p1, p) => {
QuadraticSegment::new(current_point.unwrap(), p1, p)
.linearize(epsilon)
.for_each(&mut |p| {
current_point = Some(p);
f(LinePathCommand::LineTo(p))
})
}
PathCommand::Close => {
current_point = initial_point;
f(LinePathCommand::Close)
}
}
})
}
}