building_blocks_core/
point.rs

1#[macro_use]
2pub mod point_traits;
3
4#[cfg(feature = "glam")]
5mod glam_conversions;
6#[cfg(feature = "mint")]
7mod mint_conversions;
8#[cfg(feature = "nalgebra")]
9mod nalgebra_conversions;
10#[cfg(feature = "sdfu")]
11mod sdfu_integration;
12
13mod point2;
14mod point3;
15
16pub use point2::*;
17pub use point3::*;
18
19use point_traits::*;
20
21use core::ops::{Add, AddAssign, Neg, Sub, SubAssign};
22use num::{Signed, Zero};
23use serde::{Deserialize, Serialize};
24
25/// An N-dimensional point (where N=2 or N=3), which is usually just a primitive array like
26/// `[i32; 2]` or `[i32; 3]`. It is most convenient to construct points of any dimension as:
27///
28/// ```
29/// use building_blocks_core::PointN;
30///
31/// let p2 = PointN([1, 2]); // 2D
32/// let p3 = PointN([1, 2, 3]); // 3D
33/// ```
34///
35/// Points support basic linear algebraic operations such as addition, subtraction, scalar
36/// multiplication, and scalar division.
37///
38/// ```
39/// # use building_blocks_core::PointN;
40/// #
41/// let p1 = PointN([1, 2]);
42/// let p2 = PointN([3, 4]);
43///
44/// assert_eq!(p1 + p2, PointN([4, 6]));
45/// assert_eq!(p1 - p2, PointN([-2, -2]));
46///
47/// assert_eq!(p1 * 2, PointN([2, 4]));
48/// assert_eq!(p1 / 2, PointN([0, 1]));
49///
50/// // Also some component-wise operations.
51/// assert_eq!(p1 * p2, PointN([3, 8]));
52/// assert_eq!(p1 / p2, PointN([0, 0]));
53/// assert_eq!(p2 / p1, PointN([3, 2]));
54/// ```
55///
56/// There is also a partial order defined on points which says that a point A is greater than a
57/// point B if and only if all of the components of point A are greater than point B. This is useful
58/// for easily checking is a point is inside of the extent between two other points:
59///
60/// ```
61/// # use building_blocks_core::PointN;
62/// #
63/// let min = PointN([0, 0, 0]);
64/// let least_upper_bound = PointN([3, 3, 3]);
65///
66/// let p = PointN([0, 1, 2]);
67/// assert!(min <= p && p < least_upper_bound);
68/// ```
69#[derive(Copy, Clone, Debug, Deserialize, Default, Eq, Hash, PartialEq, Serialize)]
70pub struct PointN<N>(pub N);
71
72impl<N> PointN<N>
73where
74    Self: MapComponents,
75{
76    #[inline]
77    pub fn signum(self) -> Self
78    where
79        <Self as MapComponents>::Scalar: Signed,
80    {
81        self.map_components_unary(|c| c.signum())
82    }
83}
84
85impl<N> Abs for PointN<N>
86where
87    Self: MapComponents,
88    <Self as MapComponents>::Scalar: Signed,
89{
90    #[inline]
91    fn abs(self) -> Self {
92        self.map_components_unary(|c| c.abs())
93    }
94}
95
96impl<N> Neg for PointN<N>
97where
98    Self: Copy + Sub<Output = Self> + Zero,
99{
100    type Output = Self;
101
102    #[inline]
103    fn neg(self) -> Self::Output {
104        Self::zero() - self
105    }
106}
107
108impl<N, T> Add for PointN<N>
109where
110    Self: MapComponents<Scalar = T>,
111    T: Add<Output = T>,
112{
113    type Output = Self;
114
115    #[inline]
116    fn add(self, rhs: Self) -> Self::Output {
117        self.map_components_binary(rhs, |c1, c2| c1 + c2)
118    }
119}
120
121impl<N, T> Sub for PointN<N>
122where
123    Self: MapComponents<Scalar = T>,
124    T: Sub<Output = T>,
125{
126    type Output = Self;
127
128    #[inline]
129    fn sub(self, rhs: Self) -> Self::Output {
130        self.map_components_binary(rhs, |c1, c2| c1 - c2)
131    }
132}
133
134impl<N> AddAssign for PointN<N>
135where
136    Self: Copy + Add<Output = Self>,
137{
138    #[inline]
139    fn add_assign(&mut self, rhs: Self) {
140        *self = *self + rhs;
141    }
142}
143
144impl<N> SubAssign for PointN<N>
145where
146    Self: Copy + Sub<Output = Self>,
147{
148    #[inline]
149    fn sub_assign(&mut self, rhs: Self) {
150        *self = *self - rhs;
151    }
152}
153
154impl<N> Zero for PointN<N>
155where
156    Self: Point + ConstZero,
157{
158    #[inline]
159    fn zero() -> Self {
160        Self::ZERO
161    }
162
163    #[inline]
164    fn is_zero(&self) -> bool {
165        *self == Self::zero()
166    }
167}