Skip to content
Merged
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
154 changes: 67 additions & 87 deletions c/sedona-geos/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,97 +15,77 @@
// specific language governing permissions and limitations
// under the License.
use sedona_expr::aggregate_udf::SedonaAccumulatorRef;
use sedona_expr::scalar_udf::ScalarKernelRef;
use sedona_expr::scalar_udf::{IntoScalarKernelRefs, ScalarKernelRef};

use crate::{
distance::st_distance_impl,
st_area::st_area_impl,
st_boundary::st_boundary_impl,
st_buffer::{st_buffer_impl, st_buffer_style_impl},
st_centroid::st_centroid_impl,
st_concavehull::{st_concave_hull_allow_holes_impl, st_concave_hull_impl},
st_convexhull::st_convex_hull_impl,
st_dwithin::st_dwithin_impl,
st_isring::st_is_ring_impl,
st_issimple::st_is_simple_impl,
st_isvalid::st_is_valid_impl,
st_isvalidreason::st_is_valid_reason_impl,
st_length::st_length_impl,
st_line_merge::st_line_merge_impl,
st_makevalid::st_make_valid_impl,
st_minimumclearance::st_minimum_clearance_impl,
st_minimumclearance_line::st_minimum_clearance_line_impl,
st_nrings::st_nrings_impl,
st_numinteriorrings::st_num_interior_rings_impl,
st_numpoints::st_num_points_impl,
st_perimeter::st_perimeter_impl,
st_polygonize::st_polygonize_impl,
st_polygonize_agg::st_polygonize_agg_impl,
st_simplify::st_simplify_impl,
st_simplifypreservetopology::st_simplify_preserve_topology_impl,
st_snap::st_snap_impl,
st_unaryunion::st_unary_union_impl,
};

use crate::binary_predicates::{
st_contains_impl, st_covered_by_impl, st_covers_impl, st_crosses_impl, st_disjoint_impl,
st_equals_impl, st_intersects_impl, st_overlaps_impl, st_touches_impl, st_within_impl,
};
macro_rules! define_scalar_kernels {
($($name:expr => $impl:expr),* $(,)?) => {
vec![
$(
($name, $impl().into_scalar_kernel_refs()),
)*
]
};
}

use crate::overlay::{
st_difference_impl, st_intersection_impl, st_sym_difference_impl, st_union_impl,
};
macro_rules! define_aggregate_kernels {
($($name:expr => $impl:expr),* $(,)?) => {
vec![
$(
($name, $impl()),
)*
]
};
}

