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