Skip to content

Commit

Permalink
Fix orientation of boolops geometries
Browse files Browse the repository at this point in the history
Use reverse instead of Orient since we know its always backwards. This should be a little faster, since we don't have to determine the
current winding - we already know it.
  • Loading branch information
urschrei committed Jan 31, 2025
1 parent ef55eab commit c086485
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 8 deletions.
2 changes: 2 additions & 0 deletions geo/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
println!("{}", errors[0]);
```
- BREAKING: update proj to 0.28.0
- Polygons returned by Boolean Ops are now oriented correctly (ccw shell, cw inner rings)
- <https://github.com/georust/geo/pull/1310>

## 0.29.3 - 2024.12.03

Expand Down
66 changes: 63 additions & 3 deletions geo/src/algorithm/bool_ops/i_overlay_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,16 @@ pub(super) mod convert {
}

pub fn polygon_from_shape<T: BoolOpsNum>(shape: Vec<Vec<BoolOpsCoord<T>>>) -> Polygon<T> {
let mut rings = shape.into_iter().map(|p| line_string_from_path(p));
let mut rings = shape.into_iter().map(|path| {
// From i_overlay: > Note: Outer boundary paths have a clockwise order, and holes have a counterclockwise order.
// Which is the opposite convention we use.
let mut line_string = line_string_from_path(path);
line_string.close();
line_string.0.reverse();
line_string
});
let exterior = rings.next().unwrap_or(LineString::new(vec![]));

Polygon::new(exterior, rings.collect())
}

Expand Down Expand Up @@ -82,9 +90,61 @@ pub(super) mod convert {

#[cfg(test)]
mod tests {
use geo_types::polygon;

use crate::algorithm::BooleanOps;
use crate::geometry::{MultiPolygon, Polygon};
use crate::wkt;
use crate::winding_order::WindingOrder;
use crate::{wkt, Winding};

#[test]
// see https://github.com/georust/geo/issues/1309
fn test_winding_order() {
let poly1 = polygon!((x: 0.0, y: 0.0), (x: 1.0, y: 0.0), (x: 1.0, y: 1.0));
assert!(matches!(
poly1.exterior().winding_order(),
Some(WindingOrder::CounterClockwise)
));

{
let union = poly1.union(&polygon!());
assert_eq!(union.0.len(), 1);

let union = &union.0[0];
assert!(matches!(
union.exterior().winding_order(),
Some(WindingOrder::CounterClockwise)
));
}
{
let intersection = poly1.intersection(&poly1);
assert_eq!(intersection.0.len(), 1);

let intersection = &intersection.0[0];
assert!(matches!(
intersection.exterior().winding_order(),
Some(WindingOrder::CounterClockwise)
));
}

let poly2 = polygon!((x: 0.0, y: 0.0), (x: 1.0, y: 1.0), (x: 0.0, y: 1.0));
assert!(matches!(
poly2.exterior().winding_order(),
Some(WindingOrder::CounterClockwise)
));

{
let union = poly1.union(&poly2);
assert_eq!(union.0.len(), 1);

let union = &union.0[0];
assert!(union.interiors().is_empty());
assert!(matches!(
union.exterior().winding_order(),
Some(WindingOrder::CounterClockwise)
));
}
}

#[test]
fn two_empty_polygons() {
Expand All @@ -96,7 +156,7 @@ mod tests {

#[test]
fn one_empty_polygon() {
let p1: Polygon = wkt!(POLYGON((0. 0., 0. 1., 1. 1., 1. 0., 0. 0.)));
let p1: Polygon = wkt!(POLYGON((0.0 0.0,1.0 0.0,1.0 1.0,0.0 1.0,0.0 0.0)));
let p2: Polygon = wkt!(POLYGON EMPTY);
assert_eq!(&p1.union(&p2), &MultiPolygon(vec![p1.clone()]));
assert_eq!(&p1.intersection(&p2), &wkt!(MULTIPOLYGON EMPTY));
Expand Down
4 changes: 2 additions & 2 deletions geo/src/algorithm/bool_ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ pub enum OpType {
///
/// let expected_output = wkt!(MULTIPOLYGON(
/// // left and right piece have been combined
/// ((0. 0., 0. 4., 8. 4., 8. 0., 0. 0.)),
/// ((0.0 0.0, 8.0 0.0, 8.0 4.0, 0.0 4.0, 0.0 0.0)),
/// // separate piece remains separate
/// ((14. 10., 14. 14., 18. 14.,18. 10., 14. 10.))
/// ((14.0 10.0, 18.0 10.0, 18.0 14.0, 14.0 14.0, 14.0 10.0))
/// ));
/// assert_eq!(actual_output, expected_output);
/// ```
Expand Down
6 changes: 3 additions & 3 deletions geo/src/algorithm/bool_ops/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,15 +352,15 @@ mod gh_issues {
let expected_c = wkt!(MULTIPOLYGON(
((
-22.058823 - 3.623188,
-19.458324 - 3.623188,
-19.064932 - 6.57369,
-19.458324 - 3.623188,
-22.058823 - 3.623188
)),
((
-17.60358 - 8.013862,
-14.705883 - 7.649791,
-14.705883 - 7.6497912,
-17.60358 - 8.013863,
-14.705883 - 7.6497912,
-14.705883 - 7.649791,
-17.60358 - 8.013862
))
));
Expand Down

0 comments on commit c086485

Please sign in to comment.