Skip to content

Commit a763e51

Browse files
committed
Add processor to compute geometry bounds
1 parent 97b1437 commit a763e51

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

geozero/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## UNRELEASED
22

3+
* Add `BoundsProcessor` to compute bounds of geometry
34
* Update Deps:
45
* BREAKING: `flatgeobuf` to 4.5.0
56
* BREAKING: `dbase` to 0.5.0

geozero/src/bounds.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
use crate::{FeatureProcessor, GeomProcessor, PropertyProcessor};
2+
3+
#[derive(Default, Debug, Clone, PartialEq)]
4+
pub struct Bounds {
5+
min_x: f64,
6+
min_y: f64,
7+
max_x: f64,
8+
max_y: f64,
9+
}
10+
11+
impl Bounds {
12+
pub fn extend(&mut self, x: f64, y: f64) {
13+
if x < self.min_x {
14+
self.min_x = x;
15+
}
16+
if x > self.max_x {
17+
self.max_x = x;
18+
}
19+
if y < self.min_y {
20+
self.min_y = y;
21+
}
22+
if y > self.max_y {
23+
self.max_y = y;
24+
}
25+
}
26+
27+
pub fn min_x(&self) -> f64 {
28+
self.min_x
29+
}
30+
31+
pub fn min_y(&self) -> f64 {
32+
self.min_y
33+
}
34+
35+
pub fn max_x(&self) -> f64 {
36+
self.max_x
37+
}
38+
39+
pub fn max_y(&self) -> f64 {
40+
self.max_y
41+
}
42+
}
43+
44+
/// Computes the bounds of a Geomtry
45+
#[derive(Default, Debug)]
46+
pub struct BoundsProcessor {
47+
bounds: Option<Bounds>,
48+
}
49+
50+
impl BoundsProcessor {
51+
pub fn new() -> Self {
52+
Self::default()
53+
}
54+
pub fn bounds(&self) -> Option<Bounds> {
55+
self.bounds.clone()
56+
}
57+
}
58+
59+
impl GeomProcessor for BoundsProcessor {
60+
fn xy(&mut self, x: f64, y: f64, _idx: usize) -> crate::error::Result<()> {
61+
let Some(bounds) = self.bounds.as_mut() else {
62+
self.bounds = Some(Bounds {
63+
min_x: x,
64+
min_y: y,
65+
max_x: x,
66+
max_y: y,
67+
});
68+
return Ok(());
69+
};
70+
bounds.extend(x, y);
71+
Ok(())
72+
}
73+
74+
fn coordinate(
75+
&mut self,
76+
x: f64,
77+
y: f64,
78+
_z: Option<f64>,
79+
_m: Option<f64>,
80+
_t: Option<f64>,
81+
_tm: Option<u64>,
82+
idx: usize,
83+
) -> crate::error::Result<()> {
84+
self.xy(x, y, idx)
85+
}
86+
}
87+
88+
impl PropertyProcessor for BoundsProcessor {}
89+
impl FeatureProcessor for BoundsProcessor {}
90+
91+
#[cfg(feature = "with-wkt")]
92+
#[cfg(test)]
93+
mod tests {
94+
use super::*;
95+
use crate::GeozeroGeometry;
96+
97+
#[test]
98+
fn test_bounds() {
99+
let wkt = crate::wkt::Wkt("LINESTRING(1 2,3 4,5 6)");
100+
let mut bounds_processor = BoundsProcessor::new();
101+
102+
wkt.process_geom(&mut bounds_processor).unwrap();
103+
104+
assert_eq!(
105+
bounds_processor.bounds,
106+
Some(Bounds {
107+
min_x: 1.0,
108+
min_y: 2.0,
109+
max_x: 5.0,
110+
max_y: 6.0,
111+
})
112+
)
113+
}
114+
115+
#[test]
116+
fn test_empty() {
117+
let wkt = crate::wkt::Wkt("LINESTRING EMPTY");
118+
let mut bounds_processor = BoundsProcessor::new();
119+
120+
wkt.process_geom(&mut bounds_processor).unwrap();
121+
122+
assert_eq!(bounds_processor.bounds, None);
123+
}
124+
}

geozero/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ pub use crate::wkt::conversion::*;
124124

125125
#[cfg(feature = "with-mvt")]
126126
pub mod mvt;
127+
128+
pub mod bounds;
129+
127130
#[cfg(feature = "with-mvt")]
128131
pub use crate::mvt::conversion::*;
129132

0 commit comments

Comments
 (0)