Work on the documentation.
This commit is contained in:
parent
4fd48c167d
commit
118a11b911
63
src/lib.rs
63
src/lib.rs
@ -1,10 +1,10 @@
|
|||||||
//! Spline interpolation made easy.
|
//! # Spline interpolation made easy.
|
||||||
//!
|
//!
|
||||||
//! This crate exposes splines for which each sections can be interpolated independently of each
|
//! This crate exposes splines for which each sections can be interpolated independently of each
|
||||||
//! other – i.e. it’s possible to interpolate with a linear interpolator on one section and then
|
//! other – i.e. it’s possible to interpolate with a linear interpolator on one section and then
|
||||||
//! switch to a cube Hermite interpolatior for the next section.
|
//! switch to a cubic Hermite interpolator for the next section.
|
||||||
//!
|
//!
|
||||||
//! Most of the library consists of three types:
|
//! Most of the crate consists of three types:
|
||||||
//!
|
//!
|
||||||
//! - [`Key`], which represents the control points by which the spline must pass.
|
//! - [`Key`], which represents the control points by which the spline must pass.
|
||||||
//! - [`Interpolation`], the type of possible interpolation for each segment.
|
//! - [`Interpolation`], the type of possible interpolation for each segment.
|
||||||
@ -15,15 +15,38 @@
|
|||||||
//! new control point, a new section is created. Each section is assigned an interpolation mode that
|
//! new control point, a new section is created. Each section is assigned an interpolation mode that
|
||||||
//! is picked from its lower control point.
|
//! is picked from its lower control point.
|
||||||
//!
|
//!
|
||||||
|
//! # Quickly create splines
|
||||||
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use splines::{Interpolation, Key, Spline};
|
//! use splines::{Interpolation, Key, Spline};
|
||||||
//!
|
//!
|
||||||
//! let start = Key::new(0., 0., Interpolation::Linear);
|
//! let start = Key::new(0., 0., Interpolation::Linear);
|
||||||
//! let end = Key::new(1., 10., Interpolation::Linear);
|
//! let end = Key::new(1., 10., Interpolation::Linear);
|
||||||
//! let spline = Spline::from_keys(vec![start, end]);
|
//! let spline = Spline::from_keys(vec![start, end]);
|
||||||
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! You will notice that we used `Interpolation::Linear` for both the keys. The first key `start`’s
|
||||||
|
//! interpolation will be used for the whole segment defined by those two keys. The `end`’s
|
||||||
|
//! interpolation won’t be used. You can in theory use any [`Interpolation`] you want for the last
|
||||||
|
//! key.
|
||||||
|
//!
|
||||||
|
//! # Interpolate values
|
||||||
|
//!
|
||||||
|
//! The whole purpose of splines is to interpolate discrete values to yield continuous ones. This is
|
||||||
|
//! usually done with the `Spline::sample` method. This method expects the interpolation parameter
|
||||||
|
//! (often, this will be the time of your simulation) as argument and will yield an interpolated
|
||||||
|
//! value.
|
||||||
|
//!
|
||||||
|
//! If you try to sample in out-of-bounds interpolation parameter, you’ll get no value.
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! # use splines::{Interpolation, Key, Spline};
|
||||||
|
//! # let start = Key::new(0., 0., Interpolation::Linear);
|
||||||
|
//! # let end = Key::new(1., 10., Interpolation::Linear);
|
||||||
|
//! # let spline = Spline::from_keys(vec![start, end]);
|
||||||
//! assert_eq!(spline.sample(0.), Some(0.));
|
//! assert_eq!(spline.sample(0.), Some(0.));
|
||||||
//! assert_eq!(spline.sample(1.), Some(10.));
|
//! assert_eq!(spline.sample(1.), Some(10.));
|
||||||
|
//! assert_eq!(spline.sample(1.1), None);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -109,15 +132,6 @@ impl<T> Spline<T> {
|
|||||||
/// near the beginning of the spline or its end, ensure you have enough keys around to make the
|
/// near the beginning of the spline or its end, ensure you have enough keys around to make the
|
||||||
/// sampling.
|
/// sampling.
|
||||||
pub fn sample(&self, t: f32) -> Option<T> where T: Interpolate {
|
pub fn sample(&self, t: f32) -> Option<T> where T: Interpolate {
|
||||||
let first = self.0.first().unwrap();
|
|
||||||
let last = self.0.last().unwrap();
|
|
||||||
|
|
||||||
if t <= first.t {
|
|
||||||
return Some(first.value);
|
|
||||||
} else if t >= last.t {
|
|
||||||
return Some(last.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let keys = &self.0;
|
let keys = &self.0;
|
||||||
let i = keys.binary_search_by(|key| key.t.partial_cmp(&t).unwrap_or(Ordering::Less)).ok()?;
|
let i = keys.binary_search_by(|key| key.t.partial_cmp(&t).unwrap_or(Ordering::Less)).ok()?;
|
||||||
|
|
||||||
@ -158,6 +172,29 @@ impl<T> Spline<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sample a spline at a given time with clamping.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
///
|
||||||
|
/// If you sample before the first key or after the last one, return the first key or the last
|
||||||
|
/// one, respectively. Otherwise, behave the same way as `Spline::sample`.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// This function panics if you have no key.
|
||||||
|
pub fn clamped_sample(&self, t: f32) -> T where T: Interpolate {
|
||||||
|
let first = self.0.first().unwrap();
|
||||||
|
let last = self.0.last().unwrap();
|
||||||
|
|
||||||
|
if t <= first.t {
|
||||||
|
return first.value;
|
||||||
|
} else if t >= last.t {
|
||||||
|
return last.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.sample(t).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator over spline keys.
|
/// Iterator over spline keys.
|
||||||
@ -234,7 +271,7 @@ pub(crate) fn cubic_hermite<T>(x: (T, f32), a: (T, f32), b: (T, f32), y: (T, f32
|
|||||||
// Normalize a time ([0;1]) given two control points.
|
// Normalize a time ([0;1]) given two control points.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn normalize_time<T>(t: f32, cp: &Key<T>, cp1: &Key<T>) -> f32 {
|
pub(crate) fn normalize_time<T>(t: f32, cp: &Key<T>, cp1: &Key<T>) -> f32 {
|
||||||
assert!(cp1.t != cp.t);
|
assert!(cp1.t != cp.t, "overlapping keys");
|
||||||
|
|
||||||
(t - cp.t) / (cp1.t - cp.t)
|
(t - cp.t) / (cp1.t - cp.t)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user