diff --git a/crates/bevy_math/src/cubic_splines.rs b/crates/bevy_math/src/cubic_splines.rs index bb5a988557..c0ff6cf272 100644 --- a/crates/bevy_math/src/cubic_splines.rs +++ b/crates/bevy_math/src/cubic_splines.rs @@ -472,22 +472,39 @@ impl CubicCurve

{ /// A flexible iterator used to sample curves with arbitrary functions. /// /// This splits the curve into `subdivisions` of evenly spaced `t` values across the - /// length of the curve from start (t = 0) to end (t = 1), returning an iterator that evaluates - /// the curve with the supplied `sample_function` at each `t`. + /// length of the curve from start (t = 0) to end (t = n), where `n = self.segment_count()`, + /// returning an iterator evaluating the curve with the supplied `sample_function` at each `t`. /// - /// Given `subdivisions = 2`, this will split the curve into two lines, or three points, and - /// return an iterator over those three points, one at the start, middle, and end. + /// For `subdivisions = 2`, this will split the curve into two lines, or three points, and + /// return an iterator with 3 items, the three points, one at the start, middle, and end. #[inline] - pub fn iter_samples( - &self, + pub fn iter_samples<'a, 'b: 'a>( + &'b self, subdivisions: usize, - sample_function: fn(&Self, f32) -> P, - ) -> impl Iterator + '_ { - (0..=subdivisions).map(move |i| { - let segments = self.segments.len() as f32; - let t = i as f32 / subdivisions as f32 * segments; - sample_function(self, t) - }) + mut sample_function: impl FnMut(&Self, f32) -> P + 'a, + ) -> impl Iterator + 'a { + self.iter_uniformly(subdivisions) + .map(move |t| sample_function(self, t)) + } + + /// An iterator that returns values of `t` uniformly spaced over `0..=subdivisions`. + #[inline] + fn iter_uniformly(&self, subdivisions: usize) -> impl Iterator { + let segments = self.segments.len() as f32; + let step = segments / subdivisions as f32; + (0..=subdivisions).map(move |i| i as f32 * step) + } + + /// The list of segments contained in this `CubicCurve`. + /// + /// This spline's global `t` value is equal to how many segments it has. + /// + /// All method accepting `t` on `CubicCurve` depends on the global `t`. + /// When sampling over the entire curve, you should either use one of the + /// `iter_*` methods or account for the segment count using `curve.segments().len()`. + #[inline] + pub fn segments(&self) -> &[CubicSegment

] { + &self.segments } /// Iterate over the curve split into `subdivisions`, sampling the position at each step.