physdes/
point.rs

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