# cubic_spline [![Crates.io](https://img.shields.io/crates/v/cubic_spline.svg)](https://crates.io/crates/cubic_spline/) [![npm](https://img.shields.io/npm/v/cubic-spline-rs.svg)](https://www.npmjs.com/package/cubic-spline-rs) Interpolation method for computation of cubic spline points within the range of a discrete set of known points. [Online documentation](https://docs.rs/cubic_spline/)
[Demo](https://emgyrz.github.io/cubic_spline/) ![example](img.png) ## Example ```rust use cubic_spline::{Points, Point, SplineOpts, TryFrom}; fn main() { let source = vec![(10.0, 200.0), (256.0, 390.0), (512.0, 10.0), (778.0, 200.0)]; let opts = SplineOpts::new() .tension(0.5); let mut points = Points::try_from(&source).expect("expect valid points but"); let result = points.calc_spline(&opts).expect("cant construct spline points"); assert_eq!(result.get_ref().len(), 49); let inner_vec: &mut Vec = points.get_mut(); inner_vec.push(Point::new(7.7, 1.3)); inner_vec[1].x += 0.79; inner_vec.last_mut().iter_mut().for_each(|mut p| {p.tension = Some(0.7);}); points.invert_vertically(400.0); assert_eq!(points.get_ref()[1].y, 10.0); let calculated_points = points .calc_spline(&opts.num_of_segments(33)) .unwrap(); assert_eq!(calculated_points.into_inner().len(), 133); } ``` For information on how a curve can be constructed and which points to accept, see the appropriate structures. ## Custom points If you already have some points you can implement `From` trait for `Point` struct and pass your points directly. ### Example ```rust use cubic_spline::{SplineOpts, Point, Points}; #[derive(Default)] struct MyPoint { vertical: u8, horizontal: u8, color: String, } impl<'a> From<&'a MyPoint> for Point { fn from(p: &'a MyPoint) -> Self { Point::new(&p.horizontal as f64, &p.vertical as f64) } } fn main() { let my_points: Vec = vec![MyPoint::default(),MyPoint::default()]; let spline = Points::from(&my_points) .calc_spline(&SplineOpts::default()) .unwrap(); assert_eq!(spline.get_ref().len(), 17); } ``` ## Use in Javascript It also compiled as wasm module. And you can use it in your js code but not completely. Now available only one function ```js import { getCurvePoints } from 'cubic-spline-rs' const NUM_OF_SEGMENTS = 22 const points = [10.0, 200.0, 256.0, 390.0, 512.0, 10.0, 778.0, 200.0] const curvePoints = getCurvePoints( points, { num_of_segments: NUM_OF_SEGMENTS, // *optional // tension: 0.5, // *optional // ... } ) ``` If you want to draw result points to canvas - code like this: ```js const ctx = getMyCanvas2DContext() ctx.beginPath() ctx.lineWidth = 3 ctx.strokeStyle = '#ffcc00' ctx.moveTo(curvePoints[0], curvePoints[1]) const length = curvePoints.length - 1 for (let i = 2; i < length; i += 2) { ctx.lineTo(curvePoints[i], curvePoints[i + 1]) } ctx.stroke() ctx.closePath() ``` [comment]: <> (See example [here](./www/src/Spline.ts).) ### Options | Name | Type | Default | Description | | --------------------- | :-----------------: | :-----: | ------------------------------------------------------------------------------------------- | | tension | `f64` | `0.5` | Tension | | num_of_segments | `u32` | `16` | Number of calculated points between known points | | hidden_point_at_start | `Option<(f64,f64)>` | `None` | A point that will not be drawn, but the beginning of the graph will bend as if it is there. | | hidden_point_at_end | `Option<(f64,f64)>` | `None` | A point that will not be drawn, but the end of the graph will bend as if it is there. | ```rust use cubic_spline::{SplineOpts}; fn main() { let options = SplineOpts::new() .tension(0.6) .num_of_segments(54) // .hidden_point_at_start((1.2, 3.1)) // .hidden_point_at_end((397.9, 105.5)) ; } ``` ### License This module is [MIT licensed](./LICENSE).