From 807038df73de8d4ec06d79ba34ade6e15c281e59 Mon Sep 17 00:00:00 2001 From: arriopolis Date: Fri, 9 Jan 2026 13:17:16 -0800 Subject: [PATCH] Added a spatial index to the overlayng polygon builder. Signed-off-by: arriopolis --- .../jts/operation/overlayng/PolygonBuilder.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/core/src/main/java/org/locationtech/jts/operation/overlayng/PolygonBuilder.java b/modules/core/src/main/java/org/locationtech/jts/operation/overlayng/PolygonBuilder.java index 46d6b1556c..cc8f46d261 100644 --- a/modules/core/src/main/java/org/locationtech/jts/operation/overlayng/PolygonBuilder.java +++ b/modules/core/src/main/java/org/locationtech/jts/operation/overlayng/PolygonBuilder.java @@ -19,6 +19,8 @@ import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.TopologyException; import org.locationtech.jts.util.Assert; +import org.locationtech.jts.index.SpatialIndex; +import org.locationtech.jts.index.hprtree.HPRtree; class PolygonBuilder { @@ -175,11 +177,16 @@ private static void assignHoles(OverlayEdgeRing shell, List edg */ private void placeFreeHoles(List shellList, List freeHoleList) { - // TODO: use a spatial index to improve performance + SpatialIndex index = new HPRtree(); + for (OverlayEdgeRing shell : shellList) { + index.insert(shell.getRing().getEnvelopeInternal(), shell); + } + for (OverlayEdgeRing hole : freeHoleList ) { // only place this hole if it doesn't yet have a shell if (hole.getShell() == null) { - OverlayEdgeRing shell = hole.findEdgeRingContaining(shellList); + List shellListOverlaps = index.query(hole.getRing().getEnvelopeInternal()); + OverlayEdgeRing shell = hole.findEdgeRingContaining(shellListOverlaps); // only when building a polygon-valid result if (isEnforcePolygonal && shell == null) { throw new TopologyException("unable to assign free hole to a shell", hole.getCoordinate());