geo/algorithm/relate/
mod.rs

1pub(crate) use edge_end_builder::EdgeEndBuilder;
2pub use geomgraph::intersection_matrix::IntersectionMatrix;
3use relate_operation::RelateOperation;
4
5use crate::geometry::*;
6#[deprecated(
7    since = "0.31.1",
8    note = "PreparedGeometry has moved to geo::indexed::PreparedGeometry"
9)]
10pub use crate::indexed::PreparedGeometry;
11pub use crate::relate::geomgraph::GeometryGraph;
12use crate::{BoundingRect, GeoFloat, GeometryCow, HasDimensions};
13
14mod edge_end_builder;
15pub(crate) mod geomgraph;
16mod relate_operation;
17
18/// Topologically relate two geometries based on [DE-9IM](https://en.wikipedia.org/wiki/DE-9IM) semantics.
19///
20/// See [`IntersectionMatrix`] for details. All predicates are available on the calculated matrix.
21///
22/// # Examples
23///
24/// ```
25/// use geo::{coord, Line, Rect, line_string};
26/// use crate::geo::relate::Relate;
27///
28/// let line = Line::new(coord! { x: 2.0, y: 2.0}, coord! { x: 4.0, y: 4.0 });
29/// let rect = Rect::new(coord! { x: 2.0, y: 2.0}, coord! { x: 4.0, y: 4.0 });
30/// let intersection_matrix = rect.relate(&line);
31///
32/// assert!(intersection_matrix.is_intersects());
33/// assert!(!intersection_matrix.is_disjoint());
34/// assert!(intersection_matrix.is_contains());
35/// assert!(!intersection_matrix.is_within());
36///
37/// let line = Line::new(coord! { x: 1.0, y: 1.0}, coord! { x: 5.0, y: 5.0 });
38/// let rect = Rect::new(coord! { x: 2.0, y: 2.0}, coord! { x: 4.0, y: 4.0 });
39/// let intersection_matrix = rect.relate(&line);
40/// assert!(intersection_matrix.is_intersects());
41/// assert!(!intersection_matrix.is_disjoint());
42/// assert!(!intersection_matrix.is_contains());
43/// assert!(!intersection_matrix.is_within());
44///
45/// let rect_boundary = line_string![
46///     (x: 2.0, y: 2.0),
47///     (x: 4.0, y: 2.0),
48///     (x: 4.0, y: 4.0),
49///     (x: 2.0, y: 4.0),
50///     (x: 2.0, y: 2.0)
51/// ];
52/// let intersection_matrix = rect.relate(&rect_boundary);
53/// assert!(intersection_matrix.is_intersects());
54/// assert!(!intersection_matrix.is_disjoint());
55/// // According to DE-9IM, polygons don't contain their own boundary
56/// assert!(!intersection_matrix.is_contains());
57/// assert!(!intersection_matrix.is_within());
58/// ```
59///
60/// Note: `Relate` must not be called on geometries containing `NaN` coordinates.
61pub trait Relate<F: GeoFloat>: BoundingRect<F> + HasDimensions {
62    /// Returns a noded topology graph for the geometry.
63    ///
64    /// # Params
65    ///
66    /// `idx`: 0 or 1, designating A or B (respectively) in the role this geometry plays
67    ///        in the relation. e.g. in `a.relate(b)`
68    fn geometry_graph(&self, idx: usize) -> GeometryGraph<'_, F>;
69
70    fn relate(&self, other: &impl Relate<F>) -> IntersectionMatrix
71    where
72        Self: Sized,
73    {
74        RelateOperation::new(self, other).compute_intersection_matrix()
75    }
76}
77
78macro_rules! relate_impl {
79    ($($t:ty ,)*) => {
80        $(
81            impl<F: GeoFloat> Relate<F> for $t {
82                fn geometry_graph(&self, arg_index: usize) -> GeometryGraph<'_, F> {
83                    $crate::relate::GeometryGraph::new(arg_index, GeometryCow::from(self))
84                }
85            }
86            impl<F: GeoFloat> From<$t> for PreparedGeometry<'static, $t, F> {
87                fn from(geometry: $t) -> Self {
88                    $crate::indexed::prepared_geometry::prepare_geometry(geometry)
89                }
90            }
91            impl<'a, F: GeoFloat> From<&'a $t> for PreparedGeometry<'a, &'a $t, F> {
92                fn from(geometry: &'a $t) -> Self {
93                    $crate::indexed::prepared_geometry::prepare_geometry(geometry)
94                }
95            }
96        )*
97    };
98}
99
100relate_impl![
101    Point<F>,
102    Line<F>,
103    LineString<F>,
104    Polygon<F>,
105    MultiPoint<F>,
106    MultiLineString<F>,
107    MultiPolygon<F>,
108    Rect<F>,
109    Triangle<F>,
110    GeometryCollection<F>,
111    Geometry<F>,
112];
113
114#[cfg(test)]
115mod tests {
116    #[test]
117    fn run_jts_relate_tests() {
118        jts_test_runner::assert_jts_tests_succeed("*Relate*.xml");
119    }
120}