lyon_geom/
segment.rs

1use crate::scalar::Scalar;
2use crate::{point, Box2D, LineSegment, Point, Vector};
3
4use core::ops::Range;
5
6/// Common APIs to segment types.
7pub trait Segment: Copy + Sized {
8    type Scalar: Scalar;
9
10    /// Start of the curve.
11    fn from(&self) -> Point<Self::Scalar>;
12
13    /// End of the curve.
14    fn to(&self) -> Point<Self::Scalar>;
15
16    /// Sample the curve at t (expecting t between 0 and 1).
17    fn sample(&self, t: Self::Scalar) -> Point<Self::Scalar>;
18
19    /// Sample x at t (expecting t between 0 and 1).
20    fn x(&self, t: Self::Scalar) -> Self::Scalar {
21        self.sample(t).x
22    }
23
24    /// Sample y at t (expecting t between 0 and 1).
25    fn y(&self, t: Self::Scalar) -> Self::Scalar {
26        self.sample(t).y
27    }
28
29    /// Sample the derivative at t (expecting t between 0 and 1).
30    fn derivative(&self, t: Self::Scalar) -> Vector<Self::Scalar>;
31
32    /// Sample x derivative at t (expecting t between 0 and 1).
33    fn dx(&self, t: Self::Scalar) -> Self::Scalar {
34        self.derivative(t).x
35    }
36
37    /// Sample y derivative at t (expecting t between 0 and 1).
38    fn dy(&self, t: Self::Scalar) -> Self::Scalar {
39        self.derivative(t).y
40    }
41
42    /// Split this curve into two sub-curves.
43    fn split(&self, t: Self::Scalar) -> (Self, Self);
44
45    /// Return the curve before the split point.
46    fn before_split(&self, t: Self::Scalar) -> Self;
47
48    /// Return the curve after the split point.
49    fn after_split(&self, t: Self::Scalar) -> Self;
50
51    /// Return the curve inside a given range of t.
52    ///
53    /// This is equivalent splitting at the range's end points.
54    fn split_range(&self, t_range: Range<Self::Scalar>) -> Self;
55
56    /// Swap the direction of the segment.
57    fn flip(&self) -> Self;
58
59    /// Compute the length of the segment using a flattened approximation.
60    fn approximate_length(&self, tolerance: Self::Scalar) -> Self::Scalar;
61
62    /// Approximates the curve with sequence of line segments.
63    ///
64    /// The `tolerance` parameter defines the maximum distance between the curve and
65    /// its approximation.
66    ///
67    /// The parameter `t` at the final segment is guaranteed to be equal to `1.0`.
68    #[allow(clippy::type_complexity)]
69    fn for_each_flattened_with_t(
70        &self,
71        tolerance: Self::Scalar,
72        callback: &mut dyn FnMut(&LineSegment<Self::Scalar>, Range<Self::Scalar>),
73    );
74}
75
76pub trait BoundingBox {
77    type Scalar: Scalar;
78
79    /// Returns the smallest rectangle that contains the curve.
80    fn bounding_box(&self) -> Box2D<Self::Scalar> {
81        let (min_x, max_x) = self.bounding_range_x();
82        let (min_y, max_y) = self.bounding_range_y();
83
84        Box2D {
85            min: point(min_x, min_y),
86            max: point(max_x, max_y),
87        }
88    }
89
90    /// Returns a conservative rectangle that contains the curve.
91    ///
92    /// This does not necessarily return the smallest possible bounding rectangle.
93    fn fast_bounding_box(&self) -> Box2D<Self::Scalar> {
94        let (min_x, max_x) = self.fast_bounding_range_x();
95        let (min_y, max_y) = self.fast_bounding_range_y();
96
97        Box2D {
98            min: point(min_x, min_y),
99            max: point(max_x, max_y),
100        }
101    }
102
103    /// Returns a range of x values that contains the curve.
104    fn bounding_range_x(&self) -> (Self::Scalar, Self::Scalar);
105
106    /// Returns a range of y values that contains the curve.
107    fn bounding_range_y(&self) -> (Self::Scalar, Self::Scalar);
108
109    /// Returns a range of x values that contains the curve.
110    fn fast_bounding_range_x(&self) -> (Self::Scalar, Self::Scalar);
111
112    /// Returns a range of y values that contains the curve.
113    fn fast_bounding_range_y(&self) -> (Self::Scalar, Self::Scalar);
114}
115
116macro_rules! impl_segment {
117    ($S:ty) => {
118        type Scalar = $S;
119        fn from(&self) -> Point<$S> {
120            self.from()
121        }
122        fn to(&self) -> Point<$S> {
123            self.to()
124        }
125        fn sample(&self, t: $S) -> Point<$S> {
126            self.sample(t)
127        }
128        fn x(&self, t: $S) -> $S {
129            self.x(t)
130        }
131        fn y(&self, t: $S) -> $S {
132            self.y(t)
133        }
134        fn derivative(&self, t: $S) -> Vector<$S> {
135            self.derivative(t)
136        }
137        fn dx(&self, t: $S) -> $S {
138            self.dx(t)
139        }
140        fn dy(&self, t: $S) -> $S {
141            self.dy(t)
142        }
143        fn split(&self, t: $S) -> (Self, Self) {
144            self.split(t)
145        }
146        fn before_split(&self, t: $S) -> Self {
147            self.before_split(t)
148        }
149        fn after_split(&self, t: $S) -> Self {
150            self.after_split(t)
151        }
152        fn split_range(&self, t_range: Range<$S>) -> Self {
153            self.split_range(t_range)
154        }
155        fn flip(&self) -> Self {
156            self.flip()
157        }
158        fn approximate_length(&self, tolerance: $S) -> $S {
159            self.approximate_length(tolerance)
160        }
161    };
162}