1use crate::error::Result;
7use oxigdal_core::vector::{Coordinate, LineString, MultiPolygon, Point, Polygon};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum OverlayType {
12 Intersection,
14 Union,
16 Difference,
18 SymmetricDifference,
20 Identity,
22 Update,
24}
25
26#[derive(Debug, Clone)]
28pub struct OverlayOptions {
29 pub tolerance: f64,
31 pub preserve_topology: bool,
33 pub snap_to_grid: bool,
35 pub grid_size: f64,
37 pub simplify_result: bool,
39 pub simplify_tolerance: f64,
41}
42
43impl Default for OverlayOptions {
44 fn default() -> Self {
45 Self {
46 tolerance: 1e-10,
47 preserve_topology: true,
48 snap_to_grid: false,
49 grid_size: 1e-6,
50 simplify_result: false,
51 simplify_tolerance: 1e-8,
52 }
53 }
54}
55
56#[derive(Debug, Clone)]
58struct OverlayEdge {
59 start: Coordinate,
60 end: Coordinate,
61 left_label: EdgeLabel,
62 right_label: EdgeLabel,
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67struct EdgeLabel {
68 in_a: bool,
70 in_b: bool,
72 on_boundary_a: bool,
74 on_boundary_b: bool,
76}
77
78impl EdgeLabel {
79 fn new() -> Self {
80 Self {
81 in_a: false,
82 in_b: false,
83 on_boundary_a: false,
84 on_boundary_b: false,
85 }
86 }
87
88 fn should_include(&self, overlay_type: OverlayType) -> bool {
89 match overlay_type {
90 OverlayType::Intersection => self.in_a && self.in_b,
91 OverlayType::Union => self.in_a || self.in_b,
92 OverlayType::Difference => self.in_a && !self.in_b,
93 OverlayType::SymmetricDifference => self.in_a ^ self.in_b,
94 OverlayType::Identity => self.in_a,
95 OverlayType::Update => {
96 if self.in_b {
97 true
98 } else {
99 self.in_a && !self.on_boundary_a
100 }
101 }
102 }
103 }
104}
105
106struct OverlayGraph {
108 edges: Vec<OverlayEdge>,
109 vertices: Vec<Coordinate>,
110 tolerance: f64,
111}
112
113impl OverlayGraph {
114 fn new(tolerance: f64) -> Self {
115 Self {
116 edges: Vec::new(),
117 vertices: Vec::new(),
118 tolerance,
119 }
120 }
121
122 fn add_polygon(&mut self, polygon: &Polygon, is_a: bool) -> Result<()> {
123 let coords = &polygon.exterior.coords;
125 for i in 0..coords.len().saturating_sub(1) {
126 let start = coords[i];
127 let end = coords[i + 1];
128
129 let mut label = EdgeLabel::new();
130 if is_a {
131 label.in_a = true;
132 label.on_boundary_a = true;
133 } else {
134 label.in_b = true;
135 label.on_boundary_b = true;
136 }
137
138 self.add_edge(start, end, label)?;
139 }
140
141 for interior in &polygon.interiors {
143 let coords = &interior.coords;
144 for i in 0..coords.len().saturating_sub(1) {
145 let start = coords[i];
146 let end = coords[i + 1];
147
148 let mut label = EdgeLabel::new();
149 if is_a {
150 label.in_a = true;
151 label.on_boundary_a = true;
152 } else {
153 label.in_b = true;
154 label.on_boundary_b = true;
155 }
156
157 self.add_edge(start, end, label)?;
158 }
159 }
160
161 Ok(())
162 }
163
164 fn add_edge(&mut self, start: Coordinate, end: Coordinate, label: EdgeLabel) -> Result<()> {
165 if Self::coords_equal(&start, &end, self.tolerance) {
167 return Ok(());
168 }
169
170 let start_idx = self.find_or_add_vertex(start);
172 let end_idx = self.find_or_add_vertex(end);
173
174 if start_idx == end_idx {
175 return Ok(());
176 }
177
178 let edge = OverlayEdge {
180 start: self.vertices[start_idx],
181 end: self.vertices[end_idx],
182 left_label: label,
183 right_label: label,
184 };
185
186 self.edges.push(edge);
187 Ok(())
188 }
189
190 fn find_or_add_vertex(&mut self, coord: Coordinate) -> usize {
191 for (idx, vertex) in self.vertices.iter().enumerate() {
193 if Self::coords_equal(vertex, &coord, self.tolerance) {
194 return idx;
195 }
196 }
197
198 let idx = self.vertices.len();
200 self.vertices.push(coord);
201 idx
202 }
203
204 fn coords_equal(a: &Coordinate, b: &Coordinate, tolerance: f64) -> bool {
205 (a.x - b.x).abs() < tolerance && (a.y - b.y).abs() < tolerance
206 }
207
208 fn compute_intersections(&mut self) -> Result<()> {
209 let n = self.edges.len();
211
212 let mut intersections = Vec::new();
214 for i in 0..n {
215 for j in (i + 1)..n {
216 if let Some(intersection) = self.compute_edge_intersection(i, j)? {
217 intersections.push((i, j, intersection));
218 }
219 }
220 }
221
222 use std::collections::HashMap;
224 let mut edge_splits: HashMap<usize, Vec<Coordinate>> = HashMap::new();
225
226 for (i, j, intersection) in intersections {
227 edge_splits.entry(i).or_default().push(intersection);
228 edge_splits.entry(j).or_default().push(intersection);
229 }
230
231 let mut split_edges = Vec::new();
234 for edge_idx in (0..n).rev() {
235 if let Some(split_points) = edge_splits.get(&edge_idx) {
236 let edge = self.edges[edge_idx].clone();
237
238 let mut points: Vec<Coordinate> = split_points
240 .iter()
241 .filter(|p| {
242 !Self::coords_equal(p, &edge.start, self.tolerance)
243 && !Self::coords_equal(p, &edge.end, self.tolerance)
244 })
245 .copied()
246 .collect();
247
248 if points.is_empty() {
249 continue;
250 }
251
252 points.sort_by(|a, b| {
254 let t_a = if (edge.end.x - edge.start.x).abs() > self.tolerance {
255 (a.x - edge.start.x) / (edge.end.x - edge.start.x)
256 } else {
257 (a.y - edge.start.y) / (edge.end.y - edge.start.y)
258 };
259 let t_b = if (edge.end.x - edge.start.x).abs() > self.tolerance {
260 (b.x - edge.start.x) / (edge.end.x - edge.start.x)
261 } else {
262 (b.y - edge.start.y) / (edge.end.y - edge.start.y)
263 };
264 t_a.partial_cmp(&t_b).unwrap_or(std::cmp::Ordering::Equal)
265 });
266
267 let mut segments = Vec::new();
269 let mut current_start = edge.start;
270 for point in points {
271 segments.push(OverlayEdge {
272 start: current_start,
273 end: point,
274 left_label: edge.left_label,
275 right_label: edge.right_label,
276 });
277 current_start = point;
278 }
279 segments.push(OverlayEdge {
281 start: current_start,
282 end: edge.end,
283 left_label: edge.left_label,
284 right_label: edge.right_label,
285 });
286
287 split_edges.push((edge_idx, segments));
289 }
290 }
291
292 for (edge_idx, segments) in split_edges {
294 self.edges[edge_idx] = segments[0].clone();
295 for segment in segments.into_iter().skip(1) {
296 self.edges.push(segment);
297 }
298 }
299
300 Ok(())
301 }
302
303 fn compute_edge_intersection(&self, i: usize, j: usize) -> Result<Option<Coordinate>> {
304 let e1 = &self.edges[i];
305 let e2 = &self.edges[j];
306
307 let p1 = &e1.start;
308 let p2 = &e1.end;
309 let p3 = &e2.start;
310 let p4 = &e2.end;
311
312 let d = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x);
313
314 if d.abs() < self.tolerance {
315 return Ok(None);
317 }
318
319 let t = ((p1.x - p3.x) * (p3.y - p4.y) - (p1.y - p3.y) * (p3.x - p4.x)) / d;
320 let u = -((p1.x - p2.x) * (p1.y - p3.y) - (p1.y - p2.y) * (p1.x - p3.x)) / d;
321
322 if (0.0..=1.0).contains(&t) && (0.0..=1.0).contains(&u) {
323 let x = p1.x + t * (p2.x - p1.x);
324 let y = p1.y + t * (p2.y - p1.y);
325 Ok(Some(Coordinate::new_2d(x, y)))
326 } else {
327 Ok(None)
328 }
329 }
330
331 fn split_edge_at_point(&mut self, edge_idx: usize, point: Coordinate) -> Result<()> {
332 let edge = self.edges[edge_idx].clone();
333
334 if Self::coords_equal(&edge.start, &point, self.tolerance)
336 || Self::coords_equal(&edge.end, &point, self.tolerance)
337 {
338 return Ok(());
339 }
340
341 let edge1 = OverlayEdge {
343 start: edge.start,
344 end: point,
345 left_label: edge.left_label,
346 right_label: edge.right_label,
347 };
348
349 let edge2 = OverlayEdge {
350 start: point,
351 end: edge.end,
352 left_label: edge.left_label,
353 right_label: edge.right_label,
354 };
355
356 self.edges[edge_idx] = edge1;
358 self.edges.push(edge2);
359
360 Ok(())
361 }
362
363 fn label_edges(&mut self, poly_a: &Polygon, poly_b: &Polygon) -> Result<()> {
364 for edge in &mut self.edges {
366 let mid_x = (edge.start.x + edge.end.x) / 2.0;
368 let mid_y = (edge.start.y + edge.end.y) / 2.0;
369 let midpoint = Point::new(mid_x, mid_y);
370
371 if !edge.left_label.on_boundary_a {
373 edge.left_label.in_a = crate::vector::point_in_polygon(&midpoint.coord, poly_a)?;
374 }
375 if !edge.left_label.on_boundary_b {
380 edge.left_label.in_b = crate::vector::point_in_polygon(&midpoint.coord, poly_b)?;
381 }
382 }
385
386 Ok(())
387 }
388
389 fn extract_result(&self, overlay_type: OverlayType) -> Result<Vec<Polygon>> {
390 let mut result_edges: Vec<&OverlayEdge> = self
392 .edges
393 .iter()
394 .filter(|e| e.left_label.should_include(overlay_type))
395 .collect();
396
397 let mut to_remove = Vec::new();
400 for i in 0..result_edges.len() {
401 if to_remove.contains(&i) {
402 continue;
403 }
404 for j in (i + 1)..result_edges.len() {
405 if to_remove.contains(&j) {
406 continue;
407 }
408 if Self::coords_equal(&result_edges[i].start, &result_edges[j].end, self.tolerance)
410 && Self::coords_equal(
411 &result_edges[i].end,
412 &result_edges[j].start,
413 self.tolerance,
414 )
415 {
416 to_remove.push(j);
418 }
419 }
420 }
421
422 for &idx in to_remove.iter().rev() {
424 result_edges.remove(idx);
425 }
426
427 if result_edges.is_empty() {
428 return Ok(Vec::new());
429 }
430
431 let mut polygons = Vec::new();
433 let mut used = vec![false; result_edges.len()];
434
435 for start_idx in 0..result_edges.len() {
436 if used[start_idx] {
437 continue;
438 }
439
440 let mut coords = Vec::new();
441 let mut current_idx = start_idx;
442 let start_coord = result_edges[start_idx].start;
443
444 loop {
445 if used[current_idx] {
446 break;
447 }
448
449 used[current_idx] = true;
450 let edge = result_edges[current_idx];
451 coords.push(edge.start);
452
453 let next_start = edge.end;
455 if Self::coords_equal(&next_start, &start_coord, self.tolerance) {
456 coords.push(start_coord); break;
458 }
459
460 let mut found_next = false;
462
463 for (idx, e) in result_edges.iter().enumerate() {
464 if !used[idx] && Self::coords_equal(&e.start, &next_start, self.tolerance) {
465 current_idx = idx;
466 found_next = true;
467 break;
468 }
469 }
470
471 if !found_next {
472 break;
473 }
474 }
475
476 if coords.len() >= 4 {
478 if let Ok(exterior) = LineString::new(coords) {
479 if let Ok(polygon) = Polygon::new(exterior, vec![]) {
480 polygons.push(polygon);
481 }
482 }
483 }
484 }
485
486 Ok(polygons)
487 }
488}
489
490pub fn overlay_polygon(
536 poly_a: &Polygon,
537 poly_b: &Polygon,
538 overlay_type: OverlayType,
539 options: &OverlayOptions,
540) -> Result<Vec<Polygon>> {
541 let mut graph = OverlayGraph::new(options.tolerance);
543
544 graph.add_polygon(poly_a, true)?;
546 graph.add_polygon(poly_b, false)?;
547
548 graph.compute_intersections()?;
550
551 graph.label_edges(poly_a, poly_b)?;
553
554 let mut result = graph.extract_result(overlay_type)?;
556
557 if options.simplify_result {
559 result = result
560 .into_iter()
561 .filter_map(|poly| simplify_polygon_result(&poly, options.simplify_tolerance))
562 .collect();
563 }
564
565 Ok(result)
566}
567
568fn simplify_polygon_result(polygon: &Polygon, tolerance: f64) -> Option<Polygon> {
569 use crate::vector::simplify::{SimplifyMethod, simplify_linestring};
570
571 let simplified_exterior =
572 simplify_linestring(&polygon.exterior, tolerance, SimplifyMethod::DouglasPeucker).ok()?;
573
574 let simplified_interiors: Result<Vec<LineString>> = polygon
575 .interiors
576 .iter()
577 .map(|interior| simplify_linestring(interior, tolerance, SimplifyMethod::DouglasPeucker))
578 .collect();
579
580 let simplified_interiors = simplified_interiors.ok()?;
581
582 Polygon::new(simplified_exterior, simplified_interiors).ok()
583}
584
585pub fn overlay_multipolygon(
587 multi_a: &MultiPolygon,
588 multi_b: &MultiPolygon,
589 overlay_type: OverlayType,
590 options: &OverlayOptions,
591) -> Result<MultiPolygon> {
592 let mut result_polygons = Vec::new();
593
594 for poly_a in &multi_a.polygons {
595 for poly_b in &multi_b.polygons {
596 let overlay_result = overlay_polygon(poly_a, poly_b, overlay_type, options)?;
597 result_polygons.extend(overlay_result);
598 }
599 }
600
601 Ok(MultiPolygon::new(result_polygons))
602}
603
604pub fn overlay_geometries(
606 geom_a: &Polygon,
607 geom_b: &Polygon,
608 overlay_type: OverlayType,
609 options: &OverlayOptions,
610) -> Result<Vec<Polygon>> {
611 overlay_polygon(geom_a, geom_b, overlay_type, options)
612}
613
614pub fn overlay_polygon_batch(
616 pairs: &[(Polygon, Polygon)],
617 overlay_type: OverlayType,
618 options: &OverlayOptions,
619) -> Result<Vec<Vec<Polygon>>> {
620 pairs
621 .iter()
622 .map(|(a, b)| overlay_polygon(a, b, overlay_type, options))
623 .collect()
624}
625
626#[cfg(test)]
627mod tests {
628 use super::*;
629
630 fn create_square(x: f64, y: f64, size: f64) -> Polygon {
631 let coords = vec![
632 Coordinate::new_2d(x, y),
633 Coordinate::new_2d(x + size, y),
634 Coordinate::new_2d(x + size, y + size),
635 Coordinate::new_2d(x, y + size),
636 Coordinate::new_2d(x, y),
637 ];
638 let exterior = LineString::new(coords).expect("Failed to create linestring");
639 Polygon::new(exterior, vec![]).expect("Failed to create polygon")
640 }
641
642 #[test]
643 fn test_overlay_intersection() {
644 let poly1 = create_square(0.0, 0.0, 10.0);
645 let poly2 = create_square(5.0, 5.0, 10.0);
646
647 let result = overlay_polygon(
648 &poly1,
649 &poly2,
650 OverlayType::Intersection,
651 &OverlayOptions::default(),
652 );
653
654 assert!(result.is_ok());
655 let polygons = result.expect("Overlay failed");
656 assert!(!polygons.is_empty());
657 }
658
659 #[test]
660 fn test_overlay_union() {
661 let poly1 = create_square(0.0, 0.0, 10.0);
662 let poly2 = create_square(5.0, 5.0, 10.0);
663
664 let result = overlay_polygon(
665 &poly1,
666 &poly2,
667 OverlayType::Union,
668 &OverlayOptions::default(),
669 );
670
671 assert!(result.is_ok());
672 let polygons = result.expect("Overlay failed");
673 assert!(!polygons.is_empty());
674 }
675
676 #[test]
677 fn test_overlay_difference() {
678 let poly1 = create_square(0.0, 0.0, 10.0);
679 let poly2 = create_square(5.0, 5.0, 10.0);
680
681 let result = overlay_polygon(
682 &poly1,
683 &poly2,
684 OverlayType::Difference,
685 &OverlayOptions::default(),
686 );
687
688 assert!(result.is_ok());
689 }
690
691 #[test]
692 fn test_overlay_non_overlapping() {
693 let poly1 = create_square(0.0, 0.0, 5.0);
694 let poly2 = create_square(10.0, 10.0, 5.0);
695
696 let result = overlay_polygon(
697 &poly1,
698 &poly2,
699 OverlayType::Intersection,
700 &OverlayOptions::default(),
701 );
702
703 assert!(result.is_ok());
704 let polygons = result.expect("Overlay failed");
705 assert!(polygons.is_empty()); }
707
708 #[test]
709 fn test_edge_label_logic() {
710 let label = EdgeLabel::new();
711 assert!(!label.should_include(OverlayType::Intersection));
712
713 let mut label = EdgeLabel::new();
714 label.in_a = true;
715 label.in_b = true;
716 assert!(label.should_include(OverlayType::Intersection));
717 assert!(label.should_include(OverlayType::Union));
718 assert!(!label.should_include(OverlayType::Difference));
719 }
720
721 #[test]
722 fn test_overlay_batch() {
723 let poly1 = create_square(0.0, 0.0, 10.0);
724 let poly2 = create_square(5.0, 5.0, 10.0);
725 let poly3 = create_square(10.0, 0.0, 10.0);
726
727 let pairs = vec![(poly1.clone(), poly2), (poly1, poly3)];
728
729 let result = overlay_polygon_batch(
730 &pairs,
731 OverlayType::Intersection,
732 &OverlayOptions::default(),
733 );
734
735 assert!(result.is_ok());
736 let results = result.expect("Batch overlay failed");
737 assert_eq!(results.len(), 2);
738 }
739}