-
Notifications
You must be signed in to change notification settings - Fork 46
Open
Description
Hi,
I was porting some DuckDB and Shapely code to SedonaDB to see if I could get better performance. While it does run faster, I found that the output of ST_Covers was not identical to PostGIS, DuckDB and Shapely in some cases.
I narrowed it down to the case when the child geometry is identical to a hole of the parent geometry.
Here's the smallest reproduction I could create:
# /// script
# requires-python = ">=3.14"
# dependencies = [
# "apache-sedona[db]>=1.8.1",
# "duckdb>=1.5.0",
# "shapely>=2.1.2",
# ]
# ///
import duckdb
import sedona.db
import shapely
parent_wkt = "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (1 1, 1 2, 2 1, 1 1))"
child_wkt = "POLYGON ((1 1, 1 2, 2 1, 1 1))"
duckdb_connection = duckdb.connect()
duckdb_connection.execute("install spatial")
duckdb_connection.execute("load spatial")
sedona_connection = sedona.db.connect()
parent_geometry = shapely.from_wkt(parent_wkt)
child_geometry = shapely.from_wkt(child_wkt)
for predicate, shapely_value in [
("ST_Intersects", shapely.intersects(parent_geometry, child_geometry)),
("ST_Covers", shapely.covers(parent_geometry, child_geometry)),
("ST_Contains", shapely.contains(parent_geometry, child_geometry)),
]:
duckdb_value = duckdb_connection.execute(
f"select {predicate}(ST_GeomFromText('{parent_wkt}'), ST_GeomFromText('{child_wkt}'))"
).fetchone()[0]
sedona_value = sedona_connection.sql(
f"select {predicate}(ST_GeomFromWKT('{parent_wkt}'), ST_GeomFromWKT('{child_wkt}')) as value"
).to_pandas()["value"][0]
print(
f"{predicate} duckdb={duckdb_value} sedona={sedona_value} shapely={shapely_value}"
)
Output:
ST_Intersects duckdb=True sedona=True shapely=True
ST_Covers duckdb=False sedona=True shapely=False
ST_Contains duckdb=False sedona=True shapely=False
Postgis:
postgres=# SELECT
ST_Intersects(parent, child) AS intersects,
ST_Covers(parent, child) AS covers,
ST_Contains(parent, child) AS contains
FROM (
SELECT
'POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (1 1, 1 2, 2 1, 1 1))'::geometry AS parent,
'POLYGON ((1 1, 1 2, 2 1, 1 1))'::geometry AS child
) t;
intersects | covers | contains
------------+--------+----------
t | f | f
(1 row)
ST_Covers and ST_Contains return true with SedonaDB but false with the other 3.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels