use crate::array::{
GeometryArray, LineStringArray, MultiLineStringArray, MultiPointArray, MultiPolygonArray,
PointArray, PolygonArray, WKBArray,
};
use arrow_array::OffsetSizeTrait;
use geo::algorithm::convex_hull::ConvexHull as GeoConvexHull;
use geo::Polygon;
pub trait ConvexHull<O: OffsetSizeTrait> {
fn convex_hull(&self) -> PolygonArray<O>;
}
macro_rules! iter_geo_impl {
($type:ty) => {
impl<O: OffsetSizeTrait> ConvexHull<O> for $type {
fn convex_hull(&self) -> PolygonArray<O> {
let output_geoms: Vec<Option<Polygon>> = self
.iter_geo()
.map(|maybe_g| maybe_g.map(|geom| geom.convex_hull()))
.collect();
output_geoms.into()
}
}
};
}
iter_geo_impl!(PointArray);
iter_geo_impl!(LineStringArray<O>);
iter_geo_impl!(PolygonArray<O>);
iter_geo_impl!(MultiPointArray<O>);
iter_geo_impl!(MultiLineStringArray<O>);
iter_geo_impl!(MultiPolygonArray<O>);
iter_geo_impl!(WKBArray<O>);
impl<O: OffsetSizeTrait> ConvexHull<O> for GeometryArray<O> {
crate::geometry_array_delegate_impl! {
fn convex_hull(&self) -> PolygonArray<O>;
}
}
#[cfg(test)]
mod tests {
use super::ConvexHull;
use crate::array::{LineStringArray, MultiPointArray};
use crate::trait_::GeoArrayAccessor;
use geo::{line_string, polygon, MultiPoint, Point};
#[test]
fn convex_hull_for_multipoint() {
let input_geom: MultiPoint = vec![
Point::new(0.0, 10.0),
Point::new(1.0, 1.0),
Point::new(10.0, 0.0),
Point::new(1.0, -1.0),
Point::new(0.0, -10.0),
Point::new(-1.0, -1.0),
Point::new(-10.0, 0.0),
Point::new(-1.0, 1.0),
Point::new(0.0, 10.0),
]
.into();
let input_array: MultiPointArray<i64> = vec![input_geom].into();
let result_array = input_array.convex_hull();
let expected = polygon![
(x:0.0, y: -10.0),
(x:10.0, y: 0.0),
(x:0.0, y:10.0),
(x:-10.0, y:0.0),
(x:0.0, y:-10.0),
];
assert_eq!(expected, result_array.get_as_geo(0).unwrap());
}
#[test]
fn convex_hull_linestring_test() {
let input_geom = line_string![
(x: 0.0, y: 10.0),
(x: 1.0, y: 1.0),
(x: 10.0, y: 0.0),
(x: 1.0, y: -1.0),
(x: 0.0, y: -10.0),
(x: -1.0, y: -1.0),
(x: -10.0, y: 0.0),
(x: -1.0, y: 1.0),
(x: 0.0, y: 10.0),
];
let input_array: LineStringArray<i64> = vec![input_geom].into();
let result_array = input_array.convex_hull();
let expected = polygon![
(x: 0.0, y: -10.0),
(x: 10.0, y: 0.0),
(x: 0.0, y: 10.0),
(x: -10.0, y: 0.0),
(x: 0.0, y: -10.0),
];
assert_eq!(expected, result_array.get_as_geo(0).unwrap());
}
}