From f6d5ad9bbc5e66842d82fe1479bd579e1ec764a5 Mon Sep 17 00:00:00 2001 From: "Simeon H.K. Fitch" Date: Mon, 18 Apr 2022 18:26:52 -0400 Subject: [PATCH 1/4] Added ability to get an owned reference to inner geometry. --- src/vector/geometry.rs | 31 ++++++++++++++++++++++++++- src/vector/vector_tests/mod.rs | 38 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/vector/geometry.rs b/src/vector/geometry.rs index 11f5bb3e6..767d43104 100644 --- a/src/vector/geometry.rs +++ b/src/vector/geometry.rs @@ -1,6 +1,8 @@ use std::cell::RefCell; use std::ffi::CString; -use std::fmt::{self, Debug}; +use std::fmt::{self, Debug, Formatter}; +use std::marker::PhantomData; +use std::ops::Deref; use std::ptr::null_mut; use libc::{c_char, c_double, c_int, c_void}; @@ -310,6 +312,13 @@ impl Geometry { Geometry::with_c_geometry(c_geom, false) } + /// Get a reference to the geometry at given `index` + pub fn get_geometry(&self, index: usize) -> Result { + let geom = unsafe { self.get_unowned_geometry(index) }; + let gref = GeometryRef { geom, _lifetime: PhantomData::default() }; + Ok(gref) + } + pub fn add_geometry(&mut self, mut sub: Geometry) -> Result<()> { assert!(sub.owned); sub.owned = false; @@ -444,6 +453,26 @@ pub fn geometry_type_to_name(ty: OGRwkbGeometryType::Type) -> String { _string(rv) } +/// Reference to owned geometry +pub struct GeometryRef<'a> { + geom: Geometry, + _lifetime: PhantomData<&'a ()> +} + +impl Deref for GeometryRef<'_> { + type Target = Geometry; + + fn deref(&self) -> &Self::Target { + &self.geom + } +} + +impl Debug for GeometryRef<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.geom, f) + } +} + #[cfg(test)] mod tests { use crate::spatial_ref::SpatialRef; diff --git a/src/vector/vector_tests/mod.rs b/src/vector/vector_tests/mod.rs index dce01dda2..d2883ee7a 100644 --- a/src/vector/vector_tests/mod.rs +++ b/src/vector/vector_tests/mod.rs @@ -120,6 +120,7 @@ where #[cfg(test)] mod tests { + use gdal_sys::OGRwkbGeometryType::{wkbLinearRing, wkbLineString, wkbPolygon}; use super::*; use crate::errors::{GdalError, Result}; @@ -508,6 +509,43 @@ mod tests { }); } + #[test] + fn test_ring_points() { + let mut ring = Geometry::empty(wkbLinearRing).unwrap(); + ring.add_point_2d((1179091.1646903288, 712782.8838459781)); + ring.add_point_2d((1161053.0218226474, 667456.2684348812)); + ring.add_point_2d((1214704.933941905, 641092.8288590391)); + ring.add_point_2d((1228580.428455506, 682719.3123998424)); + ring.add_point_2d((1218405.0658121984, 721108.1805541387)); + ring.add_point_2d((1179091.1646903288, 712782.8838459781)); + assert!(!ring.is_empty()); + assert_eq!(ring.get_point_vec().len(), 6); + let mut poly = Geometry::empty(wkbPolygon).unwrap(); + poly.add_geometry(ring.to_owned()).unwrap(); + // Points are in ring, not containing geometry. + // NB: In Python SWIG bindings, `GetPoints` is fallible. + assert!(poly.get_point_vec().is_empty()); + assert_eq!(poly.geometry_count(), 1); + let ring_out = poly.get_geometry(0).unwrap(); + // NB: `wkb()` shows it to be a `LINEARRING`, but returned type is LineString + assert_eq!(ring_out.geometry_type(), wkbLineString); + assert!(!&ring_out.is_empty()); + assert_eq!(ring.get_point_vec(), ring_out.get_point_vec()); + } + + #[test] + fn test_get_inner_points() { + let geom = Geometry::bbox(0., 0., 1., 1.).unwrap(); + assert!(!geom.is_empty()); + assert_eq!(geom.geometry_count(), 1); + assert!(geom.area() > 0.); + assert_eq!(geom.geometry_type(), OGRwkbGeometryType::wkbPolygon); + assert!(geom.json().unwrap().contains("Polygon")); + let inner = geom.get_geometry(0).unwrap(); + let points = inner.get_point_vec(); + assert!(!points.is_empty()); + } + #[test] fn test_wkt() { with_feature("roads.geojson", 236194095, |feature| { From e3217a18a18b3526c22a57f9e79bdc0ceef47e38 Mon Sep 17 00:00:00 2001 From: "Simeon H.K. Fitch" Date: Sat, 14 May 2022 10:41:24 -0400 Subject: [PATCH 2/4] Updated changelog. --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 375e7a8ca..be92a79d1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,6 +31,10 @@ - +- Add `GeometryRef<'a>` to reference owned nested geometry in a lifetime-safe way. + + - + ## 0.12 - Bump Rust edition to 2021 From d6fdd6a89da232636d42976f89a744baa963b335 Mon Sep 17 00:00:00 2001 From: "Simeon H.K. Fitch" Date: Tue, 17 May 2022 12:34:29 -0400 Subject: [PATCH 3/4] Removed superfluous Result wrapping --- src/vector/geometry.rs | 5 ++--- src/vector/vector_tests/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vector/geometry.rs b/src/vector/geometry.rs index 767d43104..30a3cb9e1 100644 --- a/src/vector/geometry.rs +++ b/src/vector/geometry.rs @@ -313,10 +313,9 @@ impl Geometry { } /// Get a reference to the geometry at given `index` - pub fn get_geometry(&self, index: usize) -> Result { + pub fn get_geometry(&self, index: usize) -> GeometryRef { let geom = unsafe { self.get_unowned_geometry(index) }; - let gref = GeometryRef { geom, _lifetime: PhantomData::default() }; - Ok(gref) + GeometryRef { geom, _lifetime: PhantomData::default() } } pub fn add_geometry(&mut self, mut sub: Geometry) -> Result<()> { diff --git a/src/vector/vector_tests/mod.rs b/src/vector/vector_tests/mod.rs index d2883ee7a..1b6b6d274 100644 --- a/src/vector/vector_tests/mod.rs +++ b/src/vector/vector_tests/mod.rs @@ -526,7 +526,7 @@ mod tests { // NB: In Python SWIG bindings, `GetPoints` is fallible. assert!(poly.get_point_vec().is_empty()); assert_eq!(poly.geometry_count(), 1); - let ring_out = poly.get_geometry(0).unwrap(); + let ring_out = poly.get_geometry(0); // NB: `wkb()` shows it to be a `LINEARRING`, but returned type is LineString assert_eq!(ring_out.geometry_type(), wkbLineString); assert!(!&ring_out.is_empty()); @@ -541,7 +541,7 @@ mod tests { assert!(geom.area() > 0.); assert_eq!(geom.geometry_type(), OGRwkbGeometryType::wkbPolygon); assert!(geom.json().unwrap().contains("Polygon")); - let inner = geom.get_geometry(0).unwrap(); + let inner = geom.get_geometry(0); let points = inner.get_point_vec(); assert!(!points.is_empty()); } From 655feb577aeb117bb66c56f955a46fe51d6599ee Mon Sep 17 00:00:00 2001 From: "Simeon H.K. Fitch" Date: Mon, 13 Jun 2022 14:35:51 -0400 Subject: [PATCH 4/4] Fixed formatting. --- src/vector/geometry.rs | 7 +++++-- src/vector/vector_tests/mod.rs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vector/geometry.rs b/src/vector/geometry.rs index 30a3cb9e1..a52272c9a 100644 --- a/src/vector/geometry.rs +++ b/src/vector/geometry.rs @@ -315,7 +315,10 @@ impl Geometry { /// Get a reference to the geometry at given `index` pub fn get_geometry(&self, index: usize) -> GeometryRef { let geom = unsafe { self.get_unowned_geometry(index) }; - GeometryRef { geom, _lifetime: PhantomData::default() } + GeometryRef { + geom, + _lifetime: PhantomData::default(), + } } pub fn add_geometry(&mut self, mut sub: Geometry) -> Result<()> { @@ -455,7 +458,7 @@ pub fn geometry_type_to_name(ty: OGRwkbGeometryType::Type) -> String { /// Reference to owned geometry pub struct GeometryRef<'a> { geom: Geometry, - _lifetime: PhantomData<&'a ()> + _lifetime: PhantomData<&'a ()>, } impl Deref for GeometryRef<'_> { diff --git a/src/vector/vector_tests/mod.rs b/src/vector/vector_tests/mod.rs index 1b6b6d274..e9c54b6b5 100644 --- a/src/vector/vector_tests/mod.rs +++ b/src/vector/vector_tests/mod.rs @@ -120,9 +120,9 @@ where #[cfg(test)] mod tests { - use gdal_sys::OGRwkbGeometryType::{wkbLinearRing, wkbLineString, wkbPolygon}; use super::*; use crate::errors::{GdalError, Result}; + use gdal_sys::OGRwkbGeometryType::{wkbLineString, wkbLinearRing, wkbPolygon}; #[test] fn test_feature_count() {