Skip to main content

physdes/
merge_obj.rs

1use crate::generic::MinDist;
2use crate::interval::{Enlarge, Intersect};
3use crate::point::Point;
4use std::cmp;
5
6/// Represents a merge object that encapsulates a point with coordinates of type T1 and T2.
7///
8/// The MergeObj struct is used for geometric operations such as distance calculation,
9/// enlargement, intersection, and merging with other merge objects.
10///
11/// # Examples
12///
13/// ```
14/// use physdes::merge_obj::MergeObj;
15///
16/// let merge_obj = MergeObj::new(3, 4);
17/// let internal_point = merge_obj.get_impl();
18/// assert_eq!(internal_point.xcoord, 3);
19/// assert_eq!(internal_point.ycoord, 4);
20/// ```
21#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)]
22pub struct MergeObj<T1, T2> {
23    impl_: Point<T1, T2>,
24}
25
26impl<T1, T2> MergeObj<T1, T2> {
27    pub const fn new(xcoord: T1, ycoord: T2) -> MergeObj<T1, T2> {
28        MergeObj {
29            impl_: Point::new(xcoord, ycoord),
30        }
31    }
32
33    pub const fn construct(xcoord: i32, ycoord: i32) -> MergeObj<i32, i32> {
34        let impl_ = Point::new(xcoord + ycoord, xcoord - ycoord);
35        MergeObj { impl_ }
36    }
37
38    /// Returns a reference to the internal Point of the MergeObj
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use physdes::merge_obj::MergeObj;
44    ///
45    /// let merge_obj = MergeObj::new(3, 4);
46    /// let internal_point = merge_obj.get_impl();
47    /// assert_eq!(internal_point.xcoord, 3);
48    /// assert_eq!(internal_point.ycoord, 4);
49    /// ```
50    pub fn get_impl(&self) -> &Point<T1, T2> {
51        &self.impl_
52    }
53}
54
55impl<T1, T2> MergeObj<T1, T2>
56where
57    T1: MinDist<T1>,
58    T2: MinDist<T2>,
59{
60    pub fn min_dist_with(&self, other: &MergeObj<T1, T2>) -> u32 {
61        cmp::max(
62            self.impl_.xcoord.min_dist_with(&other.impl_.xcoord),
63            self.impl_.ycoord.min_dist_with(&other.impl_.ycoord),
64        )
65    }
66}
67
68impl<T1, T2> MergeObj<T1, T2>
69where
70    T1: MinDist<T1> + Enlarge<i32, Output = T1> + Intersect<T1, Output = T1>,
71    T2: MinDist<T2> + Enlarge<i32, Output = T2> + Intersect<T2, Output = T2>,
72{
73    pub fn enlarge_with(&self, alpha: i32) -> MergeObj<T1, T2> {
74        let xcoord = self.impl_.xcoord.enlarge_with(alpha);
75        let ycoord = self.impl_.ycoord.enlarge_with(alpha);
76        MergeObj::new(xcoord, ycoord)
77    }
78
79    pub fn intersect_with(&self, other: &MergeObj<T1, T2>) -> MergeObj<T1, T2> {
80        let point = self.impl_.intersect_with(&other.impl_);
81        MergeObj::new(point.xcoord, point.ycoord)
82    }
83
84    pub fn merge_with(&self, other: &MergeObj<T1, T2>) -> MergeObj<T1, T2> {
85        let alpha = self.min_dist_with(other);
86        let half = alpha / 2;
87        let trr1 = self.enlarge_with(half as i32);
88        let trr2 = other.enlarge_with((alpha - half) as i32);
89        trr1.intersect_with(&trr2)
90    }
91}
92
93#[cfg(test)]
94mod test {
95    // #![allow(non_upper_case_globals)]
96
97    use super::*;
98    use crate::interval::Interval;
99    use crate::vector2::Vector2;
100
101    // use crate::generic::Overlap;
102    // use crate::interval::Interval;
103
104    // use core::i32;
105
106    #[test]
107    fn test_merge_obj() {
108        let obj1 = MergeObj::<i32, i32>::construct(4, 5);
109        let obj2 = MergeObj::<i32, i32>::construct(7, 9);
110
111        assert_ne!(obj1, obj2);
112        assert_eq!(obj1.min_dist_with(&obj2), 7);
113        // assert_eq!(min_dist(&obj1, &obj2), 7);
114    }
115
116    #[test]
117    fn test_merge() {
118        let obj1: MergeObj<Interval<i32>, Interval<i32>> =
119            MergeObj::new(Interval::new(200, 600), Interval::new(200, 600));
120        let obj2: MergeObj<Interval<i32>, Interval<i32>> =
121            MergeObj::new(Interval::new(500, 900), Interval::new(500, 900));
122        let merged = obj1.merge_with(&obj2);
123        println!("{:?}", merged);
124        assert_eq!(
125            merged,
126            MergeObj::new(Interval::new(500, 600), Interval::new(500, 600))
127        );
128    }
129
130    #[test]
131    fn test_merge_2() {
132        let mut obj1: MergeObj<Interval<i32>, Interval<i32>> =
133            MergeObj::new(Interval::new(4, 5), Interval::new(4, 5));
134        let obj2: MergeObj<Interval<i32>, Interval<i32>> =
135            MergeObj::new(Interval::new(7, 9), Interval::new(7, 9));
136        let vec = Vector2::new(Interval::new(2, 3), Interval::new(2, 3));
137        obj1.impl_.xcoord.lb += vec.x_.lb;
138        obj1.impl_.xcoord.ub += vec.x_.ub;
139        obj1.impl_.ycoord.lb += vec.y_.lb;
140        obj1.impl_.ycoord.ub += vec.y_.ub;
141        obj1.impl_.xcoord.lb -= vec.x_.lb;
142        obj1.impl_.xcoord.ub -= vec.x_.ub;
143        obj1.impl_.ycoord.lb -= vec.y_.lb;
144        obj1.impl_.ycoord.ub -= vec.y_.ub;
145        assert_eq!(
146            obj1,
147            MergeObj::new(Interval::new(4, 5), Interval::new(4, 5))
148        );
149        let result1 = obj1.enlarge_with(3);
150        assert_eq!(
151            result1,
152            MergeObj::new(Interval::new(1, 8), Interval::new(1, 8))
153        );
154        let result2 = obj2.enlarge_with(4);
155        assert_eq!(
156            result2,
157            MergeObj::new(Interval::new(3, 13), Interval::new(3, 13))
158        );
159        let result3 = result1.intersect_with(&result2);
160        assert_eq!(
161            result3,
162            MergeObj::new(Interval::new(3, 8), Interval::new(3, 8))
163        );
164    }
165
166    #[test]
167    fn test_min_dist_with_more_cases() {
168        let obj1 = MergeObj::<i32, i32>::construct(0, 0);
169        let obj2 = MergeObj::<i32, i32>::construct(3, 4);
170        assert_eq!(obj1.min_dist_with(&obj2), 7);
171
172        let obj3 = MergeObj::<i32, i32>::construct(-3, -4);
173        assert_eq!(obj1.min_dist_with(&obj3), 7);
174    }
175
176    #[test]
177    fn test_enlarge_with_more_cases() {
178        let obj1: MergeObj<Interval<i32>, Interval<i32>> =
179            MergeObj::new(Interval::new(200, 600), Interval::new(200, 600));
180        let enlarged = obj1.enlarge_with(100);
181        assert_eq!(
182            enlarged,
183            MergeObj::new(Interval::new(100, 700), Interval::new(100, 700))
184        );
185    }
186
187    #[test]
188    fn test_intersect_with_more_cases() {
189        let obj1: MergeObj<Interval<i32>, Interval<i32>> =
190            MergeObj::new(Interval::new(200, 600), Interval::new(200, 600));
191        let obj2: MergeObj<Interval<i32>, Interval<i32>> =
192            MergeObj::new(Interval::new(500, 900), Interval::new(500, 900));
193        let intersected = obj1.intersect_with(&obj2);
194        assert_eq!(
195            intersected,
196            MergeObj::new(Interval::new(500, 600), Interval::new(500, 600))
197        );
198
199        let obj3 = MergeObj::new(Interval::new(700, 900), Interval::new(700, 900));
200        let intersected2 = obj1.intersect_with(&obj3);
201        assert!(intersected2.impl_.xcoord.is_invalid());
202        assert!(intersected2.impl_.ycoord.is_invalid());
203    }
204
205    #[test]
206    fn test_merge_with_more_cases() {
207        let obj1: MergeObj<Interval<i32>, Interval<i32>> =
208            MergeObj::new(Interval::new(0, 100), Interval::new(0, 100));
209        let obj2: MergeObj<Interval<i32>, Interval<i32>> =
210            MergeObj::new(Interval::new(100, 200), Interval::new(100, 200));
211        let merged = obj1.merge_with(&obj2);
212        assert_eq!(
213            merged,
214            MergeObj::new(Interval::new(100, 100), Interval::new(100, 100))
215        );
216    }
217}