Problem
I have a polygon dataset containing many features with holes of various sizes. For my downstream modeling workflow, I need polygons without any holes. The challenge is to remove these holes efficiently while maintaining reasonable geometric properties and computational performance.
Details
My dataset contains polygons with:
- Small holes that could be filled without significant impact
- Large holes that shouldn't simply be filled as they represent meaningful gaps
- Complex polygons with multiple holes of mixed sizes
- Varying exterior boundary complexity
Requirements Output polygons must have no holes; Preserve reasonable geometric integrity; Handle large datasets efficiently; Maintain topological consistency
What I Have Tried
Approach 1: Hybrid Fill/Split Strategy
Fills small holes (≤500m²) directly
Splits polygons along large holes by creating cutting lines through hole centroids
Uses cuts extending from exterior to exterior

# Simplified version of the splitting logic
def process_holes_hybrid(polygon, area_threshold=500):
if not polygon.interiors:
return [polygon]
small_holes = []
large_holes = []
for interior in polygon.interiors:
hole_area = Polygon(interior).area
if hole_area <= area_threshold:
small_holes.append(interior)
else:
large_holes.append(interior)
# Fill small holes by excluding them from new exterior
# Split along large holes using cutting lines
Problems with Approach 1: Works well for simple cases but fails with complex polygons;
Multiple large holes create overlapping cutting lines;
Complex exterior boundaries lead to nonsensical results;
Difficult to ensure proper topology
Approach 2: Triangulation and Reaggregation Triangulate the polygon using constrained Delaunay triangulation. Reaggregate triangles iteratively based on compactness metrics
from shapely import constrained_delaunay_triangles
import math
def calculate_polsby_popper(polygon):
area = polygon.area
perimeter = polygon.length
return (4 * math.pi * area) / (perimeter**2)
def explode_polygon_to_triangles(polygon):
triangles = constrained_delaunay_triangles(polygon)
return [geom for geom in triangles.geoms if isinstance(geom, Polygon)]
def optimize_polygon_compactness(polygons, max_iterations=3):
# Iteratively merge neighboring triangles if compactness improves
for iteration in range(max_iterations):
merged_any = False
# Logic to merge adjacent polygons based on:
# - Neighborhood check: poly1.distance(poly2) < threshold
# - Compactness improvement
# - Area preservation
Problems with Approach 2: Computationally expensive even for small polygons, Results not geometrically meaningful, Difficult to control the final polygon characteristics
Question
What's the best way to remove holes from polygons without breaking the geometry? Are there existing tools or libraries that handle this better than writing custom code? I need a solution that:
- Works with complex polygons having multiple holes
- Doesn't drastically change the polygon shape or area
- Performs reasonably well on large datasets
Environment: Python with GeoPandas/Shapely (but open to other tools and have access to ArcGIS Pro etc.)


Polygon(polygon.exterior.coords)?