Skip to main content

geop_core_geometry/nurb_curve/
translate.rs

1use geop_core_math::{scalars::Scalar, vector::Vector3};
2
3use super::NurbCurve;
4
5impl<S: Scalar> NurbCurve<S, 4> {
6    /// This 3-D curve shifted by `offset` — same shape and parametrization,
7    /// every point moved by `offset`. Translates each (homogeneous) control
8    /// point by `offset * weight`, leaving weights and the knot vector
9    /// untouched.
10    pub fn translate(&self, offset: Vector3<S>) -> Self {
11        let control_points = self
12            .control_points
13            .iter()
14            .map(|cp| {
15                let w = cp[3];
16                geop_core_math::vector::Vector4::from_array([
17                    cp[0].add(offset[0].mul(w)),
18                    cp[1].add(offset[1].mul(w)),
19                    cp[2].add(offset[2].mul(w)),
20                    w,
21                ])
22            })
23            .collect();
24        Self {
25            degree: self.degree,
26            control_points,
27            knot_vector: self.knot_vector.clone(),
28            // Every control point moved by exactly `offset`, so the box
29            // moves by `offset` too — cheaper than rescanning the points.
30            aabb: [
31                self.aabb[0].add(offset[0]),
32                self.aabb[1].add(offset[1]),
33                self.aabb[2].add(offset[2]),
34            ],
35        }
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use geop_core_math::for_all_scalars;
42    use geop_core_math::{scalars::Scalar, vector::Vector3};
43
44    use super::super::NurbCurve3D;
45
46    fn check_translate_shifts_evaluated_points<S: Scalar>() {
47        let curve = NurbCurve3D::try_new(
48            1,
49            vec![
50                geop_core_math::vector::Vector4::from_array([S::ZERO, S::ZERO, S::ZERO, S::ONE]),
51                geop_core_math::vector::Vector4::from_array([S::ONE, S::ZERO, S::ZERO, S::ONE]),
52            ],
53            vec![S::ZERO, S::ZERO, S::ONE, S::ONE],
54        )
55        .unwrap();
56        let offset = Vector3::from_array([S::from_f64(2.0), S::from_f64(3.0), S::from_f64(-1.0)]);
57        let shifted = curve.translate(offset);
58        for t in [0.0, 0.3, 1.0] {
59            let a = shifted.evaluate(S::from_f64(t)).unwrap();
60            let b = curve.evaluate(S::from_f64(t)).unwrap().add(&offset);
61            assert!(a.could_be_equal(&b));
62        }
63    }
64    #[test]
65    fn translate_shifts_evaluated_points() {
66        for_all_scalars!(check_translate_shifts_evaluated_points);
67    }
68}