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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
use crate::vector::Geometry;
/// # Geometric Predicates
///
/// These methods provide common [spatial relations](https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates) between
/// two geometries.
impl Geometry {
/// Tests if two geometries [_intersect_][DE-9IM];
/// `self` and `other` have at least one point in common.
///
/// If GEOS is enabled, then this is done in rigorous fashion, otherwise `true` is returned
/// if the envelopes (bounding boxes) of the two geometries overlap. Check with [`VersionInfo::has_geos`][has_geos].
///
/// See: [`OGR_G_Intersects`][OGR_G_Intersects]
///
/// [DE-9IM]: https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates
/// [OGR_G_Intersects]: https://gdal.org/api/vector_c_api.html#ogr__api_8h_1acaed6926b75cd33a42b284c10def6e87
/// [has_geos]: crate::version::VersionInfo::has_geos
pub fn intersects(&self, other: &Self) -> bool {
let p = unsafe { gdal_sys::OGR_G_Intersects(self.c_geometry(), other.c_geometry()) };
p != 0
}
/// Tests if this geometry [_contains_][DE-9IM] the other geometry;
/// `other` lies in `self`, and the interiors intersect.
///
/// # Notes
/// * Geometry validity is not checked, and invalid geometry will generate unpredictable results.
/// Use [`Geometry::is_valid`] if validity might be in question.
/// * If GEOS is *not* enabled, this function will always return `false`. Check with [`VersionInfo::has_geos`][has_geos].
///
/// See: [`OGR_G_Contains`][OGR_G_Contains]
///
/// [DE-9IM]: https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates
/// [OGR_G_Contains]: https://gdal.org/api/vector_c_api.html#_CPPv414OGR_G_Contains12OGRGeometryH12OGRGeometryH
/// [has_geos]: crate::version::VersionInfo::has_geos
pub fn contains(&self, other: &Self) -> bool {
let p = unsafe { gdal_sys::OGR_G_Contains(self.c_geometry(), other.c_geometry()) };
p != 0
}
/// Tests if this geometry and the other geometry are [_disjoint_][DE-9IM];
/// `self` and `other` form a set of disconnected geometries.
///
/// # Notes
/// * Geometry validity is not checked, and invalid geometry will generate unpredictable results.
/// Use [`Geometry::is_valid`] if validity might be in question.
/// * If GEOS is *not* enabled, this function will always return `false`. Check with [`VersionInfo::has_geos`][has_geos].
///
/// See: [`OGR_G_Disjoint`][OGR_G_Disjoint]
///
/// [DE-9IM]: https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates
/// [OGR_G_Disjoint]: https://gdal.org/api/vector_c_api.html#_CPPv414OGR_G_Disjoint12OGRGeometryH12OGRGeometryH
/// [has_geos]: crate::version::VersionInfo::has_geos
pub fn disjoint(&self, other: &Self) -> bool {
let p = unsafe { gdal_sys::OGR_G_Disjoint(self.c_geometry(), other.c_geometry()) };
p != 0
}
/// Tests if this geometry and the other geometry are [_touching_][DE-9IM];
/// `self` and `other` have at least one point in common, but their interiors do not intersect.
///
/// # Notes
/// * Geometry validity is not checked, and invalid geometry will generate unpredictable results.
/// Use [`Geometry::is_valid`] if validity might be in question.
/// * If GEOS is *not* enabled, this function will always return `false`. Check with [`VersionInfo::has_geos`][has_geos].
///
/// See: [`OGR_G_Touches`][OGR_G_Touches]
///
/// [DE-9IM]: https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates
/// [OGR_G_Touches]: https://gdal.org/api/ogrgeometry_cpp.html#_CPPv4NK11OGRGeometry7TouchesEPK11OGRGeometry
/// [has_geos]: crate::version::VersionInfo::has_geos
pub fn touches(&self, other: &Self) -> bool {
let p = unsafe { gdal_sys::OGR_G_Touches(self.c_geometry(), other.c_geometry()) };
p != 0
}
/// Tests if this geometry and the other geometry are [_crossing_][DE-9IM];
/// `self` and `other` have some but not all interior points in common, and the dimension of
/// the intersection is less than that of at least one of them.
///
/// # Notes
/// * Geometry validity is not checked, and invalid geometry will generate unpredictable results.
/// Use [`Geometry::is_valid`] if validity might be in question.
/// * If GEOS is *not* enabled, this function will always return `false`. Check with [`VersionInfo::has_geos`][has_geos].
///
/// See: [`OGR_G_Crosses`][OGR_G_Crosses]
///
/// [DE-9IM]: https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates
/// [OGR_G_Crosses]: https://gdal.org/api/ogrgeometry_cpp.html#_CPPv4NK11OGRGeometry7CrossesEPK11OGRGeometry
/// [has_geos]: crate::version::VersionInfo::has_geos
pub fn crosses(&self, other: &Self) -> bool {
let p = unsafe { gdal_sys::OGR_G_Crosses(self.c_geometry(), other.c_geometry()) };
p != 0
}
/// Tests if this geometry is [_within_][DE-9IM] the other;
/// `self` lies fully in the interior of `other`.
///
/// # Notes
/// * Geometry validity is not checked, and invalid geometry will generate unpredictable results.
/// Use [`Geometry::is_valid`] if validity might be in question.
/// * If GEOS is *not* enabled, this function will always return `false`. Check with [`VersionInfo::has_geos`][has_geos].
///
/// See: [`OGR_G_Within`][OGR_G_Within]
///
/// [DE-9IM]: https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates
/// [OGR_G_Within]: https://gdal.org/api/ogrgeometry_cpp.html#_CPPv4NK11OGRGeometry6WithinEPK11OGRGeometry
/// [has_geos]: crate::version::VersionInfo::has_geos
pub fn within(&self, other: &Self) -> bool {
let p = unsafe { gdal_sys::OGR_G_Within(self.c_geometry(), other.c_geometry()) };
p != 0
}
/// Tests if this geometry and the other [_overlap_][DE-9IM];
/// `self` and `other` they have some but not all points in common,
/// they have the same dimension,
/// and the intersection of the interiors has the same dimension as the geometries.
///
/// # Notes
/// * Geometry validity is not checked, and invalid geometry will generate unpredictable results.
/// Use [`Geometry::is_valid`] if validity might be in question.
/// * If GEOS is *not* enabled, this function will always return `false`. Check with [`VersionInfo::has_geos`][has_geos].
///
/// See: [`OGR_G_Overlaps`][OGR_G_Overlaps]
///
/// [DE-9IM]: https://en.wikipedia.org/wiki/DE-9IM#Spatial_predicates
/// [OGR_G_Overlaps]: https://gdal.org/api/ogrgeometry_cpp.html#_CPPv4NK11OGRGeometry8OverlapsEPK11OGRGeometry
/// [has_geos]: crate::version::VersionInfo::has_geos
pub fn overlaps(&self, other: &Self) -> bool {
let p = unsafe { gdal_sys::OGR_G_Overlaps(self.c_geometry(), other.c_geometry()) };
p != 0
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_intersects() {
let poly = Geometry::from_wkt("POLYGON((0 0,5 5,10 0,0 0))").unwrap();
let point = Geometry::from_wkt("POINT(10 0)").unwrap();
assert!(poly.intersects(&point));
}
#[test]
fn test_contains() {
let poly = Geometry::from_wkt("POLYGON((0 0,5 5,10 0,0 0))").unwrap();
let point = Geometry::from_wkt("POINT(10 0)").unwrap();
assert!(!poly.contains(&point));
let point = Geometry::from_wkt("POINT(0.1 0.01)").unwrap();
assert!(poly.contains(&point));
}
#[test]
fn test_disjoint() {
let poly = Geometry::from_wkt("POLYGON((0 0,5 5,10 0,0 0))").unwrap();
let line = Geometry::from_wkt("LINESTRING(-1 -1, -2 -2)").unwrap();
assert!(poly.disjoint(&line));
}
#[test]
fn test_touches() {
let line1 = Geometry::from_wkt("LINESTRING(0 0, 10 10)").unwrap();
let line2 = Geometry::from_wkt("LINESTRING(0 0, 0 10)").unwrap();
assert!(line1.touches(&line2));
}
#[test]
fn test_crosses() {
let line1 = Geometry::from_wkt("LINESTRING(0 0, 10 10)").unwrap();
let line2 = Geometry::from_wkt("LINESTRING(10 0, 0 10)").unwrap();
assert!(line1.crosses(&line2));
}
#[test]
fn test_within() {
let poly1 = Geometry::from_wkt("POLYGON((0 0, 10 10, 10 0, 0 0))").unwrap();
let poly2 = Geometry::from_wkt("POLYGON((-90 -90, -90 90, 190 -90, -90 -90))").unwrap();
assert!(poly1.within(&poly2));
assert!(!poly2.within(&poly1));
}
#[test]
fn test_overlaps() {
let poly1 = Geometry::from_wkt("POLYGON((0 0, 10 10, 10 0, 0 0))").unwrap();
let poly2 = Geometry::from_wkt("POLYGON((0 -5,10 5,10 -5,0 -5))").unwrap();
assert!(poly1.overlaps(&poly2));
}
}