pub fn scalar_kernels() -> Vec<(&'static str, ScalarKernelRef)> {
vec![
("st_area", st_area_impl()),
("st_boundary", st_boundary_impl()),
("st_buffer", st_buffer_impl()),
("st_buffer", st_buffer_style_impl()),
("st_centroid", st_centroid_impl()),
("st_concavehull", st_concave_hull_allow_holes_impl()),
("st_concavehull", st_concave_hull_impl()),
("st_contains", st_contains_impl()),
("st_convexhull", st_convex_hull_impl()),
("st_coveredby", st_covered_by_impl()),
("st_covers", st_covers_impl()),
("st_crosses", st_crosses_impl()),
("st_difference", st_difference_impl()),
("st_disjoint", st_disjoint_impl()),
("st_distance", st_distance_impl()),
("st_dwithin", st_dwithin_impl()),
("st_equals", st_equals_impl()),
("st_intersection", st_intersection_impl()),
("st_intersects", st_intersects_impl()),
("st_isring", st_is_ring_impl()),
("st_issimple", st_is_simple_impl()),
("st_isvalid", st_is_valid_impl()),
("st_isvalidreason", st_is_valid_reason_impl()),
("st_length", st_length_impl()),
("st_linemerge", st_line_merge_impl()),
("st_numinteriorrings", st_num_interior_rings_impl()),
("st_numpoints", st_num_points_impl()),
("st_nrings", st_nrings_impl()),
("st_makevalid", st_make_valid_impl()),
("st_minimumclearance", st_minimum_clearance_impl()),
("st_minimumclearanceline", st_minimum_clearance_line_impl()),
("st_overlaps", st_overlaps_impl()),
("st_perimeter", st_perimeter_impl()),
("st_polygonize", st_polygonize_impl()),
("st_simplify", st_simplify_impl()),
(
"st_simplifypreservetopology",
st_simplify_preserve_topology_impl(),
),
("st_snap", st_snap_impl()),
("st_symdifference", st_sym_difference_impl()),
("st_touches", st_touches_impl()),
("st_unaryunion", st_unary_union_impl()),
("st_union", st_union_impl()),
("st_within", st_within_impl()),
]
pub fn scalar_kernels() -> Vec<(&'static str, Vec<ScalarKernelRef>)> {
define_scalar_kernels!(
"st_area" => crate::st_area::st_area_impl,
"st_boundary" => crate::st_boundary::st_boundary_impl,
"st_buffer" => crate::st_buffer::st_buffer_impl,
"st_buffer" => crate::st_buffer::st_buffer_style_impl,
"st_centroid" => crate::st_centroid::st_centroid_impl,
"st_concavehull" => crate::st_concavehull::st_concave_hull_allow_holes_impl,
"st_concavehull" => crate::st_concavehull::st_concave_hull_impl,
"st_contains" => crate::binary_predicates::st_contains_impl,
"st_convexhull" => crate::st_convexhull::st_convex_hull_impl,
"st_coveredby" => crate::binary_predicates::st_covered_by_impl,
"st_covers" => crate::binary_predicates::st_covers_impl,
"st_crosses" => crate::binary_predicates::st_crosses_impl,
"st_difference" => crate::overlay::st_difference_impl,
"st_disjoint" => crate::binary_predicates::st_disjoint_impl,
"st_distance" => crate::distance::st_distance_impl,
"st_dwithin" => crate::st_dwithin::st_dwithin_impl,
"st_equals" => crate::binary_predicates::st_equals_impl,
"st_intersection" => crate::overlay::st_intersection_impl,
"st_intersects" => crate::binary_predicates::st_intersects_impl,
"st_isring" => crate::st_isring::st_is_ring_impl,
"st_issimple" => crate::st_issimple::st_is_simple_impl,
"st_isvalid" => crate::st_isvalid::st_is_valid_impl,
"st_isvalidreason" => crate::st_isvalidreason::st_is_valid_reason_impl,
"st_length" => crate::st_length::st_length_impl,
"st_linemerge" => crate::st_line_merge::st_line_merge_impl,
"st_makevalid" => crate::st_makevalid::st_make_valid_impl,
"st_minimumclearance" => crate::st_minimumclearance::st_minimum_clearance_impl,
"st_minimumclearanceline" => crate::st_minimumclearance_line::st_minimum_clearance_line_impl,
"st_nrings" => crate::st_nrings::st_nrings_impl,
"st_numinteriorrings" => crate::st_numinteriorrings::st_num_interior_rings_impl,
"st_numpoints" => crate::st_numpoints::st_num_points_impl,
"st_overlaps" => crate::binary_predicates::st_overlaps_impl,
"st_perimeter" => crate::st_perimeter::st_perimeter_impl,
"st_polygonize" => crate::st_polygonize::st_polygonize_impl,
"st_simplify" => crate::st_simplify::st_simplify_impl,
"st_simplifypreservetopology" => crate::st_simplifypreservetopology::st_simplify_preserve_topology_impl,
"st_snap" => crate::st_snap::st_snap_impl,
"st_symdifference" => crate::overlay::st_sym_difference_impl,
"st_touches" => crate::binary_predicates::st_touches_impl,
"st_unaryunion" => crate::st_unaryunion::st_unary_union_impl,
"st_union" => crate::overlay::st_union_impl,
"st_within" => crate::binary_predicates::st_within_impl,
)
}

pub fn aggregate_kernels() -> Vec<(&'static str, SedonaAccumulatorRef)> {
vec![("st_polygonize_agg", st_polygonize_agg_impl())]
define_aggregate_kernels!(
"st_polygonize_agg" => crate::st_polygonize_agg::st_polygonize_agg_impl,
)
}
16 changes: 11 additions & 5 deletions c/sedona-geos/src/st_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ use arrow_schema::DataType;
use datafusion_common::{error::Result, DataFusionError};
use datafusion_expr::ColumnarValue;
use geos::Geom;
use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
use sedona_expr::{
item_crs::ItemCrsKernel,
scalar_udf::{ScalarKernelRef, SedonaScalarKernel},
};
use sedona_schema::{datatypes::SedonaType, matchers::ArgMatcher};

use crate::executor::GeosExecutor;

/// ST_Area() implementation using the geos crate
pub fn st_area_impl() -> ScalarKernelRef {
Arc::new(STArea {})
pub fn st_area_impl() -> Vec<ScalarKernelRef> {
ItemCrsKernel::wrap_impl(STArea {})
}

#[derive(Debug)]
Expand Down Expand Up @@ -78,13 +81,16 @@ mod tests {
use datafusion_common::ScalarValue;
use rstest::rstest;
use sedona_expr::scalar_udf::SedonaScalarUDF;
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_VIEW_GEOMETRY};
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_GEOMETRY_ITEM_CRS, WKB_VIEW_GEOMETRY};
use sedona_testing::testers::ScalarUdfTester;

use super::*;

#[rstest]
fn udf(#[values(WKB_GEOMETRY, WKB_VIEW_GEOMETRY)] sedona_type: SedonaType) {
fn udf(
#[values(WKB_GEOMETRY, WKB_VIEW_GEOMETRY, WKB_GEOMETRY_ITEM_CRS.clone())]
sedona_type: SedonaType,
) {
let udf = SedonaScalarUDF::from_impl("st_area", st_area_impl());
let tester = ScalarUdfTester::new(udf.into(), vec![sedona_type]);
tester.assert_return_type(DataType::Float64);
Expand Down
21 changes: 17 additions & 4 deletions c/sedona-geos/src/st_boundary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ use arrow_array::builder::BinaryBuilder;
use datafusion_common::{error::Result, DataFusionError};
use datafusion_expr::ColumnarValue;
use geos::{Geom, Geometry, GeometryTypes};
use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
use sedona_expr::{
item_crs::ItemCrsKernel,
scalar_udf::{ScalarKernelRef, SedonaScalarKernel},
};
use sedona_geometry::wkb_factory::WKB_MIN_PROBABLE_BYTES;
use sedona_schema::{
datatypes::{SedonaType, WKB_GEOMETRY},
Expand All @@ -32,8 +35,8 @@ use crate::executor::GeosExecutor;
use crate::geos_to_wkb::write_geos_geometry;

/// ST_Boundary() implementation using the geos crate
pub fn st_boundary_impl() -> ScalarKernelRef {
Arc::new(STBoundary {})
pub fn st_boundary_impl() -> Vec<ScalarKernelRef> {
ItemCrsKernel::wrap_impl(STBoundary {})
}

#[derive(Debug)]
Expand Down Expand Up @@ -284,7 +287,7 @@ fn collect_boundary_components(
mod tests {
use rstest::rstest;
use sedona_expr::scalar_udf::SedonaScalarUDF;
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_VIEW_GEOMETRY};
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_GEOMETRY_ITEM_CRS, WKB_VIEW_GEOMETRY};
use sedona_testing::testers::ScalarUdfTester;

use super::*;
Expand Down Expand Up @@ -367,4 +370,14 @@ mod tests {
let result = tester.invoke_scalar("GEOMETRYCOLLECTION EMPTY").unwrap();
tester.assert_scalar_result_equals(result, "GEOMETRYCOLLECTION EMPTY");
}

#[rstest]
fn udf_invoke_item_crs(#[values(WKB_GEOMETRY_ITEM_CRS.clone())] sedona_type: SedonaType) {
let udf = SedonaScalarUDF::from_impl("st_boundary", st_boundary_impl());
let tester = ScalarUdfTester::new(udf.into(), vec![sedona_type.clone()]);
tester.assert_return_type(sedona_type);

let result = tester.invoke_scalar("POINT (1 3)").unwrap();
tester.assert_scalar_result_equals(result, "GEOMETRYCOLLECTION EMPTY");
}
}
28 changes: 22 additions & 6 deletions c/sedona-geos/src/st_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use datafusion_common::error::Result;
use datafusion_common::{DataFusionError, ScalarValue};
use datafusion_expr::ColumnarValue;
use geos::{BufferParams, CapStyle, Geom, JoinStyle};
use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
use sedona_expr::{
item_crs::ItemCrsKernel,
scalar_udf::{ScalarKernelRef, SedonaScalarKernel},
};
use sedona_geometry::wkb_factory::WKB_MIN_PROBABLE_BYTES;
use sedona_schema::{
datatypes::{SedonaType, WKB_GEOMETRY},
Expand All @@ -46,8 +49,8 @@ use crate::geos_to_wkb::write_geos_geometry;
/// - side: both, left, right
/// - mitre_limit/miter_limit: numeric value
/// - quad_segs/quadrant_segments: integer value
pub fn st_buffer_impl() -> ScalarKernelRef {
Arc::new(STBuffer {})
pub fn st_buffer_impl() -> Vec<ScalarKernelRef> {
ItemCrsKernel::wrap_impl(STBuffer {})
}

#[derive(Debug)]
Expand All @@ -72,8 +75,8 @@ impl SedonaScalarKernel for STBuffer {
}
}

pub fn st_buffer_style_impl() -> ScalarKernelRef {
Arc::new(STBufferStyle {})
pub fn st_buffer_style_impl() -> Vec<ScalarKernelRef> {
ItemCrsKernel::wrap_impl(STBufferStyle {})
}
#[derive(Debug)]
struct STBufferStyle {}
Expand Down Expand Up @@ -296,7 +299,7 @@ mod tests {
use datafusion_common::ScalarValue;
use rstest::rstest;
use sedona_expr::scalar_udf::SedonaScalarUDF;
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_VIEW_GEOMETRY};
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_GEOMETRY_ITEM_CRS, WKB_VIEW_GEOMETRY};
use sedona_testing::compare::assert_array_equal;
use sedona_testing::create::create_array;
use sedona_testing::testers::ScalarUdfTester;
Expand Down Expand Up @@ -728,4 +731,17 @@ mod tests {
"Should handle complex string with both sides."
);
}

#[rstest]
fn udf_invoke_item_crs(#[values(WKB_GEOMETRY_ITEM_CRS.clone())] sedona_type: SedonaType) {
let udf = SedonaScalarUDF::from_impl("st_buffer", st_buffer_impl());
let tester = ScalarUdfTester::new(
udf.into(),
vec![sedona_type.clone(), SedonaType::Arrow(DataType::Float64)],
);
tester.assert_return_type(sedona_type);

let result = tester.invoke_scalar_scalar("POINT (0 0)", 1.0).unwrap();
assert!(!result.is_null());
}
}
23 changes: 19 additions & 4 deletions c/sedona-geos/src/st_centroid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ use arrow_array::builder::BinaryBuilder;
use datafusion_common::{error::Result, DataFusionError};
use datafusion_expr::ColumnarValue;
use geos::Geom;
use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
use sedona_expr::{
item_crs::ItemCrsKernel,
scalar_udf::{ScalarKernelRef, SedonaScalarKernel},
};
use sedona_geometry::wkb_factory::WKB_MIN_PROBABLE_BYTES;
use sedona_schema::{
datatypes::{SedonaType, WKB_GEOMETRY},
Expand All @@ -31,8 +34,8 @@ use crate::executor::GeosExecutor;
use crate::geos_to_wkb::write_geos_geometry;

/// ST_Centroid() implementation using the geos crate
pub fn st_centroid_impl() -> ScalarKernelRef {
Arc::new(STCentroid {})
pub fn st_centroid_impl() -> Vec<ScalarKernelRef> {
ItemCrsKernel::wrap_impl(STCentroid {})
}

#[derive(Debug)]
Expand Down Expand Up @@ -85,7 +88,7 @@ mod tests {
use datafusion_common::ScalarValue;
use rstest::rstest;
use sedona_expr::scalar_udf::SedonaScalarUDF;
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_VIEW_GEOMETRY};
use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_GEOMETRY_ITEM_CRS, WKB_VIEW_GEOMETRY};
use sedona_testing::compare::assert_array_equal;
use sedona_testing::create::create_array;
use sedona_testing::testers::ScalarUdfTester;
Expand Down Expand Up @@ -118,4 +121,16 @@ mod tests {
);
assert_array_equal(&tester.invoke_wkb_array(input_wkt).unwrap(), &expected);
}

#[rstest]
fn udf_invoke_item_crs(#[values(WKB_GEOMETRY_ITEM_CRS.clone())] sedona_type: SedonaType) {
let udf = SedonaScalarUDF::from_impl("st_centroid", st_centroid_impl());
let tester = ScalarUdfTester::new(udf.into(), vec![sedona_type.clone()]);
tester.assert_return_type(sedona_type);

let result = tester
.invoke_scalar("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))")
.unwrap();
tester.assert_scalar_result_equals(result, "POINT (0.5 0.5)");
}
}
Loading