geo/algorithm/monotone/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
mod mono_poly;
use crate::{Coord, GeoNum, Intersects, MultiPolygon, Polygon};
pub use mono_poly::MonoPoly;

mod segment;
use segment::RcSegment;
pub(crate) use segment::Segment;

mod sweep;
pub(crate) use sweep::SimpleSweep;

mod builder;
pub use builder::monotone_subdivision;

/// A multi-polygon represented as a collection of (disjoint) monotone polygons.
///
/// This structure is optimized for point-in-polygon queries, and is typically
/// much faster than the equivalent method on `Polygon`.  This is because a
/// single monotone polygon can be tested for intersection with a point in
/// `O(log n)` time, where `n` is the number of vertices in the polygon.  In
/// contrast, the equivalent method on `Polygon` is `O(n)`.  Typically, a
/// polygon can be sub-divided into a small number of monotone polygons, thus
/// providing a significant speed-up.
///
/// # Example
///
/// Construct a `MonotonicPolygons` from a `Polygon`, or a `MultiPolygon` using
/// `MontonicPolygons::from`, and query point intersection via the
/// `Intersects<Coord>` trait.
///
/// ```rust
/// use geo::prelude::*;
/// use geo::{polygon, coord};
///
/// let polygon = polygon![
///     (x: -2., y: 1.),
///     (x: 1., y: 3.),
///     (x: 4., y: 1.),
///     (x: 1., y: -1.),
///     (x: -2., y: 1.),
/// ];
/// let mp = MonotonicPolygons::from(polygon);
/// assert!(mp.intersects(&coord!(x: -2., y: 1.)));
/// ```
#[derive(Clone, Debug)]
pub struct MonotonicPolygons<T: GeoNum>(Vec<MonoPoly<T>>);

impl<T: GeoNum> MonotonicPolygons<T> {
    /// Get a reference to the monotone polygons.
    pub fn subdivisions(&self) -> &Vec<MonoPoly<T>> {
        &self.0
    }

    /// Reduce to inner `Vec` of monotone polygons.
    pub fn into_subdivisions(self) -> Vec<MonoPoly<T>> {
        self.0
    }
}
impl<T: GeoNum> From<Polygon<T>> for MonotonicPolygons<T> {
    fn from(poly: Polygon<T>) -> Self {
        Self(monotone_subdivision([poly]))
    }
}

impl<T: GeoNum> From<MultiPolygon<T>> for MonotonicPolygons<T> {
    fn from(mp: MultiPolygon<T>) -> Self {
        Self(monotone_subdivision(mp.0))
    }
}

impl<T: GeoNum> Intersects<Coord<T>> for MonotonicPolygons<T> {
    fn intersects(&self, other: &Coord<T>) -> bool {
        self.0.iter().any(|mp| mp.intersects(other))
    }
}

#[cfg(test)]
mod tests;