Skip to main content

geometry_adapt_nalgebra/
vector.rs

1//! [`Point`] adapters for `nalgebra::Vector2` / `nalgebra::Vector3`.
2//!
3//! `nalgebra` vectors are `(x, y[, z])` in memory just like its
4//! points, so they adapt to the [`Point`] concept with the same
5//! shape as [`crate::NaPoint2`] / [`crate::NaPoint3`]. As with the
6//! points, the orphan rule forbids implementing the foreign
7//! [`geometry_trait::Point`] for the foreign `nalgebra::Vector2`
8//! directly, so each is wrapped in a local `#[repr(transparent)]`
9//! newtype. Coordinate access goes through `nalgebra`'s
10//! `Index<usize>` impl (`self.0[D]`).
11
12use geometry_coords::CoordinateScalar;
13use geometry_cs::Cartesian;
14use geometry_tag::PointTag;
15use geometry_trait::{Geometry, Point, PointMut};
16use nalgebra::{Scalar, Vector2, Vector3};
17
18/// Shape-only adapter for `nalgebra::Vector2<T>`.
19///
20/// `#[repr(transparent)]` so `&NaVector2<T>` is layout-compatible
21/// with `&nalgebra::Vector2<T>`. Pins `Cs = Cartesian`, `DIM = 2`.
22///
23/// # Examples
24///
25/// ```
26/// use geometry_adapt_nalgebra::NaVector2;
27/// use geometry_algorithm::distance;
28/// use nalgebra::Vector2;
29///
30/// let a = NaVector2::new(Vector2::new(0.0_f64, 0.0));
31/// let b = NaVector2::new(Vector2::new(3.0_f64, 4.0));
32/// assert_eq!(distance(&a, &b), 5.0);
33/// ```
34#[repr(transparent)]
35pub struct NaVector2<T: Scalar>(pub Vector2<T>);
36
37impl<T: Scalar> NaVector2<T> {
38    /// Wrap a `nalgebra::Vector2` so the geometry concepts apply to it.
39    #[inline]
40    #[must_use]
41    pub const fn new(inner: Vector2<T>) -> Self {
42        Self(inner)
43    }
44
45    /// Unwrap, returning the `nalgebra::Vector2`.
46    #[inline]
47    #[must_use]
48    pub fn into_inner(self) -> Vector2<T> {
49        self.0
50    }
51}
52
53impl<T: CoordinateScalar + Scalar> Geometry for NaVector2<T> {
54    type Kind = PointTag;
55    type Point = Self;
56}
57
58impl<T: CoordinateScalar + Scalar> Point for NaVector2<T> {
59    type Scalar = T;
60    type Cs = Cartesian;
61    const DIM: usize = 2;
62
63    #[inline]
64    fn get<const D: usize>(&self) -> T {
65        self.0[D]
66    }
67}
68
69impl<T: CoordinateScalar + Scalar> PointMut for NaVector2<T> {
70    #[inline]
71    fn set<const D: usize>(&mut self, value: T) {
72        self.0[D] = value;
73    }
74}
75
76/// Shape-only adapter for `nalgebra::Vector3<T>`.
77///
78/// `#[repr(transparent)]` so `&NaVector3<T>` is layout-compatible
79/// with `&nalgebra::Vector3<T>`. Pins `Cs = Cartesian`, `DIM = 3`.
80///
81/// # Examples
82///
83/// ```
84/// use geometry_adapt_nalgebra::NaVector3;
85/// use geometry_algorithm::distance;
86/// use nalgebra::Vector3;
87///
88/// let origin = NaVector3::new(Vector3::new(0.0_f64, 0.0, 0.0));
89/// let z_axis = NaVector3::new(Vector3::new(0.0_f64, 0.0, 1.0));
90/// assert_eq!(distance(&origin, &z_axis), 1.0);
91/// ```
92#[repr(transparent)]
93pub struct NaVector3<T: Scalar>(pub Vector3<T>);
94
95impl<T: Scalar> NaVector3<T> {
96    /// Wrap a `nalgebra::Vector3` so the geometry concepts apply to it.
97    #[inline]
98    #[must_use]
99    pub const fn new(inner: Vector3<T>) -> Self {
100        Self(inner)
101    }
102
103    /// Unwrap, returning the `nalgebra::Vector3`.
104    #[inline]
105    #[must_use]
106    pub fn into_inner(self) -> Vector3<T> {
107        self.0
108    }
109}
110
111impl<T: CoordinateScalar + Scalar> Geometry for NaVector3<T> {
112    type Kind = PointTag;
113    type Point = Self;
114}
115
116impl<T: CoordinateScalar + Scalar> Point for NaVector3<T> {
117    type Scalar = T;
118    type Cs = Cartesian;
119    const DIM: usize = 3;
120
121    #[inline]
122    fn get<const D: usize>(&self) -> T {
123        self.0[D]
124    }
125}
126
127impl<T: CoordinateScalar + Scalar> PointMut for NaVector3<T> {
128    #[inline]
129    fn set<const D: usize>(&mut self, value: T) {
130        self.0[D] = value;
131    }
132}