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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
use crate::scalar::Scalar;
use crate::{point, Box2D, LineSegment, Point, Vector};
use core::ops::Range;
/// Common APIs to segment types.
pub trait Segment: Copy + Sized {
type Scalar: Scalar;
/// Start of the curve.
fn from(&self) -> Point<Self::Scalar>;
/// End of the curve.
fn to(&self) -> Point<Self::Scalar>;
/// Sample the curve at t (expecting t between 0 and 1).
fn sample(&self, t: Self::Scalar) -> Point<Self::Scalar>;
/// Sample x at t (expecting t between 0 and 1).
fn x(&self, t: Self::Scalar) -> Self::Scalar {
self.sample(t).x
}
/// Sample y at t (expecting t between 0 and 1).
fn y(&self, t: Self::Scalar) -> Self::Scalar {
self.sample(t).y
}
/// Sample the derivative at t (expecting t between 0 and 1).
fn derivative(&self, t: Self::Scalar) -> Vector<Self::Scalar>;
/// Sample x derivative at t (expecting t between 0 and 1).
fn dx(&self, t: Self::Scalar) -> Self::Scalar {
self.derivative(t).x
}
/// Sample y derivative at t (expecting t between 0 and 1).
fn dy(&self, t: Self::Scalar) -> Self::Scalar {
self.derivative(t).y
}
/// Split this curve into two sub-curves.
fn split(&self, t: Self::Scalar) -> (Self, Self);
/// Return the curve before the split point.
fn before_split(&self, t: Self::Scalar) -> Self;
/// Return the curve after the split point.
fn after_split(&self, t: Self::Scalar) -> Self;
/// Return the curve inside a given range of t.
///
/// This is equivalent splitting at the range's end points.
fn split_range(&self, t_range: Range<Self::Scalar>) -> Self;
/// Swap the direction of the segment.
fn flip(&self) -> Self;
/// Compute the length of the segment using a flattened approximation.
fn approximate_length(&self, tolerance: Self::Scalar) -> Self::Scalar;
/// Approximates the curve with sequence of line segments.
///
/// The `tolerance` parameter defines the maximum distance between the curve and
/// its approximation.
///
/// The parameter `t` at the final segment is guaranteed to be equal to `1.0`.
#[allow(clippy::type_complexity)]
fn for_each_flattened_with_t(
&self,
tolerance: Self::Scalar,
callback: &mut dyn FnMut(&LineSegment<Self::Scalar>, Range<Self::Scalar>),
);
}
pub trait BoundingBox {
type Scalar: Scalar;
/// Returns the smallest rectangle that contains the curve.
fn bounding_box(&self) -> Box2D<Self::Scalar> {
let (min_x, max_x) = self.bounding_range_x();
let (min_y, max_y) = self.bounding_range_y();
Box2D {
min: point(min_x, min_y),
max: point(max_x, max_y),
}
}
/// Returns a conservative rectangle that contains the curve.
///
/// This does not necessarily return the smallest possible bounding rectangle.
fn fast_bounding_box(&self) -> Box2D<Self::Scalar> {
let (min_x, max_x) = self.fast_bounding_range_x();
let (min_y, max_y) = self.fast_bounding_range_y();
Box2D {
min: point(min_x, min_y),
max: point(max_x, max_y),
}
}
/// Returns a range of x values that contains the curve.
fn bounding_range_x(&self) -> (Self::Scalar, Self::Scalar);
/// Returns a range of y values that contains the curve.
fn bounding_range_y(&self) -> (Self::Scalar, Self::Scalar);
/// Returns a range of x values that contains the curve.
fn fast_bounding_range_x(&self) -> (Self::Scalar, Self::Scalar);
/// Returns a range of y values that contains the curve.
fn fast_bounding_range_y(&self) -> (Self::Scalar, Self::Scalar);
}
macro_rules! impl_segment {
($S:ty) => {
type Scalar = $S;
fn from(&self) -> Point<$S> {
self.from()
}
fn to(&self) -> Point<$S> {
self.to()
}
fn sample(&self, t: $S) -> Point<$S> {
self.sample(t)
}
fn x(&self, t: $S) -> $S {
self.x(t)
}
fn y(&self, t: $S) -> $S {
self.y(t)
}
fn derivative(&self, t: $S) -> Vector<$S> {
self.derivative(t)
}
fn dx(&self, t: $S) -> $S {
self.dx(t)
}
fn dy(&self, t: $S) -> $S {
self.dy(t)
}
fn split(&self, t: $S) -> (Self, Self) {
self.split(t)
}
fn before_split(&self, t: $S) -> Self {
self.before_split(t)
}
fn after_split(&self, t: $S) -> Self {
self.after_split(t)
}
fn split_range(&self, t_range: Range<$S>) -> Self {
self.split_range(t_range)
}
fn flip(&self) -> Self {
self.flip()
}
fn approximate_length(&self, tolerance: $S) -> $S {
self.approximate_length(tolerance)
}
};
}