Skip to content

Commit

Permalink
Merge #274
Browse files Browse the repository at this point in the history
274: Ability to get owned reference to inner geometry. r=rmanoka a=metasim

- [x] I agree to follow the project's [code of conduct](https://github.com/georust/gdal/blob/master/CODE_OF_CONDUCT.md).
- [x] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users.
---

Closes #269 



Co-authored-by: Simeon H.K. Fitch <fitch@astraea.io>
  • Loading branch information
bors[bot] and metasim committed Jun 14, 2022
2 parents fb6e260 + 7938e13 commit af69b1d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGES.md
Expand Up @@ -35,6 +35,10 @@

- <https://github.com/georust/gdal/pull/246>

- Add `GeometryRef<'a>` to reference owned nested geometry in a lifetime-safe way.

- <https://github.com/georust/gdal/pull/274>

- Add support for MDArray API

- <https://github.com/georust/gdal/pull/273>
Expand Down
33 changes: 32 additions & 1 deletion 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};
Expand Down Expand Up @@ -310,6 +312,15 @@ 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) -> GeometryRef {
let geom = unsafe { self.get_unowned_geometry(index) };
GeometryRef {
geom,
_lifetime: PhantomData::default(),
}
}

pub fn add_geometry(&mut self, mut sub: Geometry) -> Result<()> {
assert!(sub.owned);
sub.owned = false;
Expand Down Expand Up @@ -444,6 +455,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;
Expand Down
38 changes: 38 additions & 0 deletions src/vector/vector_tests/mod.rs
Expand Up @@ -122,6 +122,7 @@ where
mod tests {
use super::*;
use crate::errors::{GdalError, Result};
use gdal_sys::OGRwkbGeometryType::{wkbLineString, wkbLinearRing, wkbPolygon};

#[test]
fn test_feature_count() {
Expand Down Expand Up @@ -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);
// 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);
let points = inner.get_point_vec();
assert!(!points.is_empty());
}

#[test]
fn test_wkt() {
with_feature("roads.geojson", 236194095, |feature| {
Expand Down

0 comments on commit af69b1d

Please sign in to comment.