1use iron_shapes::prelude::{Angle, CoordinateType, REdge, Rect, RotateOrtho};
8use itertools::Itertools;
9use num_traits::{Bounded, Zero};
10
11pub fn decompose_rectangles<T, I>(redges: I) -> Vec<Rect<T>>
34where
35 T: Ord + Bounded + Copy + Zero,
36 I: Iterator<Item = REdge<T>>,
37{
38 decompose_disjoint_and_maximal_rectangles(redges, true, false)
39}
40
41pub fn decompose_rectangles_vertical<T, I>(redges: I) -> Vec<Rect<T>>
44where
45 T: CoordinateType + Ord + Bounded + Copy + Zero,
46 I: Iterator<Item = REdge<T>>,
47{
48 let redges = redges.map(|e| e.rotate_ortho(Angle::R90));
49
50 let sliced = decompose_rectangles(redges);
51
52 sliced
53 .into_iter()
54 .map(|r| r.rotate_ortho(Angle::R270))
55 .collect()
56}
57
58pub fn decompose_maximal_rectangles<T, I>(redges: I) -> Vec<Rect<T>>
81where
82 T: Ord + Bounded + Copy + Zero,
83 I: Iterator<Item = REdge<T>>,
84{
85 decompose_disjoint_and_maximal_rectangles(redges, false, true)
86}
87
88fn decompose_disjoint_and_maximal_rectangles<T, I>(
96 redges: I,
97 find_disjoint_rectangles: bool,
98 find_maximal_rectangles: bool,
99) -> Vec<Rect<T>>
100where
101 T: Ord + Bounded + Copy + Zero,
102 I: Iterator<Item = REdge<T>>,
103{
104 {
109 let vertical_edges: Vec<_> = redges
111 .filter(|e| e.is_vertical() && e.start != e.end)
112 .map(|e| {
113 let is_left = e.start > e.end;
114 if is_left {
115 (e.reversed(), true)
116 } else {
117 (e, false)
118 }
119 })
120 .sorted_by_key(|(e, is_left)| (e.offset, !is_left, e.start, e.end))
122 .collect();
123
124 let mut open_rects: Vec<(T, T, isize, T)> =
126 vec![(T::min_value(), T::max_value(), 0, T::min_value())];
127 let mut results = Vec::new();
128
129 fn split_intervals<T: PartialOrd + Copy>(
131 intervals: &mut Vec<(T, T, isize, T)>,
132 split_location: T,
133 ) -> usize {
134 let (pos, &(a, b, value, x)) = intervals
136 .iter()
137 .enumerate()
138 .find(|(_pos, &(a, b, _val, _x))| a <= split_location && split_location < b)
139 .expect("Intervals must span the whole value range without gap.");
140
141 if split_location == a || split_location == b {
142 pos
144 } else {
145 let i1 = (a, split_location, value, x);
147 let i2 = (split_location, b, value, x);
148 intervals[pos] = i2;
149 intervals.insert(pos, i1);
150 pos + 1
151 }
152 }
153
154 fn merge_intervals<T: PartialEq + Copy>(intervals: &mut Vec<(T, T, isize, T)>) {
156 debug_assert!(intervals.len() >= 1);
157 let mut write_index = 0;
158 let mut value = (intervals[0].2, intervals[0].3);
159 for i in 1..intervals.len() {
160 let (start, end, count, x) = intervals[i];
161 let current_value = (count, x);
162 intervals[write_index].1 = end;
163
164 if current_value != value {
165 intervals[write_index].1 = start;
166 write_index += 1;
167 intervals[write_index] = intervals[i];
168 value = current_value;
169 } else {
170 }
172 }
173
174 intervals.truncate(write_index + 1);
176 }
177
178 for (current_edge, is_left) in vertical_edges {
180 debug_assert!(current_edge.start < current_edge.end);
181
182 {
183 let pos = split_intervals(&mut open_rects, current_edge.start);
184 split_intervals(&mut open_rects, current_edge.end);
185
186 open_rects
188 .iter_mut()
189 .skip(pos) .take_while(|(_a, b, _value, _x)| b <= ¤t_edge.end) .filter(|(a, _b, value, _x)| a >= ¤t_edge.start && *value == 0)
192 .for_each(|(_a, _b, _value, x)| {
193 *x = current_edge.offset;
194 });
195 }
196
197 let increment = if is_left {
198 1
200 } else {
201 -1
203 };
204
205 if find_disjoint_rectangles {
206 let increment_inv = -increment;
212 let closed_rects = open_rects
213 .iter()
214 .take_while(|(_a, b, _value, _x)| b <= ¤t_edge.end)
215 .filter(|(a, _b, value, _x)| {
216 a >= ¤t_edge.start && value == &increment_inv
217 })
218 .map(|&(a, b, _value, x_start)| {
219 let y_start = a.max(current_edge.start);
221 let y_end = b.min(current_edge.end);
222 let x_end = current_edge.offset;
223 debug_assert!(x_start != T::min_value());
224 Rect::new((x_start, y_start), (x_end, y_end))
225 });
226
227 results.extend(closed_rects);
228 }
229
230 if find_maximal_rectangles {
231 let increment_inv = -increment;
234 let closed_rects: Vec<_> = open_rects
235 .iter()
236 .take_while(|(_a, b, _value, _x)| b <= ¤t_edge.end)
237 .filter(|(a, _b, value, _x)| {
238 a >= ¤t_edge.start && value == &increment_inv
239 })
240 .collect();
241
242 let mut left_edge_xs: Vec<_> =
244 closed_rects.iter().map(|(_a, _b, _value, x)| *x).collect();
245
246 left_edge_xs.sort_unstable();
247 left_edge_xs.dedup();
248
249 let x_end = current_edge.offset;
250
251 for x_start in left_edge_xs {
252 let y_intervals = open_rects
255 .iter()
256 .filter(|(_a, _b, value, _x)| value == &increment_inv)
257 .filter(|(_, _, _, x)| x <= &x_start)
258 .map(|&(a, b, _, _)| (a, b));
259
260 let max_y_spans = {
262 let mut max_y_spans = Vec::new();
263 let mut open_interval = None;
264 for (start2, end2) in y_intervals {
265 if let Some((start1, end1)) = open_interval {
266 if start2 == end1 {
267 open_interval = Some((start1, end2))
269 } else {
270 max_y_spans.push((start1, end1));
272 open_interval = Some((start2, end2));
273 }
274 } else {
275 open_interval = Some((start2, end2))
276 }
277 }
278 if let Some(i) = open_interval {
280 max_y_spans.push(i);
281 }
282 max_y_spans
283 };
284
285 for (y_start, y_end) in max_y_spans {
287 if y_end <= current_edge.end && y_start >= current_edge.start {
288 let max_rectangle = Rect::new((x_start, y_start), (x_end, y_end));
290 results.push(max_rectangle)
291 } else {
292 }
294 }
295 }
296 }
297
298 open_rects
300 .iter_mut()
301 .take_while(|(_a, b, _value, _x)| b <= ¤t_edge.end)
302 .filter(|(a, _b, _value, _x)| a >= ¤t_edge.start)
303 .for_each(|(_, _, count, x)| {
304 *count += increment;
305
306 if *count == 0 {
307 *x = T::min_value();
309 }
310 });
311
312 merge_intervals(&mut open_rects);
314 }
315
316 results
317 }
318}
319
320#[test]
321fn test_decompose_rectangles_trivial() {
322 use iron_shapes::prelude::*;
324
325 let empty: SimpleRPolygon<i32> = SimpleRPolygon::empty();
326 let rects = decompose_rectangles(empty.edges());
327 assert_eq!(rects, vec![]);
328
329 let rect = SimpleRPolygon::try_new([(0, 0), (2, 0), (2, 2), (0, 2)]).unwrap();
331 let rects = decompose_rectangles(rect.reversed().edges());
332 assert_eq!(rects, vec![Rect::new((0, 0), (2, 2))]);
333}
334
335#[test]
336fn test_decompose_rectangles() {
337 use iron_shapes::prelude::*;
338 let poly = SimpleRPolygon::try_new([(0, 0), (2, 0), (2, 2), (1, 2), (1, 1), (0, 1)]).unwrap();
344 let rects = decompose_rectangles(poly.edges());
345 assert_eq!(
346 rects,
347 vec![Rect::new((0, 0), (2, 1)), Rect::new((1, 1), (2, 2))]
348 );
349
350 let rects = decompose_rectangles(poly.reversed().edges());
352 assert_eq!(
353 rects,
354 vec![Rect::new((0, 0), (2, 1)), Rect::new((1, 1), (2, 2))]
355 );
356}
357
358#[test]
359fn test_decompose_rectangles_overlapping() {
360 use iron_shapes::prelude::IntoEdges;
361
362 let rects = vec![Rect::new((0i32, 0), (10, 10)), Rect::new((0, 0), (5, 5))];
363
364 let decomposed = decompose_rectangles(rects.iter().flat_map(|r| r.into_edges()));
365 assert_eq!(decomposed, vec![Rect::new((0, 0), (10, 10))]);
366}
367
368#[test]
369fn test_decompose_rectangles_touching() {
370 use iron_shapes::prelude::IntoEdges;
371
372 let rects = vec![Rect::new((0i32, 0), (10, 10)), Rect::new((10, 0), (20, 10))];
373
374 let decomposed = decompose_rectangles(rects.iter().flat_map(|r| r.into_edges()));
375 assert_eq!(decomposed, vec![Rect::new((0, 0), (20, 10))]);
376}
377
378#[test]
379fn test_decompose_rectangles_vertical_touching() {
380 use iron_shapes::prelude::IntoEdges;
381
382 let rects = vec![
383 Rect::new((0i32, 0), (10, 10)),
384 Rect::new((0, 10), (10, 20)),
385 Rect::new((0, 20), (10, 30)),
386 ];
387
388 let decomposed = decompose_rectangles_vertical(rects.iter().flat_map(|r| r.into_edges()));
389 assert_eq!(decomposed, vec![Rect::new((0, 0), (10, 30))]);
390}
391
392#[test]
393fn test_decompose_maximal_rectangles() {
394 use iron_shapes::prelude::*;
395
396 let poly = SimpleRPolygon::try_new([(0, 0), (2, 0), (2, 2), (1, 2), (1, 1), (0, 1)]).unwrap();
402
403 let expected_rects = vec![Rect::new((0, 0), (2, 1)), Rect::new((1, 0), (2, 2))];
404
405 let rects = decompose_maximal_rectangles(poly.edges());
406 assert_eq!(rects, expected_rects);
407
408 let rects = decompose_maximal_rectangles(poly.reversed().edges());
410 assert_eq!(rects, expected_rects);
411}
412
413#[test]
414fn test_decompose_maximal_rectangles_2() {
415 use iron_shapes::prelude::*;
416 let poly = SimpleRPolygon::try_new([
424 (0, 0),
425 (2, 0),
426 (2, 3),
427 (0, 3),
428 (0, 2),
429 (1, 2),
430 (1, 1),
431 (0, 1),
432 ])
433 .unwrap();
434
435 let expected_rects = vec![
436 Rect::new((0, 0), (2, 1)),
437 Rect::new((0, 2), (2, 3)),
438 Rect::new((1, 0), (2, 3)),
439 ];
440
441 let rects = decompose_maximal_rectangles(poly.edges());
442 assert_eq!(rects, expected_rects);
443
444 let rects = decompose_maximal_rectangles(poly.reversed().edges());
446 assert_eq!(rects, expected_rects);
447}