@tscircuit/capacity-autorouter 0.0.222 → 0.0.224

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -88,6 +88,21 @@ interface SimplifiedPcbTrace {
88
88
  y: number;
89
89
  to_layer: string;
90
90
  from_layer: string;
91
+ } | {
92
+ route_type: "jumper";
93
+ /** Starting point of the jumper pad */
94
+ start: {
95
+ x: number;
96
+ y: number;
97
+ };
98
+ /** Ending point of the jumper pad */
99
+ end: {
100
+ x: number;
101
+ y: number;
102
+ };
103
+ /** Footprint size, typically "0805" */
104
+ footprint: "0805" | "0603" | "1206";
105
+ layer: string;
91
106
  }>;
92
107
  }
93
108
  type SimplifiedPcbTraces = Array<SimplifiedPcbTrace>;
@@ -188,6 +203,7 @@ declare class CapacityMeshEdgeSolver extends BaseSolver {
188
203
  type PortPoint = {
189
204
  connectionName: string;
190
205
  rootConnectionName?: string;
206
+ portPointId?: string;
191
207
  x: number;
192
208
  y: number;
193
209
  z: number;
@@ -233,11 +249,49 @@ type HighDensityIntraNodeRoute$1 = {
233
249
  }>;
234
250
  };
235
251
  type HighDensityRoute$1 = HighDensityIntraNodeRoute$1;
252
+ /**
253
+ * A jumper component used to allow traces to cross on single-layer PCBs.
254
+ * Uses a 0805 footprint (2.0mm x 1.25mm / 0.08" x 0.05").
255
+ */
256
+ type Jumper = {
257
+ route_type: "jumper";
258
+ /** Starting point of the jumper */
259
+ start: {
260
+ x: number;
261
+ y: number;
262
+ };
263
+ /** Ending point of the jumper */
264
+ end: {
265
+ x: number;
266
+ y: number;
267
+ };
268
+ /** Footprint size, typically "0805" */
269
+ footprint: "0805" | "0603" | "1206";
270
+ };
271
+ /**
272
+ * An intra-node route that uses jumpers instead of vias for single-layer PCBs.
273
+ */
274
+ type HighDensityIntraNodeRouteWithJumpers = {
275
+ connectionName: string;
276
+ rootConnectionName?: string;
277
+ traceThickness: number;
278
+ route: Array<{
279
+ x: number;
280
+ y: number;
281
+ z: number;
282
+ }>;
283
+ jumpers: Jumper[];
284
+ };
236
285
 
237
286
  interface HighDensityHyperParameters {
238
287
  FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: number;
239
288
  FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: number;
240
289
  FUTURE_CONNECTION_PROXIMITY_VD: number;
290
+ /**
291
+ * Alternative to FUTURE_CONNECTION_PROXIMITY_VD that accepts mm
292
+ * Used by high density w/ jumpers solver
293
+ * */
294
+ FUTURE_CONNECTION_TRACE_PROXIMITY: number;
241
295
  MISALIGNED_DIST_PENALTY_FACTOR: number;
242
296
  VIA_PENALTY_FACTOR_2: number;
243
297
  SHUFFLE_SEED: number;
@@ -248,6 +302,18 @@ interface HighDensityHyperParameters {
248
302
  BOUNDARY_PADDING: number;
249
303
  ITERATION_PENALTY: number;
250
304
  MINIMUM_FINAL_ACCEPTANCE_GAP?: number;
305
+ OBSTACLE_PROX_PENALTY_FACTOR?: number;
306
+ OBSTACLE_PROX_SIGMA?: number;
307
+ EDGE_PROX_PENALTY_FACTOR?: number;
308
+ EDGE_PROX_SIGMA?: number;
309
+ ALLOW_DIAGONAL?: boolean;
310
+ FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY?: number;
311
+ FUTURE_CONNECTION_JUMPER_PAD_PENALTY?: number;
312
+ JUMPER_JUMPER_PAD_PROXIMITY?: number;
313
+ JUMPER_JUMPER_PAD_PENALTY?: number;
314
+ FUTURE_CONNECTION_LINE_PROXIMITY?: number;
315
+ FUTURE_CONNECTION_LINE_PENALTY?: number;
316
+ MIN_TRAVEL_BEFORE_JUMPER?: number;
251
317
  }
252
318
 
253
319
  type Node = {
@@ -277,9 +343,13 @@ declare class SingleRouteCandidatePriorityQueue<T extends Node = Node> {
277
343
  enqueue(item: T): void;
278
344
  heapifyUp(): void;
279
345
  heapifyDown(): void;
346
+ /**
347
+ * Returns the top N candidates sorted by f value (lowest first)
348
+ */
349
+ getTopN(n: number): T[];
280
350
  }
281
351
 
282
- type FutureConnection = {
352
+ type FutureConnection$1 = {
283
353
  connectionName: string;
284
354
  points: {
285
355
  x: number;
@@ -328,7 +398,7 @@ declare class SingleHighDensityRouteSolver extends BaseSolver {
328
398
  candidates: SingleRouteCandidatePriorityQueue;
329
399
  connectionName: string;
330
400
  solvedPath: HighDensityIntraNodeRoute$1 | null;
331
- futureConnections: FutureConnection[];
401
+ futureConnections: FutureConnection$1[];
332
402
  hyperParameters: Partial<HighDensityHyperParameters>;
333
403
  connMap?: ConnectivityMap;
334
404
  /** For debugging/animating the exploration */
@@ -364,7 +434,7 @@ declare class SingleHighDensityRouteSolver extends BaseSolver {
364
434
  traceThickness?: number;
365
435
  obstacleMargin?: number;
366
436
  layerCount?: number;
367
- futureConnections?: FutureConnection[];
437
+ futureConnections?: FutureConnection$1[];
368
438
  hyperParameters?: Partial<HighDensityHyperParameters>;
369
439
  connMap?: ConnectivityMap;
370
440
  });
@@ -1404,7 +1474,7 @@ declare class PortPointPathingSolver extends BaseSolver {
1404
1474
  offBoardNodes: InputNodeWithPortPoints[];
1405
1475
  /** Cache of base node cost (cost of node in current committed state) */
1406
1476
  private baseNodeCostCache;
1407
- constructor({ simpleRouteJson, inputNodes, capacityMeshNodes, colorMap, nodeMemoryPfMap, hyperParameters, precomputedInitialParams, }: {
1477
+ constructor({ simpleRouteJson, inputNodes, capacityMeshNodes, colorMap, nodeMemoryPfMap, hyperParameters, precomputedInitialParams, fixedRoutes, }: {
1408
1478
  simpleRouteJson: SimpleRouteJson;
1409
1479
  capacityMeshNodes: CapacityMeshNode[];
1410
1480
  inputNodes: InputNodeWithPortPoints[];
@@ -1412,6 +1482,8 @@ declare class PortPointPathingSolver extends BaseSolver {
1412
1482
  nodeMemoryPfMap?: Map<CapacityMeshNodeId, number>;
1413
1483
  hyperParameters?: Partial<PortPointPathingHyperParameters>;
1414
1484
  precomputedInitialParams?: PrecomputedInitialParams;
1485
+ /** Pre-routed connections that should not be re-routed but should appear in results */
1486
+ fixedRoutes?: ConnectionPathResult[];
1415
1487
  });
1416
1488
  private clearCostCaches;
1417
1489
  private clampPf;
@@ -1533,6 +1605,10 @@ interface HyperPortPointPathingSolverParams {
1533
1605
  numShuffleSeeds?: number;
1534
1606
  minAllowedBoardScore?: number;
1535
1607
  hyperParameters?: Partial<PortPointPathingHyperParameters>;
1608
+ /** Pre-routed connections that should not be re-routed but should appear in results */
1609
+ fixedRoutes?: ConnectionPathResult[];
1610
+ /** Custom precomputed params (if provided, skips internal precomputation) */
1611
+ precomputedInitialParams?: PrecomputedInitialParams;
1536
1612
  }
1537
1613
  declare class HyperPortPointPathingSolver extends HyperParameterSupervisorSolver<PortPointPathingSolver> {
1538
1614
  private params;
@@ -1611,6 +1687,7 @@ interface SectionPath {
1611
1687
  y: number;
1612
1688
  z: number;
1613
1689
  nodeId: CapacityMeshNodeId;
1690
+ portPointId?: string;
1614
1691
  }>;
1615
1692
  /** Index in original path where this segment starts */
1616
1693
  originalStartIndex: number;
@@ -1668,6 +1745,16 @@ interface MultiSectionPortPointOptimizerParams {
1668
1745
  /** Node assigned port points from initial run */
1669
1746
  initialNodeAssignedPortPoints: Map<CapacityMeshNodeId, PortPoint[]>;
1670
1747
  effort?: number;
1748
+ /**
1749
+ * Fraction of connections in a section to rip/replace (0-1).
1750
+ * Default 1 means rip all connections. Values less than 1 keep some traces.
1751
+ */
1752
+ FRACTION_TO_REPLACE?: number;
1753
+ /**
1754
+ * If true, always rip connections that have same-layer intersections,
1755
+ * even if they would otherwise be kept due to FRACTION_TO_REPLACE.
1756
+ */
1757
+ ALWAYS_RIP_INTERSECTIONS?: boolean;
1671
1758
  }
1672
1759
  /**
1673
1760
  * MultiSectionPortPointOptimizer runs local optimization on sections of the
@@ -1717,6 +1804,20 @@ declare class MultiSectionPortPointOptimizer extends BaseSolver {
1717
1804
  MAX_SECTION_ATTEMPTS: number;
1718
1805
  /** Acceptable probability of failure threshold */
1719
1806
  ACCEPTABLE_PF: number;
1807
+ /**
1808
+ * Fraction of connections in a section to rip/replace (0-1).
1809
+ * Default 1 means rip all connections. Values less than 1 keep some traces.
1810
+ */
1811
+ FRACTION_TO_REPLACE: number;
1812
+ /**
1813
+ * If true, always rip connections that have same-layer intersections,
1814
+ * even if they would otherwise be kept due to FRACTION_TO_REPLACE.
1815
+ *
1816
+ * Uses a greedy vertex cover approach: for each intersection, only one
1817
+ * connection is ripped (chosen based on the shuffle seed), rather than
1818
+ * ripping all connections involved in intersections.
1819
+ */
1820
+ ALWAYS_RIP_INTERSECTIONS: boolean;
1720
1821
  effort: number;
1721
1822
  constructor(params: MultiSectionPortPointOptimizerParams);
1722
1823
  /**
@@ -1756,10 +1857,22 @@ declare class MultiSectionPortPointOptimizer extends BaseSolver {
1756
1857
  sectionPath: SectionPath;
1757
1858
  originalConnectionResult: ConnectionPathResult;
1758
1859
  }>;
1860
+ /** Port points from connections that are being kept (not ripped) in the current section */
1861
+ currentSectionKeptPortPoints: Map<CapacityMeshNodeId, PortPoint[]>;
1862
+ /** Connection results for connections being kept (not ripped) - used for visualization */
1863
+ currentSectionFixedRoutes: ConnectionPathResult[];
1864
+ /**
1865
+ * Determine which connections to rip based on FRACTION_TO_REPLACE and ALWAYS_RIP_INTERSECTIONS.
1866
+ * Returns a set of connection names that should be ripped (re-routed).
1867
+ */
1868
+ determineConnectionsToRip(section: PortPointSection, allConnectionNames: string[]): Set<string>;
1759
1869
  /**
1760
1870
  * Create a SimpleRouteJson for just the section's connections.
1761
1871
  * Includes both fully contained connections AND cut paths (partial connections
1762
1872
  * that pass through the section).
1873
+ *
1874
+ * Respects FRACTION_TO_REPLACE and ALWAYS_RIP_INTERSECTIONS to determine which
1875
+ * connections to include for re-routing.
1763
1876
  */
1764
1877
  createSectionSimpleRouteJson(section: PortPointSection): SimpleRouteJson;
1765
1878
  /**
@@ -2786,6 +2899,480 @@ declare class SimpleHighDensitySolver extends BaseSolver {
2786
2899
  visualize(): GraphicsObject;
2787
2900
  }
2788
2901
 
2902
+ type FutureConnection = {
2903
+ connectionName: string;
2904
+ points: {
2905
+ x: number;
2906
+ y: number;
2907
+ z: number;
2908
+ }[];
2909
+ };
2910
+ /**
2911
+ * Components that make up the g (cost so far) calculation
2912
+ */
2913
+ type GComponents = {
2914
+ /** Total path distance traveled from start */
2915
+ distFromStart: number;
2916
+ /** Cumulative weighted penalty for being near obstacles */
2917
+ weightedMmNearObstacle: number;
2918
+ /** Cumulative weighted penalty for being near edges */
2919
+ weightedMmNearEdge: number;
2920
+ /** Cumulative weighted penalty for being near future connection start/end points */
2921
+ weightedMmNearFutureConnectionStartEnd: number;
2922
+ /** Cumulative weighted penalty for being near future connection lines */
2923
+ weightedMmNearFutureConnectionLine: number;
2924
+ /** Cumulative jumper penalty (includes jumper distance + penalty factor) */
2925
+ jumperPenalty: number;
2926
+ /** Cumulative penalty for jumper pads near future connections */
2927
+ jumperPadFutureConnectionPenalty: number;
2928
+ /** Total g value (sum of all components) */
2929
+ total: number;
2930
+ };
2931
+ /**
2932
+ * Components that make up the h (heuristic) calculation
2933
+ */
2934
+ type HComponents = {
2935
+ distanceToGoal: number;
2936
+ obstacleProximity: number;
2937
+ edgeProximity: number;
2938
+ futureConnectionStartEndProximityPenalty: number;
2939
+ futureConnectionLine: number;
2940
+ total: number;
2941
+ /** Stored rates (penalty per mm) for derivative computation */
2942
+ obstacleProximityRate: number;
2943
+ edgeProximityRate: number;
2944
+ futureConnectionStartEndProximityRate: number;
2945
+ futureConnectionLineRate: number;
2946
+ };
2947
+ /**
2948
+ * Extended node type that tracks jumper usage
2949
+ */
2950
+ type JumperNode = Node & {
2951
+ /** If this node was reached via a jumper, this contains jumper info */
2952
+ jumperEntry?: {
2953
+ x: number;
2954
+ y: number;
2955
+ };
2956
+ /** Track if this movement is the exit of a jumper */
2957
+ isJumperExit?: boolean;
2958
+ /** Count of jumpers used to reach this node */
2959
+ jumperCount?: number;
2960
+ /** Stored g components for debugging/visualization */
2961
+ gComponents?: GComponents;
2962
+ /** Stored h components for debugging/visualization */
2963
+ hComponents?: HComponents;
2964
+ };
2965
+ declare class SingleHighDensityRouteWithJumpersSolver extends BaseSolver {
2966
+ obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[];
2967
+ bounds: {
2968
+ minX: number;
2969
+ maxX: number;
2970
+ minY: number;
2971
+ maxY: number;
2972
+ };
2973
+ boundsSize: {
2974
+ width: number;
2975
+ height: number;
2976
+ };
2977
+ boundsCenter: {
2978
+ x: number;
2979
+ y: number;
2980
+ };
2981
+ A: {
2982
+ x: number;
2983
+ y: number;
2984
+ z: number;
2985
+ };
2986
+ B: {
2987
+ x: number;
2988
+ y: number;
2989
+ z: number;
2990
+ };
2991
+ roundedGoalPosition: {
2992
+ x: number;
2993
+ y: number;
2994
+ z: number;
2995
+ };
2996
+ straightLineDistance: number;
2997
+ traceThickness: number;
2998
+ obstacleMargin: number;
2999
+ minCellSize: number;
3000
+ cellStep: number;
3001
+ GREEDY_MULTIPLER: number;
3002
+ numRoutes: number;
3003
+ /** Penalty factor for using a jumper (relative to distance) */
3004
+ JUMPER_PENALTY_FACTOR: number;
3005
+ /** Future connection proximity parameters */
3006
+ FUTURE_CONNECTION_START_END_PENALTY: number;
3007
+ FUTURE_CONNECTION_START_END_PROXIMITY: number;
3008
+ /** Future connection jumper pad penalty parameters */
3009
+ FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY: number;
3010
+ FUTURE_CONNECTION_JUMPER_PAD_PENALTY: number;
3011
+ /** Jumper-to-jumper pad proximity penalty parameters */
3012
+ JUMPER_JUMPER_PAD_PROXIMITY: number;
3013
+ JUMPER_JUMPER_PAD_PENALTY: number;
3014
+ /** Future connection line proximity penalty parameters */
3015
+ FUTURE_CONNECTION_LINE_PROXIMITY: number;
3016
+ FUTURE_CONNECTION_LINE_PENALTY: number;
3017
+ /** Obstacle proximity penalty parameters (repulsive field) */
3018
+ OBSTACLE_PROX_PENALTY_FACTOR: number;
3019
+ OBSTACLE_PROX_SIGMA: number;
3020
+ /** Edge proximity penalty parameters */
3021
+ EDGE_PROX_PENALTY_FACTOR: number;
3022
+ EDGE_PROX_SIGMA: number;
3023
+ /** Whether to allow diagonal movement in pathfinding */
3024
+ ALLOW_DIAGONAL: boolean;
3025
+ /** Minimum distance traveled before allowing jumper neighbors */
3026
+ MIN_TRAVEL_BEFORE_JUMPER: number;
3027
+ CELL_SIZE_FACTOR: number;
3028
+ exploredNodes: Set<string>;
3029
+ candidates: SingleRouteCandidatePriorityQueue<JumperNode>;
3030
+ connectionName: string;
3031
+ rootConnectionName?: string;
3032
+ solvedPath: HighDensityIntraNodeRouteWithJumpers | null;
3033
+ futureConnections: FutureConnection[];
3034
+ hyperParameters: Partial<HighDensityHyperParameters>;
3035
+ connMap?: ConnectivityMap;
3036
+ /** For debugging/animating the exploration */
3037
+ debug_exploredNodesOrdered: string[];
3038
+ debug_exploredNodeValues: Map<string, {
3039
+ g: number;
3040
+ h: number;
3041
+ f: number;
3042
+ gComponents?: GComponents;
3043
+ hComponents?: HComponents;
3044
+ }>;
3045
+ debug_nodesTooCloseToObstacle: Set<string>;
3046
+ debug_nodePathToParentIntersectsObstacle: Set<string>;
3047
+ debugEnabled: boolean;
3048
+ initialNodeGridOffset: {
3049
+ x: number;
3050
+ y: number;
3051
+ };
3052
+ /** Existing jumpers that act as obstacles */
3053
+ existingJumpers: Jumper[];
3054
+ constructor(opts: {
3055
+ connectionName: string;
3056
+ rootConnectionName?: string;
3057
+ obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[];
3058
+ minDistBetweenEnteringPoints: number;
3059
+ bounds: {
3060
+ minX: number;
3061
+ maxX: number;
3062
+ minY: number;
3063
+ maxY: number;
3064
+ };
3065
+ A: {
3066
+ x: number;
3067
+ y: number;
3068
+ z: number;
3069
+ };
3070
+ B: {
3071
+ x: number;
3072
+ y: number;
3073
+ z: number;
3074
+ };
3075
+ traceThickness?: number;
3076
+ obstacleMargin?: number;
3077
+ futureConnections?: FutureConnection[];
3078
+ hyperParameters?: Partial<HighDensityHyperParameters>;
3079
+ connMap?: ConnectivityMap;
3080
+ });
3081
+ handleSimpleCases(): void;
3082
+ get jumperPenaltyDistance(): number;
3083
+ /**
3084
+ * Check if a node is too close to an obstacle trace or jumper
3085
+ */
3086
+ isNodeTooCloseToObstacle(node: JumperNode, margin?: number): boolean;
3087
+ /**
3088
+ * Check if a node is too close to a jumper's pads
3089
+ * Traces CAN route under the body of the jumper, just not under the pads
3090
+ */
3091
+ isNodeTooCloseToJumper(node: {
3092
+ x: number;
3093
+ y: number;
3094
+ }, jumper: Jumper, margin: number): boolean;
3095
+ isNodeTooCloseToEdge(node: JumperNode): boolean;
3096
+ doesPathToParentIntersectObstacle(node: JumperNode): boolean;
3097
+ /**
3098
+ * Check if a line segment intersects with a jumper's pads
3099
+ * Segments CAN pass under the jumper body, just not through the pads
3100
+ */
3101
+ doesSegmentIntersectJumperPads(p1: {
3102
+ x: number;
3103
+ y: number;
3104
+ }, p2: {
3105
+ x: number;
3106
+ y: number;
3107
+ }, jumper: Jumper): boolean;
3108
+ /**
3109
+ * Check if a line segment intersects with an axis-aligned rectangle
3110
+ */
3111
+ doesSegmentIntersectRect(p1: {
3112
+ x: number;
3113
+ y: number;
3114
+ }, p2: {
3115
+ x: number;
3116
+ y: number;
3117
+ }, center: {
3118
+ x: number;
3119
+ y: number;
3120
+ }, halfWidth: number, halfHeight: number): boolean;
3121
+ /**
3122
+ * Find obstacles between current node and a target position
3123
+ * Returns the obstacle segment(s) that block the direct path
3124
+ */
3125
+ findObstaclesBetween(from: {
3126
+ x: number;
3127
+ y: number;
3128
+ }, to: {
3129
+ x: number;
3130
+ y: number;
3131
+ }): Array<{
3132
+ A: {
3133
+ x: number;
3134
+ y: number;
3135
+ };
3136
+ B: {
3137
+ x: number;
3138
+ y: number;
3139
+ };
3140
+ }>;
3141
+ computeHComponents(node: JumperNode): HComponents;
3142
+ computeH(node: JumperNode): number;
3143
+ computeGComponents(node: JumperNode): GComponents;
3144
+ computeG(node: JumperNode): number;
3145
+ computeF(g: number, h: number): number;
3146
+ getClosestFutureConnectionPoint(node: JumperNode): {
3147
+ x: number;
3148
+ y: number;
3149
+ z: number;
3150
+ } | null;
3151
+ getFutureConnectionStartEndPenalty(node: JumperNode): number;
3152
+ /**
3153
+ * Calculate penalty for being close to future connection line segments.
3154
+ * This penalty is computed by summing the segment-to-point distance between
3155
+ * the node and all unrouted future connection start-to-end segments.
3156
+ * The penalty helps routes avoid crossing directly over future connection paths.
3157
+ */
3158
+ getFutureConnectionLinePenalty(node: JumperNode): number;
3159
+ /**
3160
+ * Calculate penalty for jumper pads placed near future connection start/end points.
3161
+ * This disincentivizes placing jumper pads in areas that will be needed for future routing.
3162
+ * The distance is calculated as the minimum distance from either jumper pad to any future connection point.
3163
+ */
3164
+ getJumperPadFutureConnectionPenalty(node: JumperNode): number;
3165
+ /**
3166
+ * Compute the minimum distance from a node to any obstacle (trace segments and jumper pads)
3167
+ */
3168
+ getClearanceToObstacles(node: {
3169
+ x: number;
3170
+ y: number;
3171
+ }): number;
3172
+ /**
3173
+ * Compute distance from a point to the nearest jumper pad
3174
+ */
3175
+ distanceToJumperPads(p: {
3176
+ x: number;
3177
+ y: number;
3178
+ }, j: Jumper): number;
3179
+ /**
3180
+ * Compute distance from a point to an axis-aligned rectangle (0 if inside)
3181
+ */
3182
+ pointToRectDistance(p: {
3183
+ x: number;
3184
+ y: number;
3185
+ }, c: {
3186
+ x: number;
3187
+ y: number;
3188
+ }, halfW: number, halfH: number): number;
3189
+ /**
3190
+ * Compute minimum distance from a node to the nearest boundary edge
3191
+ */
3192
+ getClearanceToEdge(node: {
3193
+ x: number;
3194
+ y: number;
3195
+ }): number;
3196
+ /**
3197
+ * Compute the obstacle proximity penalty (repulsive field)
3198
+ * Returns a high value near obstacles, ~0 far away
3199
+ */
3200
+ getObstacleProximityPenalty(node: JumperNode): number;
3201
+ /**
3202
+ * Compute the edge proximity penalty (repulsive field near boundaries)
3203
+ * Returns a high value near edges, ~0 far away
3204
+ * Penalty is reduced as we approach the goal (which is always on an edge)
3205
+ */
3206
+ getEdgeProximityPenalty(node: JumperNode): number;
3207
+ getNodeKey(node: JumperNode): string;
3208
+ /**
3209
+ * Calculate potential jumper positions to cross an obstacle
3210
+ */
3211
+ getJumperNeighbors(node: JumperNode): JumperNode[];
3212
+ /**
3213
+ * Calculate the exit position for a jumper that clears an obstacle
3214
+ */
3215
+ calculateJumperExit(entry: JumperNode, obstacle: {
3216
+ A: {
3217
+ x: number;
3218
+ y: number;
3219
+ };
3220
+ B: {
3221
+ x: number;
3222
+ y: number;
3223
+ };
3224
+ }, direction: {
3225
+ dx: number;
3226
+ dy: number;
3227
+ }): JumperNode | null;
3228
+ /**
3229
+ * Check if a jumper's pads are too close to obstacle traces
3230
+ */
3231
+ isJumperTooCloseToTraces(entry: {
3232
+ x: number;
3233
+ y: number;
3234
+ }, exit: {
3235
+ x: number;
3236
+ y: number;
3237
+ }): boolean;
3238
+ /**
3239
+ * Verify that a jumper placement is valid (doesn't overlap with existing jumpers or traces)
3240
+ */
3241
+ isJumperPlacementValid(entry: JumperNode, exit: JumperNode): boolean;
3242
+ /**
3243
+ * Check if two jumpers overlap
3244
+ */
3245
+ doJumpersOverlap(j1: Jumper, j2: Jumper): boolean;
3246
+ /**
3247
+ * Get all jumpers in the path to a node
3248
+ */
3249
+ getJumpersInPath(node: JumperNode): Jumper[];
3250
+ getNeighbors(node: JumperNode): JumperNode[];
3251
+ getNodePath(node: JumperNode): JumperNode[];
3252
+ setSolvedPath(node: JumperNode): void;
3253
+ computeProgress(currentNode: JumperNode, goalDist: number): number;
3254
+ _step(): void;
3255
+ /**
3256
+ * Draw the two pads of an 0805 jumper
3257
+ * Pad dimensions are rotated based on jumper orientation
3258
+ */
3259
+ private drawJumperPads;
3260
+ visualize(): GraphicsObject;
3261
+ }
3262
+
3263
+ /**
3264
+ * IntraNodeSolverWithJumpers is designed for single-layer nodes that use
3265
+ * 0805 jumpers to allow traces to jump over each other.
3266
+ *
3267
+ * Unlike the standard IntraNodeRouteSolver which uses vias to change layers,
3268
+ * this solver operates on a single layer and uses physical jumper components
3269
+ * to handle trace crossings.
3270
+ */
3271
+ declare class IntraNodeSolverWithJumpers extends BaseSolver {
3272
+ nodeWithPortPoints: NodeWithPortPoints;
3273
+ colorMap: Record<string, string>;
3274
+ unsolvedConnections: {
3275
+ connectionName: string;
3276
+ rootConnectionName?: string;
3277
+ points: {
3278
+ x: number;
3279
+ y: number;
3280
+ z: number;
3281
+ }[];
3282
+ }[];
3283
+ totalConnections: number;
3284
+ solvedRoutes: HighDensityIntraNodeRouteWithJumpers[];
3285
+ failedSubSolvers: SingleHighDensityRouteWithJumpersSolver[];
3286
+ hyperParameters: Partial<HighDensityHyperParameters>;
3287
+ minDistBetweenEnteringPoints: number;
3288
+ traceWidth: number;
3289
+ activeSubSolver: SingleHighDensityRouteWithJumpersSolver | null;
3290
+ lastActiveSubSolver: SingleHighDensityRouteWithJumpersSolver | null;
3291
+ connMap?: ConnectivityMap;
3292
+ get failedSolvers(): SingleHighDensityRouteWithJumpersSolver[];
3293
+ get activeSolver(): SingleHighDensityRouteWithJumpersSolver | null;
3294
+ constructor(params: {
3295
+ nodeWithPortPoints: NodeWithPortPoints;
3296
+ colorMap?: Record<string, string>;
3297
+ hyperParameters?: Partial<HighDensityHyperParameters>;
3298
+ connMap?: ConnectivityMap;
3299
+ traceWidth?: number;
3300
+ });
3301
+ getConstructorParams(): {
3302
+ nodeWithPortPoints: NodeWithPortPoints;
3303
+ colorMap: Record<string, string>;
3304
+ hyperParameters: Partial<HighDensityHyperParameters>;
3305
+ connMap: ConnectivityMap | undefined;
3306
+ traceWidth: number;
3307
+ };
3308
+ computeProgress(): number;
3309
+ _step(): void;
3310
+ /**
3311
+ * Draw the two pads of an 0805 jumper
3312
+ * Pad dimensions are rotated based on jumper orientation
3313
+ */
3314
+ private drawJumperPads;
3315
+ visualize(): GraphicsObject;
3316
+ }
3317
+
3318
+ interface NodeAnalysis {
3319
+ node: NodeWithPortPoints;
3320
+ hasCrossings: boolean;
3321
+ numSameLayerCrossings: number;
3322
+ isSingleLayer: boolean;
3323
+ }
3324
+ /**
3325
+ * HighDensitySolver intelligently selects the appropriate solver for each node:
3326
+ * - SimpleHighDensitySolver for nodes without crossings (faster, force-directed)
3327
+ * - IntraNodeSolverWithJumpers for single-layer nodes with crossings (uses 0805 jumpers)
3328
+ *
3329
+ * This solver processes nodes in batches based on their characteristics.
3330
+ */
3331
+ declare class JumperHighDensitySolver extends BaseSolver {
3332
+ allNodes: NodeWithPortPoints[];
3333
+ nodeAnalyses: NodeAnalysis[];
3334
+ routes: (HighDensityIntraNodeRoute$1 & {
3335
+ jumpers?: HighDensityIntraNodeRouteWithJumpers["jumpers"];
3336
+ })[];
3337
+ colorMap: Record<string, string>;
3338
+ traceWidth: number;
3339
+ viaDiameter: number;
3340
+ connMap?: ConnectivityMap;
3341
+ hyperParameters?: Partial<HighDensityHyperParameters>;
3342
+ nodesWithoutCrossings: NodeWithPortPoints[];
3343
+ nodesWithCrossings: NodeWithPortPoints[];
3344
+ simpleHighDensitySolver?: SimpleHighDensitySolver;
3345
+ jumperSolvers: IntraNodeSolverWithJumpers[];
3346
+ currentJumperSolverIndex: number;
3347
+ phase: "analyzing" | "simple" | "jumpers" | "done";
3348
+ constructor({ nodePortPoints, colorMap, traceWidth, viaDiameter, connMap, hyperParameters, }: {
3349
+ nodePortPoints: NodeWithPortPoints[];
3350
+ colorMap?: Record<string, string>;
3351
+ traceWidth?: number;
3352
+ viaDiameter?: number;
3353
+ connMap?: ConnectivityMap;
3354
+ hyperParameters?: Partial<HighDensityHyperParameters>;
3355
+ });
3356
+ /**
3357
+ * Analyze all nodes to determine which solver to use for each
3358
+ */
3359
+ _analyzeNodes(): void;
3360
+ _step(): void;
3361
+ _stepSimpleSolver(): void;
3362
+ _initializeJumperSolvers(): void;
3363
+ _stepJumperSolvers(): void;
3364
+ computeProgress(): number;
3365
+ getConstructorParams(): {
3366
+ nodePortPoints: NodeWithPortPoints[];
3367
+ colorMap: Record<string, string>;
3368
+ traceWidth: number;
3369
+ viaDiameter: number;
3370
+ connMap: ConnectivityMap | undefined;
3371
+ hyperParameters: Partial<HighDensityHyperParameters> | undefined;
3372
+ };
3373
+ visualize(): GraphicsObject;
3374
+ }
3375
+
2789
3376
  /**
2790
3377
  * ObstacleTree wraps different spatial index implementations:
2791
3378
  * - 'native': original spatial-hash grid
@@ -3185,7 +3772,9 @@ declare class AssignableAutoroutingPipeline2 extends BaseSolver {
3185
3772
  relateNodesToOffBoardConnections?: RelateNodesToOffBoardConnectionsSolver;
3186
3773
  colorMap: Record<string, string>;
3187
3774
  highDensityRouteSolver?: HighDensitySolver;
3775
+ /** @deprecated Use highDensitySolver instead */
3188
3776
  simpleHighDensityRouteSolver?: SimpleHighDensitySolver;
3777
+ highDensitySolver?: JumperHighDensitySolver;
3189
3778
  highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver;
3190
3779
  singleLayerNodeMerger?: SingleLayerNodeMergerSolver;
3191
3780
  offboardPathFragmentSolver?: PortPointOffboardPathFragmentSolver;
@@ -3209,7 +3798,7 @@ declare class AssignableAutoroutingPipeline2 extends BaseSolver {
3209
3798
  capacityNodes: CapacityMeshNode[] | null;
3210
3799
  capacityEdges: CapacityMeshEdge[] | null;
3211
3800
  cacheProvider: CacheProvider | null;
3212
- pipelineDef: (PipelineStep$1<typeof NetToPointPairsSolver> | PipelineStep$1<typeof RectDiffPipeline> | PipelineStep$1<typeof RelateNodesToOffBoardConnectionsSolver> | PipelineStep$1<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep$1<typeof AvailableSegmentPointSolver> | PipelineStep$1<typeof HyperPortPointPathingSolver> | PipelineStep$1<typeof SimpleHighDensitySolver> | PipelineStep$1<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep$1<typeof TraceSimplificationSolver> | PipelineStep$1<typeof TraceKeepoutSolver> | PipelineStep$1<typeof TraceWidthSolver>)[];
3801
+ pipelineDef: (PipelineStep$1<typeof NetToPointPairsSolver> | PipelineStep$1<typeof RectDiffPipeline> | PipelineStep$1<typeof RelateNodesToOffBoardConnectionsSolver> | PipelineStep$1<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep$1<typeof AvailableSegmentPointSolver> | PipelineStep$1<typeof HyperPortPointPathingSolver> | PipelineStep$1<typeof MultiSectionPortPointOptimizer> | PipelineStep$1<typeof SimpleHighDensitySolver> | PipelineStep$1<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep$1<typeof TraceSimplificationSolver> | PipelineStep$1<typeof TraceKeepoutSolver> | PipelineStep$1<typeof TraceWidthSolver>)[];
3213
3802
  constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$1);
3214
3803
  getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$1];
3215
3804
  currentPipelineStepIndex: number;
@@ -3989,4 +4578,4 @@ declare const convertSrjToGraphicsObject: (srj: SimpleRouteJson) => {
3989
4578
  points: Point$5[];
3990
4579
  };
3991
4580
 
3992
- export { AssignableAutoroutingPipeline1Solver, AssignableAutoroutingPipeline2, AutoroutingPipeline1_OriginalUnravel, AutoroutingPipelineSolver2_PortPointPathing as AutoroutingPipelineSolver, type AutoroutingPipelineSolverOptions, type CachableSolver, type CacheProvider, CapacityMeshSolver, InMemoryCache, LocalStorageCache, calculateOptimalCapacityDepth, convertSrjToGraphicsObject, getGlobalInMemoryCache, getGlobalLocalStorageCache, getTunedTotalCapacity1, setupGlobalCaches };
4581
+ export { AssignableAutoroutingPipeline1Solver, AssignableAutoroutingPipeline2, AutoroutingPipeline1_OriginalUnravel, AutoroutingPipelineSolver2_PortPointPathing as AutoroutingPipelineSolver, type AutoroutingPipelineSolverOptions, type CachableSolver, type CacheProvider, CapacityMeshSolver, type HighDensityIntraNodeRouteWithJumpers, JumperHighDensitySolver as HighDensitySolver, InMemoryCache, IntraNodeSolverWithJumpers, type Jumper, LocalStorageCache, SingleHighDensityRouteWithJumpersSolver, calculateOptimalCapacityDepth, convertSrjToGraphicsObject, getGlobalInMemoryCache, getGlobalLocalStorageCache, getTunedTotalCapacity1, setupGlobalCaches };