Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CubicCurve::segment_count + iter_samples adjustment #8711

Merged
merged 3 commits into from
May 31, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 30 additions & 13 deletions crates/bevy_math/src/cubic_splines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,22 +472,39 @@ impl<P: Point> CubicCurve<P> {
/// 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<Item = P> + '_ {
(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<Item = P> + '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<Item = f32> {
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<P>] {
&self.segments
}

/// Iterate over the curve split into `subdivisions`, sampling the position at each step.
Expand Down