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}
163