1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
use crate::array::{
GeometryArray, LineStringArray, MultiLineStringArray, MultiPointArray, MultiPolygonArray,
MutablePointArray, PointArray, PolygonArray, WKBArray,
};
use crate::GeometryArrayTrait;
use arrow_array::OffsetSizeTrait;
use geo::algorithm::centroid::Centroid as GeoCentroid;
/// Calculation of the centroid.
/// The centroid is the arithmetic mean position of all points in the shape.
/// Informally, it is the point at which a cutout of the shape could be perfectly
/// balanced on the tip of a pin.
/// The geometric centroid of a convex object always lies in the object.
/// A non-convex object might have a centroid that _is outside the object itself_.
///
/// # Examples
///
/// ```
/// use geoarrow2::algorithm::geo::Centroid;
/// use geoarrow2::array::PolygonArray;
/// use geoarrow2::trait_::GeoArrayAccessor;
/// use geo::{point, polygon};
///
/// // rhombus shaped polygon
/// let polygon = polygon![
/// (x: -2., y: 1.),
/// (x: 1., y: 3.),
/// (x: 4., y: 1.),
/// (x: 1., y: -1.),
/// (x: -2., y: 1.),
/// ];
/// let polygon_array: PolygonArray<i32> = vec![polygon].into();
///
/// assert_eq!(
/// Some(point!(x: 1., y: 1.)),
/// polygon_array.centroid().get_as_geo(0),
/// );
/// ```
pub trait Centroid {
/// See: <https://en.wikipedia.org/wiki/Centroid>
///
/// # Examples
///
/// ```
/// use geoarrow2::algorithm::geo::Centroid;
/// use geoarrow2::array::LineStringArray;
/// use geoarrow2::trait_::GeoArrayAccessor;
/// use geo::{line_string, point};
///
/// let line_string = line_string![
/// (x: 40.02f64, y: 116.34),
/// (x: 40.02f64, y: 118.23),
/// ];
/// let line_string_array: LineStringArray<i32> = vec![line_string].into();
///
/// assert_eq!(
/// Some(point!(x: 40.02, y: 117.285)),
/// line_string_array.centroid().get_as_geo(0),
/// );
/// ```
fn centroid(&self) -> PointArray;
}
impl Centroid for PointArray {
fn centroid(&self) -> PointArray {
self.clone()
}
}
/// Implementation that iterates over geo objects
macro_rules! iter_geo_impl {
($type:ty) => {
impl<O: OffsetSizeTrait> Centroid for $type {
fn centroid(&self) -> PointArray {
let mut output_array = MutablePointArray::with_capacity(self.len());
self.iter_geo().for_each(|maybe_g| {
output_array.push_point(maybe_g.and_then(|g| g.centroid()).as_ref())
});
output_array.into()
}
}
};
}
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> Centroid for GeometryArray<O> {
crate::geometry_array_delegate_impl! {
fn centroid(&self) -> PointArray;
}
}