nalgebra/geometry/
point_ops.rs

1use num::{One, Zero};
2use std::ops::{
3    Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
4};
5
6use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub};
7
8use crate::base::constraint::{
9    AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint,
10};
11use crate::base::dimension::{Dim, DimName, U1};
12use crate::base::storage::Storage;
13use crate::base::{Const, Matrix, OVector, Scalar, Vector};
14
15use crate::allocator::Allocator;
16use crate::geometry::{OPoint, Point};
17use crate::DefaultAllocator;
18
19/*
20 *
21 * Indexing.
22 *
23 */
24impl<T: Scalar, D: DimName> Index<usize> for OPoint<T, D>
25where
26    DefaultAllocator: Allocator<T, D>,
27{
28    type Output = T;
29
30    #[inline]
31    fn index(&self, i: usize) -> &Self::Output {
32        &self.coords[i]
33    }
34}
35
36impl<T: Scalar, D: DimName> IndexMut<usize> for OPoint<T, D>
37where
38    DefaultAllocator: Allocator<T, D>,
39{
40    #[inline]
41    fn index_mut(&mut self, i: usize) -> &mut Self::Output {
42        &mut self.coords[i]
43    }
44}
45
46/*
47 *
48 * Neg.
49 *
50 */
51impl<T: Scalar + ClosedNeg, D: DimName> Neg for OPoint<T, D>
52where
53    DefaultAllocator: Allocator<T, D>,
54{
55    type Output = Self;
56
57    #[inline]
58    fn neg(self) -> Self::Output {
59        Self::Output::from(-self.coords)
60    }
61}
62
63impl<'a, T: Scalar + ClosedNeg, D: DimName> Neg for &'a OPoint<T, D>
64where
65    DefaultAllocator: Allocator<T, D>,
66{
67    type Output = OPoint<T, D>;
68
69    #[inline]
70    fn neg(self) -> Self::Output {
71        Self::Output::from(-&self.coords)
72    }
73}
74
75/*
76 *
77 * Subtraction & Addition.
78 *
79 */
80
81// Point - Point
82add_sub_impl!(Sub, sub, ClosedSub;
83    (D, U1), (D, U1) -> (D, U1)
84    const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
85    self: &'a OPoint<T, D>, right: &'b OPoint<T, D>, Output = OVector<T, D>;
86    &self.coords - &right.coords; 'a, 'b);
87
88add_sub_impl!(Sub, sub, ClosedSub;
89    (D, U1), (D, U1) -> (D, U1)
90    const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
91    self: &'a OPoint<T, D>, right: OPoint<T, D>, Output = OVector<T, D>;
92    &self.coords - right.coords; 'a);
93
94add_sub_impl!(Sub, sub, ClosedSub;
95    (D, U1), (D, U1) -> (D, U1)
96    const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
97    self: OPoint<T, D>, right: &'b OPoint<T, D>, Output = OVector<T, D>;
98    self.coords - &right.coords; 'b);
99
100add_sub_impl!(Sub, sub, ClosedSub;
101    (D, U1), (D, U1) -> (D, U1)
102    const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
103    self: OPoint<T, D>, right: OPoint<T, D>, Output = OVector<T, D>;
104    self.coords - right.coords; );
105
106// Point - Vector
107add_sub_impl!(Sub, sub, ClosedSub;
108    (D1, U1), (D2, U1) -> (D1, U1)
109    const;
110    for D1, D2, SB;
111    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
112    self: &'a OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
113    Self::Output::from(&self.coords - right); 'a, 'b);
114
115add_sub_impl!(Sub, sub, ClosedSub;
116    (D1, U1), (D2, U1) -> (D1, U1)
117    const;
118    for D1, D2, SB;
119    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
120    self: &'a OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
121    Self::Output::from(&self.coords - &right); 'a); // TODO: should not be a ref to `right`.
122
123add_sub_impl!(Sub, sub, ClosedSub;
124    (D1, U1), (D2, U1) -> (D1, U1)
125    const;
126    for D1, D2, SB;
127    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
128    self: OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
129    Self::Output::from(self.coords - right); 'b);
130
131add_sub_impl!(Sub, sub, ClosedSub;
132    (D1, U1), (D2, U1) -> (D1, U1)
133    const;
134    for D1, D2, SB;
135    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
136    self: OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
137    Self::Output::from(self.coords - right); );
138
139// Point + Vector
140add_sub_impl!(Add, add, ClosedAdd;
141    (D1, U1), (D2, U1) -> (D1, U1)
142    const;
143    for D1, D2, SB;
144    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
145    self: &'a OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
146    Self::Output::from(&self.coords + right); 'a, 'b);
147
148add_sub_impl!(Add, add, ClosedAdd;
149    (D1, U1), (D2, U1) -> (D1, U1)
150    const;
151    for D1, D2, SB;
152    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
153    self: &'a OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
154    Self::Output::from(&self.coords + &right); 'a); // TODO: should not be a ref to `right`.
155
156add_sub_impl!(Add, add, ClosedAdd;
157    (D1, U1), (D2, U1) -> (D1, U1)
158    const;
159    for D1, D2, SB;
160    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
161    self: OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
162    Self::Output::from(self.coords + right); 'b);
163
164add_sub_impl!(Add, add, ClosedAdd;
165    (D1, U1), (D2, U1) -> (D1, U1)
166    const;
167    for D1, D2, SB;
168    where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
169    self: OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
170    Self::Output::from(self.coords + right); );
171
172// TODO: replace by the shared macro: add_sub_assign_impl?
173macro_rules! op_assign_impl(
174    ($($TraitAssign: ident, $method_assign: ident, $bound: ident);* $(;)*) => {$(
175        impl<'b, T, D1: DimName, D2: Dim, SB> $TraitAssign<&'b Vector<T, D2, SB>> for OPoint<T, D1>
176            where T: Scalar + $bound,
177                  SB: Storage<T, D2>,
178                  ShapeConstraint: SameNumberOfRows<D1, D2>,
179                  DefaultAllocator: Allocator<T, D1> {
180
181            #[inline]
182            fn $method_assign(&mut self, right: &'b Vector<T, D2, SB>) {
183                self.coords.$method_assign(right)
184            }
185        }
186
187        impl<T, D1: DimName, D2: Dim, SB> $TraitAssign<Vector<T, D2, SB>> for OPoint<T, D1>
188            where T: Scalar + $bound,
189                  SB: Storage<T, D2>,
190                  ShapeConstraint: SameNumberOfRows<D1, D2>,
191                  DefaultAllocator: Allocator<T, D1> {
192
193            #[inline]
194            fn $method_assign(&mut self, right: Vector<T, D2, SB>) {
195                self.coords.$method_assign(right)
196            }
197        }
198    )*}
199);
200
201op_assign_impl!(
202    AddAssign, add_assign, ClosedAdd;
203    SubAssign, sub_assign, ClosedSub;
204);
205
206/*
207 *
208 * Matrix × Point
209 *
210 */
211md_impl_all!(
212    Mul, mul;
213    (Const<R1>, Const<C1>), (Const<D2>, U1)
214    const D2, R1, C1;
215    for SA;
216    where SA: Storage<T, Const<R1>, Const<C1>>,
217          ShapeConstraint: AreMultipliable<Const<R1>, Const<C1>, Const<D2>, U1>;
218    self: Matrix<T, Const<R1>, Const<C1>, SA>, right: Point<T, D2>, Output = Point<T, R1>;
219    [val val] => Point::from(self * right.coords);
220    [ref val] => Point::from(self * right.coords);
221    [val ref] => Point::from(self * &right.coords);
222    [ref ref] => Point::from(self * &right.coords);
223);
224
225/*
226 *
227 * Point ×/÷ Scalar
228 *
229 */
230macro_rules! componentwise_scalarop_impl(
231    ($Trait: ident, $method: ident, $bound: ident;
232     $TraitAssign: ident, $method_assign: ident) => {
233        impl<T: Scalar + $bound, D: DimName> $Trait<T> for OPoint<T, D>
234        where DefaultAllocator: Allocator<T, D>
235        {
236            type Output = OPoint<T, D>;
237
238            #[inline]
239            fn $method(self, right: T) -> Self::Output {
240                OPoint::from(self.coords.$method(right))
241            }
242        }
243
244        impl<'a, T: Scalar + $bound, D: DimName> $Trait<T> for &'a OPoint<T, D>
245        where DefaultAllocator: Allocator<T, D>
246        {
247            type Output = OPoint<T, D>;
248
249            #[inline]
250            fn $method(self, right: T) -> Self::Output {
251                OPoint::from((&self.coords).$method(right))
252            }
253        }
254
255        impl<T: Scalar + $bound, D: DimName> $TraitAssign<T> for OPoint<T, D>
256            where DefaultAllocator: Allocator<T, D>
257        {
258            #[inline]
259            fn $method_assign(&mut self, right: T) {
260                self.coords.$method_assign(right)
261            }
262        }
263    }
264);
265
266componentwise_scalarop_impl!(Mul, mul, ClosedMul; MulAssign, mul_assign);
267componentwise_scalarop_impl!(Div, div, ClosedDiv; DivAssign, div_assign);
268
269macro_rules! left_scalar_mul_impl(
270    ($($T: ty),* $(,)*) => {$(
271        impl<D: DimName> Mul<OPoint<$T, D>> for $T
272        where DefaultAllocator: Allocator<$T, D>
273        {
274            type Output = OPoint<$T, D>;
275
276            #[inline]
277            fn mul(self, right: OPoint<$T, D>) -> Self::Output {
278                OPoint::from(self * right.coords)
279            }
280        }
281
282        impl<'b, D: DimName> Mul<&'b OPoint<$T, D>> for $T
283        where DefaultAllocator: Allocator<$T, D>
284        {
285            type Output = OPoint<$T, D>;
286
287            #[inline]
288            fn mul(self, right: &'b OPoint<$T, D>) -> Self::Output {
289                OPoint::from(self * &right.coords)
290            }
291        }
292    )*}
293);
294
295left_scalar_mul_impl!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);