Skip to content

Commit

Permalink
Implement explode_geometries method (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
edpft committed Sep 19, 2022
1 parent 6c28420 commit 028a3f9
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 57 deletions.
133 changes: 76 additions & 57 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions geopolars/Cargo.toml
Expand Up @@ -52,3 +52,7 @@ bench = false
[[bench]]
name = "affine"
harness = false

[[bench]]
name = "explode"
harness = false
30 changes: 30 additions & 0 deletions geopolars/benches/explode.rs
@@ -0,0 +1,30 @@
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use geo::Geometry;
use geo::MultiPoint;
use geo::Point;
use geopolars::error::Result;
use geopolars::geoseries::GeoSeries;
use polars::prelude::*;

fn generate_multipoint_series() -> Result<Series> {
let points: Vec<Point> = (0..90_000).map(|_| Point::new(0., 0.)).collect();
let multipoints: Vec<Geometry> = points
.chunks(2)
.map(|points| MultiPoint::new(points.to_vec()))
.map(Geometry::MultiPoint)
.collect();
let series = Series::from_geom_vec(&multipoints).unwrap();
Ok(series)
}

fn bench_explode(b: &mut Bencher) {
let series = generate_multipoint_series().expect("Unable to generate multipoint series");
b.iter(|| GeoSeries::explode(&series))
}

fn explode_benchmark(c: &mut Criterion) {
c.bench_function("explode", bench_explode);
}

criterion_group!(benches, explode_benchmark);
criterion_main!(benches);
89 changes: 89 additions & 0 deletions geopolars/src/geoseries.rs
Expand Up @@ -70,6 +70,9 @@ pub trait GeoSeries {
/// Applies to GeoSeries containing only Polygons. Returns `None` for other geometry types.
fn exterior(&self) -> Result<Series>;

/// Explodes multi-part geometries into multiple single geometries.
fn explode(&self) -> Result<Series>;

/// Create a Series from a vector of geometries
fn from_geom_vec(geoms: &[Geometry<f64>]) -> Result<Series>;

Expand Down Expand Up @@ -307,6 +310,62 @@ impl GeoSeries for Series {
Ok(series)
}

fn explode(&self) -> Result<Series> {
let mut exploded_vector = Vec::new();

for geometry in iter_geom(self) {
match geometry {
Geometry::Point(geometry) => {
let point = Geometry::Point(geometry);
exploded_vector.push(point)
}
Geometry::MultiPoint(geometry) => {
for geom in geometry.into_iter() {
let point = Geometry::Point(geom);
exploded_vector.push(point)
}
}
Geometry::Line(geometry) => {
let line = Geometry::Line(geometry);
exploded_vector.push(line)
}
Geometry::LineString(geometry) => {
let line_string = Geometry::LineString(geometry);
exploded_vector.push(line_string)
}
Geometry::MultiLineString(geometry) => {
for geom in geometry.into_iter() {
let line_string = Geometry::LineString(geom);
exploded_vector.push(line_string)
}
}
Geometry::Polygon(geometry) => {
let polygon = Geometry::Polygon(geometry);
exploded_vector.push(polygon)
}
Geometry::MultiPolygon(geometry) => {
for geom in geometry.into_iter() {
let polygon = Geometry::Polygon(geom);
exploded_vector.push(polygon)
}
}
Geometry::Rect(geometry) => {
let rectangle = Geometry::Rect(geometry);
exploded_vector.push(rectangle)
}
Geometry::Triangle(geometry) => {
let triangle = Geometry::Triangle(geometry);
exploded_vector.push(triangle)
}
_ => unimplemented!(),
};
}

let exploded_series = Series::from_geom_vec(&exploded_vector)?;

Ok(exploded_series)
}

fn exterior(&self) -> Result<Series> {
let mut output_array = MutableBinaryArray::<i32>::with_capacity(self.len());

Expand Down Expand Up @@ -943,6 +1002,36 @@ mod tests {
assert_eq!(10.0_f64, as_vec[0]);
}
#[test]
fn explode() {
let point_0 = Point::new(0., 0.);
let point_1 = Point::new(1., 1.);
let point_2 = Point::new(2., 2.);
let point_3 = Point::new(3., 3.);
let point_4 = Point::new(4., 4.);

let expected_series = Series::from_geom_vec(&[
Geometry::Point(point_0),
Geometry::Point(point_1),
Geometry::Point(point_2),
Geometry::Point(point_3),
Geometry::Point(point_4),
])
.unwrap();

let multipoint_0 = MultiPoint::new(vec![point_0, point_1]);
let multipoint_1 = MultiPoint::new(vec![point_2, point_3, point_4]);

let input_series = Series::from_geom_vec(&[
Geometry::MultiPoint(multipoint_0),
Geometry::MultiPoint(multipoint_1),
])
.unwrap();

let output_series = GeoSeries::explode(&input_series).unwrap();

assert_eq!(output_series, expected_series);
}
#[test]
fn haversine_length() {
let mut test_data = MutableBinaryArray::<i32>::with_capacity(1);

Expand Down

0 comments on commit 028a3f9

Please sign in to comment.