@@ -2,6 +2,7 @@ import { BaseSolver } from "@tscircuit/solver-utils"
22import type { GraphicsObject } from "graphics-debug"
33import type { SimpleRouteJson } from "../types/srj-types"
44import type { Placed3D , XYRect } from "./rectdiff/types"
5+ import { FlatbushIndex } from "../data-structures/FlatbushIndex"
56
67export interface RectEdge {
78 rect : XYRect
@@ -53,6 +54,7 @@ interface GapFillState {
5354 layerCount : number
5455
5556 edges : RectEdge [ ]
57+ edgeSpatialIndex : FlatbushIndex < RectEdge >
5658
5759 phase : SubPhase
5860 currentEdgeIndex : number
@@ -86,12 +88,16 @@ export class GapFillSolver extends BaseSolver {
8688
8789 const edges = this . extractEdges ( input . placedRects )
8890
91+ // Build spatial index for fast edge-to-edge queries
92+ const edgeSpatialIndex = this . buildEdgeSpatialIndex ( edges )
93+
8994 return {
9095 srj : input . simpleRouteJson ,
9196 inputRects : input . placedRects ,
9297 obstaclesByLayer : input . obstaclesByLayer ,
9398 layerCount,
9499 edges,
100+ edgeSpatialIndex,
95101 phase : "SELECT_PRIMARY_EDGE" ,
96102 currentEdgeIndex : 0 ,
97103 nearbyEdgeCandidateIndex : 0 ,
@@ -103,6 +109,24 @@ export class GapFillSolver extends BaseSolver {
103109 }
104110 }
105111
112+ private buildEdgeSpatialIndex ( edges : RectEdge [ ] ) : FlatbushIndex < RectEdge > {
113+ const index = new FlatbushIndex < RectEdge > ( edges . length )
114+
115+ for ( const edge of edges ) {
116+ // Create bounding box for edge (padded by max search distance)
117+ const padding = 2.0 // Max edge distance threshold
118+ const minX = Math . min ( edge . x1 , edge . x2 ) - padding
119+ const minY = Math . min ( edge . y1 , edge . y2 ) - padding
120+ const maxX = Math . max ( edge . x1 , edge . x2 ) + padding
121+ const maxY = Math . max ( edge . y1 , edge . y2 ) + padding
122+
123+ index . insert ( edge , minX , minY , maxX , maxY )
124+ }
125+
126+ index . finish ( )
127+ return index
128+ }
129+
106130 private extractEdges ( rects : Placed3D [ ] ) : RectEdge [ ] {
107131 const edges : RectEdge [ ] = [ ]
108132
@@ -216,8 +240,23 @@ export class GapFillSolver extends BaseSolver {
216240 private stepFindNearbyEdges ( ) : void {
217241 const primaryEdge = this . state . currentPrimaryEdge !
218242
243+ // Query spatial index for candidate edges near this primary edge
244+ const padding = 2.0 // Max distance threshold
245+ const minX = Math . min ( primaryEdge . x1 , primaryEdge . x2 ) - padding
246+ const minY = Math . min ( primaryEdge . y1 , primaryEdge . y2 ) - padding
247+ const maxX = Math . max ( primaryEdge . x1 , primaryEdge . x2 ) + padding
248+ const maxY = Math . max ( primaryEdge . y1 , primaryEdge . y2 ) + padding
249+
250+ const candidates = this . state . edgeSpatialIndex . search (
251+ minX ,
252+ minY ,
253+ maxX ,
254+ maxY ,
255+ )
256+
257+ // Check only the nearby candidates (not all edges!)
219258 this . state . currentNearbyEdges = [ ]
220- for ( const candidate of this . state . edges ) {
259+ for ( const candidate of candidates ) {
221260 if (
222261 candidate !== primaryEdge &&
223262 this . isNearbyParallelEdge ( primaryEdge , candidate )
0 commit comments