Skip to content

Commit

Permalink
Add processor to compute geometry bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelkirk committed Jan 15, 2025
1 parent 97b1437 commit 7a810a9
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions geozero/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## UNRELEASED

* Add `BoundsProcessor` to compute bounds of geometry
* Update Deps:
* BREAKING: `flatgeobuf` to 4.5.0
* BREAKING: `dbase` to 0.5.0
Expand Down
123 changes: 123 additions & 0 deletions geozero/src/bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use crate::{FeatureProcessor, GeomProcessor, PropertyProcessor};

#[derive(Default, Debug, Clone, PartialEq)]
pub struct Bounds {
min_x: f64,
min_y: f64,
max_x: f64,
max_y: f64,
}

impl Bounds {
pub fn extend(&mut self, x: f64, y: f64) {
if x < self.min_x {
self.min_x = x;
}
if x > self.max_x {
self.max_x = x;
}
if y < self.min_y {
self.min_y = y;
}
if y > self.max_y {
self.max_y = y;
}
}

pub fn min_x(&self) -> f64 {
self.min_x
}

pub fn min_y(&self) -> f64 {
self.min_y
}

pub fn max_x(&self) -> f64 {
self.max_x
}

pub fn max_y(&self) -> f64 {
self.max_y
}
}

/// Computes the bounds of a Geomtry
#[derive(Default, Debug)]
pub struct BoundsProcessor {
bounds: Option<Bounds>,
}

impl BoundsProcessor {
pub fn new() -> Self {
Self::default()
}
pub fn bounds(&self) -> Option<Bounds> {
self.bounds.clone()
}
}

impl GeomProcessor for BoundsProcessor {
fn xy(&mut self, x: f64, y: f64, _idx: usize) -> crate::error::Result<()> {
let Some(bounds) = self.bounds.as_mut() else {
self.bounds = Some(Bounds {
min_x: x,
min_y: y,
max_x: x,
max_y: y,
});
return Ok(());
};
bounds.extend(x, y);
Ok(())
}

fn coordinate(
&mut self,
x: f64,
y: f64,
_z: Option<f64>,
_m: Option<f64>,
_t: Option<f64>,
_tm: Option<u64>,
idx: usize,
) -> crate::error::Result<()> {
self.xy(x, y, idx)
}
}

impl PropertyProcessor for BoundsProcessor {}
impl FeatureProcessor for BoundsProcessor {}

#[cfg(test)]
mod tests {
use super::*;
use crate::GeozeroGeometry;

#[test]
fn test_bounds() {
let wkt = crate::wkt::Wkt("LINESTRING(1 2,3 4,5 6)");
let mut bounds_processor = BoundsProcessor::new();

wkt.process_geom(&mut bounds_processor).unwrap();

assert_eq!(
bounds_processor.bounds,
Some(Bounds {
min_x: 1.0,
min_y: 2.0,
max_x: 5.0,
max_y: 6.0,
})
)
}

#[test]
fn test_empty() {
let wkt = crate::wkt::Wkt("LINESTRING EMPTY");
let mut bounds_processor = BoundsProcessor::new();

wkt.process_geom(&mut bounds_processor).unwrap();

assert_eq!(bounds_processor.bounds, None);
}
}
3 changes: 3 additions & 0 deletions geozero/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ pub use crate::wkt::conversion::*;

#[cfg(feature = "with-mvt")]
pub mod mvt;

pub mod bounds;

#[cfg(feature = "with-mvt")]
pub use crate::mvt::conversion::*;

Expand Down

0 comments on commit 7a810a9

Please sign in to comment.