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}