Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary operations simplification #809

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions benches/nybb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::fs::File;

use arrow_ipc::reader::FileReader;
use criterion::{criterion_group, criterion_main, Criterion};
use geoarrow::algorithm::geo::EuclideanDistance;
use geoarrow::algorithm::geo::EuclideanDistanceScalar;
use geoarrow::array::{MultiPolygonArray, PointArray};
use geoarrow::trait_::ArrayAccessor;
use geoarrow::trait_::{ArrayAccessor, NativeGeometryAccessor};

fn load_nybb() -> MultiPolygonArray<2> {
let file = File::open("fixtures/nybb.arrow").unwrap();
Expand Down Expand Up @@ -39,9 +39,9 @@ pub fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("euclidean distance to scalar point", |b| {
b.iter(|| {
let point = geo::Point::new(0.0f64, 0.0f64);
let point_array = PointArray::from(vec![point].as_slice());
let point_array = PointArray::<2>::from(vec![point].as_slice());

let _distances = array.euclidean_distance(&point_array.value(0));
let _distances = array.euclidean_distance(&point_array.value_as_geometry(0));
})
});
}
Expand Down
79 changes: 4 additions & 75 deletions src/algorithm/broadcasting/geometry.rs
Original file line number Diff line number Diff line change
@@ -1,78 +1,7 @@
use crate::algorithm::broadcasting::linestring::BroadcastLineStringIter;
use crate::algorithm::broadcasting::multilinestring::BroadcastMultiLineStringIter;
use crate::algorithm::broadcasting::multipoint::BroadcastMultiPointIter;
use crate::algorithm::broadcasting::multipolygon::BroadcastMultiPolygonIter;
use crate::algorithm::broadcasting::point::BroadcastPointIter;
use crate::algorithm::broadcasting::polygon::BroadcastPolygonIter;
use crate::algorithm::broadcasting::{
BroadcastableLineString, BroadcastableMultiLineString, BroadcastableMultiPoint,
BroadcastableMultiPolygon, BroadcastablePoint, BroadcastablePolygon,
};
use crate::scalar::Geometry;
use arrow_array::OffsetSizeTrait;
use crate::trait_::NativeGeometryAccessor;

