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> {
42 MergeObj {
43 impl_: Point::new(xcoord, ycoord),
44 }
45 }
46
47 pub const fn construct(xcoord: i32, ycoord: i32) -> MergeObj<i32, i32> {
70 let impl_ = Point::new(xcoord + ycoord, xcoord - ycoord);
71 MergeObj { impl_ }
72 }
73
74 pub fn get_impl(&self) -> &Point<T1, T2> {
87 &self.impl_
88 }
89}
90
91impl<T1, T2> MergeObj<T1, T2>
92where
93 T1: MinDist<T1>,
94 T2: MinDist<T2>,
95{
96 pub fn min_dist_with(&self, other: &MergeObj<T1, T2>) -> u32 {
116 cmp::max(
117 self.impl_.xcoord.min_dist_with(&other.impl_.xcoord),
118 self.impl_.ycoord.min_dist_with(&other.impl_.ycoord),
119 )
120 }
121}
122
123impl<T1, T2> MergeObj<T1, T2>
124where
125 T1: MinDist<T1> + Enlarge<i32, Output = T1> + Intersect<T1, Output = T1>,
126 T2: MinDist<T2> + Enlarge<i32, Output = T2> + Intersect<T2, Output = T2>,
127{
128 pub fn enlarge_with(&self, alpha: i32) -> MergeObj<T1, T2> {
137 let xcoord = self.impl_.xcoord.enlarge_with(alpha);
138 let ycoord = self.impl_.ycoord.enlarge_with(alpha);
139 MergeObj::new(xcoord, ycoord)
140 }
141
142 pub fn intersect_with(&self, other: &MergeObj<T1, T2>) -> MergeObj<T1, T2> {
151 let point = self.impl_.intersect_with(&other.impl_);
152 MergeObj::new(point.xcoord, point.ycoord)
153 }
154
155 pub fn merge_with(&self, other: &MergeObj<T1, T2>) -> MergeObj<T1, T2> {
171 let alpha = self.min_dist_with(other);
172 let half = alpha / 2;
173 let trr1 = self.enlarge_with(half as i32);
174 let trr2 = other.enlarge_with((alpha - half) as i32);
175 trr1.intersect_with(&trr2)
176 }
177}
178
179#[cfg(test)]
180mod test {
181 use super::*;
184 use crate::interval::Interval;
185 use crate::vector2::Vector2;
186
187 #[test]
193 fn test_merge_obj() {
194 let obj1 = MergeObj::<i32, i32>::construct(4, 5);
195 let obj2 = MergeObj::<i32, i32>::construct(7, 9);
196
197 assert_ne!(obj1, obj2);
198 assert_eq!(obj1.min_dist_with(&obj2), 7);
199 }
201
202 #[test]
203 fn test_merge() {
204 let obj1: MergeObj<Interval<i32>, Interval<i32>> =
205 MergeObj::new(Interval::new(200, 600), Interval::new(200, 600));
206 let obj2: MergeObj<Interval<i32>, Interval<i32>> =
207 MergeObj::new(Interval::new(500, 900), Interval::new(500, 900));
208 let merged = obj1.merge_with(&obj2);
209 println!("{:?}", merged);
210 assert_eq!(
211 merged,
212 MergeObj::new(Interval::new(500, 600), Interval::new(500, 600))
213 );
214 }
215
216 #[test]
217 fn test_merge_2() {
218 let mut obj1: MergeObj<Interval<i32>, Interval<i32>> =
219 MergeObj::new(Interval::new(4, 5), Interval::new(4, 5));
220 let obj2: MergeObj<Interval<i32>, Interval<i32>> =
221 MergeObj::new(Interval::new(7, 9), Interval::new(7, 9));
222 let vec = Vector2::new(Interval::new(2, 3), Interval::new(2, 3));
223 obj1.impl_.xcoord.lb += vec.x_.lb;
224 obj1.impl_.xcoord.ub += vec.x_.ub;
225 obj1.impl_.ycoord.lb += vec.y_.lb;
226 obj1.impl_.ycoord.ub += vec.y_.ub;
227 obj1.impl_.xcoord.lb -= vec.x_.lb;
228 obj1.impl_.xcoord.ub -= vec.x_.ub;
229 obj1.impl_.ycoord.lb -= vec.y_.lb;
230 obj1.impl_.ycoord.ub -= vec.y_.ub;
231 assert_eq!(
232 obj1,
233 MergeObj::new(Interval::new(4, 5), Interval::new(4, 5))
234 );
235 let result1 = obj1.enlarge_with(3);
236 assert_eq!(
237 result1,
238 MergeObj::new(Interval::new(1, 8), Interval::new(1, 8))
239 );
240 let result2 = obj2.enlarge_with(4);
241 assert_eq!(
242 result2,
243 MergeObj::new(Interval::new(3, 13), Interval::new(3, 13))
244 );
245 let result3 = result1.intersect_with(&result2);
246 assert_eq!(
247 result3,
248 MergeObj::new(Interval::new(3, 8), Interval::new(3, 8))
249 );
250 }
251
252 #[test]
253 fn test_min_dist_with_more_cases() {
254 let obj1 = MergeObj::<i32, i32>::construct(0, 0);
255 let obj2 = MergeObj::<i32, i32>::construct(3, 4);
256 assert_eq!(obj1.min_dist_with(&obj2), 7);
257
258 let obj3 = MergeObj::<i32, i32>::construct(-3, -4);
259 assert_eq!(obj1.min_dist_with(&obj3), 7);
260 }
261
262 #[test]
263 fn test_enlarge_with_more_cases() {
264 let obj1: MergeObj<Interval<i32>, Interval<i32>> =
265 MergeObj::new(Interval::new(200, 600), Interval::new(200, 600));
266 let enlarged = obj1.enlarge_with(100);
267 assert_eq!(
268 enlarged,
269 MergeObj::new(Interval::new(100, 700), Interval::new(100, 700))
270 );
271 }
272
273 #[test]
274 fn test_intersect_with_more_cases() {
275 let obj1: MergeObj<Interval<i32>, Interval<i32>> =
276 MergeObj::new(Interval::new(200, 600), Interval::new(200, 600));
277 let obj2: MergeObj<Interval<i32>, Interval<i32>> =
278 MergeObj::new(Interval::new(500, 900), Interval::new(500, 900));
279 let intersected = obj1.intersect_with(&obj2);
280 assert_eq!(
281 intersected,
282 MergeObj::new(Interval::new(500, 600), Interval::new(500, 600))
283 );
284
285 let obj3 = MergeObj::new(Interval::new(700, 900), Interval::new(700, 900));
286 let intersected2 = obj1.intersect_with(&obj3);
287 assert!(intersected2.impl_.xcoord.is_invalid());
288 assert!(intersected2.impl_.ycoord.is_invalid());
289 }
290
291 #[test]
292 fn test_merge_with_more_cases() {
293 let obj1: MergeObj<Interval<i32>, Interval<i32>> =
294 MergeObj::new(Interval::new(0, 100), Interval::new(0, 100));
295 let obj2: MergeObj<Interval<i32>, Interval<i32>> =
296 MergeObj::new(Interval::new(100, 200), Interval::new(100, 200));
297 let merged = obj1.merge_with(&obj2);
298 assert_eq!(
299 merged,
300 MergeObj::new(Interval::new(100, 100), Interval::new(100, 100))
301 );
302 }
303
304 #[test]
305 fn test_get_impl() {
306 let mo = MergeObj::new(3, 5);
307 let impl_ref = mo.get_impl();
308 assert_eq!(impl_ref.xcoord, 3);
309 assert_eq!(impl_ref.ycoord, 5);
310 }
311}