Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 74 additions & 2 deletions geo-benches/src/contains_properly.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,77 @@
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use geo::PreparedGeometry;
use geo::algorithm::{ContainsProperly, Convert, Relate};
use geo::algorithm::{Contains, ContainsProperly, Convert, Relate};
use geo::wkt;
use geo::{coord, geometry::*};
use std::iter::once;

fn coord_in_line(c: &mut Criterion) {
{
let mut group = c.benchmark_group("multipoint");
let line = Line::new(coord! {x:10.,y:10.}, coord! {x:0.,y:0.});
let point: MultiPoint<f64> = MultiPoint::new(
std::iter::successors(Some((0.1, 0.1)), |(x, y)| Some((x + 0.1, y + 0.1)))
.take_while(|(x, _y)| *x < 10.0)
.map(|(x, y)| Point::new(x, y))
.collect::<Vec<_>>(),
);

group.bench_function("contains multipoint (Trait)", |bencher| {
bencher.iter(|| {
assert!(criterion::black_box(&line).contains(criterion::black_box(&point)));
});
});
group.bench_function("contains_properly multipoint (Trait)", |bencher| {
bencher.iter(|| {
assert!(
criterion::black_box(&line).contains_properly(criterion::black_box(&point))
);
});
});
group.finish();
}
{
let mut group = c.benchmark_group("mid");
let line = Line::new(coord! {x:0.,y:0.}, coord! {x:10.,y:10.});
let c = coord! {x:5.,y:5.};
let point = Point::new(5., 5.);

group.bench_function("contains pt (Trait)", |bencher| {
bencher.iter(|| {
assert!(criterion::black_box(&line).contains(criterion::black_box(&c)));
});
});
group.bench_function("contains_properly pt (Trait)", |bencher| {
bencher.iter(|| {
assert!(
criterion::black_box(&line).contains_properly(criterion::black_box(&point))
);
});
});
group.finish();
}
{
let mut group = c.benchmark_group("end");
let line = Line::new(coord! {x:0.,y:0.}, coord! {x:10.,y:10.});
let c = coord! {x:5.,y:5.};
let point = Point::new(5., 5.);

group.bench_function("contains pt (Trait)", |bencher| {
bencher.iter(|| {
assert!(criterion::black_box(&line).contains(criterion::black_box(&c)));
});
});
group.bench_function("contains_properly pt (Trait)", |bencher| {
bencher.iter(|| {
assert!(
criterion::black_box(&line).contains_properly(criterion::black_box(&point))
);
});
});
group.finish();
}
}

fn compare_simple_in_complex(c: &mut Criterion) {
c.bench_function(
"complex polygon contains_properly polygon (Trait)",
Expand Down Expand Up @@ -192,7 +259,12 @@ fn polygon_polygon_scaling(c: &mut Criterion) {
}
}

criterion_group!(benches, compare_simple_in_complex, compare_poly_in_poly,);
criterion_group!(
benches,
compare_simple_in_complex,
compare_poly_in_poly,
coord_in_line
);
criterion_group!(benches_scaling, polygon_polygon_scaling);

criterion_main!(benches, benches_scaling);
2 changes: 1 addition & 1 deletion geo/src/algorithm/contains_properly/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ where
impl_contains_properly_geometry_for!(Point<T>);
impl_contains_properly_geometry_for!(MultiPoint<T>);

impl_contains_properly_geometry_for!(Line<T>);
// impl_contains_properly_geometry_for!(Line<T>);
impl_contains_properly_geometry_for!(LineString<T>);
impl_contains_properly_geometry_for!(MultiLineString<T>);

Expand Down
41 changes: 32 additions & 9 deletions geo/src/algorithm/contains_properly/line.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
use super::{ContainsProperly, impl_contains_properly_from_relate};
use crate::GeoFloat;
use super::{ContainsProperly, value_in_range_exclusive};
use crate::algorithm::kernels::Kernel;
use crate::geometry::*;
use crate::{BoundingRect, CoordsIter, GeoNum, HasDimensions, Orientation};

impl_contains_properly_from_relate!(Line<T>, [
Point<T>,MultiPoint<T>,
Line<T>, LineString<T>, MultiLineString<T>,
Polygon<T>,MultiPolygon<T>,
GeometryCollection<T>,
Rect<T>,Triangle<T>
]);
impl<G, T> ContainsProperly<G> for Line<T>
where
T: GeoNum,
G: CoordsIter<Scalar = T> + HasDimensions + BoundingRect<T>,
{
fn contains_properly(&self, rhs: &G) -> bool {
if HasDimensions::is_empty(rhs) {
return false;
}

// orient the bounds once
let x_bound = if self.start.x < self.end.x {
(self.start.x, self.end.x)
} else {
(self.end.x, self.start.x)
};
let y_bound = if self.start.y < self.end.y {
(self.start.y, self.end.y)
} else {
(self.end.y, self.start.y)
};

rhs.coords_iter().all(|c| {
value_in_range_exclusive(c.x, x_bound.0, x_bound.1)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find any tests for line.contains_properly — that was my mistake from the original PR review. Can you add some now?

&& value_in_range_exclusive(c.y, y_bound.0, y_bound.1)
&& T::Ker::orient2d(self.start, self.end, c) == Orientation::Collinear
})
}
}
10 changes: 10 additions & 0 deletions geo/src/algorithm/contains_properly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ macro_rules! impl_contains_properly_geometry_for {
}
use impl_contains_properly_geometry_for;

// Helper function to check value lies between min and max.
// Only makes sense if min <= max (or always false)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a debug_assert to enforce a calling contract.

#[inline]
fn value_in_range_exclusive<T>(value: T, min: T, max: T) -> bool
where
T: std::cmp::PartialOrd,
{
value > min && value < max
}

#[cfg(test)]
mod test {
use super::*;
Expand Down