Skip to content

Commit ae9a000

Browse files
committed
IMPL: Implement example codes for calculus of BSpline
1 parent c978eae commit ae9a000

7 files changed

Lines changed: 161 additions & 0 deletions

File tree

example_data/bspline_calculus.png

98.5 KB
Loading
119 KB
Loading

example_data/bspline_integral.png

92.6 KB
Loading

example_data/bspline_original.png

91.7 KB
Loading

example_data/bspline_with_area.png

86.8 KB
Loading

examples/area_under_spline.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use peroxide::fuga::*;
2+
use anyhow::Result;
3+
4+
fn main() -> Result<()> {
5+
// 1. Define the B-spline
6+
let degree = 3;
7+
let knots = vec![0f64, 1f64, 2f64, 3f64, 4f64];
8+
let control_points = vec![
9+
vec![0f64, 0f64],
10+
vec![1f64, 2f64],
11+
vec![2f64, -1f64],
12+
vec![3f64, 1f64],
13+
vec![4f64, -1f64],
14+
vec![5f64, 2f64],
15+
vec![6f64, 0f64],
16+
];
17+
18+
let spline = BSpline::clamped(degree, knots, control_points.clone())?;
19+
let deriv_spline = spline.derivative()?;
20+
21+
// 2. Define the integrand for ∫y dx = ∫ y(t) * (dx/dt) dt
22+
let integrand = |t: f64, s: &BSpline, ds: &BSpline| -> f64 {
23+
let p = s.eval(t);
24+
let dp = ds.eval(t);
25+
let y_t = p.1;
26+
let dx_dt = dp.0;
27+
y_t * dx_dt
28+
};
29+
30+
// 3. Perform numerical integration using self-contained Gauss-Legendre quadrature
31+
let t_start = 0f64;
32+
let t_end = 4f64;
33+
34+
//let area = gauss_legendre_integrate(
35+
// |t| integrand(t, &spline, &deriv_spline),
36+
// t_start,
37+
// t_end,
38+
// 64,
39+
//);
40+
let area = integrate(|t| integrand(t, &spline, &deriv_spline), (t_start, t_end), G7K15R(1e-4, 20));
41+
42+
// 4. Print the result
43+
println!("The area under the B-spline curve (∫y dx) is: {}", area);
44+
45+
// For verification, let's plot the original curve
46+
#[cfg(feature = "plot")]
47+
{
48+
let t = linspace(t_start, t_end, 200);
49+
let (x, y): (Vec<f64>, Vec<f64>) = spline.eval_vec(&t).into_iter().unzip();
50+
51+
let mut plt = Plot2D::new();
52+
plt.set_title(&format!("Original B-Spline (Area approx. {:.4})", area))
53+
.set_xlabel("x")
54+
.set_ylabel("y")
55+
.insert_pair((x.clone(), y.clone()))
56+
.insert_pair((control_points.iter().map(|p| p[0]).collect(), control_points.iter().map(|p| p[1]).collect()))
57+
.set_plot_type(vec![(0, PlotType::Line), (1, PlotType::Scatter)])
58+
.set_color(vec![(0, "blue"), (1, "red")])
59+
.set_legend(vec!["Spline", "Control Points"])
60+
.set_style(PlotStyle::Nature)
61+
.set_path("example_data/bspline_with_area.png")
62+
.set_dpi(600)
63+
.savefig()?;
64+
65+
println!("Generated plot: example_data/bspline_with_area.png");
66+
}
67+
68+
Ok(())
69+
}