/// An enum over all broadcastable geometry types.
///
/// [`IntoIterator`] is implemented for this, where it will iterate over the `Array` variant
/// normally but will iterate over the `Scalar` variant forever.
#[derive(Debug)]
pub enum BroadcastableGeometry<'a, O: OffsetSizeTrait> {
Point(BroadcastablePoint<'a>),
LineString(BroadcastableLineString<'a, O>),
Polygon(BroadcastablePolygon<'a, O>),
MultiPoint(BroadcastableMultiPoint<'a, O>),
MultiLineString(BroadcastableMultiLineString<'a, O>),
MultiPolygon(BroadcastableMultiPolygon<'a, O>),
}

pub enum BroadcastGeometryIter<'a, O: OffsetSizeTrait> {
Point(BroadcastPointIter<'a>),
LineString(BroadcastLineStringIter<'a, O>),
Polygon(BroadcastPolygonIter<'a, O>),
MultiPoint(BroadcastMultiPointIter<'a, O>),
MultiLineString(BroadcastMultiLineStringIter<'a, O>),
MultiPolygon(BroadcastMultiPolygonIter<'a, O>),
}

impl<'a, O: OffsetSizeTrait> IntoIterator for &'a BroadcastableGeometry<'a, O> {
type Item = Option<Geometry<'a, O>>;
type IntoIter = BroadcastGeometryIter<'a, O>;

fn into_iter(self) -> Self::IntoIter {
match self {
BroadcastableGeometry::Point(p) => BroadcastGeometryIter::Point(p.into_iter()),
BroadcastableGeometry::LineString(p) => {
BroadcastGeometryIter::LineString(p.into_iter())
}
BroadcastableGeometry::Polygon(p) => BroadcastGeometryIter::Polygon(p.into_iter()),
BroadcastableGeometry::MultiPoint(p) => {
BroadcastGeometryIter::MultiPoint(p.into_iter())
}
BroadcastableGeometry::MultiLineString(p) => {
BroadcastGeometryIter::MultiLineString(p.into_iter())
}
BroadcastableGeometry::MultiPolygon(p) => {
BroadcastGeometryIter::MultiPolygon(p.into_iter())
}
}
}
}

impl<'a, O: OffsetSizeTrait> Iterator for BroadcastGeometryIter<'a, O> {
type Item = Option<Geometry<'a, O>>;

fn next(&mut self) -> Option<Self::Item> {
match self {
BroadcastGeometryIter::Point(p) => p.next().map(|g| g.map(Geometry::Point)),
BroadcastGeometryIter::LineString(p) => p.next().map(|g| g.map(Geometry::LineString)),
BroadcastGeometryIter::Polygon(p) => p.next().map(|g| g.map(Geometry::Polygon)),
BroadcastGeometryIter::MultiPoint(p) => p.next().map(|g| g.map(Geometry::MultiPoint)),
BroadcastGeometryIter::MultiLineString(p) => {
p.next().map(|g| g.map(Geometry::MultiLineString))
}
BroadcastGeometryIter::MultiPolygon(p) => {
p.next().map(|g| g.map(Geometry::MultiPolygon))
}
}
}
pub enum BroadcastableGeoGeometry<'a> {
Scalar(&'a geo::Geometry),
Array(&'a dyn NativeGeometryAccessor<'a, 2>),
}
78 changes: 78 additions & 0 deletions src/algorithm/broadcasting/geometry_bak.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use crate::algorithm::broadcasting::linestring::BroadcastLineStringIter;
use crate::algorithm::broadcasting::multilinestring::BroadcastMultiLineStringIter;
use crate::algorithm::broadcasting::multipoint::BroadcastMultiPointIter;
use crate::algorithm::broadcasting::multipolygon::BroadcastMultiPolygonIter;
use crate::algorithm::broadcasting::point::BroadcastPointIter;
use crate::algorithm::broadcasting::polygon::BroadcastPolygonIter;
use crate::algorithm::broadcasting::{
BroadcastableLineString, BroadcastableMultiLineString, BroadcastableMultiPoint,
BroadcastableMultiPolygon, BroadcastablePoint, BroadcastablePolygon,
};
use crate::scalar::Geometry;
use arrow_array::OffsetSizeTrait;

/// An enum over all broadcastable geometry types.
///
/// [`IntoIterator`] is implemented for this, where it will iterate over the `Array` variant
/// normally but will iterate over the `Scalar` variant forever.
#[derive(Debug)]
pub enum BroadcastableGeometry<'a, O: OffsetSizeTrait> {
Point(BroadcastablePoint<'a>),
LineString(BroadcastableLineString<'a, O>),
Polygon(BroadcastablePolygon<'a, O>),
MultiPoint(BroadcastableMultiPoint<'a, O>),
MultiLineString(BroadcastableMultiLineString<'a, O>),
MultiPolygon(BroadcastableMultiPolygon<'a, O>),
}

pub enum BroadcastGeometryIter<'a, O: OffsetSizeTrait> {
Point(BroadcastPointIter<'a>),
LineString(BroadcastLineStringIter<'a, O>),
Polygon(BroadcastPolygonIter<'a, O>),
MultiPoint(BroadcastMultiPointIter<'a, O>),
MultiLineString(BroadcastMultiLineStringIter<'a, O>),
MultiPolygon(BroadcastMultiPolygonIter<'a, O>),
}

impl<'a, O: OffsetSizeTrait> IntoIterator for &'a BroadcastableGeometry<'a, O> {
type Item = Option<Geometry<'a, O>>;
type IntoIter = BroadcastGeometryIter<'a, O>;

fn into_iter(self) -> Self::IntoIter {
match self {
BroadcastableGeometry::Point(p) => BroadcastGeometryIter::Point(p.into_iter()),
BroadcastableGeometry::LineString(p) => {
BroadcastGeometryIter::LineString(p.into_iter())
}
BroadcastableGeometry::Polygon(p) => BroadcastGeometryIter::Polygon(p.into_iter()),
BroadcastableGeometry::MultiPoint(p) => {
BroadcastGeometryIter::MultiPoint(p.into_iter())
}
BroadcastableGeometry::MultiLineString(p) => {
BroadcastGeometryIter::MultiLineString(p.into_iter())
}
BroadcastableGeometry::MultiPolygon(p) => {
BroadcastGeometryIter::MultiPolygon(p.into_iter())
}
}
}
}

impl<'a, O: OffsetSizeTrait> Iterator for BroadcastGeometryIter<'a, O> {
type Item = Option<Geometry<'a, O>>;

fn next(&mut self) -> Option<Self::Item> {
match self {
BroadcastGeometryIter::Point(p) => p.next().map(|g| g.map(Geometry::Point)),
BroadcastGeometryIter::LineString(p) => p.next().map(|g| g.map(Geometry::LineString)),
BroadcastGeometryIter::Polygon(p) => p.next().map(|g| g.map(Geometry::Polygon)),
BroadcastGeometryIter::MultiPoint(p) => p.next().map(|g| g.map(Geometry::MultiPoint)),
BroadcastGeometryIter::MultiLineString(p) => {
p.next().map(|g| g.map(Geometry::MultiLineString))
}
BroadcastGeometryIter::MultiPolygon(p) => {
p.next().map(|g| g.map(Geometry::MultiPolygon))
}
}
}
}
2 changes: 1 addition & 1 deletion src/algorithm/broadcasting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
mod primitive;
mod vec;

// pub use geometry::BroadcastableGeometry;
// pub use geometry::BroadcastableGeoGeometry;
// pub use linestring::BroadcastableLineString;
// pub use multilinestring::BroadcastableMultiLineString;
// pub use multipoint::BroadcastableMultiPoint;
Expand Down
11 changes: 1 addition & 10 deletions src/algorithm/geo/affine_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,6 @@ impl AffineOps<&AffineTransform> for &dyn NativeArray {
}
}

impl AffineOps<&AffineTransform> for ChunkedPointArray<2> {
type Output = Self;

fn affine_transform(&self, transform: &AffineTransform) -> Self::Output {
self.map(|chunk| chunk.affine_transform(transform))
.try_into()
.unwrap()
}
}

macro_rules! impl_chunked {
($struct_name:ty) => {
impl AffineOps<&AffineTransform> for $struct_name {
Expand All @@ -173,6 +163,7 @@ macro_rules! impl_chunked {
};
}

impl_chunked!(ChunkedPointArray<2>);
impl_chunked!(ChunkedLineStringArray<2>);
impl_chunked!(ChunkedPolygonArray<2>);
impl_chunked!(ChunkedMultiPointArray<2>);
Expand Down
89 changes: 19 additions & 70 deletions src/algorithm/geo/contains.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::algorithm::native::{Binary, Unary};
use crate::algorithm::native::binary::try_binary_boolean_native_geometry;
use crate::algorithm::native::Unary;
use crate::array::*;
use crate::datatypes::{Dimension, NativeType};
use crate::error::GeoArrowError;
Expand All @@ -10,7 +11,7 @@ use crate::io::geo::{
geometry_collection_to_geo, geometry_to_geo, line_string_to_geo, multi_line_string_to_geo,
multi_point_to_geo, multi_polygon_to_geo, point_to_geo, polygon_to_geo,
};
use crate::trait_::{ArrayAccessor, NativeScalar};
use crate::trait_::{ArrayAccessor, NativeGeometryAccessor, NativeScalar};
use crate::NativeArray;
use arrow_array::builder::BooleanBuilder;
use arrow_array::BooleanArray;
Expand Down Expand Up @@ -50,84 +51,32 @@ use geo::Contains as _Contains;
/// // Point in Polygon
/// assert!(polygon.contains(&point!(x: 1., y: 1.)));
/// ```
pub trait Contains<Rhs = Self> {
fn contains(&self, rhs: &Rhs) -> BooleanArray;
}

// ┌────────────────────────────────┐
// │ Implementations for RHS arrays │
// └────────────────────────────────┘

// Note: this implementation is outside the macro because it is not generic over O
impl Contains for PointArray<2> {
fn contains(&self, rhs: &Self) -> BooleanArray {
self.try_binary_boolean(rhs, |left, right| {
Ok(left.to_geo().contains(&right.to_geo()))
})
.unwrap()
}
pub trait Contains<'a, Rhs> {
fn contains(&'a self, rhs: &'a Rhs) -> BooleanArray;
}

// Implementation that iterates over geo objects
macro_rules! iter_geo_impl {
($first:ty, $second:ty) => {
impl<'a> Contains<$second> for $first {
fn contains(&self, rhs: &$second) -> BooleanArray {
self.try_binary_boolean(rhs, |left, right| {
Ok(left.to_geo().contains(&right.to_geo()))
($array_type:ty) => {
impl<'a, R: NativeGeometryAccessor<'a, 2>> Contains<'a, R> for $array_type {
fn contains(&'a self, rhs: &'a R) -> BooleanArray {
try_binary_boolean_native_geometry(self, rhs, |l, r| {
Ok(l.to_geo().contains(&r.to_geo()))
})
.unwrap()
}
}
};
}

// Implementations on PointArray
iter_geo_impl!(PointArray<2>, LineStringArray<2>);
iter_geo_impl!(PointArray<2>, PolygonArray<2>);
iter_geo_impl!(PointArray<2>, MultiPointArray<2>);
iter_geo_impl!(PointArray<2>, MultiLineStringArray<2>);
iter_geo_impl!(PointArray<2>, MultiPolygonArray<2>);

// Implementations on LineStringArray
iter_geo_impl!(LineStringArray<2>, PointArray<2>);
iter_geo_impl!(LineStringArray<2>, LineStringArray<2>);
iter_geo_impl!(LineStringArray<2>, PolygonArray<2>);
iter_geo_impl!(LineStringArray<2>, MultiPointArray<2>);
iter_geo_impl!(LineStringArray<2>, MultiLineStringArray<2>);
iter_geo_impl!(LineStringArray<2>, MultiPolygonArray<2>);

// Implementations on PolygonArray
iter_geo_impl!(PolygonArray<2>, PointArray<2>);
iter_geo_impl!(PolygonArray<2>, LineStringArray<2>);
iter_geo_impl!(PolygonArray<2>, PolygonArray<2>);
iter_geo_impl!(PolygonArray<2>, MultiPointArray<2>);
iter_geo_impl!(PolygonArray<2>, MultiLineStringArray<2>);
iter_geo_impl!(PolygonArray<2>, MultiPolygonArray<2>);

// Implementations on MultiPointArray
iter_geo_impl!(MultiPointArray<2>, PointArray<2>);
iter_geo_impl!(MultiPointArray<2>, LineStringArray<2>);
iter_geo_impl!(MultiPointArray<2>, PolygonArray<2>);
iter_geo_impl!(MultiPointArray<2>, MultiPointArray<2>);
iter_geo_impl!(MultiPointArray<2>, MultiLineStringArray<2>);
iter_geo_impl!(MultiPointArray<2>, MultiPolygonArray<2>);

// Implementations on MultiLineStringArray
iter_geo_impl!(MultiLineStringArray<2>, PointArray<2>);
iter_geo_impl!(MultiLineStringArray<2>, LineStringArray<2>);
iter_geo_impl!(MultiLineStringArray<2>, PolygonArray<2>);
iter_geo_impl!(MultiLineStringArray<2>, MultiPointArray<2>);
iter_geo_impl!(MultiLineStringArray<2>, MultiLineStringArray<2>);
iter_geo_impl!(MultiLineStringArray<2>, MultiPolygonArray<2>);

// Implementations on MultiPolygonArray
iter_geo_impl!(MultiPolygonArray<2>, PointArray<2>);
iter_geo_impl!(MultiPolygonArray<2>, LineStringArray<2>);
iter_geo_impl!(MultiPolygonArray<2>, PolygonArray<2>);
iter_geo_impl!(MultiPolygonArray<2>, MultiPointArray<2>);
iter_geo_impl!(MultiPolygonArray<2>, MultiLineStringArray<2>);
iter_geo_impl!(MultiPolygonArray<2>, MultiPolygonArray<2>);
iter_geo_impl!(PointArray<2>);
iter_geo_impl!(LineStringArray<2>);
iter_geo_impl!(PolygonArray<2>);
iter_geo_impl!(MultiPointArray<2>);
iter_geo_impl!(MultiLineStringArray<2>);
iter_geo_impl!(MultiPolygonArray<2>);
iter_geo_impl!(MixedGeometryArray<2>);
iter_geo_impl!(GeometryCollectionArray<2>);
iter_geo_impl!(RectArray<2>);

// ┌─────────────────────────────────┐
// │ Implementations for RHS scalars │
Expand Down
Loading
Loading