Skip to content

Commit

Permalink
Merge #379
Browse files Browse the repository at this point in the history
379: add union operation for geometry r=metasim a=zredb

- [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.
---
This is my first time to commit code to this repository. I see that vecotr only has an intersection operation at present, so I try to add a union operation to it. If it can be accepted, I will add other operations in the same way later.


Co-authored-by: zhb <[email protected]>
  • Loading branch information
bors[bot] and zhb authored Mar 16, 2023
2 parents 1dbc602 + cb62db5 commit 7b874de
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changes

## Unreleased
- Added `Geometry::union`

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

- Added `Geometry::from_gml`

Expand Down
79 changes: 77 additions & 2 deletions src/vector/ops/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ impl Geometry {
/// otherwise the result might be wrong.
///
/// # Returns
/// Some(Geometry) if both Geometries contain pointers
/// None if either geometry is missing the gdal pointer, or there is an error.
/// `Some(geometry)` if both Geometries contain pointers
/// `None` if either geometry is missing the GDAL pointer, or there is an error.
///
/// See: [`OGR_G_Intersection`](https://gdal.org/api/vector_c_api.html#_CPPv418OGR_G_Intersection12OGRGeometryH12OGRGeometryH)
pub fn intersection(&self, other: &Self) -> Option<Self> {
Expand All @@ -32,6 +32,35 @@ impl Geometry {
}
Some(unsafe { Geometry::with_c_geometry(ogr_geom, true) })
}

/// Compute union.
///
/// Generates a new geometry which is the region of union of
/// the two geometries operated on.
/// Geometry validity is not checked. In case you are unsure of the
/// validity of the input geometries, call IsValid() before,
/// otherwise the result might be wrong.
///
/// # Returns
/// `Some(geometry)` if both Geometries contain pointers.
/// `None` if either geometry is missing the GDAL pointer, or there is an error.
///
/// See: [`OGR_G_Union`](https://gdal.org/api/vector_c_api.html#_CPPv419OGR_G_UnionCascaded12OGRGeometryH)
pub fn union(&self, other: &Self) -> Option<Self> {
if !self.has_gdal_ptr() {
return None;
}
if !other.has_gdal_ptr() {
return None;
}
unsafe {
let ogr_geom = gdal_sys::OGR_G_Union(self.c_geometry(), other.c_geometry());
if ogr_geom.is_null() {
return None;
}
Some(Geometry::with_c_geometry(ogr_geom, true))
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -84,4 +113,50 @@ mod tests {

assert_eq!(inter.unwrap().area(), 0.0);
}

#[test]
#[allow(clippy::float_cmp)]
fn test_union_success() {
let geom =
Geometry::from_wkt("POLYGON ((0.0 10.0, 0.0 0.0, 10.0 0.0, 10.0 10.0, 0.0 10.0))")
.unwrap();
let other = Geometry::from_wkt("POLYGON ((1 -5, 1 1, -5 1, -5 -5, 1 -5))").unwrap();

let res = geom.union(&other);

assert!(res.is_some());

let res = res.unwrap();

assert_eq!(res.area(), 135.0);
}

#[test]
fn test_union_no_gdal_ptr() {
let geom =
Geometry::from_wkt("POLYGON ((0.0 10.0, 0.0 0.0, 10.0 0.0, 10.0 10.0, 0.0 10.0))")
.unwrap();
let other = unsafe { Geometry::lazy_feature_geometry() };

let res = geom.union(&other);

assert!(res.is_none());
}

#[test]
#[allow(clippy::float_cmp)]
fn test_union_no_intersects() {
let geom =
Geometry::from_wkt("POLYGON ((0.0 5.0, 0.0 0.0, 5.0 0.0, 5.0 5.0, 0.0 5.0))").unwrap();

let other =
Geometry::from_wkt("POLYGON ((15.0 15.0, 15.0 20.0, 20.0 20.0, 20.0 15.0, 15.0 15.0))")
.unwrap();

let res = geom.union(&other);

assert!(res.is_some());

assert_eq!(res.unwrap().area(), 50.0);
}
}

0 comments on commit 7b874de

Please sign in to comment.