Expand description
Spline interpolations
§Available splines
- Cubic spline
- Cubic Hermite spline
- B-spline
§Spline<T>
trait
§Methods
fn eval(&self, t: f64) -> T
: Evaluate the spline at t- For Cubic Spline, t means x (domain) and
T = f64
- For B-Spline, t means parameter of curve and
T = (f64, f64)
- For Cubic Spline, t means x (domain) and
fn eval_vec(&self, v: &[f64]) -> Vec<T>
: Evaluate spline values for an array vfn eval_with_cond<F>(&self, t: f64, cond: F) -> T
: Evaluate the spline at t, with a conditionfn eval_vec_with_cond<F>(&self, v: &[f64], cond: F) -> Vec<T>
: Evaluate spline values for an array v, with a condition
§PolynomialSpline
trait
§Methods
fn polynomial_at(&self, x: f64) -> &Polynomial
: Get the polynomial at xfn number_of_polynomials(&self) -> usize
: Get the number of polynomialsfn get_ranged_polynomials(&self) -> &Vec<(Range<f64>, Polynomial)>
: Get the polynomials
§Low-level interface
§Members
CubicSpline
: Structure for cubic splinefn from_nodes(node_x: &[f64], node_y: &[f64]) -> Result<Self>
: Create a cubic spline from nodesfn extend_with_nodes(&mut self, node_x: Vec<f64>, node_y: Vec<f64>) -> Result<()>
: Extend the spline with nodes
CubicHermiteSpline
: Structure for cubic Hermite splinefn from_nodes_with_slopes(node_x: &[f64], node_y: &[f64], m: &[f64]) -> Result<Self>
: Create a Cubic Hermite spline from nodes with slopesfn from_nodes(node_x: &[f64], node_y: &[f64], slope_method: SlopeMethod) -> Result<Self>
: Create a Cubic Hermite spline from nodes with slope estimation methodsSlopeMethod
: Enum for slope estimation methodsAkima
: Akima’s method to estimate slopes (Akima (1970))Quadratic
: Using quadratic interpolation to estimate slopes
BSpline
: Structure for B-Splinefn open(degree: usize, knots: Vec<f64>, control_points: Vec<Vec<f64>>) -> Result<Self>
: Create an open B-Splinefn clamped(degree: usize, knots: Vec<f64>, control_points: Vec<Vec<f64>>) -> Result<Self>
: Create a clamped B-Splinefn cox_de_boor(t: f64, i: f64)
: Cox-de Boor recursion formula (Here, use iteration instead of recursion)
§Usage (Cubic Spline Family)
use peroxide::fuga::*;
fn main() -> Result<(), Box<dyn Error>> {
let x = seq(0, 10, 1);
let y = x.fmap(|t| t.sin());
let cs = CubicSpline::from_nodes(&x, &y)?;
let cs_akima = CubicHermiteSpline::from_nodes(&x, &y, Akima)?;
let cs_quad = CubicHermiteSpline::from_nodes(&x, &y, Quadratic)?;
cs.polynomial_at(0f64).print();
cs_akima.polynomial_at(0f64).print();
cs_quad.polynomial_at(0f64).print();
// -0.1523x^3 + 0.9937x
// 0.1259x^3 - 0.5127x^2 + 1.2283x
// -0.0000x^3 - 0.3868x^2 + 1.2283x
let new_x = seq(4, 6, 0.1);
let new_y = new_x.fmap(|t| t.sin());
let y_cs = cs.eval_vec(&new_x);
let y_akima = cs_akima.eval_vec(&new_x);
let y_quad = cs_quad.eval_vec(&new_x);
let mut df = DataFrame::new(vec![]);
df.push("x", Series::new(new_x));
df.push("y", Series::new(new_y));
df.push("y_cs", Series::new(y_cs));
df.push("y_akima", Series::new(y_akima));
df.push("y_quad", Series::new(y_quad));
df.print();
// x y y_cs y_akima y_quad
// r[0] 5 -0.9589 -0.9589 -0.9589 -0.9589
// r[1] 5.2 -0.8835 -0.8826 -0.8583 -0.8836
// r[2] 5.4 -0.7728 -0.7706 -0.7360 -0.7629
// r[3] 5.6 -0.6313 -0.6288 -0.5960 -0.6120
// r[4] 5.8 -0.4646 -0.4631 -0.4424 -0.4459
// r[5] 6 -0.2794 -0.2794 -0.2794 -0.2794
Ok(())
}
§Usage (B-Spline)
use peroxide::fuga::*;
fn main() -> Result<(), Box<dyn Error>> {
let knots = vec![0f64, 1f64, 2f64, 3f64];
let degree = 3;
let control_points = vec![
vec![0f64, 2f64],
vec![0.2, -1f64],
vec![0.4, 1f64],
vec![0.6, -1f64],
vec![0.8, 1f64],
vec![1f64, 2f64],
];
let spline = BSpline::clamped(degree, knots, control_points.clone())?;
let t = linspace(0f64, 3f64, 200);
let (x, y): (Vec<f64>, Vec<f64>) = spline.eval_vec(&t).into_iter().unzip();
let control_x = control_points.iter().map(|v| v[0]).collect::<Vec<f64>>();
let control_y = control_points.iter().map(|v| v[1]).collect::<Vec<f64>>();
let mut plt = Plot2D::new();
plt
.insert_pair((x.clone(), y.clone()))
.insert_pair((control_x.clone(), control_y.clone()))
.set_plot_type(vec![(1, PlotType::Scatter)])
.set_color(vec![(0, "darkblue"), (1, "red")])
.set_xlabel(r"$x$")
.set_ylabel(r"$y$")
.set_style(PlotStyle::Nature)
.set_dpi(600)
.set_path("example_data/b_spline_test.png")
.savefig()?;
let mut df = DataFrame::new(vec![]);
df.push("t", Series::new(t));
df.push("x", Series::new(x));
df.push("y", Series::new(y));
df.print();
Ok(())
}
- Result for above code is:
§High-level interface
§Functions
fn cubic_spline(node_x: &[f64], node_y: &[f64]) -> CubicSpline
: Create a cubic spline from nodesfn cubic_hermite_spline(node_x: &[f64], node_y: &[f64], m: &[f64]) -> CubicHermiteSpline
: Create a cubic Hermite spline from nodes with slopes
§Usage
use peroxide::fuga::*;
fn main() -> Result<(), Box<dyn Error>> {
let x = seq(0, 10, 1);
let y = x.fmap(|t| t.sin());
let cs = cubic_spline(&x, &y)?;
let cs_akima = cubic_hermite_spline(&x, &y, Akima)?;
let cs_quad = cubic_hermite_spline(&x, &y, Quadratic)?;
cs.polynomial_at(0f64).print();
cs_akima.polynomial_at(0f64).print();
cs_quad.polynomial_at(0f64).print();
// -0.1523x^3 + 0.9937x
// 0.1259x^3 - 0.5127x^2 + 1.2283x
// -0.0000x^3 - 0.3868x^2 + 1.2283x
let new_x = seq(4, 6, 0.1);
let new_y = new_x.fmap(|t| t.sin());
let y_cs = cs.eval_vec(&new_x);
let y_akima = cs_akima.eval_vec(&new_x);
let y_quad = cs_quad.eval_vec(&new_x);
let mut df = DataFrame::new(vec![]);
df.push("x", Series::new(new_x));
df.push("y", Series::new(new_y));
df.push("y_cs", Series::new(y_cs));
df.push("y_akima", Series::new(y_akima));
df.push("y_quad", Series::new(y_quad));
df.print();
// x y y_cs y_akima y_quad
// r[0] 5 -0.9589 -0.9589 -0.9589 -0.9589
// r[1] 5.2 -0.8835 -0.8826 -0.8583 -0.8836
// r[2] 5.4 -0.7728 -0.7706 -0.7360 -0.7629
// r[3] 5.6 -0.6313 -0.6288 -0.5960 -0.6120
// r[4] 5.8 -0.4646 -0.4631 -0.4424 -0.4459
// r[5] 6 -0.2794 -0.2794 -0.2794 -0.2794
Ok(())
}
§Calculus with polynomial splines
§Usage
use peroxide::fuga::*;
use std::f64::consts::PI;
fn main() -> Result<(), Box<dyn Error>> {
let x = seq(0, 10, 1);
let y = x.fmap(|t| t.sin());
let cs = cubic_spline(&x, &y)?;
let cs_akima = cubic_hermite_spline(&x, &y, Akima)?;
let cs_quad = cubic_hermite_spline(&x, &y, Quadratic)?;
println!("============ Polynomial at x=0 ============");
cs.polynomial_at(0f64).print();
cs_akima.polynomial_at(0f64).print();
cs_quad.polynomial_at(0f64).print();
println!("============ Derivative at x=0 ============");
cs.derivative().polynomial_at(0f64).print();
cs_akima.derivative().polynomial_at(0f64).print();
cs_quad.derivative().polynomial_at(0f64).print();
println!("============ Integral at x=0 ============");
cs.integral().polynomial_at(0f64).print();
cs_akima.integral().polynomial_at(0f64).print();
cs_quad.integral().polynomial_at(0f64).print();
println!("============ Integrate from x=0 to x=pi ============");
cs.integrate((0f64, PI)).print();
cs_akima.integrate((0f64, PI)).print();
cs_quad.integrate((0f64, PI)).print();
// ============ Polynomial at x=0 ============
// -0.1523x^3 + 0.9937x
// 0.1259x^3 - 0.5127x^2 + 1.2283x
// -0.0000x^3 - 0.3868x^2 + 1.2283x
// ============ Derivative at x=0 ============
// -0.4568x^2 + 0.9937
// 0.3776x^2 - 1.0254x + 1.2283
// -0.0000x^2 - 0.7736x + 1.2283
// ============ Integral at x=0 ============
// -0.0381x^4 + 0.4969x^2
// 0.0315x^4 - 0.1709x^3 + 0.6141x^2
// -0.0000x^4 - 0.1289x^3 + 0.6141x^2
// ============ Integrate from x=0 to x=pi ============
// 1.9961861265456702
// 2.0049920614062775
// 2.004327391790717
Ok(())
}
§B-Spline utils
UnitCubicBasis
: Single cubic B-Spline basis functionCubicBSplineBases
: Uniform Cubic B-Spline basis functions
§References
- Gary D. Knott, Interpolating Splines, Birkhäuser Boston, MA, (2000).
Structs§
- B-Spline
- Uniform Cubic B-Spline basis functions
- Cubic Spline (Natural)
- Unit Cubic Basis Function
Enums§
Traits§
Functions§
- Cubic Spline (Natural)