examples/bspline_calculus.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use peroxide::fuga::*;
2+
use anyhow::Result;
3+
4+
fn main() -> Result<()> {
5+
// 1. Define the B-spline
6+
let degree = 3;
7+
let knots = vec![0f64, 1f64, 2f64, 3f64, 4f64];
8+
let control_points = vec![
9+
vec![0f64, 0f64],
10+
vec![1f64, 2f64],
11+
vec![2f64, -1f64],
12+
vec![3f64, 1f64],
13+
vec![4f64, -1f64],
14+
vec![5f64, 2f64],
15+
vec![6f64, 0f64],
16+
];
17+
18+
let spline = BSpline::clamped(degree, knots.clone(), control_points.clone())?;
19+
20+
// 2. Get the derivative and integral
21+
let deriv_spline = spline.derivative()?;
22+
let integ_spline = spline.integral()?;
23+
24+
// 3. Evaluate points on all splines
25+
let t = linspace(0f64, 4f64, 200);
26+
let (x, y): (Vec<f64>, Vec<f64>) = spline.eval_vec(&t).into_iter().unzip();
27+
let (dx, dy): (Vec<f64>, Vec<f64>) = deriv_spline.eval_vec(&t).into_iter().unzip();
28+
let (ix, iy): (Vec<f64>, Vec<f64>) = integ_spline.eval_vec(&t).into_iter().unzip();
29+
30+
// 4. Plotting
31+
#[cfg(feature = "plot")]
32+
{
33+
// Plot Original Spline and its control points
34+
let control_x: Vec<f64> = control_points.iter().map(|p| p[0]).collect();
35+
let control_y: Vec<f64> = control_points.iter().map(|p| p[1]).collect();
36+
37+
let mut plt = Plot2D::new();
38+
plt.set_title("Original B-Spline")
39+
.set_xlabel("x")
40+
.set_ylabel("y")
41+
.insert_pair((x.clone(), y.clone()))
42+
.insert_pair((control_x, control_y))
43+
.set_plot_type(vec![(0, PlotType::Line), (1, PlotType::Scatter)])
44+
.set_color(vec![(0, "darkblue"), (1, "darkred")])
45+
.set_legend(vec!["Spline", "Control Points"])
46+
.set_style(PlotStyle::Nature)
47+
.set_path("example_data/bspline_original.png")
48+
.set_dpi(600)
49+
.savefig()?;
50+
51+
// Plot Derivative (Hodograph) and its control points
52+
let deriv_control_x: Vec<f64> = deriv_spline.control_points.iter().map(|p| p[0]).collect();
53+
let deriv_control_y: Vec<f64> = deriv_spline.control_points.iter().map(|p| p[1]).collect();
54+
55+
let mut plt_deriv = Plot2D::new();
56+
plt_deriv.set_title("B-Spline Derivative (Hodograph)")
57+
.set_xlabel("dx/dt")
58+
.set_ylabel("dy/dt")
59+
.insert_pair((dx, dy))
60+
.insert_pair((deriv_control_x, deriv_control_y))
61+
.set_plot_type(vec![(0, PlotType::Line), (1, PlotType::Scatter)])
62+
.set_color(vec![(0, "darkblue"), (1, "darkred")])
63+
.set_legend(vec!["Derivative", "Derivative Control Points"])
64+
.set_style(PlotStyle::Nature)
65+
.set_path("example_data/bspline_derivative.png")
66+
.set_dpi(600)
67+
.savefig()?;
68+
69+
// Plot Integral and its control points
70+
let integ_control_x: Vec<f64> = integ_spline.control_points.iter().map(|p| p[0]).collect();
71+
let integ_control_y: Vec<f64> = integ_spline.control_points.iter().map(|p| p[1]).collect();
72+
73+
let mut plt_integ = Plot2D::new();
74+
plt_integ.set_title("B-Spline Integral")
75+
.set_xlabel("Integral of x")
76+
.set_ylabel("Integral of y")
77+
.insert_pair((ix, iy))
78+
.insert_pair((integ_control_x, integ_control_y))
79+
.set_plot_type(vec![(0, PlotType::Line), (1, PlotType::Scatter)])
80+
.set_color(vec![(0, "darkblue"), (1, "darkred")])
81+
.set_legend(vec!["Integral", "Integral Control Points"])
82+
.set_style(PlotStyle::Nature)
83+
.set_path("example_data/bspline_integral.png")
84+
.set_dpi(600)
85+
.savefig()?;
86+
}
87+
88+
println!("Generated plots for original, derivative, and integral splines.");
89+
println!("Please check 'example_data/bspline_original.png', 'example_data/bspline_derivative.png', and 'example_data/bspline_integral.png'.");
90+
91+
Ok(())
92+
}

0 commit comments

Comments
 (0)