geoarrow_expr_geo/
relate.rs1use arrow_array::BooleanArray;
2use geo::Relate;
3use geo::relate::IntersectionMatrix;
4use geoarrow_array::{GeoArrowArray, GeoArrowArrayAccessor};
5use geoarrow_schema::error::{GeoArrowError, GeoArrowResult};
6
7use crate::util::downcast::downcast_geoarrow_array_two_args;
8use crate::util::to_geo::geometry_to_geo;
9
10pub fn relate_boolean(
11 left_array: &dyn GeoArrowArray,
12 right_array: &dyn GeoArrowArray,
13 relate_cb: impl Fn(IntersectionMatrix) -> bool,
14) -> GeoArrowResult<BooleanArray> {
15 if left_array.len() != right_array.len() {
16 Err(GeoArrowError::InvalidGeoArrow(
17 "Input arrays must have the same length".to_string(),
18 ))
19 } else {
20 downcast_geoarrow_array_two_args!(left_array, right_array, _relate_impl, relate_cb)
21 }
22}
23
24fn _relate_impl<'a>(
25 left_array: &'a impl GeoArrowArrayAccessor<'a>,
26 right_array: &'a impl GeoArrowArrayAccessor<'a>,
27 relate_cb: impl Fn(IntersectionMatrix) -> bool,
28) -> GeoArrowResult<BooleanArray> {
29 let mut builder = BooleanArray::builder(left_array.len());
30
31 for (maybe_left, maybe_right) in left_array.iter().zip(right_array.iter()) {
32 match (maybe_left, maybe_right) {
33 (Some(left), Some(right)) => {
34 let left_geom = geometry_to_geo(&left?)?;
35 let right_geom = geometry_to_geo(&right?)?;
36 let matrix = left_geom.relate(&right_geom);
37 builder.append_value(relate_cb(matrix));
38 }
39 _ => {
40 builder.append_null();
42 }
43 }
44 }
45
46 Ok(builder.finish())
47}