| Crates.io | uniform-cubic-splines |
| lib.rs | uniform-cubic-splines |
| version | 0.5.0 |
| created_at | 2020-10-30 04:12:36.778336+00 |
| updated_at | 2025-08-16 15:24:18.035+00 |
| description | Simple uniform cubic spline evaluation and inversion. |
| homepage | |
| repository | https://github.com/virtualritz/uniform-cubic-splines/ |
| max_upload_size | |
| id | 306883 |
| size | 138,923 |
uniform-cubic-splinesUniform cubic spline interpolation & inversion.
This crate supports the following types of splines:

Curve widget with a 1D Catmull-Rom spline with non-uniform knot
spacing and knot multiplicity using this crate for interpolation
(drawn using tiny-skia).
The crate uses generics to allow interpolation of any type for which certain traits are defined.
I.e. you can use this crate to interpolate splines in 1D, 2D, 3D, etc.
[dependencies]
uniform-cubic-splines = { version = "0.4" }
Using a combination of spline_inverse() and spline() it is
possible to compute a full spline-with-nonuniform-abscissæ:
use uniform_cubic_splines::prelude::*;
// We want to evaluate the spline at knot value 0.3.
let x = 0.3;
// The first and last points are never interpolated.
let knot_spacing = [0.0, 0.0, 0.1, 0.3, 1.0, 1.0];
let knots = [0.0, 0.0, 1.3, 4.2, 3.2, 3.2];
let v = spline_inverse::<CatmullRom, _>(x, &knot_spacing).unwrap();
let y = spline::<CatmullRom, _, _>(v, &knots).unwrap();
assert!((y - 4.2).abs() < 1e-6);
monotonic_check -- The
spline_inverse()/spline_inverse_with()
code will check if the knot vector is monotonic (enabled by default). Performance impact: Disabling this feature can improve spline_inverse performance by ~5-10% by eliminating monotonicity validation overhead. Only disable if you can guarantee monotonic input, as non-monotonic knots will produce undefined results.The Spline trait can be implemented for vector types from external math libraries. See the tests/nalgebra_integration.rs file for a complete example of implementing the trait for nalgebra::Vector3<f32> and nalgebra::Point3<f32>.
use nalgebra::Vector3;
use uniform_cubic_splines::{spline, CatmullRom};
// After implementing the Spline trait for Vector3<f32>
let knots = vec![
Vector3::new(0.0, 0.0, 0.0),
Vector3::new(1.0, 1.0, 1.0),
Vector3::new(2.0, 0.0, 2.0),
Vector3::new(3.0, -1.0, 3.0),
];
let result = spline::<CatmullRom, _, _>(0.5, &knots).unwrap();
Note that vector types from math libraries need custom Spline implementations because:
x must be a scalar (f32/f64)Float traitSee tests/nalgebra_integration.rs for an example of implementing the Spline trait for vector types using wrapper structs.
f16 & f128 SupportThis crate supports f16 and f128 types on a nightly toolchain if you use this repository as an overlay in your Cargo.toml.
[patch.crates-io]
uniform-cubic-splines = {
git = "https://github.com/virtualritz/uniform-cubic-splines.git"
}
This will be supported without an overlay once this PR on
num-traitsis merged and published.
The code was originally a Rust port of the implementation found in the Open Shading Language C++ source. However, it has since diverged significantly with numerous optimizations and improvements:
spline_inverse: Uses binary search for segment location
(O(log n) instead of O(n)) for splines with >12 segments.If you come from a background of computer graphics/shading languages used in offline rendering this crate should feel like home.
The implementation has been heavily optimized beyond the original OSL C++ source.
spline_inverse: For splines with >12 segments, uses
binary search (O(log n)) instead of linear search (O(n)), providing up to
7x speedup for 1,000+ segments.Spline trait allows specialized implementations for different types.Result<T, SplineError> instead of panicking on invalid inputs.Performance for scalar types (f32 and f64):
| Points | f32 spline() |
f32 spline_inverse() |
f64 spline() |
f64 spline_inverse() |
|---|---|---|---|---|
| 10 | 2.4 ns | 19 ns | 2.3 ns | 18 ns |
| 50 | 2.4 ns | 39 ns | 2.4 ns | 39 ns |
| 100 | 2.4 ns | 62 ns | 2.4 ns | 72 ns |
| 500 | 2.4 ns | 265 ns | 2.6 ns | 263 ns |
Benchmarks taken on Ubuntu with rustc 1.83.0-nightly on an AMD Ryzen 7 6800H laptop.
The trait-based architecture allows external math libraries to provide their own optimized implementations for vector types.