Skip to content

Commit

Permalink
Merge branch 'main' into kyle/geo-traits-crate
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron authored Oct 12, 2024
2 parents 03f6615 + 2a55920 commit 31435e8
Show file tree
Hide file tree
Showing 10 changed files with 1,285 additions and 11 deletions.
5 changes: 5 additions & 0 deletions geo/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
Haversine::distance(p1, p2)
```
* <https://github.com/georust/geo/pull/1216>
* Change IntersectionMatrix::is_equal_topo to now consider empty geometries as equal.
* <https://github.com/georust/geo/pull/1223>
* Fix `(LINESTRING EMPTY).contains(LINESTRING EMPTY)` and `(MULTIPOLYGON EMPTY).contains(MULTIPOINT EMPTY)` which previously
reported true
* <https://github.com/georust/geo/pull/1227>

## 0.28.0

Expand Down
96 changes: 94 additions & 2 deletions geo/benches/contains.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use criterion::{criterion_group, criterion_main, Criterion};
use geo::contains::Contains;
use geo::{coord, point, polygon, Line, Point, Polygon, Rect, Triangle};
use geo::algorithm::{Contains, Convert, Relate};
use geo::geometry::*;
use geo::{coord, point, polygon};

fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("point in simple polygon", |bencher| {
Expand Down Expand Up @@ -145,6 +146,97 @@ fn criterion_benchmark(c: &mut Criterion) {
assert!(criterion::black_box(&rect).contains(criterion::black_box(&polygon)));
});
});

c.bench_function(
"LineString not contains LineString (Contains trait)",
|bencher| {
let ls_1: geo::LineString<f64> = geo_test_fixtures::poly1();
let ls_2: geo::LineString<f64> = geo_test_fixtures::poly2();

bencher.iter(|| {
assert!(!ls_1.contains(&ls_2));
});
},
);

c.bench_function(
"LineString not contains LineString (Relate trait)",
|bencher| {
let ls_1: geo::LineString<f64> = geo_test_fixtures::poly1();
let ls_2: geo::LineString<f64> = geo_test_fixtures::poly2();

bencher.iter(|| {
assert!(!ls_1.relate(&ls_2).is_contains());
});
},
);

c.bench_function(
"LineString contains LineString (Contains trait)",
|bencher| {
let ls_1: LineString<f64> = geo_test_fixtures::poly1();
let mut ls_2 = LineString::new(ls_1.0[1..].to_vec());
ls_2.0.pop();

bencher.iter(|| {
assert!(ls_1.contains(&ls_2));
});
},
);

c.bench_function("LineString contains LineString (Relate trait)", |bencher| {
let ls_1: geo::LineString<f64> = geo_test_fixtures::poly1();
let mut ls_2 = LineString::new(ls_1.0[1..].to_vec());
ls_2.0.pop();

bencher.iter(|| {
assert!(ls_1.relate(&ls_2).is_contains());
});
});

c.bench_function("MultiPolygon contains MultiPoint (Contains trait)", |bencher| {
let p_1: Polygon<f64> = Polygon::new(geo_test_fixtures::poly1(), vec![]);
let p_2: Polygon<f64> = Polygon::new(geo_test_fixtures::poly2(), vec![]);
let multi_poly = MultiPolygon(vec![p_1, p_2]);
let multi_point: MultiPoint<f64> = geo::wkt!(MULTIPOINT (-60 10,-60 -70,-120 -70,-120 10,-40 80,30 80,30 10,-40 10,100 210,100 120,30 120,30 210,-185 -135,-100 -135,-100 -230,-185 -230)).convert();

bencher.iter(|| {
assert!(multi_poly.contains(&multi_point));
});
});

c.bench_function("MultiPolygon contains MultiPoint (Relate trait)", |bencher| {
let p_1: Polygon<f64> = Polygon::new(geo_test_fixtures::poly1(), vec![]);
let p_2: Polygon<f64> = Polygon::new(geo_test_fixtures::poly2(), vec![]);
let multi_poly = MultiPolygon(vec![p_1, p_2]);
let multi_point: MultiPoint<f64> = geo::wkt!(MULTIPOINT (-60 10,-60 -70,-120 -70,-120 10,-40 80,30 80,30 10,-40 10,100 210,100 120,30 120,30 210,-185 -135,-100 -135,-100 -230,-185 -230)).convert();

bencher.iter(|| {
assert!(multi_poly.relate(&multi_point).is_contains());
});
});

c.bench_function("MultiPolygon not contains MultiPoint (Contains trait)", |bencher| {
let p_1: Polygon<f64> = Polygon::new(geo_test_fixtures::poly1(), vec![]);
let p_2: Polygon<f64> = Polygon::new(geo_test_fixtures::poly2(), vec![]);
let multi_poly = MultiPolygon(vec![p_1, p_2]);
let multi_point: MultiPoint<f64> = geo::wkt!(MULTIPOINT (-160 10,-60 -70,-120 -70,-120 10,-40 80,30 80,30 10,-40 10,100 210,100 120,30 120,30 210,-185 -135,-100 -135,-100 -230,-185 -230)).convert();

bencher.iter(|| {
assert!(multi_poly.contains(&multi_point));
});
});

c.bench_function("MultiPolygon not contains MultiPoint (Relate trait)", |bencher| {
let p_1: Polygon<f64> = Polygon::new(geo_test_fixtures::poly1(), vec![]);
let p_2: Polygon<f64> = Polygon::new(geo_test_fixtures::poly2(), vec![]);
let multi_poly = MultiPolygon(vec![p_1, p_2]);
let multi_point: MultiPoint<f64> = geo::wkt!(MULTIPOINT (-160 10,-60 -70,-120 -70,-120 10,-40 80,30 80,30 10,-40 10,100 210,100 120,30 120,30 210,-185 -135,-100 -135,-100 -230,-185 -230)).convert();

bencher.iter(|| {
assert!(multi_poly.relate(&multi_point).is_contains());
});
});
}

criterion_group!(benches, criterion_benchmark);
Expand Down
5 changes: 4 additions & 1 deletion geo/src/algorithm/contains/line_string.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{impl_contains_from_relate, impl_contains_geometry_for, Contains};
use crate::algorithm::Intersects;
use crate::geometry::*;
use crate::{CoordNum, GeoFloat, GeoNum};
use crate::{CoordNum, GeoFloat, GeoNum, HasDimensions};

// ┌────────────────────────────────┐
// │ Implementations for LineString │
Expand Down Expand Up @@ -110,6 +110,9 @@ where
T: GeoNum,
{
fn contains(&self, rhs: &LineString<T>) -> bool {
if self.is_empty() || rhs.is_empty() {
return false;
}
rhs.lines().all(|l| self.contains(&l))
}
}
Expand Down
5 changes: 4 additions & 1 deletion geo/src/algorithm/contains/polygon.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{impl_contains_from_relate, impl_contains_geometry_for, Contains};
use crate::geometry::*;
use crate::Relate;
use crate::{GeoFloat, GeoNum};
use crate::{HasDimensions, Relate};

// ┌─────────────────────────────┐
// │ Implementations for Polygon │
Expand Down Expand Up @@ -53,6 +53,9 @@ where

impl<T: GeoNum> Contains<MultiPoint<T>> for MultiPolygon<T> {
fn contains(&self, rhs: &MultiPoint<T>) -> bool {
if self.is_empty() || rhs.is_empty() {
return false;
}
rhs.iter().all(|point| self.contains(point))
}
}
Expand Down
12 changes: 12 additions & 0 deletions geo/src/algorithm/relate/geomgraph/intersection_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,11 @@ impl IntersectionMatrix {
/// - Matches `[T*F**FFF*]`
/// - This predicate is **reflexive, symmetric, and transitive**
pub fn is_equal_topo(&self) -> bool {
if self == &Self::empty_disjoint() {
// Any two empty geometries are topologically equal
return true;
}

self.0[CoordPos::Inside][CoordPos::Inside] != Dimensions::Empty
&& self.0[CoordPos::Inside][CoordPos::Outside] == Dimensions::Empty
&& self.0[CoordPos::Outside][CoordPos::Inside] == Dimensions::Empty
Expand Down Expand Up @@ -754,4 +759,11 @@ mod tests {
fn matches_wildcard() {
assert!(subject().matches("F0011122*").unwrap());
}

#[test]
fn empty_is_equal_topo() {
let empty_polygon = Polygon::<f64>::new(LineString::new(vec![]), vec![]);
let im = empty_polygon.relate(&empty_polygon);
assert!(im.is_equal_topo());
}
}
Loading

0 comments on commit 31435e8

Please sign in to comment.