1use crate::generic::MinDist;
2use crate::interval::{Enlarge, Intersect};
3use crate::point::Point;
4use std::cmp;
5
6#[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 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 use super::*;
98 use crate::interval::Interval;
99 use crate::vector2::Vector2;
100
101 #[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 }
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}