geo/algorithm/monotone/
mod.rs

1mod mono_poly;
2use crate::{Coord, GeoNum, Intersects, MultiPolygon, Polygon};
3pub use mono_poly::MonoPoly;
4
5mod segment;
6use segment::RcSegment;
7pub(crate) use segment::Segment;
8
9mod sweep;
10pub(crate) use sweep::SimpleSweep;
11
12mod builder;
13pub use builder::monotone_subdivision;
14
15/// A multi-polygon represented as a collection of (disjoint) monotone polygons.
16///
17/// This structure is optimized for point-in-polygon queries, and is typically
18/// much faster than the equivalent method on `Polygon`.  This is because a
19/// single monotone polygon can be tested for intersection with a point in
20/// `O(log n)` time, where `n` is the number of vertices in the polygon.  In
21/// contrast, the equivalent method on `Polygon` is `O(n)`.  Typically, a
22/// polygon can be sub-divided into a small number of monotone polygons, thus
23/// providing a significant speed-up.
24///
25/// # Example
26///
27/// Construct a `MonotonicPolygons` from a `Polygon`, or a `MultiPolygon` using
28/// `MontonicPolygons::from`, and query point intersection via the
29/// `Intersects<Coord>` trait.
30///
31/// ```rust
32/// use geo::prelude::*;
33/// use geo::{polygon, coord};
34///
35/// let polygon = polygon![
36///     (x: -2., y: 1.),
37///     (x: 1., y: 3.),
38///     (x: 4., y: 1.),
39///     (x: 1., y: -1.),
40///     (x: -2., y: 1.),
41/// ];
42/// let mp = MonotonicPolygons::from(polygon);
43/// assert!(mp.intersects(&coord!(x: -2., y: 1.)));
44/// ```
45#[derive(Clone, Debug)]
46pub struct MonotonicPolygons<T: GeoNum>(Vec<MonoPoly<T>>);
47
48impl<T: GeoNum> MonotonicPolygons<T> {
49    /// Get a reference to the monotone polygons.
50    pub fn subdivisions(&self) -> &Vec<MonoPoly<T>> {
51        &self.0
52    }
53
54    /// Reduce to inner `Vec` of monotone polygons.
55    pub fn into_subdivisions(self) -> Vec<MonoPoly<T>> {
56        self.0
57    }
58}
59impl<T: GeoNum> From<Polygon<T>> for MonotonicPolygons<T> {
60    fn from(poly: Polygon<T>) -> Self {
61        Self(monotone_subdivision([poly]))
62    }
63}
64
65impl<T: GeoNum> From<MultiPolygon<T>> for MonotonicPolygons<T> {
66    fn from(mp: MultiPolygon<T>) -> Self {
67        Self(monotone_subdivision(mp.0))
68    }
69}
70
71impl<T: GeoNum> Intersects<Coord<T>> for MonotonicPolygons<T> {
72    fn intersects(&self, other: &Coord<T>) -> bool {
73        self.0.iter().any(|mp| mp.intersects(other))
74    }
75}
76
77#[cfg(test)]
78mod tests;