geop_core_geometry/nurb_curve/
sweep.rs1use crate::nurb_surface::NurbSurface3D;
2use geop_core_math::{scalars::Scalar, vector::Vector3};
3
4use super::NurbCurve;
5
6impl NurbCurve<4> {
7 pub fn sweep(&self, offset: Vector3) -> NurbSurface3D {
13 let shifted = self.translate(offset);
14 let mut control_points = Vec::with_capacity(self.control_points.len() * 2);
15 for i in 0..self.control_points.len() {
16 control_points.push(self.control_points[i]);
17 control_points.push(shifted.control_points[i]);
18 }
19 NurbSurface3D::try_new(
20 self.degree,
21 1,
22 control_points,
23 self.knot_vector.clone(),
24 vec![Scalar::ZERO, Scalar::ZERO, Scalar::ONE, Scalar::ONE],
25 )
26 .expect("sweeping a valid curve always yields a valid ruled surface")
27 }
28}
29
30#[cfg(test)]
31mod tests {
32 use geop_core_math::{scalars::Scalar, vector::Vector3};
33
34 use super::super::NurbCurve3D;
35
36 #[test]
37 fn sweep_matches_curve_plus_offset() {
38 let curve = NurbCurve3D::try_new(
39 1,
40 vec![
41 geop_core_math::vector::Vector4::from_array([
42 Scalar::ZERO,
43 Scalar::ZERO,
44 Scalar::ZERO,
45 Scalar::ONE,
46 ]),
47 geop_core_math::vector::Vector4::from_array([
48 Scalar::ONE,
49 Scalar::ZERO,
50 Scalar::ZERO,
51 Scalar::ONE,
52 ]),
53 ],
54 vec![Scalar::ZERO, Scalar::ZERO, Scalar::ONE, Scalar::ONE],
55 )
56 .unwrap();
57 let offset = Vector3::from_array([Scalar::ZERO, Scalar::ZERO, Scalar::from_f64(2.0)]);
58 let surface = curve.sweep(offset);
59
60 for t in [0.0, 0.4, 1.0] {
61 let a = surface.evaluate(Scalar::from_f64(t), Scalar::ZERO).unwrap();
62 let b = curve.evaluate(Scalar::from_f64(t)).unwrap();
63 assert!(a.could_be_equal(&b));
64
65 let a_top = surface.evaluate(Scalar::from_f64(t), Scalar::ONE).unwrap();
66 let b_top = curve.evaluate(Scalar::from_f64(t)).unwrap().add(&offset);
67 assert!(a_top.could_be_equal(&b_top));
68 }
69 }
70}