-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Received this error: TopologyException: unable to assign free hole to a shell at 5718.16259765625 3264.425048828125
Appears this could be due to self intersecting polygons.
Updated fix_invalid_geometry to the following to handle this and now sample completes successfully.
def fix_self_intersection(poly):
"""
Attempts to fix self-intersecting polygons using buffer(0).
Returns the fixed Polygon, or None if fixing failed or result is not a Polygon.
"""
if poly.is_valid:
return poly
try:
# buffer(0) is a common trick to fix self-intersections
fixed_poly = poly.buffer(0)
# buffer(0) might return MultiPolygon - take largest component
if fixed_poly.geom_type == 'MultiPolygon':
fixed_poly = max(fixed_poly.geoms, key=lambda p: p.area)
# Ensure the result is actually a Polygon (not Point/LineString/Empty)
if fixed_poly.geom_type == 'Polygon':
return fixed_poly
return None
except Exception:
return None
def fix_invalid_geometry(gdf: gpd.GeoDataFrame):
"""
Fix invalid geometries by first attempting to resort coordinates,
and then attempting to fix self-intersections via buffer(0) for those
that remain invalid.
"""
# 1. Identify initial invalid geometries
mask = ~gdf.geometry.is_valid
if not mask.any():
return gdf
# 2. First attempt: Resort coordinates
fixed_step1 = gdf.loc[mask].geometry.apply(resort_coordinates)
gdf.loc[mask, gdf.geometry.name] = fixed_step1
# 3. Check if any are STILL invalid after resort
sub_gdf = gdf.loc[mask]
mask_still_invalid = ~sub_gdf.geometry.is_valid
# If everything is fixed, we are done
if not mask_still_invalid.any():
return gdf
# Get the global indices of rows that are still invalid
problem_indices = sub_gdf[mask_still_invalid].index
# 4. Second attempt: Fix self-intersections (buffer(0))
fixed_step2 = gdf.loc[problem_indices].geometry.apply(fix_self_intersection)
# Update the GeoDataFrame
# Note: this will assign None if the fix failed.
gdf.loc[problem_indices, gdf.geometry.name] = fixed_step2
return gdf
Metadata
Metadata
Assignees
Labels
No labels