#![cfg_attr(feature = "doc-images",
cfg_attr(all(),
doc = ::embed_doc_image::embed_image!("points", "doc-images/plots/generation/points.svg"),
doc = ::embed_doc_image::embed_image!("manual", "doc-images/plots/generation/manual.svg"),
doc = ::embed_doc_image::embed_image!("interpolation", "doc-images/plots/generation/interpolation.svg"),
doc = ::embed_doc_image::embed_image!("fit-loose-all", "doc-images/plots/generation/fit-loose-all.svg"),
doc = ::embed_doc_image::embed_image!("fit-loose-half", "doc-images/plots/generation/fit-loose-half.svg"),
doc = ::embed_doc_image::embed_image!("fit-loose-half-penalized", "doc-images/plots/generation/fit-loose-half-penalized.svg")))]
use crate::curve::{
knots, parameters,
points::{
methods::{fit, fit::Penalization, interpolation},
ControlPoints, DataPoints, Points,
},
Curve, CurveError,
};
#[derive()]
pub enum Generation<'a> {
Manual {
degree: usize,
points: ControlPoints,
knots: knots::Generation,
},
Interpolation {
degree: usize,
points: &'a DataPoints,
},
LeastSquaresFit {
degree: usize,
points: &'a DataPoints,
intended_segments: usize,
method: fit::Method,
penalization: Option<Penalization>,
},
}
pub fn generate(generation: Generation) -> Result<Curve, CurveError> {
match generation {
Generation::Manual { degree, points, knots: method } => {
let n = points.segments();
let p = degree;
if points.segments() < degree {
return Err(CurveError::DegreeAndSegmentsMismatch { p, n });
}
let data_points = DataPoints::new(points.matrix().clone());
let knots = match method {
knots::Generation::Uniform => knots::methods::uniform(p, n),
knots::Generation::Manual { knots } => Ok(knots.clone()),
knots::Generation::Method {
parameter_method,
knot_method,
} => {
let params = parameters::generate(&data_points, parameter_method);
knots::generate(p, n, ¶ms, knot_method)
}
};
Curve::new(knots?, points)
}
Generation::Interpolation { degree, points } => {
let params = parameters::generate(points, parameters::Method::EquallySpaced); let knots = knots::generate(degree, points.segments(), ¶ms, knots::Method::Uniform)?;
let points = ControlPoints::new_with_capacity(
interpolation::interpolate(&knots, points, ¶ms),
knots.degree() + 1,
);
Curve::new(knots, points)
}
Generation::LeastSquaresFit { degree, points, intended_segments, method, penalization } => {
let params = parameters::generate(points, parameters::Method::EquallySpaced);
let knots = knots::generate(degree, intended_segments, ¶ms, knots::Method::Uniform)?;
let points = match method {
fit::Method::FixedEnds => ControlPoints::new_with_capacity(
fit::fixed::fit(&knots, points, ¶ms, penalization)
.map_err(|err| CurveError::FitError { err })?,
degree + 1,
),
fit::Method::LooseEnds => ControlPoints::new_with_capacity(
fit::loose::fit(&knots, points, ¶ms, penalization)
.map_err(|err| CurveError::FitError { err })?,
degree + 1,
),
};
Curve::new(knots, points)
}
}
}