Skip to content

Commit

Permalink
Macro for geometry array impl (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron authored Jul 12, 2023
1 parent 321ae32 commit e68beb5
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 167 deletions.
20 changes: 2 additions & 18 deletions src/algorithm/geo/affine_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,23 +87,7 @@ impl AffineOps for MultiPointArray {
}

impl AffineOps for GeometryArray {
fn affine_transform(&self, transform: BroadcastableVec<AffineTransform>) -> Self {
match self {
GeometryArray::WKB(arr) => GeometryArray::WKB(arr.affine_transform(transform)),
GeometryArray::Point(arr) => GeometryArray::Point(arr.affine_transform(transform)),
GeometryArray::LineString(arr) => {
GeometryArray::LineString(arr.affine_transform(transform))
}
GeometryArray::Polygon(arr) => GeometryArray::Polygon(arr.affine_transform(transform)),
GeometryArray::MultiPoint(arr) => {
GeometryArray::MultiPoint(arr.affine_transform(transform))
}
GeometryArray::MultiLineString(arr) => {
GeometryArray::MultiLineString(arr.affine_transform(transform))
}
GeometryArray::MultiPolygon(arr) => {
GeometryArray::MultiPolygon(arr.affine_transform(transform))
}
}
crate::geometry_array_delegate_impl! {
fn affine_transform(&self, transform: BroadcastableVec<AffineTransform>) -> Self;
}
}
24 changes: 3 additions & 21 deletions src/algorithm/geo/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,27 +128,9 @@ impl Area for WKBArray {
}

impl Area for GeometryArray {
fn signed_area(&self) -> PrimitiveArray<f64> {
match self {
GeometryArray::WKB(arr) => arr.signed_area(),
GeometryArray::Point(arr) => arr.signed_area(),
GeometryArray::LineString(arr) => arr.signed_area(),
GeometryArray::Polygon(arr) => arr.signed_area(),
GeometryArray::MultiPoint(arr) => arr.signed_area(),
GeometryArray::MultiLineString(arr) => arr.signed_area(),
GeometryArray::MultiPolygon(arr) => arr.signed_area(),
}
}
crate::geometry_array_delegate_impl! {
fn signed_area(&self) -> PrimitiveArray<f64>;

fn unsigned_area(&self) -> PrimitiveArray<f64> {
match self {
GeometryArray::WKB(arr) => arr.unsigned_area(),
GeometryArray::Point(arr) => arr.unsigned_area(),
GeometryArray::LineString(arr) => arr.unsigned_area(),
GeometryArray::Polygon(arr) => arr.unsigned_area(),
GeometryArray::MultiPoint(arr) => arr.unsigned_area(),
GeometryArray::MultiLineString(arr) => arr.unsigned_area(),
GeometryArray::MultiPolygon(arr) => arr.unsigned_area(),
}
fn unsigned_area(&self) -> PrimitiveArray<f64>;
}
}
12 changes: 2 additions & 10 deletions src/algorithm/geo/bounding_rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,7 @@ iter_geo_impl!(MultiPolygonArray);
iter_geo_impl!(WKBArray);

impl BoundingRect for GeometryArray {
fn bounding_rect(&self) -> PolygonArray {
match self {
GeometryArray::WKB(arr) => arr.bounding_rect(),
GeometryArray::Point(arr) => arr.bounding_rect(),
GeometryArray::LineString(arr) => arr.bounding_rect(),
GeometryArray::Polygon(arr) => arr.bounding_rect(),
GeometryArray::MultiPoint(arr) => arr.bounding_rect(),
GeometryArray::MultiLineString(arr) => arr.bounding_rect(),
GeometryArray::MultiPolygon(arr) => arr.bounding_rect(),
}
crate::geometry_array_delegate_impl! {
fn bounding_rect(&self) -> PolygonArray;
}
}
12 changes: 2 additions & 10 deletions src/algorithm/geo/center.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,7 @@ impl Center for WKBArray {
}

impl Center for GeometryArray {
fn center(&self) -> PointArray {
match self {
GeometryArray::WKB(arr) => arr.center(),
GeometryArray::Point(arr) => arr.center(),
GeometryArray::LineString(arr) => arr.center(),
GeometryArray::Polygon(arr) => arr.center(),
GeometryArray::MultiPoint(arr) => arr.center(),
GeometryArray::MultiLineString(arr) => arr.center(),
GeometryArray::MultiPolygon(arr) => arr.center(),
}
crate::geometry_array_delegate_impl! {
fn center(&self) -> PointArray;
}
}
12 changes: 2 additions & 10 deletions src/algorithm/geo/centroid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,7 @@ impl Centroid for WKBArray {
}

impl Centroid for GeometryArray {
fn centroid(&self) -> PointArray {
match self {
GeometryArray::WKB(arr) => arr.centroid(),
GeometryArray::Point(arr) => arr.centroid(),
GeometryArray::LineString(arr) => arr.centroid(),
GeometryArray::Polygon(arr) => arr.centroid(),
GeometryArray::MultiPoint(arr) => arr.centroid(),
GeometryArray::MultiLineString(arr) => arr.centroid(),
GeometryArray::MultiPolygon(arr) => arr.centroid(),
}
crate::geometry_array_delegate_impl! {
fn centroid(&self) -> PointArray;
}
}
25 changes: 3 additions & 22 deletions src/algorithm/geo/chamberlain_duquette_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,27 +151,8 @@ impl ChamberlainDuquetteArea for WKBArray {
}

impl ChamberlainDuquetteArea for GeometryArray {
fn chamberlain_duquette_signed_area(&self) -> PrimitiveArray<f64> {
match self {
GeometryArray::WKB(arr) => arr.chamberlain_duquette_signed_area(),
GeometryArray::Point(arr) => arr.chamberlain_duquette_signed_area(),
GeometryArray::LineString(arr) => arr.chamberlain_duquette_signed_area(),
GeometryArray::Polygon(arr) => arr.chamberlain_duquette_signed_area(),
GeometryArray::MultiPoint(arr) => arr.chamberlain_duquette_signed_area(),
GeometryArray::MultiLineString(arr) => arr.chamberlain_duquette_signed_area(),
GeometryArray::MultiPolygon(arr) => arr.chamberlain_duquette_signed_area(),
}
}

fn chamberlain_duquette_unsigned_area(&self) -> PrimitiveArray<f64> {
match self {
GeometryArray::WKB(arr) => arr.chamberlain_duquette_unsigned_area(),
GeometryArray::Point(arr) => arr.chamberlain_duquette_unsigned_area(),
GeometryArray::LineString(arr) => arr.chamberlain_duquette_unsigned_area(),
GeometryArray::Polygon(arr) => arr.chamberlain_duquette_unsigned_area(),
GeometryArray::MultiPoint(arr) => arr.chamberlain_duquette_unsigned_area(),
GeometryArray::MultiLineString(arr) => arr.chamberlain_duquette_unsigned_area(),
GeometryArray::MultiPolygon(arr) => arr.chamberlain_duquette_unsigned_area(),
}
crate::geometry_array_delegate_impl! {
fn chamberlain_duquette_signed_area(&self) -> PrimitiveArray<f64>;
fn chamberlain_duquette_unsigned_area(&self) -> PrimitiveArray<f64>;
}
}
12 changes: 2 additions & 10 deletions src/algorithm/geo/convex_hull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,8 @@ iter_geo_impl!(MultiPolygonArray);
iter_geo_impl!(WKBArray);

impl ConvexHull for GeometryArray {
fn convex_hull(&self) -> PolygonArray {
match self {
GeometryArray::WKB(arr) => arr.convex_hull(),
GeometryArray::Point(arr) => arr.convex_hull(),
GeometryArray::LineString(arr) => arr.convex_hull(),
GeometryArray::Polygon(arr) => arr.convex_hull(),
GeometryArray::MultiPoint(arr) => arr.convex_hull(),
GeometryArray::MultiLineString(arr) => arr.convex_hull(),
GeometryArray::MultiPolygon(arr) => arr.convex_hull(),
}
crate::geometry_array_delegate_impl! {
fn convex_hull(&self) -> PolygonArray;
}
}

Expand Down
70 changes: 4 additions & 66 deletions src/algorithm/geo/rotate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,71 +157,9 @@ iter_geo_impl!(MultiPolygonArray);
iter_geo_impl!(WKBArray);

impl Rotate for GeometryArray {
fn rotate_around_centroid(&self, degrees: BroadcastablePrimitive<f64>) -> Self {
match self {
GeometryArray::WKB(arr) => GeometryArray::WKB(arr.rotate_around_centroid(degrees)),
GeometryArray::Point(arr) => GeometryArray::Point(arr.rotate_around_centroid(degrees)),
GeometryArray::LineString(arr) => {
GeometryArray::LineString(arr.rotate_around_centroid(degrees))
}
GeometryArray::Polygon(arr) => {
GeometryArray::Polygon(arr.rotate_around_centroid(degrees))
}
GeometryArray::MultiPoint(arr) => {
GeometryArray::MultiPoint(arr.rotate_around_centroid(degrees))
}
GeometryArray::MultiLineString(arr) => {
GeometryArray::MultiLineString(arr.rotate_around_centroid(degrees))
}
GeometryArray::MultiPolygon(arr) => {
GeometryArray::MultiPolygon(arr.rotate_around_centroid(degrees))
}
}
}

fn rotate_around_center(&self, degrees: BroadcastablePrimitive<f64>) -> Self {
match self {
GeometryArray::WKB(arr) => GeometryArray::WKB(arr.rotate_around_center(degrees)),
GeometryArray::Point(arr) => GeometryArray::Point(arr.rotate_around_center(degrees)),
GeometryArray::LineString(arr) => {
GeometryArray::LineString(arr.rotate_around_center(degrees))
}
GeometryArray::Polygon(arr) => {
GeometryArray::Polygon(arr.rotate_around_center(degrees))
}
GeometryArray::MultiPoint(arr) => {
GeometryArray::MultiPoint(arr.rotate_around_center(degrees))
}
GeometryArray::MultiLineString(arr) => {
GeometryArray::MultiLineString(arr.rotate_around_center(degrees))
}
GeometryArray::MultiPolygon(arr) => {
GeometryArray::MultiPolygon(arr.rotate_around_center(degrees))
}
}
}

fn rotate_around_point(&self, degrees: BroadcastablePrimitive<f64>, point: geo::Point) -> Self {
match self {
GeometryArray::WKB(arr) => GeometryArray::WKB(arr.rotate_around_point(degrees, point)),
GeometryArray::Point(arr) => {
GeometryArray::Point(arr.rotate_around_point(degrees, point))
}
GeometryArray::LineString(arr) => {
GeometryArray::LineString(arr.rotate_around_point(degrees, point))
}
GeometryArray::Polygon(arr) => {
GeometryArray::Polygon(arr.rotate_around_point(degrees, point))
}
GeometryArray::MultiPoint(arr) => {
GeometryArray::MultiPoint(arr.rotate_around_point(degrees, point))
}
GeometryArray::MultiLineString(arr) => {
GeometryArray::MultiLineString(arr.rotate_around_point(degrees, point))
}
GeometryArray::MultiPolygon(arr) => {
GeometryArray::MultiPolygon(arr.rotate_around_point(degrees, point))
}
}
crate::geometry_array_delegate_impl! {
fn rotate_around_centroid(&self, degrees: BroadcastablePrimitive<f64>) -> Self;
fn rotate_around_center(&self, degrees: BroadcastablePrimitive<f64>) -> Self;
fn rotate_around_point(&self, degrees: BroadcastablePrimitive<f64>, point: geo::Point) -> Self;
}
}
38 changes: 38 additions & 0 deletions src/algorithm/geo/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,41 @@ pub(crate) fn zeroes(len: usize, validity: Option<&Bitmap>) -> PrimitiveArray<f6
let values = vec![0.0f64; len];
PrimitiveArray::new(DataType::Float64, values.into(), validity.cloned())
}

/// Implements the common pattern where a Geometry enum simply delegates its trait impl to it's inner type.
// This is derived from geo https://github.com/georust/geo/blob/d4c858308ba910f69beab175e08af263b17c5f9f/geo/src/types.rs#L119-L158
#[macro_export]
macro_rules! geometry_array_delegate_impl {
($($a:tt)*) => { $crate::__geometry_array_delegate_impl_helper!{ GeometryArray, $($a)* } }
}

#[doc(hidden)]
#[macro_export]
macro_rules! __geometry_array_delegate_impl_helper {
(
$enum:ident,
$(
$(#[$outer:meta])*
fn $func_name: ident(&$($self_life:lifetime)?self $(, $arg_name: ident: $arg_type: ty)*) -> $return: ty;
)+
) => {
$(
$(#[$outer])*
fn $func_name(&$($self_life)? self, $($arg_name: $arg_type),*) -> $return {
match self {
$enum::WKB(g) => g.$func_name($($arg_name),*).into(),
$enum::Point(g) => g.$func_name($($arg_name),*).into(),
// $enum::Line(g) => g.$func_name($($arg_name),*).into(),
$enum::LineString(g) => g.$func_name($($arg_name),*).into(),
$enum::Polygon(g) => g.$func_name($($arg_name),*).into(),
$enum::MultiPoint(g) => g.$func_name($($arg_name),*).into(),
$enum::MultiLineString(g) => g.$func_name($($arg_name),*).into(),
$enum::MultiPolygon(g) => g.$func_name($($arg_name),*).into(),
// $enum::GeometryCollection(g) => g.$func_name($($arg_name),*).into(),
// $enum::Rect(g) => g.$func_name($($arg_name),*).into(),
// $enum::Triangle(g) => g.$func_name($($arg_name),*).into(),
}
}
)+
};
}
43 changes: 43 additions & 0 deletions src/array/geometry/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,46 @@ impl TryFrom<&dyn Array> for GeometryArray {
}
}
}

// TODO: write a macro to dedupe these `From`s
impl From<PointArray> for GeometryArray {
fn from(value: PointArray) -> Self {
GeometryArray::Point(value)
}
}

impl From<LineStringArray> for GeometryArray {
fn from(value: LineStringArray) -> Self {
GeometryArray::LineString(value)
}
}

impl From<PolygonArray> for GeometryArray {
fn from(value: PolygonArray) -> Self {
GeometryArray::Polygon(value)
}
}

impl From<MultiPointArray> for GeometryArray {
fn from(value: MultiPointArray) -> Self {
GeometryArray::MultiPoint(value)
}
}

impl From<MultiLineStringArray> for GeometryArray {
fn from(value: MultiLineStringArray) -> Self {
GeometryArray::MultiLineString(value)
}
}

impl From<MultiPolygonArray> for GeometryArray {
fn from(value: MultiPolygonArray) -> Self {
GeometryArray::MultiPolygon(value)
}
}

impl From<WKBArray> for GeometryArray {
fn from(value: WKBArray) -> Self {
GeometryArray::WKB(value)
}
}

0 comments on commit e68beb5

Please sign in to comment.