You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@sedona.apache.org by "Kontinuation (via GitHub)" <gi...@apache.org> on 2025/09/12 16:23:20 UTC
[PR] ST_Distance and ST_DWithin based on georust/geo [sedona-db]
Kontinuation opened a new pull request, #73:
URL: https://github.com/apache/sedona-db/pull/73
This patch implements ST_Distance and ST_DWithin using georust/geo's Euclidean distance function.
Performance comparison with GEOS-based implementation:
GEO:
```
geo-st_distance-ArrayScalar(Point, Polygon(10))
time: [19.120 ms 19.171 ms 19.227 ms]
geo-st_distance-ArrayScalar(Point, Polygon(500))
time: [446.14 ms 448.10 ms 450.64 ms]
```
GEOS:
```
geos-st_distance-ArrayScalar(Polygon(10), Polygon(10))
time: [187.51 ms 188.38 ms 189.72 ms]
geos-st_distance-ArrayScalar(Polygon(10), Polygon(500))
time: [2.8651 s 2.8735 s 2.8822 s]
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] ST_Distance and ST_DWithin based on georust/geo [sedona-db]
Posted by "jesspav (via GitHub)" <gi...@apache.org>.
jesspav commented on PR #73:
URL: https://github.com/apache/sedona-db/pull/73#issuecomment-3286277328
Looks great!
Do these functions not apply to geographies?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] ST_Distance and ST_DWithin based on georust/geo [sedona-db]
Posted by "Kontinuation (via GitHub)" <gi...@apache.org>.
Kontinuation commented on PR #73:
URL: https://github.com/apache/sedona-db/pull/73#issuecomment-3286300851
> Looks great! Do these functions not apply to geographies?
Geographies has its own implementation of ST_Distance: https://github.com/apache/sedona-db/blob/3d0122730166c6b9eb5e9fc303d0262829673191/c/sedona-s2geography/src/scalar_kernel.rs#L85-L91
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] ST_Distance and ST_DWithin based on georust/geo [sedona-db]
Posted by "jiayuasu (via GitHub)" <gi...@apache.org>.
jiayuasu merged PR #73:
URL: https://github.com/apache/sedona-db/pull/73
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] ST_Distance and ST_DWithin based on georust/geo [sedona-db]
Posted by "Kontinuation (via GitHub)" <gi...@apache.org>.
Kontinuation commented on code in PR #73:
URL: https://github.com/apache/sedona-db/pull/73#discussion_r2345112335
##########
rust/sedona-geo/src/st_dwithin.rs:
##########
@@ -0,0 +1,166 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+use std::sync::Arc;
+
+use arrow_array::builder::BooleanBuilder;
+use arrow_schema::DataType;
+use datafusion_common::{error::Result, DataFusionError};
+use datafusion_expr::ColumnarValue;
+use geo::{Distance, Euclidean};
+use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
+use sedona_functions::executor::WkbExecutor;
+use sedona_schema::{datatypes::SedonaType, matchers::ArgMatcher};
+use wkb::reader::Wkb;
+
+use crate::to_geo::item_to_geometry;
+
+/// ST_DWithin() implementation using [Euclidean] [Distance]
+pub fn st_dwithin_impl() -> ScalarKernelRef {
+ Arc::new(STDWithin {})
+}
+
+#[derive(Debug)]
+struct STDWithin {}
+
+impl SedonaScalarKernel for STDWithin {
+ fn return_type(&self, args: &[SedonaType]) -> Result<Option<SedonaType>> {
+ let matcher = ArgMatcher::new(
+ vec![
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_numeric(),
+ ],
+ SedonaType::Arrow(DataType::Boolean),
+ );
+
+ matcher.match_args(args)
+ }
+
+ fn invoke_batch(
+ &self,
+ arg_types: &[SedonaType],
+ args: &[ColumnarValue],
+ ) -> Result<ColumnarValue> {
+ // Extract the constant scalar value before looping over the input geometries
+ let distance: Option<f64>;
+ let arg2 = args[2].cast_to(&DataType::Float64, None)?;
+ if let ColumnarValue::Scalar(scalar_arg) = &arg2 {
+ if scalar_arg.is_null() {
+ distance = None;
+ } else {
+ distance = Some(f64::try_from(scalar_arg.clone())?);
+ }
+ } else {
+ return Err(DataFusionError::Execution(format!(
+ "Invalid distance: {:?}",
+ args[2]
+ )));
+ }
Review Comment:
I am simply replicating what st_dwithin for GEOS does: https://github.com/apache/sedona-db/blob/aa4f80a5732e0799e8637930304e86ad2d7c46bb/c/sedona-geos/src/st_dwithin.rs#L56-L70
I'll address the same problem in GEOS UDF code in this patch.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] ST_Distance and ST_DWithin based on georust/geo [sedona-db]
Posted by "paleolimbot (via GitHub)" <gi...@apache.org>.
paleolimbot commented on code in PR #73:
URL: https://github.com/apache/sedona-db/pull/73#discussion_r2345064736
##########
rust/sedona-geo/src/st_dwithin.rs:
##########
@@ -0,0 +1,166 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+use std::sync::Arc;
+
+use arrow_array::builder::BooleanBuilder;
+use arrow_schema::DataType;
+use datafusion_common::{error::Result, DataFusionError};
+use datafusion_expr::ColumnarValue;
+use geo::{Distance, Euclidean};
+use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
+use sedona_functions::executor::WkbExecutor;
+use sedona_schema::{datatypes::SedonaType, matchers::ArgMatcher};
+use wkb::reader::Wkb;
+
+use crate::to_geo::item_to_geometry;
+
+/// ST_DWithin() implementation using [Euclidean] [Distance]
+pub fn st_dwithin_impl() -> ScalarKernelRef {
+ Arc::new(STDWithin {})
+}
+
+#[derive(Debug)]
+struct STDWithin {}
+
+impl SedonaScalarKernel for STDWithin {
+ fn return_type(&self, args: &[SedonaType]) -> Result<Option<SedonaType>> {
+ let matcher = ArgMatcher::new(
+ vec![
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_numeric(),
+ ],
+ SedonaType::Arrow(DataType::Boolean),
+ );
+
+ matcher.match_args(args)
+ }
+
+ fn invoke_batch(
+ &self,
+ arg_types: &[SedonaType],
+ args: &[ColumnarValue],
+ ) -> Result<ColumnarValue> {
+ // Extract the constant scalar value before looping over the input geometries
+ let distance: Option<f64>;
+ let arg2 = args[2].cast_to(&DataType::Float64, None)?;
+ if let ColumnarValue::Scalar(scalar_arg) = &arg2 {
+ if scalar_arg.is_null() {
+ distance = None;
+ } else {
+ distance = Some(f64::try_from(scalar_arg.clone())?);
+ }
+ } else {
+ return Err(DataFusionError::Execution(format!(
+ "Invalid distance: {:?}",
+ args[2]
+ )));
+ }
+
+ let executor = WkbExecutor::new(arg_types, args);
+ let mut builder = BooleanBuilder::with_capacity(executor.num_iterations());
+ executor.execute_wkb_wkb_void(|maybe_wkb0, maybe_wkb1| {
+ match (maybe_wkb0, maybe_wkb1, distance) {
+ (Some(wkb0), Some(wkb1), Some(distance)) => {
+ builder.append_value(invoke_scalar(wkb0, wkb1, distance)?);
+ }
+ _ => builder.append_null(),
+ }
+
+ Ok(())
+ })?;
+
+ executor.finish(Arc::new(builder.finish()))
+ }
+}
+
+fn invoke_scalar(wkb_a: &Wkb, wkb_b: &Wkb, distance_bound: f64) -> Result<bool> {
+ let geom_a = item_to_geometry(wkb_a)?;
+ let geom_b = item_to_geometry(wkb_b)?;
Review Comment:
Just double-checking: do we need these conversions, or is the distance metric implemented for the generic case?
Also, it should be more efficient to use the `GeoTypesExecutor`, which should ensure that scalar inputs on either the right or left are only converted once.
##########
rust/sedona-geo/src/st_dwithin.rs:
##########
@@ -0,0 +1,166 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+use std::sync::Arc;
+
+use arrow_array::builder::BooleanBuilder;
+use arrow_schema::DataType;
+use datafusion_common::{error::Result, DataFusionError};
+use datafusion_expr::ColumnarValue;
+use geo::{Distance, Euclidean};
+use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
+use sedona_functions::executor::WkbExecutor;
+use sedona_schema::{datatypes::SedonaType, matchers::ArgMatcher};
+use wkb::reader::Wkb;
+
+use crate::to_geo::item_to_geometry;
+
+/// ST_DWithin() implementation using [Euclidean] [Distance]
+pub fn st_dwithin_impl() -> ScalarKernelRef {
+ Arc::new(STDWithin {})
+}
+
+#[derive(Debug)]
+struct STDWithin {}
+
+impl SedonaScalarKernel for STDWithin {
+ fn return_type(&self, args: &[SedonaType]) -> Result<Option<SedonaType>> {
+ let matcher = ArgMatcher::new(
+ vec![
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_numeric(),
+ ],
+ SedonaType::Arrow(DataType::Boolean),
+ );
+
+ matcher.match_args(args)
+ }
+
+ fn invoke_batch(
+ &self,
+ arg_types: &[SedonaType],
+ args: &[ColumnarValue],
+ ) -> Result<ColumnarValue> {
+ // Extract the constant scalar value before looping over the input geometries
+ let distance: Option<f64>;
+ let arg2 = args[2].cast_to(&DataType::Float64, None)?;
+ if let ColumnarValue::Scalar(scalar_arg) = &arg2 {
+ if scalar_arg.is_null() {
+ distance = None;
+ } else {
+ distance = Some(f64::try_from(scalar_arg.clone())?);
+ }
+ } else {
+ return Err(DataFusionError::Execution(format!(
+ "Invalid distance: {:?}",
+ args[2]
+ )));
+ }
Review Comment:
This will error when `distance` isn't a constant? I think you could probably handle this case with:
```rust
let arg2_array = arg2.to_array(executor.num_iterations())?;
let arg2_f64_array = as_float64_array(&arg2_array)?;
let arg2_iter = arg2_f64_array.iter();
// In the loop
let distance = arg2_iter.next().unwrap()
```
That is possibly slower for the scalar case and could be kept separate if it ends up mattering.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] ST_Distance and ST_DWithin based on georust/geo [sedona-db]
Posted by "Kontinuation (via GitHub)" <gi...@apache.org>.
Kontinuation commented on code in PR #73:
URL: https://github.com/apache/sedona-db/pull/73#discussion_r2345116892
##########
rust/sedona-geo/src/st_dwithin.rs:
##########
@@ -0,0 +1,166 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+use std::sync::Arc;
+
+use arrow_array::builder::BooleanBuilder;
+use arrow_schema::DataType;
+use datafusion_common::{error::Result, DataFusionError};
+use datafusion_expr::ColumnarValue;
+use geo::{Distance, Euclidean};
+use sedona_expr::scalar_udf::{ScalarKernelRef, SedonaScalarKernel};
+use sedona_functions::executor::WkbExecutor;
+use sedona_schema::{datatypes::SedonaType, matchers::ArgMatcher};
+use wkb::reader::Wkb;
+
+use crate::to_geo::item_to_geometry;
+
+/// ST_DWithin() implementation using [Euclidean] [Distance]
+pub fn st_dwithin_impl() -> ScalarKernelRef {
+ Arc::new(STDWithin {})
+}
+
+#[derive(Debug)]
+struct STDWithin {}
+
+impl SedonaScalarKernel for STDWithin {
+ fn return_type(&self, args: &[SedonaType]) -> Result<Option<SedonaType>> {
+ let matcher = ArgMatcher::new(
+ vec![
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_geometry(),
+ ArgMatcher::is_numeric(),
+ ],
+ SedonaType::Arrow(DataType::Boolean),
+ );
+
+ matcher.match_args(args)
+ }
+
+ fn invoke_batch(
+ &self,
+ arg_types: &[SedonaType],
+ args: &[ColumnarValue],
+ ) -> Result<ColumnarValue> {
+ // Extract the constant scalar value before looping over the input geometries
+ let distance: Option<f64>;
+ let arg2 = args[2].cast_to(&DataType::Float64, None)?;
+ if let ColumnarValue::Scalar(scalar_arg) = &arg2 {
+ if scalar_arg.is_null() {
+ distance = None;
+ } else {
+ distance = Some(f64::try_from(scalar_arg.clone())?);
+ }
+ } else {
+ return Err(DataFusionError::Execution(format!(
+ "Invalid distance: {:?}",
+ args[2]
+ )));
+ }
+
+ let executor = WkbExecutor::new(arg_types, args);
+ let mut builder = BooleanBuilder::with_capacity(executor.num_iterations());
+ executor.execute_wkb_wkb_void(|maybe_wkb0, maybe_wkb1| {
+ match (maybe_wkb0, maybe_wkb1, distance) {
+ (Some(wkb0), Some(wkb1), Some(distance)) => {
+ builder.append_value(invoke_scalar(wkb0, wkb1, distance)?);
+ }
+ _ => builder.append_null(),
+ }
+
+ Ok(())
+ })?;
+
+ executor.finish(Arc::new(builder.finish()))
+ }
+}
+
+fn invoke_scalar(wkb_a: &Wkb, wkb_b: &Wkb, distance_bound: f64) -> Result<bool> {
+ let geom_a = item_to_geometry(wkb_a)?;
+ let geom_b = item_to_geometry(wkb_b)?;
Review Comment:
The generic distance PR was merged 1 hour ago. I'll remove the conversion and call distance_ext directly on WKB values.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org