mirror of
https://github.com/wassname/geopandas.git
synced 2026-09-10 12:00:21 +08:00
BUG: Fix handling of empty shapely geometries in clip() (#2595)
This commit is contained in:
@@ -27,6 +27,7 @@ Deprecations and compatibility notes:
|
||||
- resolve ``matplotlib.cm`` warning in ``.explore()`` (#2596)
|
||||
|
||||
Bug fixes:
|
||||
- Fix cryptic error message in ``geopandas.clip()`` when clipping with an empty geometry (#2589)
|
||||
- Accessing `gdf.geometry` where the active geometry column is missing, and a column named `"geometry"` is present
|
||||
will now raise an `AttributeError`, rather than returning `gdf["geometry"]` (#2575)
|
||||
- Combining GeoSeries/GeoDataFrames with ``pandas.concat`` will no longer silently
|
||||
|
||||
@@ -7,6 +7,7 @@ A module to clip vector data using GeoPandas.
|
||||
"""
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import pandas.api.types
|
||||
from shapely.geometry import Polygon, MultiPolygon, box
|
||||
|
||||
@@ -168,7 +169,11 @@ def clip(gdf, mask, keep_geom_type=False):
|
||||
elif mask_is_list_like:
|
||||
box_mask = mask
|
||||
else:
|
||||
box_mask = mask.bounds
|
||||
# Avoid empty tuple returned by .bounds when geometry is empty. A tuple of
|
||||
# all nan values is consistent with the behavior of
|
||||
# {GeoSeries, GeoDataFrame}.total_bounds for empty geometries.
|
||||
# TODO(shapely) can simpely use mask.bounds once relying on Shapely 2.0
|
||||
box_mask = mask.bounds if not mask.is_empty else (np.nan,) * 4
|
||||
box_gdf = gdf.total_bounds
|
||||
if not (
|
||||
((box_mask[0] <= box_gdf[2]) and (box_gdf[0] <= box_mask[2]))
|
||||
|
||||
@@ -450,3 +450,28 @@ def test_clip_single_multipoly_no_extra_geoms(
|
||||
multi = buffered_locations.dissolve(by="type").reset_index()
|
||||
clipped = clip(multi, masks)
|
||||
assert clipped.geom_type[0] == "Polygon"
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:All-NaN slice encountered")
|
||||
@pytest.mark.parametrize(
|
||||
"mask",
|
||||
[
|
||||
Polygon(),
|
||||
(np.nan,) * 4,
|
||||
(np.nan, 0, np.nan, 1),
|
||||
GeoSeries([Polygon(), Polygon()], crs="EPSG:3857"),
|
||||
GeoSeries([Polygon(), Polygon()], crs="EPSG:3857").to_frame(),
|
||||
GeoSeries([], crs="EPSG:3857"),
|
||||
GeoSeries([], crs="EPSG:3857").to_frame(),
|
||||
],
|
||||
)
|
||||
def test_clip_empty_mask(buffered_locations, mask):
|
||||
"""Test that clipping with empty mask returns an empty result."""
|
||||
clipped = clip(buffered_locations, mask)
|
||||
assert_geodataframe_equal(
|
||||
clipped,
|
||||
GeoDataFrame([], columns=["geometry", "type"], crs="EPSG:3857"),
|
||||
check_index_type=False,
|
||||
)
|
||||
clipped = clip(buffered_locations.geometry, mask)
|
||||
assert_geoseries_equal(clipped, GeoSeries([], crs="EPSG:3857"))
|
||||
|
||||
Reference in New Issue
Block a user