physdes/
point.rs

1// #![no_std]
2
3use super::Vector2;
4use crate::generic::{Contain, Displacement, MinDist, Overlap};
5use crate::interval::{Hull, Intersect};
6// use core::cmp::Ordering;
7// #[cfg(any(test, feature = "std"))]
8#[cfg(test)]
9use core::hash;
10use core::ops::{Add, Neg, Sub};
11use num_traits::Num;
12
13/// The code defines a generic Point struct with x and y coordinates.
14///
15/// Properties:
16///
17/// * `xcoord`: The `xcoord` property represents the x-coordinate of a point in a two-dimensional space.
18///             It is a generic type `T`, which means it can be any type that implements the necessary traits for
19///             the `Point` struct.
20/// * `ycoord`: The `ycoord` property represents the y-coordinate of a point in a two-dimensional space.
21///             It is a generic type `T`, which means it can be any type that implements the necessary traits for
22///             the `Point` struct.
23#[derive(PartialEq, Eq, Copy, PartialOrd, Ord, Clone, Hash, Debug, Default)]
24pub struct Point<T1, T2> {
25    /// x portion of the Point object
26    pub xcoord: T1,
27    /// y portion of the Point object
28    pub ycoord: T2,
29}
30
31impl<T1, T2> Point<T1, T2> {
32    /// The `new` function creates a new `Point` with the given x and y coordinates.
33    ///
34    /// Arguments:
35    ///
36    /// * `xcoord`: The `xcoord` parameter represents the x-coordinate of the point. It is of type `T`,
37    ///             which means it can be any type that implements the necessary traits for mathematical operations.
38    /// * `ycoord`: The `ycoord` parameter represents the y-coordinate of the point. It is used to
39    ///             specify the vertical position of the point in a two-dimensional coordinate system.
40    ///
41    /// Returns:
42    ///
43    /// The `new` function returns a new instance of the `Point` struct with the specified `xcoord` and
44    /// `ycoord` values.
45    ///
46    /// # Examples
47    ///
48    /// ```
49    /// use physdes::point::Point;
50    /// assert_eq!(Point::new(3, 4).xcoord, 3);
51    /// assert_eq!(Point::new(3, 4).ycoord, 4);
52    /// ```
53    #[inline]
54    pub const fn new(xcoord: T1, ycoord: T2) -> Self {
55        Point { xcoord, ycoord }
56    }
57}
58
59/// Implements the `Display` trait for the `Point` struct, which allows it to be
60/// printed in the format `(x, y)` where `x` and `y` are the coordinates of the point.
61///
62/// This implementation assumes that the `xcoord` and `ycoord` fields of the `Point`
63/// struct implement the `std::fmt::Display` trait, which is enforced by the generic
64/// type constraints `T1: std::fmt::Display` and `T2: std::fmt::Display`.
65impl<T1: std::fmt::Display, T2: std::fmt::Display> std::fmt::Display for Point<T1, T2> {
66    #[inline]
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        write!(f, "({}, {})", self.xcoord, self.ycoord)
69    }
70}
71
72/// Flips the coordinates of the `Point` struct, swapping the `xcoord` and `ycoord` fields.
73///
74/// This is a convenience method that can be used to quickly create a new `Point` with the
75/// `xcoord` and `ycoord` fields swapped. It is implemented for `Point` structs where both
76/// the `xcoord` and `ycoord` fields implement the `Clone` trait.
77///
78/// # Examples
79///
80/// use my_crate::Point;
81///
82/// let p = Point { xcoord: 1, ycoord: 2 };
83/// let flipped = p.flip();
84/// assert_eq!(flipped, Point { xcoord: 2, ycoord: 1 });
85///
86impl<T1: Clone, T2: Clone> Point<T1, T2> {
87    #[inline]
88    pub fn flip(&self) -> Point<T2, T1> {
89        Point {
90            xcoord: self.ycoord.clone(),
91            ycoord: self.xcoord.clone(),
92        }
93    }
94}
95
96// impl<T1: Ord + Copy, T2: Ord + Copy> PartialOrd for Point<T1, T2> {
97//     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
98//         Some((self.xcoord, self.ycoord).cmp(&(other.xcoord, other.ycoord)))
99//         // Some(self.xcoord.partial_cmp(&other.xcoord).then(self.ycoord.partial_cmp(&other.ycoord)))
100//     }
101// }
102
103// impl<T, U> Overlap<U> for Point<T1, T2>
104// where
105//     U: Overlap<T1, T2>,
106// {
107//     fn overlaps(&self, other: &U) -> bool {
108//         other.overlaps(&self.xcoord) && other.overlaps(&self.ycoord)
109//     }
110// }
111
112// impl<T, U> Contain<U> for Point<T1, T2>
113// where
114//     T: Contain<U>,
115// {
116//     fn contains(&self, other: &U) -> bool {
117//         self.xcoord.contains(other) && self.ycoord.contains(other)
118//     }
119// }
120
121/// Checks if two `Point` instances overlap.
122///
123/// This implementation checks if the `xcoord` and `ycoord` components of the two `Point` instances
124/// overlap, using the `Overlap` trait implementation for their respective component types.
125///
126/// # Example
127///
128/// use your_crate::Point;
129///
130/// let p1 = Point::new(1, 2);
131/// let p2 = Point::new(2, 3);
132/// assert!(p1.overlaps(&p2));
133///
134impl<T1, T2, U1, U2> Overlap<Point<U1, U2>> for Point<T1, T2>
135where
136    T1: Overlap<U1>,
137    T2: Overlap<U2>,
138{
139    /// The `overlaps` function checks if two points overlap in both x and y coordinates.
140    ///
141    /// Arguments:
142    ///
143    /// * `other`: The `other` parameter in the `overlaps` method is a reference to another `Point`
144    ///            struct with generic types `U1` and `U2`.
145    ///
146    /// Returns:
147    ///
148    /// The `overlaps` method is returning a boolean value, which indicates whether the x-coordinate of
149    /// the current `Point` instance overlaps with the x-coordinate of the `other` `Point` instance, and
150    /// whether the y-coordinate of the current `Point` instance overlaps with the y-coordinate of the
151    /// `other` `Point` instance. The method returns `true` if both conditions are met, and
152    #[inline]
153    fn overlaps(&self, other: &Point<U1, U2>) -> bool {
154        self.xcoord.overlaps(&other.xcoord) && self.ycoord.overlaps(&other.ycoord)
155    }
156}
157
158/// Checks if a `Point<T1, T2>` contains a `Point<U1, U2>`.
159///
160/// This implementation checks if the `xcoord` and `ycoord` fields of the `Point<T1, T2>`
161/// contain the corresponding fields of the `Point<U1, U2>`. The `T1` and `T2` types
162/// must implement the `Contain` trait for `U1` and `U2` respectively.
163impl<T1, T2, U1, U2> Contain<Point<U1, U2>> for Point<T1, T2>
164where
165    T1: Contain<U1>,
166    T2: Contain<U2>,
167{
168    /// The `contains` function checks if a Point contains another Point by comparing their x and y
169    /// coordinates.
170    ///
171    /// Arguments:
172    ///
173    /// * `other`: The `other` parameter is a reference to a `Point` struct with generic types `U1` and
174    ///             `U2`. It represents another point that you want to check for containment within the current
175    ///             `Point` instance.
176    ///
177    /// Returns:
178    ///
179    /// The `contains` method is returning a boolean value, which indicates whether the `xcoord` and
180    /// `ycoord` of the current `Point` instance contain the `xcoord` and `ycoord` of the `other`
181    /// `Point` instance respectively.
182    #[inline]
183    fn contains(&self, other: &Point<U1, U2>) -> bool {
184        self.xcoord.contains(&other.xcoord) && self.ycoord.contains(&other.ycoord)
185    }
186}
187
188/// The above Rust code is implementing a trait `MinDist` for the `Point` struct. The `MinDist` trait
189/// defines a method `min_dist_with` that calculates the minimum distance between two points based on
190/// the minimum distance between their individual coordinates (`xcoord` and `ycoord`). The
191/// implementation specifies that the minimum distance between two points is calculated by adding the
192/// minimum distances between their respective x and y coordinates.
193impl<T1, T2, U1, U2> MinDist<Point<U1, U2>> for Point<T1, T2>
194where
195    T1: MinDist<U1>,
196    T2: MinDist<U2>,
197{
198    /// The function calculates the minimum distance between two points in a two-dimensional space.
199    ///
200    /// Arguments:
201    ///
202    /// * `other`: The `other` parameter is a reference to a `Point` struct with generic types `U1` and
203    ///             `U2`.
204    ///
205    /// Returns:
206    ///
207    /// The `min_dist_with` method is returning the sum of the minimum distances between the
208    /// x-coordinate of `self` and the x-coordinate of `other`, and the y-coordinate of `self` and the
209    /// y-coordinate of `other`.
210    #[inline]
211    fn min_dist_with(&self, other: &Point<U1, U2>) -> u32 {
212        self.xcoord.min_dist_with(&other.xcoord) + self.ycoord.min_dist_with(&other.ycoord)
213    }
214}
215
216/// The above Rust code is implementing a `Displacement` trait for the `Point` struct. The
217/// `Displacement` trait is generic over two types `T1` and `T2`, and it requires that `T1` and `T2`
218/// implement the `Displacement` trait with an associated type `Output`.
219impl<T1, T2> Displacement<Point<T1, T2>> for Point<T1, T2>
220where
221    T1: Displacement<T1, Output = T1>,
222    T2: Displacement<T2, Output = T2>,
223{
224    type Output = Vector2<T1, T2>;
225
226    /// The `displace` function calculates the displacement between two points in Rust.
227    ///
228    /// Arguments:
229    ///
230    /// * `other`: The `other` parameter in the `displace` method is a reference to another `Point`
231    ///             object with the same generic types `T1` and `T2` as the current `Point` object.
232    #[inline]
233    fn displace(&self, other: &Point<T1, T2>) -> Self::Output {
234        Self::Output::new(
235            self.xcoord.displace(&other.xcoord),
236            self.ycoord.displace(&other.ycoord),
237        )
238    }
239}
240
241// impl<T1, T2> Hull<Point<T1, T2>> for Point<T1, T2>
242// where
243//     T1: Hull<T1, Output=Interval<T1>>,
244//     T2: Hull<T2, Output=Interval<T2>>,
245// {
246//     type Output = Point<Interval<T1>, Interval<T2>>;
247//     fn hull_with(&self, other: &Point<T1, T2>) -> Self::Output {
248//         Self::Output::new(
249//             self.xcoord.hull_with(&other.xcoord),
250//             self.ycoord.hull_with(&other.ycoord),
251//         )
252//     }
253// }
254
255/// The above code is implementing a trait called `Hull` for the `Point` struct in Rust. The `Hull`
256/// trait defines a method `hull_with` that calculates the hull (convex hull, for example) of two
257/// points. The implementation specifies that the output type of the hull operation on two `Point`
258/// instances is a new `Point` with the hull operation applied to the x and y coordinates of the points.
259/// The implementation also specifies that the hull operation is applied to the generic types `T1` and
260/// `T2` where `T1` and `T
261impl<T1, T2> Hull<Point<T1, T2>> for Point<T1, T2>
262where
263    T1: Hull<T1>,
264    T2: Hull<T2>,
265{
266    type Output = Point<T1::Output, T2::Output>;
267
268    /// The function `hull_with` calculates the hull with another `Point` object by combining their x
269    /// and y coordinates.
270    ///
271    /// Arguments:
272    ///
273    /// * `other`: The `other` parameter in the `hull_with` method is a reference to another `Point`
274    ///             struct with the same generic types `T1` and `T2` as the current `Point` struct. It is used to
275    ///             combine the coordinates of the current `Point` with the coordinates
276    #[inline]
277    fn hull_with(&self, other: &Point<T1, T2>) -> Self::Output {
278        Self::Output::new(
279            self.xcoord.hull_with(&other.xcoord),
280            self.ycoord.hull_with(&other.ycoord),
281        )
282    }
283}
284
285/// The above Rust code is implementing an `Intersect` trait for the `Point` struct. The `Intersect`
286/// trait is defined for two generic types `T1` and `T2`, and it requires that `T1` and `T2` implement
287/// the `Intersect` trait themselves.
288impl<T1, T2> Intersect<Point<T1, T2>> for Point<T1, T2>
289where
290    T1: Intersect<T1>,
291    T2: Intersect<T2>,
292{
293    type Output = Point<T1::Output, T2::Output>;
294
295    /// The `intersect_with` function takes another `Point` as input and returns a new `Point` with
296    /// intersected coordinates.
297    ///
298    /// Arguments:
299    ///
300    /// * `other`: The `other` parameter in the `intersect_with` method is a reference to another
301    ///             `Point` struct with the same generic types `T1` and `T2` as the current `Point` struct. It is
302    ///             used to compare and intersect the `xcoord` and `ycoord`
303    #[inline]
304    fn intersect_with(&self, other: &Point<T1, T2>) -> Self::Output {
305        Self::Output::new(
306            self.xcoord.intersect_with(&other.xcoord),
307            self.ycoord.intersect_with(&other.ycoord),
308        )
309    }
310}
311
312macro_rules! forward_xf_xf_binop {
313    (impl $imp:ident, $method:ident) => {
314        impl<'a, 'b, T1: Clone + Num, T2: Clone + Num> $imp<&'b Vector2<T1, T2>>
315            for &'a Point<T1, T2>
316        {
317            type Output = Point<T1, T2>;
318
319            #[inline]
320            fn $method(self, other: &Vector2<T1, T2>) -> Self::Output {
321                self.clone().$method(other.clone())
322            }
323        }
324    };
325}
326
327macro_rules! forward_xf_val_binop {
328    (impl $imp:ident, $method:ident) => {
329        impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<Vector2<T1, T2>> for &'a Point<T1, T2> {
330            type Output = Point<T1, T2>;
331
332            #[inline]
333            fn $method(self, other: Vector2<T1, T2>) -> Self::Output {
334                self.clone().$method(other)
335            }
336        }
337    };
338}
339
340/// The above code is a Rust macro definition that creates an implementation for a binary operation on a
341/// custom type `Point<T1, T2>` and a reference to `Vector2<T1, T2>`. The macro is used to generate
342/// implementations for various traits and methods for the specified types. In this case, it generates
343/// an implementation for a specific binary operation method specified by the input parameters ``
344/// and ``.
345macro_rules! forward_val_xf_binop {
346    (impl $imp:ident, $method:ident) => {
347        /// The above code is implementing a trait for a specific type in Rust. The trait being
348        /// implemented is not explicitly mentioned in the code snippet, but based on the syntax used
349        /// (`impl Trait for Type`), it appears to be a custom trait defined elsewhere in the codebase.
350        /// The code is implementing the trait for a specific type `Point<T1, T2>`, where `T1` and `T2`
351        /// are generic types that must implement the `Clone` and `Num` traits.
352        impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<&'a Vector2<T1, T2>> for Point<T1, T2> {
353            type Output = Point<T1, T2>;
354
355            /// The function implements a method that performs a specific operation on two Vector2
356            /// instances in Rust.
357            ///
358            /// Arguments:
359            ///
360            /// * `other`: The `other` parameter in the code snippet represents a reference to a
361            ///             `Vector2` struct with generic types `T1` and `T2`. This parameter is used as the input
362            ///             for the method being called on `self`.
363            #[inline]
364            fn $method(self, other: &Vector2<T1, T2>) -> Self::Output {
365                self.$method(other.clone())
366            }
367        }
368    };
369}
370
371macro_rules! forward_all_binop {
372    (impl $imp:ident, $method:ident) => {
373        forward_xf_xf_binop!(impl $imp, $method);
374        forward_xf_val_binop!(impl $imp, $method);
375        forward_val_xf_binop!(impl $imp, $method);
376    };
377}
378
379// arithmetic
380forward_all_binop!(impl Add, add);
381
382// (a, b) + (c, d) == (a + c), (b + d)
383impl<T1: Clone + Num, T2: Clone + Num> Add<Vector2<T1, T2>> for Point<T1, T2> {
384    type Output = Self;
385
386    /// Translate a new Point
387    ///
388    /// # Examples
389    ///
390    /// ```
391    /// use physdes::point::Point;
392    /// use physdes::vector2::Vector2;
393    ///
394    /// assert_eq!(Point::new(3, 4) + Vector2::new(5, 3), Point::new(8, 7));
395    /// assert_eq!(Point::new(3, 4) + Vector2::new(-5, -3), Point::new(-2, 1));
396    /// assert_eq!(Point::new(3, 4) + Vector2::new(5, -3), Point::new(8, 1));
397    /// assert_eq!(Point::new(3, 4) + Vector2::new(-5, 3), Point::new(-2, 7));
398    /// assert_eq!(Point::new(3, 4) + Vector2::new(0, 0), Point::new(3, 4));
399    /// assert_eq!(Point::new(3, 4) + Vector2::new(0, 5), Point::new(3, 9));
400    /// ```
401    #[inline]
402    fn add(self, other: Vector2<T1, T2>) -> Self::Output {
403        Self::Output::new(self.xcoord + other.x_, self.ycoord + other.y_)
404    }
405}
406
407forward_all_binop!(impl Sub, sub);
408
409/// (a, b) - (c, d) == (a - c), (b - d)
410/// The above Rust code snippet is implementing the subtraction operation for a Point struct. It defines
411/// the implementation of the Sub trait for subtracting a Vector2 from a Point. The code defines the
412/// behavior of subtracting a Vector2 from a Point to get a new Point with updated coordinates.
413impl<T1: Clone + Num, T2: Clone + Num> Sub<Vector2<T1, T2>> for Point<T1, T2> {
414    type Output = Self;
415
416    /// Translate a new Point
417    ///
418    /// # Examples
419    ///
420    /// ```
421    /// use physdes::point::Point;
422    /// use physdes::vector2::Vector2;
423    /// assert_eq!(Point::new(3, 4) - Vector2::new(5, 3), Point::new(-2, 1));
424    /// assert_eq!(Point::new(3, 4) - Vector2::new(-5, -3), Point::new(8, 7));
425    /// assert_eq!(Point::new(3, 4) - Vector2::new(5, -3), Point::new(-2, 7));
426    /// assert_eq!(Point::new(3, 4) - Vector2::new(-5, 3), Point::new(8, 1));
427    /// assert_eq!(Point::new(3, 4) - Vector2::new(0, 0), Point::new(3, 4));
428    /// assert_eq!(Point::new(3, 4) - Vector2::new(0, 5), Point::new(3, -1));
429    /// assert_eq!(Point::new(3, 4) - Vector2::new(5, 0), Point::new(-2, 4));
430    /// ```
431    #[inline]
432    fn sub(self, other: Vector2<T1, T2>) -> Self::Output {
433        Self::Output::new(self.xcoord - other.x_, self.ycoord - other.y_)
434    }
435}
436
437macro_rules! forward_xf_xf_binop2 {
438    (impl $imp:ident, $method:ident) => {
439        impl<'a, 'b, T1: Clone + Num, T2: Clone + Num> $imp<&'b Point<T1, T2>>
440            for &'a Point<T1, T2>
441        {
442            type Output = Vector2<T1, T2>;
443
444            #[inline]
445            fn $method(self, other: &Point<T1, T2>) -> Self::Output {
446                self.clone().$method(other.clone())
447            }
448        }
449    };
450}
451
452macro_rules! forward_xf_val_binop2 {
453    (impl $imp:ident, $method:ident) => {
454        impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<Point<T1, T2>> for &'a Point<T1, T2> {
455            type Output = Vector2<T1, T2>;
456
457            #[inline]
458            fn $method(self, other: Point<T1, T2>) -> Self::Output {
459                self.clone().$method(other)
460            }
461        }
462    };
463}
464
465macro_rules! forward_val_xf_binop2 {
466    (impl $imp:ident, $method:ident) => {
467        impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<&'a Point<T1, T2>> for Point<T1, T2> {
468            type Output = Vector2<T1, T2>;
469
470            #[inline]
471            fn $method(self, other: &Point<T1, T2>) -> Self::Output {
472                self.$method(other.clone())
473            }
474        }
475    };
476}
477
478macro_rules! forward_all_binop2 {
479    (impl $imp:ident, $method:ident) => {
480        forward_xf_xf_binop2!(impl $imp, $method);
481        forward_xf_val_binop2!(impl $imp, $method);
482        forward_val_xf_binop2!(impl $imp, $method);
483    };
484}
485
486// arithmetic
487forward_all_binop2!(impl Sub, sub);
488
489/// The above code is implementing the subtraction operation for a custom Point struct in Rust. It
490/// defines the behavior of subtracting one Point from another Point, resulting in a Vector2
491/// representing the displacement between the two points. The `sub` function takes two Point objects as
492/// input and returns a Vector2 object with the x and y coordinates calculated by subtracting the
493/// corresponding coordinates of the two points. The code also includes examples demonstrating the usage
494/// of the subtraction operation with different scenarios.
495impl<T1: Clone + Num, T2: Clone + Num> Sub for Point<T1, T2> {
496    type Output = Vector2<T1, T2>;
497
498    /// Displacement of two Points
499    ///
500    /// Arguments:
501    ///
502    /// * `other`: The `other` parameter is of the same type as `self` and represents the other object
503    ///             that you want to subtract from `self`.
504    ///
505    /// # Examples
506    ///
507    /// ```
508    /// use physdes::point::Point;
509    /// use physdes::vector2::Vector2;
510    ///
511    /// assert_eq!(Point::new(3, 4) - Point::new(5, 3), Vector2::new(-2, 1));
512    /// assert_eq!(Point::new(3, 4) - Point::new(-5, -3), Vector2::new(8, 7));
513    /// assert_eq!(Point::new(3, 4) - Point::new(5, -3), Vector2::new(-2, 7));
514    /// assert_eq!(Point::new(3, 4) - Point::new(-5, 3), Vector2::new(8, 1));
515    /// assert_eq!(Point::new(3, 4) - Point::new(0, 0), Vector2::new(3, 4));
516    #[inline]
517    fn sub(self, other: Self) -> Self::Output {
518        Self::Output::new(self.xcoord - other.xcoord, self.ycoord - other.ycoord)
519    }
520}
521
522// Op Assign
523
524mod opassign {
525    use core::ops::{AddAssign, SubAssign};
526
527    use num_traits::NumAssign;
528
529    use crate::Point;
530    use crate::Vector2;
531
532    /// The above code is implementing the `AddAssign` trait for a custom type `Point<T1, T2>`. This
533    /// implementation allows instances of `Point<T1, T2>` to be added to instances of `Vector2<T1, T2>`
534    /// using the `+=` operator. Inside the `add_assign` function, the `xcoord` and `ycoord` fields of
535    /// the `Point` instance are updated by adding the corresponding `x_` and `y_` fields of the
536    /// `Vector2` instance.
537    impl<T1: Clone + NumAssign, T2: Clone + NumAssign> AddAssign<Vector2<T1, T2>> for Point<T1, T2> {
538        /// The `add_assign` function in Rust adds the x and y coordinates of another Vector2 to the
539        /// current Vector2.
540        ///
541        /// Arguments:
542        ///
543        /// * `other`: The `other` parameter in the `add_assign` function is of type `Vector2<T1, T2>`.
544        ///             It represents another instance of the `Vector2` struct with potentially different generic
545        ///             types `T1` and `T2`.
546        #[inline]
547        fn add_assign(&mut self, other: Vector2<T1, T2>) {
548            self.xcoord += other.x_;
549            self.ycoord += other.y_;
550        }
551    }
552
553    /// The above code is implementing the `SubAssign` trait for a custom type `Point<T1, T2>`. This
554    /// implementation allows instances of `Point` to be subtracted by instances of `Vector2<T1, T2>`
555    /// using the `-=` operator. Inside the implementation, it subtracts the `x_` and `y_` components of
556    /// the `other` vector from the `xcoord` and `ycoord` components of the `Point` respectively.
557    impl<T1: Clone + NumAssign, T2: Clone + NumAssign> SubAssign<Vector2<T1, T2>> for Point<T1, T2> {
558        /// The function `sub_assign` subtracts the `x_` and `y_` components of another `Vector2` from
559        /// the `xcoord` and `ycoord` components of the current `Vector2`.
560        ///
561        /// Arguments:
562        ///
563        /// * `other`: The `other` parameter in the `sub_assign` function is of type `Vector2<T1, T2>`.
564        ///             It represents another instance of the `Vector2` struct with potentially different generic
565        ///             types `T1` and `T2`. This parameter is used to subtract the `x_
566        #[inline]
567        fn sub_assign(&mut self, other: Vector2<T1, T2>) {
568            self.xcoord -= other.x_;
569            self.ycoord -= other.y_;
570        }
571    }
572
573    macro_rules! forward_op_assign {
574        (impl $imp:ident, $method:ident) => {
575            impl<'a, T1: Clone + NumAssign, T2: Clone + NumAssign> $imp<&'a Vector2<T1, T2>>
576                for Point<T1, T2>
577            {
578                #[inline]
579                fn $method(&mut self, other: &Vector2<T1, T2>) {
580                    self.$method(other.clone())
581                }
582            }
583        };
584    }
585
586    forward_op_assign!(impl AddAssign, add_assign);
587    forward_op_assign!(impl SubAssign, sub_assign);
588}
589
590/// The above code is implementing the `Neg` trait for a custom type `Point<T1, T2>`. This
591/// implementation allows for negating instances of the `Point` type. The `Neg` trait requires defining
592/// an associated type `Output` and implementing the `neg` method which returns the negated version of
593/// the `Point` instance by negating its `xcoord` and `ycoord` values.
594impl<T1: Clone + Num + Neg<Output = T1>, T2: Clone + Num + Neg<Output = T2>> Neg for Point<T1, T2> {
595    type Output = Self;
596
597    /// Negate a Points
598    ///
599    /// # Examples
600    ///
601    /// ```
602    /// use physdes::point::Point;
603    ///
604    /// assert_eq!(-Point::new(3, 4), Point::new(-3, -4));
605    /// assert_eq!(-Point::new(0, 0), Point::new(0, 0));
606    #[inline]
607    fn neg(self) -> Self::Output {
608        Self::Output::new(-self.xcoord, -self.ycoord)
609    }
610}
611
612/// The above code is implementing the `Neg` trait for a reference to a `Point<T1, T2>` struct in Rust.
613/// The `Neg` trait is used for the negation operation (unary minus) on a value.
614impl<T1: Clone + Num + Neg<Output = T1>, T2: Clone + Num + Neg<Output = T2>> Neg
615    for &Point<T1, T2>
616{
617    type Output = Point<T1, T2>;
618
619    /// The function `neg` returns the negation of the cloned value.
620    #[inline]
621    fn neg(self) -> Self::Output {
622        -self.clone()
623    }
624}
625
626#[cfg(test)]
627fn hash<T: hash::Hash>(x: &T) -> u64 {
628    use std::collections::hash_map::RandomState;
629    use std::hash::{BuildHasher, Hasher};
630    let mut hasher = <RandomState as BuildHasher>::Hasher::new();
631    x.hash(&mut hasher);
632    hasher.finish()
633}
634
635#[cfg(test)]
636mod test {
637    #![allow(non_upper_case_globals)]
638
639    use super::*;
640    use crate::generic::Overlap;
641    use crate::interval::Interval;
642
643    pub const _0_0p: Point<i32, i32> = Point {
644        xcoord: 0,
645        ycoord: 0,
646    };
647    pub const _1_0p: Point<i32, i32> = Point {
648        xcoord: 1,
649        ycoord: 0,
650    };
651    pub const _1_1p: Point<i32, i32> = Point {
652        xcoord: 1,
653        ycoord: 1,
654    };
655    pub const _0_1p: Point<i32, i32> = Point {
656        xcoord: 0,
657        ycoord: 1,
658    };
659    pub const _neg1_1p: Point<i32, i32> = Point {
660        xcoord: -1,
661        ycoord: 1,
662    };
663    // pub const all_consts: [Point<i32, i32>; 4] = [_0_0p, _1_0p, _1_1p, _neg1_1p];
664    pub const _4_2p: Point<i32, i32> = Point {
665        xcoord: 4,
666        ycoord: 2,
667    };
668
669    #[test]
670    fn test_consts() {
671        // check our constants are what Point::new creates
672        fn test(c: Point<i32, i32>, r: i32, i: i32) {
673            assert_eq!(c, Point::new(r, i));
674        }
675        test(_0_0p, 0, 0);
676        test(_1_0p, 1, 0);
677        test(_1_1p, 1, 1);
678        test(_neg1_1p, -1, 1);
679    }
680
681    #[test]
682    fn test_hash() {
683        let a = Point::new(0i32, 0i32);
684        let b = Point::new(1i32, 0i32);
685        let c = Point::new(0i32, 1i32);
686        assert!(hash(&a) != hash(&b));
687        assert!(hash(&b) != hash(&c));
688        assert!(hash(&c) != hash(&a));
689    }
690
691    #[test]
692    fn test_overlap() {
693        let a = Point::new(0i32, 0i32);
694        let b = Point::new(1i32, 0i32);
695        assert!(!a.overlaps(&b));
696    }
697
698    #[test]
699    fn test_contain() {
700        let a = Point::new(0i32, 0i32);
701        let b = Point::new(1i32, 0i32);
702        assert!(!a.contains(&b));
703    }
704
705    #[test]
706    fn test_min_dist_with() {
707        let a = Point::new(3i32, 5i32);
708        let b = Point::new(6i32, 4i32);
709        assert_eq!(a.min_dist_with(&b), 4);
710    }
711
712    #[test]
713    fn test_add() {
714        let a = Point::new(0i32, 0i32);
715        let b = Point::new(1i32, 0i32);
716        let v = Vector2::new(5i32, 6i32);
717        assert_eq!(a, a + v - v);
718        assert_eq!(b, b - v + v);
719    }
720
721    #[test]
722    fn test_sub() {
723        let a = Point::new(0i32, 0i32);
724        let b = Point::new(1i32, 0i32);
725        let v = Vector2::new(5i32, 6i32);
726        assert_eq!(a, a - v + v);
727        assert_eq!(b, b + v - v);
728    }
729
730    #[test]
731    fn test_neg() {
732        let a = Point::new(0i32, 0i32);
733        let b = Point::new(1i32, 0i32);
734        let c = Point::new(0i32, 1i32);
735        assert_eq!(a, -(-a));
736        assert_eq!(b, -(-b));
737        assert_eq!(c, -(-c));
738    }
739
740    #[test]
741    fn test_add_assign() {
742        let mut a = Point::new(1i32, 0i32);
743        let b = Point::new(6i32, 6i32);
744        let v = Vector2::new(5i32, 6i32);
745        a += v;
746        assert_eq!(a, b);
747    }
748
749    #[test]
750    fn test_sub_assign() {
751        let mut a = Point::new(1i32, 0i32);
752        let b = Point::new(-4i32, -6i32);
753        let v = Vector2::new(5i32, 6i32);
754        a -= v;
755        assert_eq!(a, b);
756    }
757
758    #[test]
759    fn test_neg_assign() {
760        let mut a = Point::new(1i32, 0i32);
761        let b = Point::new(-1i32, 0i32);
762        let c = Point::new(1i32, 0i32);
763        a = -a;
764        assert_eq!(a, b);
765        a = -a;
766        assert_eq!(a, c);
767    }
768
769    #[test]
770    fn test_point() {
771        let a = Point::new(4, 8);
772        let b = Point::new(5, 6);
773        assert!(a < b);
774        assert!(a <= b);
775        assert_ne!(b, a);
776    }
777
778    #[test]
779    fn test_point2() {
780        let a = Point::new(3, 4);
781        let r = Point::new(Interval::new(3, 4), Interval::new(5, 6)); // Rectangle
782        assert!(!r.contains(&a));
783        assert!(r.contains(&Point::new(4, 5)));
784        assert!(!r.overlaps(&a));
785        assert!(r.overlaps(&Point::new(4, 5)));
786        assert!(r.overlaps(&Point::new(4, 6)));
787        // assert_eq!(r.intersect_with(&Point::new(4, 5)), Point::new(Interval::new(4, 4), Interval::new(5, 5)));
788    }
789
790    #[test]
791    fn test_transform() {
792        let mut a = Point::new(3, 5);
793        let b = Vector2::new(5, 7);
794        assert_eq!(a + b, Point::new(8, 12));
795        assert_eq!(a - b, Point::new(-2, -2));
796        a += b;
797        assert_eq!(a, Point::new(8, 12));
798        a -= b;
799        assert_eq!(a, Point::new(3, 5));
800        assert_eq!(a.flip(), Point::new(5, 3));
801    }
802
803    #[test]
804    fn test_displacement() {
805        let a = Point::new(3, 5);
806        let b = Point::new(5, 7);
807        let c = Point::new(7, 8);
808        assert_eq!(a.displace(&b), Vector2::new(-2, -2));
809        assert_eq!(a.displace(&c), Vector2::new(-4, -3));
810        assert_eq!(b.displace(&c), Vector2::new(-2, -1));
811    }
812
813    #[test]
814    fn test_enlarge() {
815        let _a = Point::new(3, 5);
816        // assert_eq!(a.enlarge_with(2), Point::new(Interval::new(1, 5), Interval::new(3, 7)));
817    }
818
819    #[test]
820    fn test_hull() {
821        let a = Point::new(3, 5);
822        let b = Point::new(5, 7);
823        assert_eq!(
824            a.hull_with(&b),
825            Point::new(Interval::new(3, 5), Interval::new(5, 7))
826        );
827    }
828
829    #[test]
830    fn test_min_dist_with2() {
831        let a = Point::new(3, 5);
832        let b = Point::new(5, 7);
833        assert_eq!(a.min_dist_with(&b), 4);
834    }
835}