Skip to content

Commit

Permalink
test: add buffer implementation and mark broken
Browse files Browse the repository at this point in the history
  • Loading branch information
ncclementi committed Nov 9, 2023
1 parent ef697bd commit 596f3d9
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 7 deletions.
9 changes: 8 additions & 1 deletion ibis/backends/duckdb/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ def _envelope(t, op):
return sa.func.st_envelope(arg, type_=Geometry_WKB)


def _geo_buffer(t, op):
arg = t.translate(op.arg)
radius = t.translate(op.radius)
return sa.func.st_buffer(arg, radius, type_=Geometry_WKB)


def _geo_unary_union(t, op):
arg = t.translate(op.arg)
return sa.func.st_union_agg(arg, type_=Geometry_WKB)
Expand Down Expand Up @@ -562,7 +568,8 @@ def _to_json_collection(t, op):
ops.GeoPoint: _geo_point,
ops.GeoAsText: unary(sa.func.ST_AsText),
ops.GeoArea: unary(sa.func.ST_Area),
# ops.GeoBuffer: fixed_arity(sa.func.ST_Buffer, 2), duckdb sup 2 or 3?
# ops.GeoBuffer: fixed_arity(sa.func.ST_Buffer, 2),
ops.GeoBuffer: _geo_buffer,
# ops.GeoCentroid: unary(sa.func.ST_Centroid),
ops.GeoCentroid: _centroid,
ops.GeoContains: fixed_arity(sa.func.ST_Contains, 2),
Expand Down
50 changes: 44 additions & 6 deletions ibis/backends/duckdb/tests/test_geospatial.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import geopandas as gpd
import geopandas.testing as gtm
import numpy.testing as npt
import pandas.testing as tm
import pyarrow as pa
Expand Down Expand Up @@ -231,12 +232,6 @@ def test_geospatial_y(zones, zones_gdf):
tm.assert_series_equal(y.to_pandas(), gp_cen.y, check_names=False)


# def test_geospatial_buffer()
# GeoBUffer in alchemy supports 2 arguments, but duckdb is a unary?
# actually docs are wrong, it takes 2 or 3 args
# looks like we have fixed_arity(sa.func.ST_Buffer, 2)


@pytest.mark.broken(["duckdb"], raises=AssertionError, reason="no match with geopandas")
def test_geospatial_unary_union(zones, zones_gdf):
unary_union = zones.geom.unary_union().name("unary_union")
Expand All @@ -245,3 +240,46 @@ def test_geospatial_unary_union(zones, zones_gdf):

# we should try to use equals_exact but not even equals pass
assert shapely.equals(shapely.from_wkb(unary_union.to_pandas()), gp_unary_union)


def test_geospatial_buffer_point(zones, zones_gdf):
# when we add a buffer to a single point things work
cen = zones.geom.centroid().name("centroid")
gp_cen = zones_gdf.geometry.centroid

buffer = cen.buffer(100.0)
# geopandas resolution default is 16, while duckdb is 8.
gp_buffer = gp_cen.buffer(100.0, resolution=8)

gtm.assert_geoseries_equal(
gpd.GeoSeries.from_wkb(buffer.to_pandas().values), gp_buffer, check_crs=False
)

# check areas are the same
tm.assert_series_equal(buffer.area().to_pandas(), gp_buffer.area, check_names=False)


@pytest.mark.broken(["duckdb"], raises=AssertionError, reason="no match with geopandas")
def test_geospatial_buffer(zones, zones_gdf):
# When generating buffer from a more complex geometry, we get a match on the geometry
# but errors in the area for ~7% of the series.

buffer = zones.geom.buffer(100.0)
# geopandas resolution default is 16, while duckdb is 8.
gp_buffer = zones_gdf.geometry.buffer(100.0, resolution=8)

# comparing the geometries directly works
gtm.assert_geoseries_equal(
gpd.GeoSeries.from_wkb(buffer.to_pandas().values), gp_buffer, check_crs=False
)

# when we check the area we have problems
# Notice that buffer.area().to_pandas() != gpd.GeoSeries.from_wkb(buffer.to_pandas().values).area
# Not clear which area is the correct one, geopandas in their area docs says
# Area may be invalid for a geographic CRS using degrees as units;
# use GeoSeries.to_crs() to project geometries to a planar CRS before using this function.
# gp_buffere.crs says axis info is ellipsoidal. But it is not clear how to project in this case
# when trying to_crs() with different epsg, I always get inf.
tm.assert_series_equal(
buffer.area().to_pandas(), gp_buffer.area, check_names=False, check_exact=False
)

0 comments on commit 596f3d9

Please sign in to comment.