makepad_vector/geometry/
quadratic_segment.rs1use crate::geometry::{Point, Transform, Transformation};
2use crate::internal_iter::InternalIterator;
3
4#[derive(Clone, Copy, Debug, PartialEq)]
6#[repr(C)]
7pub struct QuadraticSegment {
8 pub p0: Point,
9 pub p1: Point,
10 pub p2: Point,
11}
12
13impl QuadraticSegment {
14 pub fn new(p0: Point, p1: Point, p2: Point) -> QuadraticSegment {
16 QuadraticSegment { p0, p1, p2 }
17 }
18
19 pub fn is_approximately_linear(self, epsilon: f64) -> bool {
21 let v1 = self.p1 - self.p0;
22 if let Some(vx) = (self.p2 - self.p0).normalize() {
23 v1.cross(vx).abs() < epsilon
26 } else {
27 v1.length() < epsilon
30 }
31 }
32
33 pub fn split(self, t: f64) -> (QuadraticSegment, QuadraticSegment) {
35 let p01 = self.p0.lerp(self.p1, t);
36 let p12 = self.p1.lerp(self.p2, t);
37 let p012 = p01.lerp(p12, t);
38 (
39 QuadraticSegment::new(self.p0, p01, p012),
40 QuadraticSegment::new(p012, p12, self.p2),
41 )
42 }
43
44 pub fn linearize(self, epsilon: f64) -> Linearize {
47 Linearize {
48 segment: self,
49 epsilon,
50 }
51 }
52}
53
54impl Transform for QuadraticSegment {
55 fn transform<T>(self, t: &T) -> QuadraticSegment
56 where
57 T: Transformation,
58 {
59 QuadraticSegment::new(
60 self.p0.transform(t),
61 self.p1.transform(t),
62 self.p2.transform(t),
63 )
64 }
65
66 fn transform_mut<T>(&mut self, t: &T)
67 where
68 T: Transformation,
69 {
70 *self = self.transform(t);
71 }
72}
73
74#[derive(Clone, Copy)]
77pub struct Linearize {
78 segment: QuadraticSegment,
79 epsilon: f64,
80}
81
82impl InternalIterator for Linearize {
83 type Item = Point;
84
85 fn for_each<F>(self, f: &mut F) -> bool
86 where
87 F: FnMut(Point) -> bool,
88 {
89 if self.segment.is_approximately_linear(self.epsilon) {
90 return f(self.segment.p2);
91 }
92 let (segment_0, segment_1) = self.segment.split(0.5);
93 if !segment_0.linearize(self.epsilon).for_each(f) {
94 return false;
95 }
96 segment_1.linearize(self.epsilon).for_each(f)
97 }
98}