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}