From 0bdbb451a4ac409615697ff98fa73b6fcd47f7e3 Mon Sep 17 00:00:00 2001 From: Martin Fleischmann Date: Mon, 25 Mar 2024 21:06:22 +0100 Subject: [PATCH 1/5] fix geos issue, remove precision snapping --- libpysal/cg/voronoi.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libpysal/cg/voronoi.py b/libpysal/cg/voronoi.py index 7b560e90b..aac732847 100644 --- a/libpysal/cg/voronoi.py +++ b/libpysal/cg/voronoi.py @@ -313,7 +313,6 @@ def voronoi_frames( clip: str | shapely.Geometry | None = "bounding_box", shrink: float = 0, segment: float = 0, - grid_size: float = 1e-5, return_input: bool | None = None, as_gdf: bool | None = None, ) -> gpd.GeoSeries: @@ -352,9 +351,6 @@ def voronoi_frames( segment : float, optional Distance for the segmentation of lines used to add coordinates to lines or polygons prior Voronoi tessellation, by default 0 - grid_size : float, optional - Grid size precision under which the voronoi algorithm is generated, - by default 1e-5 return_input : bool, optional Whether to return the input geometry, defaults to True as_gdf : bool, optional @@ -383,8 +379,7 @@ def voronoi_frames( "projected CRS before using voronoi_polygons.", ) # Set precision of the input geometry (avoids GEOS precision issues) - objects = shapely.set_precision(geometry.geometry.copy(), grid_size) - + objects = geometry.copy() geom_types = objects.geom_type mask_poly = geom_types.isin(["Polygon", "MultiPolygon"]) mask_line = objects.geom_type.isin(["LineString", "MultiLineString"]) @@ -430,6 +425,12 @@ def voronoi_frames( ) # Get individual polygons out of the collection polygons = gpd.GeoSeries(shapely.get_parts(voronoi), crs=geometry.crs) + + # temporary fix for libgeos/geos#1062 + if not (polygons.geom_type == "Polygon").all(): + polygons = polygons.explode(ignore_index=True) + polygons = polygons[polygons.geom_type == "Polygon"] + # Assign to each input geometry the corresponding Voronoi polygon # TODO: check if we still need indexing after shapely/shapely#1968 is released if GPD_GE_013: From 02dffe6f9caed12f3835c0213f244091fcd54207 Mon Sep 17 00:00:00 2001 From: Martin Fleischmann Date: Mon, 25 Mar 2024 21:14:31 +0100 Subject: [PATCH 2/5] work on GeoSeries only --- libpysal/cg/voronoi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libpysal/cg/voronoi.py b/libpysal/cg/voronoi.py index aac732847..0af20bcbc 100644 --- a/libpysal/cg/voronoi.py +++ b/libpysal/cg/voronoi.py @@ -378,8 +378,9 @@ def voronoi_frames( "Use 'GeoSeries.to_crs()' to re-project geometries to a " "projected CRS before using voronoi_polygons.", ) - # Set precision of the input geometry (avoids GEOS precision issues) - objects = geometry.copy() + + objects = geometry.geometry.copy() + geom_types = objects.geom_type mask_poly = geom_types.isin(["Polygon", "MultiPolygon"]) mask_line = objects.geom_type.isin(["LineString", "MultiLineString"]) From 4d02cb057a1392e2e1d33a1fdcd1a7f592eb860d Mon Sep 17 00:00:00 2001 From: Martin Fleischmann Date: Mon, 25 Mar 2024 21:22:20 +0100 Subject: [PATCH 3/5] ensure validity --- libpysal/cg/voronoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpysal/cg/voronoi.py b/libpysal/cg/voronoi.py index 0af20bcbc..f63ccbc27 100644 --- a/libpysal/cg/voronoi.py +++ b/libpysal/cg/voronoi.py @@ -425,7 +425,7 @@ def voronoi_frames( shapely.GeometryCollection(objects.values), extend_to=limit ) # Get individual polygons out of the collection - polygons = gpd.GeoSeries(shapely.get_parts(voronoi), crs=geometry.crs) + polygons = gpd.GeoSeries(shapely.get_parts(voronoi), crs=geometry.crs).make_valid() # temporary fix for libgeos/geos#1062 if not (polygons.geom_type == "Polygon").all(): From 72571b29b66cea6929cbac37b3a6bc2f0effaf5c Mon Sep 17 00:00:00 2001 From: Martin Fleischmann Date: Mon, 25 Mar 2024 21:30:45 +0100 Subject: [PATCH 4/5] bring back precision set --- libpysal/cg/voronoi.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libpysal/cg/voronoi.py b/libpysal/cg/voronoi.py index f63ccbc27..90b98eeda 100644 --- a/libpysal/cg/voronoi.py +++ b/libpysal/cg/voronoi.py @@ -313,6 +313,7 @@ def voronoi_frames( clip: str | shapely.Geometry | None = "bounding_box", shrink: float = 0, segment: float = 0, + grid_size: float = 1e-5, return_input: bool | None = None, as_gdf: bool | None = None, ) -> gpd.GeoSeries: @@ -351,6 +352,9 @@ def voronoi_frames( segment : float, optional Distance for the segmentation of lines used to add coordinates to lines or polygons prior Voronoi tessellation, by default 0 + grid_size : float, optional + Grid size precision under which the voronoi algorithm is generated, + by default 1e-5 return_input : bool, optional Whether to return the input geometry, defaults to True as_gdf : bool, optional @@ -379,7 +383,8 @@ def voronoi_frames( "projected CRS before using voronoi_polygons.", ) - objects = geometry.geometry.copy() + # Set precision of the input geometry (avoids GEOS precision issues) + objects = shapely.set_precision(geometry.geometry.copy(), grid_size) geom_types = objects.geom_type mask_poly = geom_types.isin(["Polygon", "MultiPolygon"]) From 8752980c1913efdc4d6e48cb4fb2162e28ba50c2 Mon Sep 17 00:00:00 2001 From: Martin Fleischmann Date: Mon, 25 Mar 2024 22:09:41 +0100 Subject: [PATCH 5/5] make it compatible with older geopandas --- libpysal/cg/voronoi.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libpysal/cg/voronoi.py b/libpysal/cg/voronoi.py index 90b98eeda..48e98a82f 100644 --- a/libpysal/cg/voronoi.py +++ b/libpysal/cg/voronoi.py @@ -430,7 +430,9 @@ def voronoi_frames( shapely.GeometryCollection(objects.values), extend_to=limit ) # Get individual polygons out of the collection - polygons = gpd.GeoSeries(shapely.get_parts(voronoi), crs=geometry.crs).make_valid() + polygons = gpd.GeoSeries( + shapely.make_valid(shapely.get_parts(voronoi)), crs=geometry.crs + ) # temporary fix for libgeos/geos#1062 if not (polygons.geom_type == "Polygon").all():