@tscircuit/capacity-autorouter 0.0.237 → 0.0.239

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
@@ -2,6 +2,7 @@ import * as graphics_debug from 'graphics-debug';
2
2
  import { GraphicsObject, Rect, Circle, Line, Point as Point$5 } from 'graphics-debug';
3
3
  import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
4
4
  import { RectDiffPipeline } from '@tscircuit/rectdiff';
5
+ import { JumperGraphSolver } from '@tscircuit/hypergraph';
5
6
  import { ConnectivityMap as ConnectivityMap$1 } from 'connectivity-map';
6
7
  import { Polygon } from '@tscircuit/math-utils';
7
8
 
@@ -32,7 +33,7 @@ interface SimpleRouteJson {
32
33
  nominalTraceWidth?: number;
33
34
  minViaDiameter?: number;
34
35
  defaultObstacleMargin?: number;
35
- obstacles: Obstacle$1[];
36
+ obstacles: Obstacle[];
36
37
  connections: Array<SimpleRouteConnection>;
37
38
  bounds: {
38
39
  minX: number;
@@ -47,7 +48,7 @@ interface SimpleRouteJson {
47
48
  traces?: SimplifiedPcbTraces;
48
49
  allowJumpers?: boolean;
49
50
  }
50
- interface Obstacle$1 {
51
+ interface Obstacle {
51
52
  obstacleId?: string;
52
53
  type: "rect";
53
54
  layers: string[];
@@ -102,7 +103,7 @@ interface SimplifiedPcbTrace {
102
103
  y: number;
103
104
  };
104
105
  /** Footprint size, typically "0603" */
105
- footprint: "0603" | "1206";
106
+ footprint: "0603" | "1206" | "1206x4_pair";
106
107
  layer: string;
107
108
  }>;
108
109
  }
@@ -253,7 +254,9 @@ type HighDensityIntraNodeRoute$1 = {
253
254
  type HighDensityRoute$1 = HighDensityIntraNodeRoute$1;
254
255
  /**
255
256
  * A jumper component used to allow traces to cross on single-layer PCBs.
256
- * Uses a 0603 footprint
257
+ * - "0603": Single 0603 jumper
258
+ * - "1206": Single 1206 jumper
259
+ * - "1206x4_pair": One of 4 internal jumper pairs in a 1206x4 resistor array
257
260
  */
258
261
  type Jumper = {
259
262
  route_type: "jumper";
@@ -267,8 +270,8 @@ type Jumper = {
267
270
  x: number;
268
271
  y: number;
269
272
  };
270
- /** Footprint size, typically "0603" */
271
- footprint: "0603" | "1206";
273
+ /** Footprint size */
274
+ footprint: "0603" | "1206" | "1206x4_pair";
272
275
  };
273
276
  /**
274
277
  * An intra-node route that uses jumpers instead of vias for single-layer PCBs.
@@ -898,10 +901,10 @@ declare class HighDensitySolver extends BaseSolver {
898
901
  declare class CapacityNodeTargetMerger extends BaseSolver {
899
902
  nodes: CapacityMeshNode[];
900
903
  connMap: ConnectivityMap;
901
- unprocessedObstacles: Obstacle$1[];
904
+ unprocessedObstacles: Obstacle[];
902
905
  newNodes: CapacityMeshNode[];
903
906
  removedNodeIds: Set<string>;
904
- constructor(nodes: CapacityMeshNode[], obstacles: Obstacle$1[], connMap: ConnectivityMap);
907
+ constructor(nodes: CapacityMeshNode[], obstacles: Obstacle[], connMap: ConnectivityMap);
905
908
  _step(): void;
906
909
  visualize(): GraphicsObject;
907
910
  }
@@ -1178,7 +1181,7 @@ declare class TraceSimplificationSolver extends BaseSolver {
1178
1181
  */
1179
1182
  constructor(simplificationConfig: {
1180
1183
  hdRoutes: HighDensityRoute$1[];
1181
- obstacles: Obstacle$1[];
1184
+ obstacles: Obstacle[];
1182
1185
  connMap: ConnectivityMap;
1183
1186
  colorMap: Record<string, string>;
1184
1187
  outline?: Array<{
@@ -1332,6 +1335,8 @@ interface PortPointPathingHyperParameters {
1332
1335
  RANDOM_RIP_FRACTION?: number;
1333
1336
  /** When enabled, use jumper-based pf calculation for same-layer crossings on single layer nodes */
1334
1337
  JUMPER_PF_FN_ENABLED?: boolean;
1338
+ /** Factor for penalizing deviation from straight line path */
1339
+ STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR?: number;
1335
1340
  }
1336
1341
  /**
1337
1342
  * An input port point without connectionName assigned yet.
@@ -1475,6 +1480,7 @@ declare class PortPointPathingSolver extends BaseSolver {
1475
1480
  get NODE_MAX_PF(): number;
1476
1481
  /** Penalty factor for port points that are far from the center of the segment */
1477
1482
  get CENTER_OFFSET_DIST_PENALTY_FACTOR(): number;
1483
+ get STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR(): number;
1478
1484
  colorMap: Record<string, string>;
1479
1485
  get GREEDY_MULTIPLIER(): number;
1480
1486
  MAX_CANDIDATES_IN_MEMORY: number;
@@ -1996,7 +2002,7 @@ interface CapacityMeshSolverOptions$3 {
1996
2002
  cacheProvider?: CacheProvider | null;
1997
2003
  effort?: number;
1998
2004
  }
1999
- type PipelineStep$4<T extends new (...args: any[]) => BaseSolver> = {
2005
+ type PipelineStep$3<T extends new (...args: any[]) => BaseSolver> = {
2000
2006
  solverName: string;
2001
2007
  solverClass: T;
2002
2008
  getConstructorParams: (instance: AutoroutingPipelineSolver2_PortPointPathing) => ConstructorParameters<T>;
@@ -2031,7 +2037,7 @@ declare class AutoroutingPipelineSolver2_PortPointPathing extends BaseSolver {
2031
2037
  capacityNodes: CapacityMeshNode[] | null;
2032
2038
  capacityEdges: CapacityMeshEdge[] | null;
2033
2039
  cacheProvider: CacheProvider | null;
2034
- pipelineDef: (PipelineStep$4<typeof NetToPointPairsSolver2_OffBoardConnection> | PipelineStep$4<typeof RectDiffPipeline> | PipelineStep$4<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep$4<typeof AvailableSegmentPointSolver> | PipelineStep$4<typeof HyperPortPointPathingSolver> | PipelineStep$4<typeof MultiSectionPortPointOptimizer> | PipelineStep$4<typeof HighDensitySolver> | PipelineStep$4<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep$4<typeof TraceSimplificationSolver>)[];
2040
+ pipelineDef: (PipelineStep$3<typeof NetToPointPairsSolver2_OffBoardConnection> | PipelineStep$3<typeof RectDiffPipeline> | PipelineStep$3<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep$3<typeof AvailableSegmentPointSolver> | PipelineStep$3<typeof HyperPortPointPathingSolver> | PipelineStep$3<typeof MultiSectionPortPointOptimizer> | PipelineStep$3<typeof HighDensitySolver> | PipelineStep$3<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep$3<typeof TraceSimplificationSolver>)[];
2035
2041
  constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$3);
2036
2042
  getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$3];
2037
2043
  currentPipelineStepIndex: number;
@@ -2854,7 +2860,7 @@ interface CapacityMeshSolverOptions$2 {
2854
2860
  targetMinCapacity?: number;
2855
2861
  cacheProvider?: CacheProvider | null;
2856
2862
  }
2857
- type PipelineStep$3<T extends new (...args: any[]) => BaseSolver> = {
2863
+ type PipelineStep$2<T extends new (...args: any[]) => BaseSolver> = {
2858
2864
  solverName: string;
2859
2865
  solverClass: T;
2860
2866
  getConstructorParams: (instance: AutoroutingPipeline1_OriginalUnravel) => ConstructorParameters<T>;
@@ -2891,7 +2897,7 @@ declare class AutoroutingPipeline1_OriginalUnravel extends BaseSolver {
2891
2897
  capacityNodes: CapacityMeshNode[] | null;
2892
2898
  capacityEdges: CapacityMeshEdge[] | null;
2893
2899
  cacheProvider: CacheProvider | null;
2894
- pipelineDef: (PipelineStep$3<typeof NetToPointPairsSolver2_OffBoardConnection> | PipelineStep$3<typeof RectDiffPipeline> | PipelineStep$3<typeof StrawSolver> | PipelineStep$3<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep$3<typeof DeadEndSolver> | PipelineStep$3<typeof CapacityPathingGreedySolver> | PipelineStep$3<typeof CapacityPathingMultiSectionSolver> | PipelineStep$3<typeof CapacityEdgeToPortSegmentSolver> | PipelineStep$3<typeof CapacitySegmentToPointSolver> | PipelineStep$3<typeof UnravelMultiSectionSolver> | PipelineStep$3<typeof HighDensitySolver> | PipelineStep$3<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep$3<typeof TraceSimplificationSolver>)[];
2900
+ pipelineDef: (PipelineStep$2<typeof NetToPointPairsSolver2_OffBoardConnection> | PipelineStep$2<typeof RectDiffPipeline> | PipelineStep$2<typeof StrawSolver> | PipelineStep$2<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep$2<typeof DeadEndSolver> | PipelineStep$2<typeof CapacityPathingGreedySolver> | PipelineStep$2<typeof CapacityPathingMultiSectionSolver> | PipelineStep$2<typeof CapacityEdgeToPortSegmentSolver> | PipelineStep$2<typeof CapacitySegmentToPointSolver> | PipelineStep$2<typeof UnravelMultiSectionSolver> | PipelineStep$2<typeof HighDensitySolver> | PipelineStep$2<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep$2<typeof TraceSimplificationSolver>)[];
2895
2901
  constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$2);
2896
2902
  getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$2];
2897
2903
  currentPipelineStepIndex: number;
@@ -2991,419 +2997,503 @@ declare class SimpleHighDensitySolver extends BaseSolver {
2991
2997
  visualize(): GraphicsObject;
2992
2998
  }
2993
2999
 
2994
- type FutureConnection = {
2995
- connectionName: string;
2996
- points: {
3000
+ type HyperGraphPatternType = "single_1206x4" | "1x2_1206x4" | "2x2_1206x4";
3001
+ interface JumperPrepatternSolver2HyperParameters {
3002
+ /** Pattern type for jumper placement - "single_1206x4" (~8x8mm) or "2x2_1206x4" (~14x14mm) */
3003
+ PATTERN_TYPE?: HyperGraphPatternType;
3004
+ /** Orientation of jumpers - "horizontal" or "vertical" */
3005
+ ORIENTATION?: "horizontal" | "vertical";
3006
+ }
3007
+ interface JumperPrepatternSolver2Params {
3008
+ nodeWithPortPoints: NodeWithPortPoints;
3009
+ colorMap?: Record<string, string>;
3010
+ traceWidth?: number;
3011
+ hyperParameters?: JumperPrepatternSolver2HyperParameters;
3012
+ connMap?: ConnectivityMap;
3013
+ }
3014
+ interface XYConnection {
3015
+ start: {
2997
3016
  x: number;
2998
3017
  y: number;
2999
- z: number;
3000
- }[];
3018
+ };
3019
+ end: {
3020
+ x: number;
3021
+ y: number;
3022
+ };
3023
+ connectionId: string;
3024
+ }
3025
+ declare class JumperPrepatternSolver2_HyperGraph extends BaseSolver {
3026
+ constructorParams: JumperPrepatternSolver2Params;
3027
+ nodeWithPortPoints: NodeWithPortPoints;
3028
+ colorMap: Record<string, string>;
3029
+ traceWidth: number;
3030
+ hyperParameters: JumperPrepatternSolver2HyperParameters;
3031
+ jumperGraphSolver: JumperGraphSolver | null;
3032
+ xyConnections: XYConnection[];
3033
+ graphBounds: {
3034
+ minX: number;
3035
+ maxX: number;
3036
+ minY: number;
3037
+ maxY: number;
3038
+ } | null;
3039
+ solvedRoutes: HighDensityIntraNodeRouteWithJumpers[];
3040
+ constructor(params: JumperPrepatternSolver2Params);
3041
+ getConstructorParams(): JumperPrepatternSolver2Params;
3042
+ private _buildColorMap;
3043
+ private _getPatternConfig;
3044
+ private _initializeGraph;
3045
+ _step(): void;
3046
+ private _processResults;
3047
+ getOutput(): HighDensityIntraNodeRouteWithJumpers[];
3048
+ visualize(): GraphicsObject;
3049
+ private _drawJumperPads;
3050
+ }
3051
+
3052
+ interface HyperJumperPrepatternSolver2Params {
3053
+ nodeWithPortPoints: NodeWithPortPoints;
3054
+ colorMap?: Record<string, string>;
3055
+ traceWidth?: number;
3056
+ connMap?: ConnectivityMap;
3057
+ hyperParameters?: JumperPrepatternSolver2HyperParameters;
3058
+ }
3059
+ type VariantHyperParameters = {
3060
+ PATTERN_TYPE: HyperGraphPatternType;
3061
+ ORIENTATION: "horizontal" | "vertical";
3001
3062
  };
3002
3063
  /**
3003
- * Components that make up the g (cost so far) calculation
3064
+ * HyperJumperPrepatternSolver2 runs multiple variants of JumperPrepatternSolver2_HyperGraph
3065
+ * with different pattern types and orientations, then picks the best solution.
3066
+ *
3067
+ * Variants:
3068
+ * - single_1206x4_vertical
3069
+ * - single_1206x4_horizontal
3070
+ * - 2x2_1206x4_vertical (only if node is large enough, ~14x14mm)
3071
+ * - 2x2_1206x4_horizontal (only if node is large enough, ~14x14mm)
3004
3072
  */
3005
- type GComponents = {
3006
- /** Total path distance traveled from start */
3007
- distFromStart: number;
3008
- /** Cumulative weighted penalty for being near obstacles */
3009
- weightedMmNearObstacle: number;
3010
- /** Cumulative weighted penalty for being near edges */
3011
- weightedMmNearEdge: number;
3012
- /** Cumulative weighted penalty for being near future connection start/end points */
3013
- weightedMmNearFutureConnectionStartEnd: number;
3014
- /** Cumulative weighted penalty for being near future connection lines */
3015
- weightedMmNearFutureConnectionLine: number;
3016
- /** Cumulative jumper penalty (includes jumper distance + penalty factor) */
3017
- jumperPenalty: number;
3018
- /** Cumulative penalty for jumper pads near future connections */
3019
- jumperPadFutureConnectionPenalty: number;
3020
- /** Total g value (sum of all components) */
3021
- total: number;
3022
- };
3073
+ declare class HyperJumperPrepatternSolver2 extends HyperParameterSupervisorSolver<JumperPrepatternSolver2_HyperGraph> {
3074
+ constructorParams: HyperJumperPrepatternSolver2Params;
3075
+ nodeWithPortPoints: NodeWithPortPoints;
3076
+ colorMap: Record<string, string>;
3077
+ traceWidth: number;
3078
+ connMap?: ConnectivityMap;
3079
+ baseHyperParameters?: JumperPrepatternSolver2HyperParameters;
3080
+ solvedRoutes: HighDensityIntraNodeRouteWithJumpers[];
3081
+ constructor(params: HyperJumperPrepatternSolver2Params);
3082
+ getConstructorParams(): HyperJumperPrepatternSolver2Params;
3083
+ getHyperParameterDefs(): ({
3084
+ name: string;
3085
+ possibleValues: {
3086
+ PATTERN_TYPE: HyperGraphPatternType;
3087
+ }[];
3088
+ } | {
3089
+ name: string;
3090
+ possibleValues: {
3091
+ ORIENTATION: string;
3092
+ }[];
3093
+ })[];
3094
+ getCombinationDefs(): string[][];
3095
+ generateSolver(hyperParameters: VariantHyperParameters): JumperPrepatternSolver2_HyperGraph;
3096
+ computeG(solver: JumperPrepatternSolver2_HyperGraph): number;
3097
+ computeH(solver: JumperPrepatternSolver2_HyperGraph): number;
3098
+ onSolve(solver: SupervisedSolver<JumperPrepatternSolver2_HyperGraph>): void;
3099
+ getOutput(): HighDensityIntraNodeRouteWithJumpers[];
3100
+ visualize(): GraphicsObject;
3101
+ }
3102
+
3103
+ interface NodeAnalysis {
3104
+ node: NodeWithPortPoints;
3105
+ hasCrossings: boolean;
3106
+ numSameLayerCrossings: number;
3107
+ }
3023
3108
  /**
3024
- * Components that make up the h (heuristic) calculation
3109
+ * HighDensitySolver intelligently selects the appropriate solver for each node:
3110
+ * - SimpleHighDensitySolver for nodes without crossings (faster, force-directed)
3111
+ * - IntraNodeSolverWithJumpers for single-layer nodes with crossings (uses 0603 jumpers)
3112
+ *
3113
+ * This solver processes nodes in batches based on their characteristics.
3025
3114
  */
3026
- type HComponents = {
3027
- distanceToGoal: number;
3028
- obstacleProximity: number;
3029
- edgeProximity: number;
3030
- futureConnectionStartEndProximityPenalty: number;
3031
- futureConnectionLine: number;
3032
- total: number;
3033
- /** Stored rates (penalty per mm) for derivative computation */
3034
- obstacleProximityRate: number;
3035
- edgeProximityRate: number;
3036
- futureConnectionStartEndProximityRate: number;
3037
- futureConnectionLineRate: number;
3038
- };
3115
+ declare class JumperHighDensitySolver extends BaseSolver {
3116
+ allNodes: NodeWithPortPoints[];
3117
+ nodeAnalyses: NodeAnalysis[];
3118
+ routes: HighDensityIntraNodeRoute$1[];
3119
+ colorMap: Record<string, string>;
3120
+ traceWidth: number;
3121
+ viaDiameter: number;
3122
+ connMap?: ConnectivityMap;
3123
+ hyperParameters?: Partial<HighDensityHyperParameters>;
3124
+ nodesWithoutCrossings: NodeWithPortPoints[];
3125
+ nodesWithCrossings: NodeWithPortPoints[];
3126
+ simpleHighDensitySolver?: SimpleHighDensitySolver;
3127
+ jumperSolvers: HyperJumperPrepatternSolver2[];
3128
+ currentJumperSolverIndex: number;
3129
+ phase: "analyzing" | "simple" | "jumpers" | "done";
3130
+ constructor({ nodePortPoints, colorMap, traceWidth, viaDiameter, connMap, hyperParameters, }: {
3131
+ nodePortPoints: NodeWithPortPoints[];
3132
+ colorMap?: Record<string, string>;
3133
+ traceWidth?: number;
3134
+ viaDiameter?: number;
3135
+ connMap?: ConnectivityMap;
3136
+ hyperParameters?: Partial<HighDensityHyperParameters>;
3137
+ });
3138
+ /**
3139
+ * Analyze all nodes to determine which solver to use for each
3140
+ */
3141
+ _analyzeNodes(): void;
3142
+ _step(): void;
3143
+ _stepSimpleSolver(): void;
3144
+ _initializeJumperSolvers(): void;
3145
+ _stepJumperSolvers(): void;
3146
+ computeProgress(): number;
3147
+ getConstructorParams(): {
3148
+ nodePortPoints: NodeWithPortPoints[];
3149
+ colorMap: Record<string, string>;
3150
+ traceWidth: number;
3151
+ viaDiameter: number;
3152
+ connMap: ConnectivityMap | undefined;
3153
+ hyperParameters: Partial<HighDensityHyperParameters> | undefined;
3154
+ };
3155
+ visualize(): GraphicsObject;
3156
+ }
3157
+
3039
3158
  /**
3040
- * Extended node type that tracks jumper usage
3159
+ * ObstacleTree wraps different spatial index implementations:
3160
+ * - 'native': original spatial-hash grid
3161
+ * - 'rbush': dynamic R-tree via rbush
3162
+ * - 'flatbush': static index via flatbush
3041
3163
  */
3042
- type JumperNode = Node & {
3043
- /** If this node was reached via a jumper, this contains jumper info */
3044
- jumperEntry?: {
3045
- x: number;
3046
- y: number;
3047
- };
3048
- /** Track if this movement is the exit of a jumper */
3049
- isJumperExit?: boolean;
3050
- /** Count of jumpers used to reach this node */
3051
- jumperCount?: number;
3052
- /** Stored g components for debugging/visualization */
3053
- gComponents?: GComponents;
3054
- /** Stored h components for debugging/visualization */
3055
- hComponents?: HComponents;
3056
- };
3057
- declare class SingleHighDensityRouteWithJumpersSolver extends BaseSolver {
3058
- obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[];
3059
- bounds: {
3164
+ declare class ObstacleSpatialHashIndex {
3165
+ private idx;
3166
+ private storage;
3167
+ constructor(implementation?: "native" | "rbush" | "flatbush", obstacles?: Obstacle[]);
3168
+ insert(o: Obstacle): void;
3169
+ search(bbox: {
3060
3170
  minX: number;
3061
- maxX: number;
3062
3171
  minY: number;
3172
+ maxX: number;
3063
3173
  maxY: number;
3064
- };
3065
- boundsSize: {
3066
- width: number;
3067
- height: number;
3068
- };
3069
- boundsCenter: {
3070
- x: number;
3071
- y: number;
3072
- };
3073
- A: {
3074
- x: number;
3075
- y: number;
3076
- z: number;
3077
- };
3078
- B: {
3174
+ }): Obstacle[];
3175
+ searchArea(centerX: number, centerY: number, width: number, height: number): Obstacle[];
3176
+ }
3177
+
3178
+ interface Point$1 {
3179
+ x: number;
3180
+ y: number;
3181
+ z: number;
3182
+ }
3183
+ type Point2D$3 = {
3184
+ x: number;
3185
+ y: number;
3186
+ };
3187
+ type HighDensityIntraNodeRoute = {
3188
+ connectionName: string;
3189
+ rootConnectionName?: string;
3190
+ traceThickness: number;
3191
+ viaDiameter: number;
3192
+ route: Array<{
3079
3193
  x: number;
3080
3194
  y: number;
3081
3195
  z: number;
3082
- };
3083
- roundedGoalPosition: {
3196
+ }>;
3197
+ vias: Array<{
3084
3198
  x: number;
3085
3199
  y: number;
3086
- z: number;
3087
- };
3088
- straightLineDistance: number;
3089
- traceThickness: number;
3090
- obstacleMargin: number;
3091
- minCellSize: number;
3092
- cellStep: number;
3093
- GREEDY_MULTIPLER: number;
3094
- numRoutes: number;
3095
- /** Penalty factor for using a jumper (relative to distance) */
3096
- JUMPER_PENALTY_FACTOR: number;
3097
- /** Future connection proximity parameters */
3098
- FUTURE_CONNECTION_START_END_PENALTY: number;
3099
- FUTURE_CONNECTION_START_END_PROXIMITY: number;
3100
- /** Future connection jumper pad penalty parameters */
3101
- FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY: number;
3102
- FUTURE_CONNECTION_JUMPER_PAD_PENALTY: number;
3103
- /** Jumper-to-jumper pad proximity penalty parameters */
3104
- JUMPER_JUMPER_PAD_PROXIMITY: number;
3105
- JUMPER_JUMPER_PAD_PENALTY: number;
3106
- /** Future connection line proximity penalty parameters */
3107
- FUTURE_CONNECTION_LINE_PROXIMITY: number;
3108
- FUTURE_CONNECTION_LINE_PENALTY: number;
3109
- /** Obstacle proximity penalty parameters (repulsive field) */
3110
- OBSTACLE_PROX_PENALTY_FACTOR: number;
3111
- OBSTACLE_PROX_SIGMA: number;
3112
- /** Edge proximity penalty parameters */
3113
- EDGE_PROX_PENALTY_FACTOR: number;
3114
- EDGE_PROX_SIGMA: number;
3115
- /** Whether to allow diagonal movement in pathfinding */
3116
- ALLOW_DIAGONAL: boolean;
3117
- /** Minimum distance traveled before allowing jumper neighbors */
3118
- MIN_TRAVEL_BEFORE_JUMPER: number;
3119
- CELL_SIZE_FACTOR: number;
3120
- exploredNodes: Set<string>;
3121
- candidates: SingleRouteCandidatePriorityQueue<JumperNode>;
3122
- connectionName: string;
3123
- rootConnectionName?: string;
3124
- solvedPath: HighDensityIntraNodeRouteWithJumpers | null;
3125
- futureConnections: FutureConnection[];
3126
- hyperParameters: Partial<HighDensityHyperParameters>;
3127
- connMap?: ConnectivityMap;
3128
- /** For debugging/animating the exploration */
3129
- debug_exploredNodesOrdered: string[];
3130
- debug_exploredNodeValues: Map<string, {
3131
- g: number;
3132
- h: number;
3133
- f: number;
3134
- gComponents?: GComponents;
3135
- hComponents?: HComponents;
3136
3200
  }>;
3137
- debug_nodesTooCloseToObstacle: Set<string>;
3138
- debug_nodePathToParentIntersectsObstacle: Set<string>;
3139
- debugEnabled: boolean;
3140
- initialNodeGridOffset: {
3141
- x: number;
3142
- y: number;
3143
- };
3144
- /** Existing jumpers that act as obstacles */
3145
- existingJumpers: Jumper[];
3146
- constructor(opts: {
3147
- connectionName: string;
3148
- rootConnectionName?: string;
3149
- obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[];
3150
- minDistBetweenEnteringPoints: number;
3151
- bounds: {
3152
- minX: number;
3153
- maxX: number;
3154
- minY: number;
3155
- maxY: number;
3156
- };
3157
- A: {
3158
- x: number;
3159
- y: number;
3160
- z: number;
3161
- };
3162
- B: {
3163
- x: number;
3164
- y: number;
3165
- z: number;
3166
- };
3167
- traceThickness?: number;
3168
- obstacleMargin?: number;
3169
- futureConnections?: FutureConnection[];
3170
- hyperParameters?: Partial<HighDensityHyperParameters>;
3171
- connMap?: ConnectivityMap;
3172
- });
3173
- handleSimpleCases(): void;
3174
- get jumperPenaltyDistance(): number;
3175
- /**
3176
- * Check if a node is too close to an obstacle trace or jumper
3177
- */
3178
- isNodeTooCloseToObstacle(node: JumperNode, margin?: number): boolean;
3179
- /**
3180
- * Check if a node is too close to a jumper's pads
3181
- * Traces CAN route under the body of the jumper, just not under the pads
3182
- */
3183
- isNodeTooCloseToJumper(node: {
3184
- x: number;
3185
- y: number;
3186
- }, jumper: Jumper, margin: number): boolean;
3187
- isNodeTooCloseToEdge(node: JumperNode): boolean;
3188
- doesPathToParentIntersectObstacle(node: JumperNode): boolean;
3189
- /**
3190
- * Check if a line segment intersects with a jumper's pads
3191
- * Segments CAN pass under the jumper body, just not through the pads
3192
- */
3193
- doesSegmentIntersectJumperPads(p1: {
3194
- x: number;
3195
- y: number;
3196
- }, p2: {
3197
- x: number;
3198
- y: number;
3199
- }, jumper: Jumper): boolean;
3200
- /**
3201
- * Check if a line segment intersects with an axis-aligned rectangle
3202
- */
3203
- doesSegmentIntersectRect(p1: {
3204
- x: number;
3205
- y: number;
3206
- }, p2: {
3207
- x: number;
3208
- y: number;
3209
- }, center: {
3210
- x: number;
3211
- y: number;
3212
- }, halfWidth: number, halfHeight: number): boolean;
3201
+ jumpers?: Jumper[];
3202
+ };
3203
+ type HighDensityRoute = HighDensityIntraNodeRoute;
3204
+ declare class HighDensityRouteSpatialIndex {
3205
+ private segmentBuckets;
3206
+ private viaBuckets;
3207
+ private CELL_SIZE;
3208
+ constructor(routes: HighDensityRoute[], cellSize?: number);
3213
3209
  /**
3214
- * Find obstacles between current node and a target position
3215
- * Returns the obstacle segment(s) that block the direct path
3210
+ * Finds routes that potentially conflict with a given line segment within a margin.
3211
+ * Checks both segments and vias.
3212
+ * @param segmentStart Start point of the query segment.
3213
+ * @param segmentEnd End point of the query segment.
3214
+ * @param margin The minimum required clearance distance from the query segment's centerline.
3215
+ * @returns An array of conflicting routes and their minimum distance to the segment.
3216
3216
  */
3217
- findObstaclesBetween(from: {
3218
- x: number;
3219
- y: number;
3220
- }, to: {
3221
- x: number;
3222
- y: number;
3223
- }): Array<{
3224
- A: {
3225
- x: number;
3226
- y: number;
3227
- };
3228
- B: {
3229
- x: number;
3230
- y: number;
3231
- };
3217
+ getConflictingRoutesForSegment(segmentStart: Point$1, // Keep Point for original Z data if needed elsewhere
3218
+ segmentEnd: Point$1, margin: number): Array<{
3219
+ conflictingRoute: HighDensityRoute;
3220
+ distance: number;
3232
3221
  }>;
3233
- computeHComponents(node: JumperNode): HComponents;
3234
- computeH(node: JumperNode): number;
3235
- computeGComponents(node: JumperNode): GComponents;
3236
- computeG(node: JumperNode): number;
3237
- computeF(g: number, h: number): number;
3238
- getClosestFutureConnectionPoint(node: JumperNode): {
3239
- x: number;
3240
- y: number;
3241
- z: number;
3242
- } | null;
3243
- getFutureConnectionStartEndPenalty(node: JumperNode): number;
3244
- /**
3245
- * Calculate penalty for being close to future connection line segments.
3246
- * This penalty is computed by summing the segment-to-point distance between
3247
- * the node and all unrouted future connection start-to-end segments.
3248
- * The penalty helps routes avoid crossing directly over future connection paths.
3249
- */
3250
- getFutureConnectionLinePenalty(node: JumperNode): number;
3251
3222
  /**
3252
- * Calculate penalty for jumper pads placed near future connection start/end points.
3253
- * This disincentivizes placing jumper pads in areas that will be needed for future routing.
3254
- * The distance is calculated as the minimum distance from either jumper pad to any future connection point.
3255
- */
3256
- getJumperPadFutureConnectionPenalty(node: JumperNode): number;
3257
- /**
3258
- * Compute the minimum distance from a node to any obstacle (trace segments and jumper pads)
3223
+ * Finds routes that pass near a given point within a margin.
3224
+ * Checks both segments and vias.
3225
+ * @param point The query point {x, y}. Z is ignored.
3226
+ * @param margin The minimum required clearance distance from the query point.
3227
+ * @returns An array of conflicting routes and their minimum distance to the point.
3259
3228
  */
3260
- getClearanceToObstacles(node: {
3261
- x: number;
3262
- y: number;
3263
- }): number;
3229
+ getConflictingRoutesNearPoint(point: Point2D$3, margin: number): Array<{
3230
+ conflictingRoute: HighDensityRoute;
3231
+ distance: number;
3232
+ }>;
3233
+ }
3234
+
3235
+ interface Point2D$2 {
3236
+ x: number;
3237
+ y: number;
3238
+ }
3239
+ interface Segment {
3240
+ start: Point2D$2;
3241
+ end: Point2D$2;
3242
+ }
3243
+
3244
+ interface Point2D$1 {
3245
+ x: number;
3246
+ y: number;
3247
+ }
3248
+ interface Point3D$1 extends Point2D$1 {
3249
+ z: number;
3250
+ }
3251
+ interface TraceKeepoutSolverInput {
3252
+ hdRoutes: HighDensityRoute$1[];
3253
+ obstacles: Obstacle[];
3254
+ connMap: ConnectivityMap;
3255
+ colorMap: Record<string, string>;
3256
+ keepoutRadiusSchedule?: number[];
3257
+ srj?: Pick<SimpleRouteJson, "outline" | "bounds" | "layerCount">;
3258
+ }
3259
+ /**
3260
+ * TraceKeepoutSolver adjusts traces to maintain keepout distance from obstacles
3261
+ * and non-connected traces. It works by walking along each trace with a cursor,
3262
+ * detecting obstacles within a keepout radius, and pushing the draw position
3263
+ * orthogonally to avoid them.
3264
+ *
3265
+ * The solver processes traces through multiple passes with decreasing keepout
3266
+ * radii as defined by KEEPOUT_RADIUS_SCHEDULE.
3267
+ */
3268
+ declare class TraceKeepoutSolver extends BaseSolver {
3269
+ private input;
3270
+ originalHdRoutes: HighDensityRoute$1[];
3271
+ hdRoutes: HighDensityRoute$1[];
3272
+ redrawnHdRoutes: HighDensityRoute$1[];
3273
+ KEEPOUT_RADIUS_SCHEDULE: number[];
3274
+ currentScheduleIndex: number;
3275
+ currentKeepoutRadius: number;
3276
+ unprocessedRoutes: HighDensityRoute$1[];
3277
+ smoothedCursorRoutes: HighDensityRoute$1[];
3278
+ processedRoutes: HighDensityRoute$1[];
3279
+ currentTrace: HighDensityRoute$1 | null;
3280
+ cursorPosition: Point3D$1 | null;
3281
+ lastCursorPosition: Point3D$1 | null;
3282
+ drawPosition: Point2D$1 | null;
3283
+ currentTraceSegmentIndex: number;
3284
+ currentTraceSegmentT: number;
3285
+ recordedDrawPositions: Point3D$1[];
3286
+ lastCollidingSegments: Segment[];
3287
+ obstacleSHI: ObstacleSpatialHashIndex;
3288
+ hdRouteSHI: HighDensityRouteSpatialIndex;
3289
+ boardOutlineRoutes: HighDensityRoute$1[];
3290
+ constructor(input: TraceKeepoutSolverInput);
3291
+ getSmoothDistance(): number;
3292
+ _step(): void;
3293
+ getStepDistance(): number;
3264
3294
  /**
3265
- * Compute distance from a point to the nearest jumper pad
3295
+ * Steps the cursor forward by CURSOR_STEP_DISTANCE along the trace
3296
+ * Returns false if we've reached the end of the trace
3266
3297
  */
3267
- distanceToJumperPads(p: {
3268
- x: number;
3269
- y: number;
3270
- }, j: Jumper): number;
3298
+ private stepCursorForward;
3271
3299
  /**
3272
- * Compute distance from a point to an axis-aligned rectangle (0 if inside)
3300
+ * Gets all colliding segments (obstacle edges and trace outlines) within the keepout radius
3273
3301
  */
3274
- pointToRectDistance(p: {
3275
- x: number;
3276
- y: number;
3277
- }, c: {
3302
+ private getCollidingSegments;
3303
+ positionHasCollision(position: {
3278
3304
  x: number;
3279
3305
  y: number;
3280
- }, halfW: number, halfH: number): number;
3306
+ z: number;
3307
+ }, margin?: number): boolean;
3281
3308
  /**
3282
- * Compute minimum distance from a node to the nearest boundary edge
3309
+ * Finalizes the current trace with the recorded draw positions
3283
3310
  */
3284
- getClearanceToEdge(node: {
3285
- x: number;
3286
- y: number;
3287
- }): number;
3311
+ private finalizeCurrentTrace;
3288
3312
  /**
3289
- * Compute the obstacle proximity penalty (repulsive field)
3290
- * Returns a high value near obstacles, ~0 far away
3313
+ * Simplifies the route by removing collinear points
3291
3314
  */
3292
- getObstacleProximityPenalty(node: JumperNode): number;
3315
+ private simplifyRoute;
3293
3316
  /**
3294
- * Compute the edge proximity penalty (repulsive field near boundaries)
3295
- * Returns a high value near edges, ~0 far away
3296
- * Penalty is reduced as we approach the goal (which is always on an edge)
3317
+ * Creates artificial hdRoutes representing the board outline.
3318
+ * These routes act as obstacles to prevent traces from being pushed outside the board.
3297
3319
  */
3298
- getEdgeProximityPenalty(node: JumperNode): number;
3299
- getNodeKey(node: JumperNode): string;
3300
- /**
3301
- * Calculate potential jumper positions to cross an obstacle
3302
- */
3303
- getJumperNeighbors(node: JumperNode): JumperNode[];
3304
- /**
3305
- * Calculate the exit position for a jumper that clears an obstacle
3306
- */
3307
- calculateJumperExit(entry: JumperNode, obstacle: {
3308
- A: {
3309
- x: number;
3310
- y: number;
3311
- };
3312
- B: {
3313
- x: number;
3314
- y: number;
3315
- };
3316
- }, direction: {
3317
- dx: number;
3318
- dy: number;
3319
- }): JumperNode | null;
3320
- /**
3321
- * Check if a jumper's pads are too close to obstacle traces
3322
- */
3323
- isJumperTooCloseToTraces(entry: {
3324
- x: number;
3325
- y: number;
3326
- }, exit: {
3327
- x: number;
3328
- y: number;
3329
- }): boolean;
3320
+ private createBoardOutlineRoutes;
3321
+ visualize(): GraphicsObject;
3322
+ /** Returns the redrawn routes. This is the primary output of the solver. */
3323
+ getRedrawnHdRoutes(): HighDensityRoute$1[];
3324
+ }
3325
+
3326
+ interface Point2D {
3327
+ x: number;
3328
+ y: number;
3329
+ }
3330
+ interface Point3D extends Point2D {
3331
+ z: number;
3332
+ }
3333
+ interface TraceWidthSolverInput {
3334
+ hdRoutes: HighDensityRoute$1[];
3335
+ obstacles?: Obstacle[];
3336
+ connMap?: ConnectivityMap;
3337
+ colorMap?: Record<string, string>;
3338
+ nominalTraceWidth?: number;
3339
+ minTraceWidth: number;
3340
+ obstacleMargin?: number;
3341
+ }
3342
+ /**
3343
+ * TraceWidthSolver determines the optimal trace width for each route.
3344
+ * It uses a TRACE_WIDTH_SCHEDULE to try progressively narrower widths:
3345
+ * [nominalTraceWidth, (nominalTraceWidth + minTraceWidth)/2, minTraceWidth]
3346
+ *
3347
+ * For each trace, it walks along with a cursor checking clearance.
3348
+ * If clearance is insufficient for the current width, it tries the next
3349
+ * narrower width in the schedule.
3350
+ *
3351
+ * nominalTraceWidth defaults to minTraceWidth * 2 if not specified.
3352
+ */
3353
+ declare class TraceWidthSolver extends BaseSolver {
3354
+ hdRoutes: HighDensityRoute$1[];
3355
+ hdRoutesWithWidths: HighDensityRoute$1[];
3356
+ nominalTraceWidth: number;
3357
+ minTraceWidth: number;
3358
+ obstacleMargin: number;
3359
+ TRACE_WIDTH_SCHEDULE: number[];
3360
+ unprocessedRoutes: HighDensityRoute$1[];
3361
+ processedRoutes: HighDensityRoute$1[];
3362
+ currentTrace: HighDensityRoute$1 | null;
3363
+ cursorPosition: Point3D | null;
3364
+ currentTraceSegmentIndex: number;
3365
+ currentTraceSegmentT: number;
3366
+ currentScheduleIndex: number;
3367
+ currentTargetWidth: number;
3368
+ hasInsufficientClearance: boolean;
3369
+ currentWalkMinClearance: number;
3370
+ bestMinClearance: number;
3371
+ bestWidth: number;
3372
+ lastCollidingObstacles: Obstacle[];
3373
+ lastCollidingRoutes: HighDensityRoute$1[];
3374
+ lastClearance: number;
3375
+ obstacles: Obstacle[];
3376
+ obstacleSHI?: ObstacleSpatialHashIndex;
3377
+ hdRouteSHI: HighDensityRouteSpatialIndex;
3378
+ connMap?: ConnectivityMap;
3379
+ colorMap?: Record<string, string>;
3380
+ constructor(input: TraceWidthSolverInput);
3381
+ _step(): void;
3330
3382
  /**
3331
- * Verify that a jumper placement is valid (doesn't overlap with existing jumpers or traces)
3383
+ * Initializes/resets the cursor for processing a trace
3332
3384
  */
3333
- isJumperPlacementValid(entry: JumperNode, exit: JumperNode): boolean;
3385
+ private initializeCursor;
3334
3386
  /**
3335
- * Check if two jumpers overlap
3387
+ * Steps the cursor forward by CURSOR_STEP_DISTANCE along the trace
3388
+ * Returns false if we've reached the end of the trace
3336
3389
  */
3337
- doJumpersOverlap(j1: Jumper, j2: Jumper): boolean;
3390
+ private stepCursorForward;
3338
3391
  /**
3339
- * Get all jumpers in the path to a node
3392
+ * Gets the minimum clearance at a given position from obstacles and other traces
3393
+ * Also updates lastCollidingObstacles and lastCollidingRoutes for visualization
3340
3394
  */
3341
- getJumpersInPath(node: JumperNode): Jumper[];
3342
- getNeighbors(node: JumperNode): JumperNode[];
3343
- getNodePath(node: JumperNode): JumperNode[];
3344
- setSolvedPath(node: JumperNode): void;
3345
- computeProgress(currentNode: JumperNode, goalDist: number): number;
3346
- _step(): void;
3395
+ private getClearanceAtPosition;
3347
3396
  /**
3348
- * Draw the two pads of an 0603 jumper
3349
- * Pad dimensions are rotated based on jumper orientation
3397
+ * Finalizes the current trace with the given width
3350
3398
  */
3351
- private drawJumperPads;
3399
+ private finalizeCurrentTrace;
3352
3400
  visualize(): GraphicsObject;
3401
+ /** Returns the routes with determined widths. This is the primary output of the solver. */
3402
+ getHdRoutesWithWidths(): HighDensityRoute$1[];
3353
3403
  }
3354
3404
 
3405
+ interface OffboardPortPoint {
3406
+ portPointId: string;
3407
+ x: number;
3408
+ y: number;
3409
+ /** The obstacle this port point is at the center of */
3410
+ obstacleIndex: number;
3411
+ /** The offBoardConnectsTo ids this port point is associated with */
3412
+ offBoardConnectionIds: OffBoardConnectionId[];
3413
+ /** Available Z layers for this port point based on obstacle layers */
3414
+ availableZ: number[];
3415
+ }
3416
+ interface OffboardPathFragment {
3417
+ pathFragmentId: string;
3418
+ /** The shared offBoardConnectsTo id that connects these port points */
3419
+ offBoardConnectionId: OffBoardConnectionId;
3420
+ /** The two port points connected by this path fragment */
3421
+ portPointIds: [string, string];
3422
+ /** Endpoints of this edge */
3423
+ start: {
3424
+ x: number;
3425
+ y: number;
3426
+ };
3427
+ end: {
3428
+ x: number;
3429
+ y: number;
3430
+ };
3431
+ }
3432
+ type Phase = "finding_obstacles" | "creating_fragments" | "done";
3433
+ interface PendingFragment {
3434
+ offBoardId: OffBoardConnectionId;
3435
+ pp1: OffboardPortPoint;
3436
+ pp2: OffboardPortPoint;
3437
+ }
3355
3438
  /**
3356
- * IntraNodeSolverWithJumpers is designed for single-layer nodes that use
3357
- * 0603 jumpers to allow traces to jump over each other.
3439
+ * PortPointOffboardPathFragmentSolver finds obstacles with offBoardConnectsTo
3440
+ * defined and creates port points at their centers. It then creates path
3441
+ * fragments (edges) connecting port points that share the same offBoardConnectsTo
3442
+ * ids.
3358
3443
  *
3359
- * Unlike the standard IntraNodeRouteSolver which uses vias to change layers,
3360
- * this solver operates on a single layer and uses physical jumper components
3361
- * to handle trace crossings.
3444
+ * This enables routing through off-board connections like flex cables or
3445
+ * external connectors.
3446
+ *
3447
+ * The solver iterates step-by-step:
3448
+ * 1. Phase "finding_obstacles": Process one obstacle per step, creating port points
3449
+ * 2. Phase "creating_fragments": Create one path fragment per step
3450
+ * 3. Phase "done": Solver complete
3362
3451
  */
3363
- declare class IntraNodeSolverWithJumpers extends BaseSolver {
3364
- nodeWithPortPoints: NodeWithPortPoints;
3452
+ declare class PortPointOffboardPathFragmentSolver extends BaseSolver {
3453
+ srj: SimpleRouteJson;
3365
3454
  colorMap: Record<string, string>;
3366
- unsolvedConnections: {
3367
- connectionName: string;
3368
- rootConnectionName?: string;
3369
- points: {
3370
- x: number;
3371
- y: number;
3372
- z: number;
3373
- }[];
3374
- }[];
3375
- totalConnections: number;
3376
- solvedRoutes: HighDensityIntraNodeRouteWithJumpers[];
3377
- failedSubSolvers: SingleHighDensityRouteWithJumpersSolver[];
3378
- hyperParameters: Partial<HighDensityHyperParameters>;
3379
- minDistBetweenEnteringPoints: number;
3380
- traceWidth: number;
3381
- activeSubSolver: SingleHighDensityRouteWithJumpersSolver | null;
3382
- lastActiveSubSolver: SingleHighDensityRouteWithJumpersSolver | null;
3383
- connMap?: ConnectivityMap;
3384
- get failedSolvers(): SingleHighDensityRouteWithJumpersSolver[];
3385
- get activeSolver(): SingleHighDensityRouteWithJumpersSolver | null;
3386
- constructor(params: {
3387
- nodeWithPortPoints: NodeWithPortPoints;
3455
+ /** Current phase of the solver */
3456
+ phase: Phase;
3457
+ /** Index of the current obstacle being processed */
3458
+ currentObstacleIndex: number;
3459
+ /** Obstacles that have offBoardConnectsTo defined */
3460
+ offboardObstacles: Array<{
3461
+ obstacle: Obstacle;
3462
+ index: number;
3463
+ }>;
3464
+ /** Port points created at obstacle centers */
3465
+ portPoints: OffboardPortPoint[];
3466
+ /** Map from portPointId to OffboardPortPoint */
3467
+ portPointMap: Map<string, OffboardPortPoint>;
3468
+ /** Path fragments connecting port points with shared offBoardConnectsTo */
3469
+ pathFragments: OffboardPathFragment[];
3470
+ /** Map from offBoardConnectionId to port points that share it */
3471
+ offBoardConnectionToPortPoints: Map<OffBoardConnectionId, OffboardPortPoint[]>;
3472
+ /** Pending path fragments to create (computed after obstacle phase) */
3473
+ pendingFragments: PendingFragment[];
3474
+ /** Index of current fragment being created */
3475
+ currentFragmentIndex: number;
3476
+ /** Last processed obstacle (for visualization) */
3477
+ lastProcessedObstacle: {
3478
+ obstacle: Obstacle;
3479
+ index: number;
3480
+ } | null;
3481
+ /** Last created port point (for visualization) */
3482
+ lastCreatedPortPoint: OffboardPortPoint | null;
3483
+ /** Last created path fragment (for visualization) */
3484
+ lastCreatedFragment: OffboardPathFragment | null;
3485
+ /** Color map for offBoardConnectionIds */
3486
+ offBoardColorMap: Record<string, string>;
3487
+ constructor({ srj, colorMap, }: {
3488
+ srj: SimpleRouteJson;
3388
3489
  colorMap?: Record<string, string>;
3389
- hyperParameters?: Partial<HighDensityHyperParameters>;
3390
- connMap?: ConnectivityMap;
3391
- traceWidth?: number;
3392
3490
  });
3393
- getConstructorParams(): {
3394
- nodeWithPortPoints: NodeWithPortPoints;
3395
- colorMap: Record<string, string>;
3396
- hyperParameters: Partial<HighDensityHyperParameters>;
3397
- connMap: ConnectivityMap | undefined;
3398
- traceWidth: number;
3399
- };
3400
- computeProgress(): number;
3401
3491
  _step(): void;
3402
- /**
3403
- * Draw the two pads of an 0603 jumper
3404
- * Pad dimensions are rotated based on jumper orientation
3405
- */
3406
- private drawJumperPads;
3492
+ private stepFindingObstacles;
3493
+ private computePendingFragments;
3494
+ private stepCreatingFragments;
3495
+ private layerToZ;
3496
+ computeProgress(): number;
3407
3497
  visualize(): GraphicsObject;
3408
3498
  }
3409
3499
 
@@ -3427,11 +3517,11 @@ declare class RelateNodesToOffBoardConnectionsSolver extends BaseSolver {
3427
3517
  capacityMeshNodes: CapacityMeshNode[];
3428
3518
  srj: SimpleRouteJson;
3429
3519
  };
3430
- unprocessedObstacles: Obstacle$1[];
3520
+ unprocessedObstacles: Obstacle[];
3431
3521
  nodeTree: CapacityNodeTree;
3432
3522
  offBoardConnMap: ConnectivityMap$1;
3433
3523
  nodesInNet: Map<OffBoardConnectionId, CapacityMeshNode[]>;
3434
- lastProcessedObstacle?: Obstacle$1;
3524
+ lastProcessedObstacle?: Obstacle;
3435
3525
  constructor(input: {
3436
3526
  capacityMeshNodes: CapacityMeshNode[];
3437
3527
  srj: SimpleRouteJson;
@@ -3443,1426 +3533,1248 @@ declare class RelateNodesToOffBoardConnectionsSolver extends BaseSolver {
3443
3533
  visualize(): GraphicsObject;
3444
3534
  }
3445
3535
 
3446
- type JumperFootprint = "0603" | "1206";
3447
-
3448
- interface Obstacle {
3449
- type: "rect";
3450
- obstacleId: string;
3451
- layers: string[];
3452
- center: {
3453
- x: number;
3454
- y: number;
3455
- };
3456
- width: number;
3457
- height: number;
3458
- connectedTo: string[];
3459
- offBoardConnectsTo?: string[];
3536
+ interface CapacityMeshSolverOptions$1 {
3537
+ capacityDepth?: number;
3538
+ targetMinCapacity?: number;
3539
+ cacheProvider?: CacheProvider | null;
3540
+ effort?: number;
3460
3541
  }
3461
- interface PrepatternJumper {
3462
- jumperId: string;
3463
- start: {
3464
- x: number;
3465
- y: number;
3466
- };
3467
- end: {
3468
- x: number;
3469
- y: number;
3470
- };
3471
- footprint: JumperFootprint;
3472
- offBoardConnectionId: string;
3473
- }
3474
- interface PatternResult {
3475
- jumperPadObstacles: Obstacle[];
3476
- prepatternJumpers: PrepatternJumper[];
3477
- }
3478
-
3479
- interface RemoveUnnecessaryJumpersSolverParams {
3480
- /**
3481
- * Input nodes from the PortPointPathingSolver
3482
- */
3483
- inputNodes: InputNodeWithPortPoints[];
3484
- /**
3485
- * Set of jumper off-board connection IDs that were actually used by routes
3486
- */
3487
- usedJumperOffBoardObstacleIds: Set<string>;
3488
- /**
3489
- * Connectivity map for off-board obstacles (used to check if a jumper net was used)
3490
- */
3491
- offBoardConnMap?: ConnectivityMap | null;
3492
- }
3493
- /**
3494
- * RemoveUnnecessaryJumpersSolver removes jumpers that aren't needed because
3495
- * there are no traces between the pads. It converts unused jumper nodes back
3496
- * to regular nodes so the high density solver can route through them normally.
3497
- *
3498
- * This solver runs after PortPointPathingSolver and before HighDensitySolver.
3499
- */
3500
- declare class RemoveUnnecessaryJumpersSolver extends BaseSolver {
3501
- inputNodes: InputNodeWithPortPoints[];
3502
- usedJumperOffBoardObstacleIds: Set<string>;
3503
- offBoardConnMap: ConnectivityMap | null;
3504
- /**
3505
- * Output nodes with unused jumper nodes converted to regular nodes
3506
- */
3507
- outputNodes: InputNodeWithPortPoints[];
3508
- /**
3509
- * Set of off-board connection IDs that were removed
3510
- */
3511
- removedOffBoardConnectionIds: Set<string>;
3512
- constructor(params: RemoveUnnecessaryJumpersSolverParams);
3513
- /**
3514
- * Check if a jumper off-board connection ID was used
3515
- */
3516
- private isJumperUsed;
3517
- _step(): void;
3518
- getOutput(): InputNodeWithPortPoints[];
3519
- visualize(): GraphicsObject;
3520
- }
3521
-
3522
- type PatternType = "alternating_grid" | "staggered_grid";
3523
- interface JumperPrepatternSolverHyperParameters {
3524
- /** Orientation of jumpers - "horizontal" or "vertical" */
3525
- FIRST_ORIENTATION?: "horizontal" | "vertical";
3526
- /** Jumper footprint size - defaults to "0603" */
3527
- JUMPER_FOOTPRINT?: JumperFootprint;
3528
- /** Pattern type for jumper placement - defaults to "alternating_grid" */
3529
- PATTERN_TYPE?: PatternType;
3530
- }
3531
- interface JumperPrepatternSolverParams {
3532
- nodeWithPortPoints: NodeWithPortPoints;
3533
- colorMap?: Record<string, string>;
3534
- traceWidth?: number;
3535
- jumperFootprint?: JumperFootprint;
3536
- hyperParameters?: JumperPrepatternSolverHyperParameters;
3537
- connMap?: ConnectivityMap;
3538
- }
3539
- type PipelineStep$2<T extends new (...args: any[]) => BaseSolver> = {
3542
+ type PipelineStep$1<T extends new (...args: any[]) => BaseSolver> = {
3540
3543
  solverName: string;
3541
3544
  solverClass: T;
3542
- getConstructorParams: (instance: JumperPrepatternSolver) => ConstructorParameters<T>;
3543
- onSolved?: (instance: JumperPrepatternSolver) => void;
3545
+ getConstructorParams: (instance: AssignableAutoroutingPipeline2) => ConstructorParameters<T>;
3546
+ onSolved?: (instance: AssignableAutoroutingPipeline2) => void;
3544
3547
  };
3545
- declare class JumperPrepatternSolver extends BaseSolver {
3546
- nodeWithPortPoints: NodeWithPortPoints;
3547
- colorMap: Record<string, string>;
3548
- traceWidth: number;
3549
- jumperFootprint: JumperFootprint;
3550
- hyperParameters: JumperPrepatternSolverHyperParameters;
3551
- connMap: ConnectivityMap;
3552
- prepatternJumpers: PrepatternJumper[];
3553
- patternResult: PatternResult | null;
3554
- capacityNodes: CapacityMeshNode[];
3555
- capacityEdges: CapacityMeshEdge[];
3556
- inputNodes: InputNodeWithPortPoints[];
3557
- connections: SimpleRouteConnection[];
3558
- srjWithPointPairs: SimpleRouteJson;
3548
+ declare class AssignableAutoroutingPipeline2 extends BaseSolver {
3549
+ srj: SimpleRouteJson;
3550
+ opts: CapacityMeshSolverOptions$1;
3551
+ netToPointPairsSolver?: NetToPointPairsSolver;
3559
3552
  nodeSolver?: RectDiffPipeline;
3553
+ nodeTargetMerger?: CapacityNodeTargetMerger;
3554
+ edgeSolver?: CapacityMeshEdgeSolver;
3560
3555
  relateNodesToOffBoardConnections?: RelateNodesToOffBoardConnectionsSolver;
3561
- edgeSolver?: CapacityMeshEdgeSolver2_NodeTreeOptimization;
3556
+ colorMap: Record<string, string>;
3557
+ highDensityRouteSolver?: HighDensitySolver;
3558
+ /** @deprecated Use highDensitySolver instead */
3559
+ simpleHighDensityRouteSolver?: SimpleHighDensitySolver;
3560
+ highDensitySolver?: JumperHighDensitySolver;
3561
+ highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver;
3562
+ singleLayerNodeMerger?: SingleLayerNodeMergerSolver;
3563
+ offboardPathFragmentSolver?: PortPointOffboardPathFragmentSolver;
3564
+ strawSolver?: StrawSolver;
3565
+ deadEndSolver?: DeadEndSolver;
3566
+ traceSimplificationSolver?: TraceSimplificationSolver;
3567
+ traceKeepoutSolver?: TraceKeepoutSolver;
3568
+ traceWidthSolver?: TraceWidthSolver;
3562
3569
  availableSegmentPointSolver?: AvailableSegmentPointSolver;
3563
- portPointPathingSolver?: HyperPortPointPathingSolver;
3570
+ portPointPathingSolver?: PortPointPathingSolver;
3564
3571
  multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer;
3565
- removeUnnecessaryJumpersSolver?: RemoveUnnecessaryJumpersSolver;
3566
- highDensitySolver?: SimpleHighDensitySolver;
3567
- highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver;
3568
- activeSubSolver?: BaseSolver | null;
3569
- currentPipelineStepIndex: number;
3572
+ viaDiameter: number;
3573
+ minTraceWidth: number;
3574
+ effort: number;
3570
3575
  startTimeOfPhase: Record<string, number>;
3571
3576
  endTimeOfPhase: Record<string, number>;
3572
3577
  timeSpentOnPhase: Record<string, number>;
3573
- solvedRoutes: HighDensityIntraNodeRouteWithJumpers[];
3574
- usedJumperOffBoardObstacleIds: Set<string>;
3575
- allUsedJumperOffBoardIds: Set<string>;
3576
- offBoardConnMap: ConnectivityMap | null;
3577
- pipelineDef: (PipelineStep$2<typeof RectDiffPipeline> | PipelineStep$2<typeof RelateNodesToOffBoardConnectionsSolver> | PipelineStep$2<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep$2<typeof AvailableSegmentPointSolver> | PipelineStep$2<typeof HyperPortPointPathingSolver> | PipelineStep$2<typeof RemoveUnnecessaryJumpersSolver> | PipelineStep$2<typeof SimpleHighDensitySolver> | PipelineStep$2<typeof MultipleHighDensityRouteStitchSolver>)[];
3578
- constructor(params: JumperPrepatternSolverParams);
3579
- getCurrentStageName(): string;
3578
+ activeSubSolver?: BaseSolver | null;
3579
+ connMap: ConnectivityMap;
3580
+ srjWithPointPairs?: SimpleRouteJson;
3581
+ capacityNodes: CapacityMeshNode[] | null;
3582
+ capacityEdges: CapacityMeshEdge[] | null;
3583
+ cacheProvider: CacheProvider | null;
3584
+ 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>)[];
3585
+ constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$1);
3586
+ getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$1];
3587
+ currentPipelineStepIndex: number;
3580
3588
  _step(): void;
3589
+ solveUntilPhase(phase: string): void;
3581
3590
  getCurrentPhase(): string;
3582
- _createSimpleRouteJson(): SimpleRouteJson;
3583
- _createJumperPadObstacles(): SimpleRouteJson["obstacles"];
3584
- _addPortPointObstacles(obstacles: SimpleRouteJson["obstacles"]): void;
3585
- _combineResults(): void;
3591
+ visualize(): GraphicsObject;
3586
3592
  /**
3587
- * Get all used jumpers converted to the Jumper type format
3593
+ * A lightweight version of the visualize method that can be used to stream
3594
+ * progress
3595
+ *
3596
+ * We return the most relevant graphic for the stage:
3597
+ * 1. netToPointPairs output
3598
+ * 2. Capacity Planning Output
3599
+ * 3. High Density Route Solver Output, max 200 lines
3588
3600
  */
3589
- _getUsedJumpers(): Jumper[];
3590
- getOutput(): HighDensityIntraNodeRouteWithJumpers[];
3601
+ preview(): GraphicsObject;
3602
+ _getOutputHdRoutes(): HighDensityRoute$1[];
3603
+ getConnectedOffboardObstacles(): Record<ObstacleId, RootConnectionName>;
3591
3604
  /**
3592
- * Draw the two pads of a jumper
3605
+ * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces
3593
3606
  */
3594
- private _drawJumperPads;
3595
- visualize(): GraphicsObject;
3596
- }
3597
-
3598
- type JumperSolver = IntraNodeSolverWithJumpers | JumperPrepatternSolver;
3599
- declare class HyperIntraNodeSolverWithJumpers extends HyperParameterSupervisorSolver<JumperSolver> {
3600
- constructorParams: ConstructorParameters<typeof IntraNodeSolverWithJumpers>[0];
3601
- solvedRoutes: HighDensityIntraNodeRouteWithJumpers[];
3602
- nodeWithPortPoints: NodeWithPortPoints;
3603
- connMap?: ConnectivityMap;
3604
- constructor(opts: ConstructorParameters<typeof IntraNodeSolverWithJumpers>[0]);
3605
- getConstructorParams(): {
3606
- nodeWithPortPoints: NodeWithPortPoints;
3607
- colorMap?: Record<string, string>;
3608
- hyperParameters?: Partial<HighDensityHyperParameters>;
3609
- connMap?: ConnectivityMap;
3610
- traceWidth?: number;
3611
- };
3612
- getHyperParameterDefs(): ({
3613
- name: string;
3614
- possibleValues: {
3615
- SHUFFLE_SEED: number;
3616
- }[];
3617
- } | {
3618
- name: string;
3619
- possibleValues: Array<{
3620
- USE_JUMPER_PREPATTERN: true;
3621
- } & JumperPrepatternSolverHyperParameters>;
3622
- } | {
3623
- name: string;
3624
- possibleValues: {
3625
- USE_JUMPER_PREPATTERN: boolean;
3626
- FIRST_ORIENTATION: string;
3627
- PATTERN_TYPE: string;
3628
- }[];
3629
- })[];
3630
- getCombinationDefs(): string[][];
3631
- _step(): void;
3632
- computeG(solver: JumperSolver): number;
3633
- computeH(solver: JumperSolver): number;
3634
- generateSolver(hyperParameters: Partial<HighDensityHyperParameters> & {
3635
- USE_JUMPER_PREPATTERN?: boolean;
3636
- FIRST_ORIENTATION?: "horizontal" | "vertical";
3637
- PATTERN_TYPE?: "alternating_grid" | "staggered_grid";
3638
- }): JumperSolver;
3639
- onSolve(solver: SupervisedSolver<JumperSolver>): void;
3640
- visualize(): GraphicsObject;
3607
+ getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces;
3608
+ getOutputSimpleRouteJson(): SimpleRouteJson;
3641
3609
  }
3642
3610
 
3643
- interface NodeAnalysis {
3644
- node: NodeWithPortPoints;
3645
- hasCrossings: boolean;
3646
- numSameLayerCrossings: number;
3647
- }
3648
3611
  /**
3649
- * HighDensitySolver intelligently selects the appropriate solver for each node:
3650
- * - SimpleHighDensitySolver for nodes without crossings (faster, force-directed)
3651
- * - IntraNodeSolverWithJumpers for single-layer nodes with crossings (uses 0603 jumpers)
3612
+ * Calculate the capacity of a node based on its width
3652
3613
  *
3653
- * This solver processes nodes in batches based on their characteristics.
3614
+ * This capacity corresponds to how many vias the node can fit, tuned for two
3615
+ * layers.
3616
+ *
3617
+ * @param nodeOrWidth The node or width to calculate capacity for
3618
+ * @param maxCapacityFactor Optional multiplier to adjust capacity
3619
+ * @returns The calculated capacity
3654
3620
  */
3655
- declare class JumperHighDensitySolver extends BaseSolver {
3656
- allNodes: NodeWithPortPoints[];
3657
- nodeAnalyses: NodeAnalysis[];
3658
- routes: HighDensityIntraNodeRoute$1[];
3659
- colorMap: Record<string, string>;
3660
- traceWidth: number;
3661
- viaDiameter: number;
3662
- connMap?: ConnectivityMap;
3663
- hyperParameters?: Partial<HighDensityHyperParameters>;
3664
- nodesWithoutCrossings: NodeWithPortPoints[];
3665
- nodesWithCrossings: NodeWithPortPoints[];
3666
- simpleHighDensitySolver?: SimpleHighDensitySolver;
3667
- jumperSolvers: HyperIntraNodeSolverWithJumpers[];
3668
- currentJumperSolverIndex: number;
3669
- phase: "analyzing" | "simple" | "jumpers" | "done";
3670
- constructor({ nodePortPoints, colorMap, traceWidth, viaDiameter, connMap, hyperParameters, }: {
3671
- nodePortPoints: NodeWithPortPoints[];
3672
- colorMap?: Record<string, string>;
3673
- traceWidth?: number;
3674
- viaDiameter?: number;
3675
- connMap?: ConnectivityMap;
3676
- hyperParameters?: Partial<HighDensityHyperParameters>;
3677
- });
3621
+ declare const getTunedTotalCapacity1: (nodeOrWidth: CapacityMeshNode | {
3622
+ width: number;
3623
+ availableZ?: number[];
3624
+ }, maxCapacityFactor?: number, opts?: {
3625
+ viaDiameter?: number;
3626
+ obstacleMargin?: number;
3627
+ }) => number;
3628
+ /**
3629
+ * Calculate the optimal subdivision depth to reach a target minimum capacity
3630
+ * @param initialWidth The initial width of the top-level node
3631
+ * @param targetMinCapacity The minimum capacity target (default 0.5)
3632
+ * @param maxDepth Maximum allowed depth (default 10)
3633
+ * @returns The optimal capacity depth
3634
+ */
3635
+ declare const calculateOptimalCapacityDepth: (initialWidth: number, targetMinCapacity?: number, maxDepth?: number) => number;
3636
+
3637
+ /**
3638
+ * An in-memory implementation of the CacheProvider interface.
3639
+ * Useful for testing or scenarios where persistence is not required.
3640
+ */
3641
+ declare class InMemoryCache implements CacheProvider {
3642
+ cacheHitsByPrefix: Record<string, number>;
3643
+ cacheMissesByPrefix: Record<string, number>;
3644
+ isSyncCache: boolean;
3645
+ cacheHits: number;
3646
+ cacheMisses: number;
3647
+ cache: Map<string, any>;
3678
3648
  /**
3679
- * Analyze all nodes to determine which solver to use for each
3649
+ * Retrieves a cached solution synchronously based on the cache key.
3650
+ * Increments cache hit/miss counters.
3651
+ * @param cacheKey The key to look up in the cache.
3652
+ * @returns The cached solution if found, otherwise undefined.
3680
3653
  */
3681
- _analyzeNodes(): void;
3682
- _step(): void;
3683
- _stepSimpleSolver(): void;
3684
- _initializeJumperSolvers(): void;
3685
- _stepJumperSolvers(): void;
3686
- computeProgress(): number;
3687
- getConstructorParams(): {
3688
- nodePortPoints: NodeWithPortPoints[];
3689
- colorMap: Record<string, string>;
3690
- traceWidth: number;
3691
- viaDiameter: number;
3692
- connMap: ConnectivityMap | undefined;
3693
- hyperParameters: Partial<HighDensityHyperParameters> | undefined;
3694
- };
3695
- visualize(): GraphicsObject;
3654
+ getCachedSolutionSync(cacheKey: string): any;
3655
+ /**
3656
+ * Retrieves a cached solution asynchronously. Wraps the synchronous method.
3657
+ * @param cacheKey The key to look up in the cache.
3658
+ * @returns A promise that resolves with the cached solution or undefined.
3659
+ */
3660
+ getCachedSolution(cacheKey: string): Promise<any>;
3661
+ /**
3662
+ * Stores a solution in the cache synchronously.
3663
+ * Uses structured cloning to store a copy, preventing external modifications.
3664
+ * @param cacheKey The key under which to store the solution.
3665
+ * @param cachedSolution The solution data to cache.
3666
+ */
3667
+ setCachedSolutionSync(cacheKey: string, cachedSolution: any): void;
3668
+ /**
3669
+ * Stores a solution in the cache asynchronously. Wraps the synchronous method.
3670
+ * @param cacheKey The key under which to store the solution.
3671
+ * @param cachedSolution The solution data to cache.
3672
+ * @returns A promise that resolves when the solution is cached.
3673
+ */
3674
+ setCachedSolution(cacheKey: string, cachedSolution: any): Promise<void>;
3675
+ /**
3676
+ * Clears the entire cache and resets hit/miss counters.
3677
+ */
3678
+ clearCache(): void;
3679
+ getAllCacheKeys(): string[];
3696
3680
  }
3697
3681
 
3698
3682
  /**
3699
- * ObstacleTree wraps different spatial index implementations:
3700
- * - 'native': original spatial-hash grid
3701
- * - 'rbush': dynamic R-tree via rbush
3702
- * - 'flatbush': static index via flatbush
3683
+ * A CacheProvider implementation using the browser's localStorage.
3684
+ * Note: localStorage has size limits (typically 5-10MB) and stores data as strings.
3685
+ * Complex objects will be JSON serialized/deserialized.
3703
3686
  */
3704
- declare class ObstacleSpatialHashIndex {
3705
- private idx;
3706
- private storage;
3707
- constructor(implementation?: "native" | "rbush" | "flatbush", obstacles?: Obstacle$1[]);
3708
- insert(o: Obstacle$1): void;
3709
- search(bbox: {
3710
- minX: number;
3711
- minY: number;
3712
- maxX: number;
3713
- maxY: number;
3714
- }): Obstacle$1[];
3715
- searchArea(centerX: number, centerY: number, width: number, height: number): Obstacle$1[];
3716
- }
3717
-
3718
- interface Point$1 {
3719
- x: number;
3720
- y: number;
3721
- z: number;
3722
- }
3723
- type Point2D$3 = {
3724
- x: number;
3725
- y: number;
3726
- };
3727
- type HighDensityIntraNodeRoute = {
3728
- connectionName: string;
3729
- rootConnectionName?: string;
3730
- traceThickness: number;
3731
- viaDiameter: number;
3732
- route: Array<{
3733
- x: number;
3734
- y: number;
3735
- z: number;
3736
- }>;
3737
- vias: Array<{
3738
- x: number;
3739
- y: number;
3740
- }>;
3741
- jumpers?: Jumper[];
3742
- };
3743
- type HighDensityRoute = HighDensityIntraNodeRoute;
3744
- declare class HighDensityRouteSpatialIndex {
3745
- private segmentBuckets;
3746
- private viaBuckets;
3747
- private CELL_SIZE;
3748
- constructor(routes: HighDensityRoute[], cellSize?: number);
3687
+ declare class LocalStorageCache implements CacheProvider {
3688
+ isSyncCache: boolean;
3689
+ cacheHits: number;
3690
+ cacheMisses: number;
3691
+ cacheHitsByPrefix: Record<string, number>;
3692
+ cacheMissesByPrefix: Record<string, number>;
3693
+ constructor();
3694
+ private getKey;
3749
3695
  /**
3750
- * Finds routes that potentially conflict with a given line segment within a margin.
3751
- * Checks both segments and vias.
3752
- * @param segmentStart Start point of the query segment.
3753
- * @param segmentEnd End point of the query segment.
3754
- * @param margin The minimum required clearance distance from the query segment's centerline.
3755
- * @returns An array of conflicting routes and their minimum distance to the segment.
3696
+ * Retrieves a cached solution synchronously from localStorage.
3697
+ * Increments cache hit/miss counters.
3698
+ * @param cacheKey The key to look up in the cache.
3699
+ * @returns The cached solution if found and parsed correctly, otherwise undefined.
3756
3700
  */
3757
- getConflictingRoutesForSegment(segmentStart: Point$1, // Keep Point for original Z data if needed elsewhere
3758
- segmentEnd: Point$1, margin: number): Array<{
3759
- conflictingRoute: HighDensityRoute;
3760
- distance: number;
3761
- }>;
3701
+ getCachedSolutionSync(cacheKey: string): any;
3762
3702
  /**
3763
- * Finds routes that pass near a given point within a margin.
3764
- * Checks both segments and vias.
3765
- * @param point The query point {x, y}. Z is ignored.
3766
- * @param margin The minimum required clearance distance from the query point.
3767
- * @returns An array of conflicting routes and their minimum distance to the point.
3703
+ * Retrieves a cached solution asynchronously. Wraps the synchronous method.
3704
+ * @param cacheKey The key to look up in the cache.
3705
+ * @returns A promise that resolves with the cached solution or undefined.
3768
3706
  */
3769
- getConflictingRoutesNearPoint(point: Point2D$3, margin: number): Array<{
3770
- conflictingRoute: HighDensityRoute;
3771
- distance: number;
3772
- }>;
3707
+ getCachedSolution(cacheKey: string): Promise<any>;
3708
+ /**
3709
+ * Stores a solution in localStorage synchronously.
3710
+ * The solution is JSON stringified before storing.
3711
+ * @param cacheKey The key under which to store the solution.
3712
+ * @param cachedSolution The solution data to cache.
3713
+ */
3714
+ setCachedSolutionSync(cacheKey: string, cachedSolution: any): void;
3715
+ /**
3716
+ * Stores a solution in the cache asynchronously. Wraps the synchronous method.
3717
+ * @param cacheKey The key under which to store the solution.
3718
+ * @param cachedSolution The solution data to cache.
3719
+ * @returns A promise that resolves when the solution is cached.
3720
+ */
3721
+ setCachedSolution(cacheKey: string, cachedSolution: any): Promise<void>;
3722
+ /**
3723
+ * Clears all cache entries created by this instance from localStorage
3724
+ * and resets hit/miss counters.
3725
+ */
3726
+ clearCache(): void;
3727
+ getAllCacheKeys(): string[];
3773
3728
  }
3774
3729
 
3775
- interface Point2D$2 {
3730
+ declare global {
3731
+ var TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE: LocalStorageCache;
3732
+ var TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE: InMemoryCache;
3733
+ }
3734
+ declare function getGlobalLocalStorageCache(): LocalStorageCache;
3735
+ declare function getGlobalInMemoryCache(): InMemoryCache;
3736
+ declare function setupGlobalCaches(): void;
3737
+
3738
+ interface Target$1 {
3776
3739
  x: number;
3777
3740
  y: number;
3741
+ bounds: {
3742
+ minX: number;
3743
+ minY: number;
3744
+ maxX: number;
3745
+ maxY: number;
3746
+ };
3747
+ connectionName: string;
3748
+ availableZ: number[];
3778
3749
  }
3779
- interface Segment {
3780
- start: Point2D$2;
3781
- end: Point2D$2;
3750
+ type BucketCoordinate = `${number}x${number}`;
3751
+ declare class TargetTree {
3752
+ targets: Target$1[];
3753
+ buckets: Map<BucketCoordinate, [Target$1, number][]>;
3754
+ CELL_SIZE: number;
3755
+ constructor(targets: Target$1[]);
3756
+ getBucketKey(x: number, y: number): BucketCoordinate;
3757
+ getTargetsInArea(centerX: number, centerY: number, width: number, height: number): Target$1[];
3782
3758
  }
3783
3759
 
3784
- interface Point2D$1 {
3760
+ interface CapacityMeshNodeSolverOptions$2 {
3761
+ capacityDepth?: number;
3762
+ }
3763
+ interface Target {
3785
3764
  x: number;
3786
3765
  y: number;
3766
+ bounds: {
3767
+ minX: number;
3768
+ minY: number;
3769
+ maxX: number;
3770
+ maxY: number;
3771
+ };
3772
+ connectionName: string;
3773
+ availableZ: number[];
3787
3774
  }
3788
- interface Point3D$1 extends Point2D$1 {
3789
- z: number;
3790
- }
3791
- interface TraceKeepoutSolverInput {
3792
- hdRoutes: HighDensityRoute$1[];
3793
- obstacles: Obstacle$1[];
3794
- connMap: ConnectivityMap;
3795
- colorMap: Record<string, string>;
3796
- keepoutRadiusSchedule?: number[];
3797
- srj?: Pick<SimpleRouteJson, "outline" | "bounds" | "layerCount">;
3798
- }
3799
- /**
3800
- * TraceKeepoutSolver adjusts traces to maintain keepout distance from obstacles
3801
- * and non-connected traces. It works by walking along each trace with a cursor,
3802
- * detecting obstacles within a keepout radius, and pushing the draw position
3803
- * orthogonally to avoid them.
3804
- *
3805
- * The solver processes traces through multiple passes with decreasing keepout
3806
- * radii as defined by KEEPOUT_RADIUS_SCHEDULE.
3807
- */
3808
- declare class TraceKeepoutSolver extends BaseSolver {
3809
- private input;
3810
- originalHdRoutes: HighDensityRoute$1[];
3811
- hdRoutes: HighDensityRoute$1[];
3812
- redrawnHdRoutes: HighDensityRoute$1[];
3813
- KEEPOUT_RADIUS_SCHEDULE: number[];
3814
- currentScheduleIndex: number;
3815
- currentKeepoutRadius: number;
3816
- unprocessedRoutes: HighDensityRoute$1[];
3817
- smoothedCursorRoutes: HighDensityRoute$1[];
3818
- processedRoutes: HighDensityRoute$1[];
3819
- currentTrace: HighDensityRoute$1 | null;
3820
- cursorPosition: Point3D$1 | null;
3821
- lastCursorPosition: Point3D$1 | null;
3822
- drawPosition: Point2D$1 | null;
3823
- currentTraceSegmentIndex: number;
3824
- currentTraceSegmentT: number;
3825
- recordedDrawPositions: Point3D$1[];
3826
- lastCollidingSegments: Segment[];
3827
- obstacleSHI: ObstacleSpatialHashIndex;
3828
- hdRouteSHI: HighDensityRouteSpatialIndex;
3829
- boardOutlineRoutes: HighDensityRoute$1[];
3830
- constructor(input: TraceKeepoutSolverInput);
3831
- getSmoothDistance(): number;
3832
- _step(): void;
3833
- getStepDistance(): number;
3834
- /**
3835
- * Steps the cursor forward by CURSOR_STEP_DISTANCE along the trace
3836
- * Returns false if we've reached the end of the trace
3837
- */
3838
- private stepCursorForward;
3839
- /**
3840
- * Gets all colliding segments (obstacle edges and trace outlines) within the keepout radius
3841
- */
3842
- private getCollidingSegments;
3843
- positionHasCollision(position: {
3844
- x: number;
3845
- y: number;
3846
- z: number;
3847
- }, margin?: number): boolean;
3775
+ declare class CapacityMeshNodeSolver extends BaseSolver {
3776
+ srj: SimpleRouteJson;
3777
+ opts: CapacityMeshNodeSolverOptions$2;
3778
+ unfinishedNodes: CapacityMeshNode[];
3779
+ finishedNodes: CapacityMeshNode[];
3780
+ nodeToXYOverlappingObstaclesMap: Map<CapacityMeshNodeId, Obstacle[]>;
3781
+ layerCount: number;
3782
+ protected outlinePolygon?: Polygon;
3783
+ MAX_DEPTH: number;
3784
+ targets: Target[];
3785
+ targetTree: TargetTree;
3786
+ obstacleTree: ObstacleSpatialHashIndex;
3787
+ constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions$2);
3788
+ computeTargets(): Target[];
3789
+ protected getNodeBounds(node: CapacityMeshNode): {
3790
+ minX: number;
3791
+ maxX: number;
3792
+ minY: number;
3793
+ maxY: number;
3794
+ };
3795
+ protected getNodeRect(node: CapacityMeshNode): {
3796
+ center: {
3797
+ x: number;
3798
+ y: number;
3799
+ };
3800
+ width: number;
3801
+ height: number;
3802
+ };
3803
+ _nextNodeCounter: number;
3804
+ getNextNodeId(): string;
3805
+ getCapacityFromDepth(depth: number): number;
3806
+ getTargetIfNodeContainsTarget(node: CapacityMeshNode): Target | null;
3807
+ getXYOverlappingObstacles(node: CapacityMeshNode): Obstacle[];
3808
+ getXYZOverlappingObstacles(node: CapacityMeshNode): Obstacle[];
3848
3809
  /**
3849
- * Finalizes the current trace with the recorded draw positions
3810
+ * Checks if the given mesh node overlaps with any obstacle.
3811
+ * We treat both obstacles and nodes as axis‐aligned rectangles.
3850
3812
  */
3851
- private finalizeCurrentTrace;
3813
+ doesNodeOverlapObstacle(node: CapacityMeshNode): boolean;
3852
3814
  /**
3853
- * Simplifies the route by removing collinear points
3815
+ * Checks if the entire node is contained within any obstacle.
3854
3816
  */
3855
- private simplifyRoute;
3817
+ isNodeCompletelyInsideObstacle(node: CapacityMeshNode): boolean;
3818
+ getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[];
3819
+ shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean;
3820
+ _step(): void;
3856
3821
  /**
3857
- * Creates artificial hdRoutes representing the board outline.
3858
- * These routes act as obstacles to prevent traces from being pushed outside the board.
3822
+ * Creates a GraphicsObject to visualize the mesh, its nodes, obstacles, and connection points.
3823
+ *
3824
+ * - Mesh nodes are rendered as rectangles.
3825
+ * - Nodes that have an obstacle intersection are outlined in red.
3826
+ * - Other nodes are outlined in green.
3827
+ * - Lines are drawn from a node to its parent.
3828
+ * - Obstacles are drawn as semi-transparent red rectangles.
3829
+ * - Points for each connection’s pointsToConnect are drawn in a unique color.
3859
3830
  */
3860
- private createBoardOutlineRoutes;
3861
3831
  visualize(): GraphicsObject;
3862
- /** Returns the redrawn routes. This is the primary output of the solver. */
3863
- getRedrawnHdRoutes(): HighDensityRoute$1[];
3864
3832
  }
3865
3833
 
3866
- interface Point2D {
3867
- x: number;
3868
- y: number;
3834
+ interface CapacityMeshNodeSolverOptions$1 {
3835
+ capacityDepth?: number;
3869
3836
  }
3870
- interface Point3D extends Point2D {
3871
- z: number;
3837
+ declare class CapacityMeshNodeSolver2_NodeUnderObstacle extends CapacityMeshNodeSolver {
3838
+ srj: SimpleRouteJson;
3839
+ opts: CapacityMeshNodeSolverOptions$1;
3840
+ VIA_DIAMETER: number;
3841
+ OBSTACLE_MARGIN: number;
3842
+ /**
3843
+ * The threshold for the percentage of a single-layer node that must be
3844
+ * covered by obstacles to be considered "under an obstacle"
3845
+ */
3846
+ OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES: number;
3847
+ constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions$1);
3848
+ isNodeCompletelyOutsideBounds(node: CapacityMeshNode): boolean;
3849
+ isNodePartiallyOutsideBounds(node: CapacityMeshNode): boolean;
3850
+ /**
3851
+ * Calculate the percentage of node area covered by obstacles
3852
+ */
3853
+ getObstacleCoveragePercentage(node: CapacityMeshNode): number;
3854
+ /**
3855
+ * Check if a single-layer node should be filtered due to obstacle coverage
3856
+ */
3857
+ shouldFilterSingleLayerNodeForObstacle(node: CapacityMeshNode): boolean;
3858
+ /**
3859
+ * Check if a node should be filtered due to obstacles.
3860
+ * Single-layer nodes: filtered only if >20% covered
3861
+ * Multi-layer nodes: filtered if any overlap
3862
+ */
3863
+ shouldFilterNodeForObstacle(node: CapacityMeshNode): boolean;
3864
+ createChildNodeAtPosition(parent: CapacityMeshNode, opts: {
3865
+ center: {
3866
+ x: number;
3867
+ y: number;
3868
+ };
3869
+ width: number;
3870
+ height: number;
3871
+ availableZ: number[];
3872
+ _depth?: number;
3873
+ }): CapacityMeshNode;
3874
+ getZSubdivisionChildNodes(node: CapacityMeshNode): CapacityMeshNode[];
3875
+ getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[];
3876
+ shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean;
3877
+ _step(): void;
3872
3878
  }
3873
- interface TraceWidthSolverInput {
3874
- hdRoutes: HighDensityRoute$1[];
3875
- obstacles?: Obstacle$1[];
3876
- connMap?: ConnectivityMap;
3877
- colorMap?: Record<string, string>;
3878
- nominalTraceWidth?: number;
3879
- minTraceWidth: number;
3880
- obstacleMargin?: number;
3879
+
3880
+ interface CapacityMeshNodeSolverOptions {
3881
+ capacityDepth?: number;
3881
3882
  }
3882
3883
  /**
3883
- * TraceWidthSolver determines the optimal trace width for each route.
3884
- * It uses a TRACE_WIDTH_SCHEDULE to try progressively narrower widths:
3885
- * [nominalTraceWidth, (nominalTraceWidth + minTraceWidth)/2, minTraceWidth]
3886
- *
3887
- * For each trace, it walks along with a cursor checking clearance.
3888
- * If clearance is insufficient for the current width, it tries the next
3889
- * narrower width in the schedule.
3884
+ * This capacity mesh node solver is meant to be used in contexts where vias
3885
+ * aren't allowed, but there may be assignable vias on the PCB as obstacles.
3890
3886
  *
3891
- * nominalTraceWidth defaults to minTraceWidth * 2 if not specified.
3887
+ * Behavior:
3888
+ * - Outside assignable obstacles, multi-layer nodes are *always* Z-split into single-layer nodes.
3889
+ * - During mesh subdivision, nodes overlapping with "assignable" obstacles
3890
+ * (obstacle.netIsAssignable === true) are NOT filtered, allowing normal subdivision.
3891
+ * - After the main mesh subdivision is complete:
3892
+ * 1. All nodes overlapping with assignable obstacles are removed
3893
+ * 2. Each assignable obstacle is replaced with a single multi-layer node spanning all layers
3894
+ * - Single-layer nodes that are larger than MAX_SIZE_FOR_SINGLE_LAYER_NODES are XY-subdivided.
3895
+ * - IMPORTANT: the multi-layer nodes created from assignable obstacles are **traversable**,
3896
+ * so we mark `_containsObstacle = false` and `_completelyInsideObstacle = false` on them.
3892
3897
  */
3893
- declare class TraceWidthSolver extends BaseSolver {
3894
- hdRoutes: HighDensityRoute$1[];
3895
- hdRoutesWithWidths: HighDensityRoute$1[];
3896
- nominalTraceWidth: number;
3897
- minTraceWidth: number;
3898
- obstacleMargin: number;
3899
- TRACE_WIDTH_SCHEDULE: number[];
3900
- unprocessedRoutes: HighDensityRoute$1[];
3901
- processedRoutes: HighDensityRoute$1[];
3902
- currentTrace: HighDensityRoute$1 | null;
3903
- cursorPosition: Point3D | null;
3904
- currentTraceSegmentIndex: number;
3905
- currentTraceSegmentT: number;
3906
- currentScheduleIndex: number;
3907
- currentTargetWidth: number;
3908
- hasInsufficientClearance: boolean;
3909
- currentWalkMinClearance: number;
3910
- bestMinClearance: number;
3911
- bestWidth: number;
3912
- lastCollidingObstacles: Obstacle$1[];
3913
- lastCollidingRoutes: HighDensityRoute$1[];
3914
- lastClearance: number;
3915
- obstacles: Obstacle$1[];
3916
- obstacleSHI?: ObstacleSpatialHashIndex;
3917
- hdRouteSHI: HighDensityRouteSpatialIndex;
3918
- connMap?: ConnectivityMap;
3919
- colorMap?: Record<string, string>;
3920
- constructor(input: TraceWidthSolverInput);
3921
- _step(): void;
3922
- /**
3923
- * Initializes/resets the cursor for processing a trace
3924
- */
3925
- private initializeCursor;
3926
- /**
3927
- * Steps the cursor forward by CURSOR_STEP_DISTANCE along the trace
3928
- * Returns false if we've reached the end of the trace
3929
- */
3930
- private stepCursorForward;
3898
+ declare class CapacityMeshNodeSolver_OnlyTraverseLayersInAssignableObstacles extends CapacityMeshNodeSolver2_NodeUnderObstacle {
3899
+ srj: SimpleRouteJson;
3900
+ opts: CapacityMeshNodeSolverOptions;
3901
+ MAX_SIZE_FOR_SINGLE_LAYER_NODES: number;
3902
+ constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions);
3903
+ private isObstacleAssignable;
3904
+ private getOverlappingAssignableObstacles;
3905
+ shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean;
3931
3906
  /**
3932
- * Gets the minimum clearance at a given position from obstacles and other traces
3933
- * Also updates lastCollidingObstacles and lastCollidingRoutes for visualization
3907
+ * Filter nodes for obstacles, but skip filtering for assignable obstacles.
3908
+ * Assignable obstacles will be handled separately at the end.
3934
3909
  */
3935
- private getClearanceAtPosition;
3910
+ shouldFilterNodeForObstacle(node: CapacityMeshNode): boolean;
3936
3911
  /**
3937
- * Finalizes the current trace with the given width
3912
+ * Remove nodes inside assignable obstacles and replace with single multi-layer nodes.
3913
+ * The new node's bounds are extended to cover all removed nodes' XY space.
3938
3914
  */
3939
- private finalizeCurrentTrace;
3915
+ private insertAssignableObstaclesAsNodes;
3916
+ _step(): void;
3917
+ }
3918
+
3919
+ /**
3920
+ * Variant of SingleLayerNodeMergerSolver that only merges nodes containing targets.
3921
+ * Nodes without targets are passed through unchanged.
3922
+ */
3923
+ declare class SingleLayerNodeMergerSolver_OnlyMergeTargets extends BaseSolver {
3924
+ nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>;
3925
+ currentBatchNodeIds: CapacityMeshNodeId[];
3926
+ absorbedNodeIds: Set<CapacityMeshNodeId>;
3927
+ nextBatchNodeIds: CapacityMeshNodeId[];
3928
+ batchHadModifications: boolean;
3929
+ hasComputedAdjacentNodeIds: boolean;
3930
+ newNodes: CapacityMeshNode[];
3931
+ constructor(nodes: CapacityMeshNode[]);
3932
+ computeAdjacentNodeIdsForFirstBatch(nodes: CapacityMeshNode[]): void;
3933
+ getAdjacentSameLayerUnprocessedNodes(rootNode: CapacityMeshNode): CapacityMeshNode[];
3934
+ _step(): void;
3940
3935
  visualize(): GraphicsObject;
3941
- /** Returns the routes with determined widths. This is the primary output of the solver. */
3942
- getHdRoutesWithWidths(): HighDensityRoute$1[];
3943
3936
  }
3944
3937
 
3945
- interface OffboardPortPoint {
3946
- portPointId: string;
3938
+ /**
3939
+ * This solver merges nodes that represent the same assignable obstacle into a single node.
3940
+ *
3941
+ * For each assignable obstacle:
3942
+ * - Finds all nodes that have _assignedViaObstacle pointing to that obstacle
3943
+ * - Replaces them with a single node representing the bounding box of all removed nodes
3944
+ * - Each step handles one assignable obstacle
3945
+ */
3946
+ declare class AssignableViaNodeMergerSolver extends BaseSolver {
3947
+ newNodes: CapacityMeshNode[];
3948
+ obstacleToNodesMap: Map<Obstacle, CapacityMeshNode[]>;
3949
+ obstaclesToProcess: Obstacle[];
3950
+ mergedNodeIds: Set<CapacityMeshNodeId>;
3951
+ constructor(nodes: CapacityMeshNode[]);
3952
+ _step(): void;
3953
+ visualize(): GraphicsObject;
3954
+ }
3955
+
3956
+ interface Point {
3947
3957
  x: number;
3948
3958
  y: number;
3949
- /** The obstacle this port point is at the center of */
3950
- obstacleIndex: number;
3951
- /** The offBoardConnectsTo ids this port point is associated with */
3952
- offBoardConnectionIds: OffBoardConnectionId[];
3953
- /** Available Z layers for this port point based on obstacle layers */
3954
- availableZ: number[];
3959
+ z: number;
3955
3960
  }
3956
- interface OffboardPathFragment {
3957
- pathFragmentId: string;
3958
- /** The shared offBoardConnectsTo id that connects these port points */
3959
- offBoardConnectionId: OffBoardConnectionId;
3960
- /** The two port points connected by this path fragment */
3961
- portPointIds: [string, string];
3962
- /** Endpoints of this edge */
3963
- start: {
3961
+ declare class SingleSimplifiedPathSolver extends BaseSolver {
3962
+ newRoute: HighDensityIntraNodeRoute$1["route"];
3963
+ newVias: HighDensityIntraNodeRoute$1["vias"];
3964
+ headIndex: number;
3965
+ tailIndex: number;
3966
+ inputRoute: HighDensityIntraNodeRoute$1;
3967
+ otherHdRoutes: HighDensityIntraNodeRoute$1[];
3968
+ obstacles: Obstacle[];
3969
+ connMap: ConnectivityMap;
3970
+ colorMap: Record<string, string>;
3971
+ outline?: Array<{
3964
3972
  x: number;
3965
3973
  y: number;
3974
+ }>;
3975
+ constructor(params: {
3976
+ inputRoute: HighDensityIntraNodeRoute$1;
3977
+ otherHdRoutes: HighDensityIntraNodeRoute$1[];
3978
+ obstacles: Obstacle[];
3979
+ connMap: ConnectivityMap;
3980
+ colorMap: Record<string, string>;
3981
+ outline?: Array<{
3982
+ x: number;
3983
+ y: number;
3984
+ }>;
3985
+ });
3986
+ getConstructorParams(): {
3987
+ inputRoute: HighDensityIntraNodeRoute$1;
3988
+ otherHdRoutes: HighDensityIntraNodeRoute$1[];
3989
+ obstacles: Obstacle[];
3990
+ connMap: Record<string, string[]>;
3991
+ colorMap: Record<string, string>;
3992
+ outline: {
3993
+ x: number;
3994
+ y: number;
3995
+ }[] | undefined;
3966
3996
  };
3967
- end: {
3997
+ get simplifiedRoute(): HighDensityIntraNodeRoute$1;
3998
+ isValidPath(pointsInRoute: Point[]): boolean;
3999
+ _step(): void;
4000
+ getVisualsForNewRouteAndObstacles(): GraphicsObject & Pick<Required<GraphicsObject>, "points" | "lines" | "rects" | "circles">;
4001
+ }
4002
+
4003
+ declare class MultiSimplifiedPathSolver extends BaseSolver {
4004
+ simplifiedHdRoutes: HighDensityIntraNodeRoute$1[];
4005
+ currentUnsimplifiedHdRouteIndex: number;
4006
+ activeSubSolver: SingleSimplifiedPathSolver | null;
4007
+ unsimplifiedHdRoutes: HighDensityIntraNodeRoute$1[];
4008
+ obstacles: Obstacle[];
4009
+ connMap: ConnectivityMap;
4010
+ colorMap: Record<string, string>;
4011
+ outline?: Array<{
3968
4012
  x: number;
3969
4013
  y: number;
3970
- };
4014
+ }>;
4015
+ defaultViaDiameter: number;
4016
+ constructor(params: {
4017
+ unsimplifiedHdRoutes: HighDensityIntraNodeRoute$1[];
4018
+ obstacles: Obstacle[];
4019
+ connMap?: ConnectivityMap;
4020
+ colorMap?: Record<string, string>;
4021
+ outline?: Array<{
4022
+ x: number;
4023
+ y: number;
4024
+ }>;
4025
+ defaultViaDiameter?: number;
4026
+ });
4027
+ _step(): void;
4028
+ visualize(): GraphicsObject;
3971
4029
  }
3972
- type Phase = "finding_obstacles" | "creating_fragments" | "done";
3973
- interface PendingFragment {
3974
- offBoardId: OffBoardConnectionId;
3975
- pp1: OffboardPortPoint;
3976
- pp2: OffboardPortPoint;
4030
+
4031
+ interface RouteSection {
4032
+ startIndex: number;
4033
+ endIndex: number;
4034
+ z: number;
4035
+ points: HighDensityRoute["route"];
3977
4036
  }
3978
- /**
3979
- * PortPointOffboardPathFragmentSolver finds obstacles with offBoardConnectsTo
3980
- * defined and creates port points at their centers. It then creates path
3981
- * fragments (edges) connecting port points that share the same offBoardConnectsTo
3982
- * ids.
3983
- *
3984
- * This enables routing through off-board connections like flex cables or
3985
- * external connectors.
3986
- *
3987
- * The solver iterates step-by-step:
3988
- * 1. Phase "finding_obstacles": Process one obstacle per step, creating port points
3989
- * 2. Phase "creating_fragments": Create one path fragment per step
3990
- * 3. Phase "done": Solver complete
3991
- */
3992
- declare class PortPointOffboardPathFragmentSolver extends BaseSolver {
3993
- srj: SimpleRouteJson;
3994
- colorMap: Record<string, string>;
3995
- /** Current phase of the solver */
3996
- phase: Phase;
3997
- /** Index of the current obstacle being processed */
3998
- currentObstacleIndex: number;
3999
- /** Obstacles that have offBoardConnectsTo defined */
4000
- offboardObstacles: Array<{
4001
- obstacle: Obstacle$1;
4002
- index: number;
4003
- }>;
4004
- /** Port points created at obstacle centers */
4005
- portPoints: OffboardPortPoint[];
4006
- /** Map from portPointId to OffboardPortPoint */
4007
- portPointMap: Map<string, OffboardPortPoint>;
4008
- /** Path fragments connecting port points with shared offBoardConnectsTo */
4009
- pathFragments: OffboardPathFragment[];
4010
- /** Map from offBoardConnectionId to port points that share it */
4011
- offBoardConnectionToPortPoints: Map<OffBoardConnectionId, OffboardPortPoint[]>;
4012
- /** Pending path fragments to create (computed after obstacle phase) */
4013
- pendingFragments: PendingFragment[];
4014
- /** Index of current fragment being created */
4015
- currentFragmentIndex: number;
4016
- /** Last processed obstacle (for visualization) */
4017
- lastProcessedObstacle: {
4018
- obstacle: Obstacle$1;
4019
- index: number;
4020
- } | null;
4021
- /** Last created port point (for visualization) */
4022
- lastCreatedPortPoint: OffboardPortPoint | null;
4023
- /** Last created path fragment (for visualization) */
4024
- lastCreatedFragment: OffboardPathFragment | null;
4025
- /** Color map for offBoardConnectionIds */
4026
- offBoardColorMap: Record<string, string>;
4027
- constructor({ srj, colorMap, }: {
4028
- srj: SimpleRouteJson;
4029
- colorMap?: Record<string, string>;
4037
+ declare class SingleRouteUselessViaRemovalSolver extends BaseSolver {
4038
+ obstacleSHI: ObstacleSpatialHashIndex;
4039
+ hdRouteSHI: HighDensityRouteSpatialIndex;
4040
+ unsimplifiedRoute: HighDensityRoute;
4041
+ routeSections: Array<RouteSection>;
4042
+ currentSectionIndex: number;
4043
+ TRACE_THICKNESS: number;
4044
+ OBSTACLE_MARGIN: number;
4045
+ constructor(params: {
4046
+ obstacleSHI: ObstacleSpatialHashIndex;
4047
+ hdRouteSHI: HighDensityRouteSpatialIndex;
4048
+ unsimplifiedRoute: HighDensityRoute;
4030
4049
  });
4050
+ breakRouteIntoSections(route: HighDensityRoute): never[] | this["routeSections"];
4031
4051
  _step(): void;
4032
- private stepFindingObstacles;
4033
- private computePendingFragments;
4034
- private stepCreatingFragments;
4035
- private layerToZ;
4036
- computeProgress(): number;
4052
+ /**
4053
+ * Check if an endpoint (first or last point of the route) can connect
4054
+ * to a different layer. This is only allowed if the obstacles the endpoint
4055
+ * connects to support that layer.
4056
+ */
4057
+ canEndpointConnectOnLayer(endpointX: number, endpointY: number, targetZ: number): boolean;
4058
+ canSectionMoveToLayer({ currentSection, targetZ, }: {
4059
+ currentSection: RouteSection;
4060
+ targetZ: number;
4061
+ }): boolean;
4062
+ getConstructorParams(): {
4063
+ obstacleSHI: ObstacleSpatialHashIndex;
4064
+ hdRouteSHI: HighDensityRouteSpatialIndex;
4065
+ unsimplifiedRoute: HighDensityIntraNodeRoute;
4066
+ };
4067
+ getOptimizedHdRoute(): HighDensityRoute;
4037
4068
  visualize(): GraphicsObject;
4038
4069
  }
4039
4070
 
4040
- interface CapacityMeshSolverOptions$1 {
4041
- capacityDepth?: number;
4042
- targetMinCapacity?: number;
4043
- cacheProvider?: CacheProvider | null;
4044
- effort?: number;
4045
- }
4046
- type PipelineStep$1<T extends new (...args: any[]) => BaseSolver> = {
4047
- solverName: string;
4048
- solverClass: T;
4049
- getConstructorParams: (instance: AssignableAutoroutingPipeline2) => ConstructorParameters<T>;
4050
- onSolved?: (instance: AssignableAutoroutingPipeline2) => void;
4051
- };
4052
- declare class AssignableAutoroutingPipeline2 extends BaseSolver {
4053
- srj: SimpleRouteJson;
4054
- opts: CapacityMeshSolverOptions$1;
4055
- netToPointPairsSolver?: NetToPointPairsSolver;
4056
- nodeSolver?: RectDiffPipeline;
4057
- nodeTargetMerger?: CapacityNodeTargetMerger;
4058
- edgeSolver?: CapacityMeshEdgeSolver;
4059
- relateNodesToOffBoardConnections?: RelateNodesToOffBoardConnectionsSolver;
4071
+ interface UselessViaRemovalSolverInput {
4072
+ unsimplifiedHdRoutes: HighDensityRoute$1[];
4073
+ obstacles: Obstacle[];
4060
4074
  colorMap: Record<string, string>;
4061
- highDensityRouteSolver?: HighDensitySolver;
4062
- /** @deprecated Use highDensitySolver instead */
4063
- simpleHighDensityRouteSolver?: SimpleHighDensitySolver;
4064
- highDensitySolver?: JumperHighDensitySolver;
4065
- highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver;
4066
- singleLayerNodeMerger?: SingleLayerNodeMergerSolver;
4067
- offboardPathFragmentSolver?: PortPointOffboardPathFragmentSolver;
4068
- strawSolver?: StrawSolver;
4069
- deadEndSolver?: DeadEndSolver;
4070
- traceSimplificationSolver?: TraceSimplificationSolver;
4071
- traceKeepoutSolver?: TraceKeepoutSolver;
4072
- traceWidthSolver?: TraceWidthSolver;
4073
- availableSegmentPointSolver?: AvailableSegmentPointSolver;
4074
- portPointPathingSolver?: PortPointPathingSolver;
4075
- multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer;
4076
- viaDiameter: number;
4077
- minTraceWidth: number;
4078
- effort: number;
4079
- startTimeOfPhase: Record<string, number>;
4080
- endTimeOfPhase: Record<string, number>;
4081
- timeSpentOnPhase: Record<string, number>;
4082
- activeSubSolver?: BaseSolver | null;
4083
- connMap: ConnectivityMap;
4084
- srjWithPointPairs?: SimpleRouteJson;
4085
- capacityNodes: CapacityMeshNode[] | null;
4086
- capacityEdges: CapacityMeshEdge[] | null;
4087
- cacheProvider: CacheProvider | null;
4088
- 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>)[];
4089
- constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$1);
4090
- getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$1];
4091
- currentPipelineStepIndex: number;
4075
+ layerCount: number;
4076
+ }
4077
+ declare class UselessViaRemovalSolver extends BaseSolver {
4078
+ private input;
4079
+ unsimplifiedHdRoutes: HighDensityRoute$1[];
4080
+ optimizedHdRoutes: HighDensityRoute$1[];
4081
+ unprocessedRoutes: HighDensityRoute$1[];
4082
+ activeSubSolver?: SingleRouteUselessViaRemovalSolver | null | undefined;
4083
+ obstacleSHI: ObstacleSpatialHashIndex | null;
4084
+ hdRouteSHI: HighDensityRouteSpatialIndex | null;
4085
+ constructor(input: UselessViaRemovalSolverInput);
4092
4086
  _step(): void;
4093
- solveUntilPhase(phase: string): void;
4094
- getCurrentPhase(): string;
4087
+ getOptimizedHdRoutes(): HighDensityRoute$1[] | null;
4095
4088
  visualize(): GraphicsObject;
4096
- /**
4097
- * A lightweight version of the visualize method that can be used to stream
4098
- * progress
4099
- *
4100
- * We return the most relevant graphic for the stage:
4101
- * 1. netToPointPairs output
4102
- * 2. Capacity Planning Output
4103
- * 3. High Density Route Solver Output, max 200 lines
4104
- */
4105
- preview(): GraphicsObject;
4106
- _getOutputHdRoutes(): HighDensityRoute$1[];
4107
- getConnectedOffboardObstacles(): Record<ObstacleId, RootConnectionName>;
4108
- /**
4109
- * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces
4110
- */
4111
- getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces;
4112
- getOutputSimpleRouteJson(): SimpleRouteJson;
4113
4089
  }
4114
4090
 
4091
+ type Candidate = {
4092
+ prevCandidate: Candidate | null;
4093
+ node: CapacityMeshNode;
4094
+ f: number;
4095
+ g: number;
4096
+ h: number;
4097
+ };
4098
+ type AssignableViaCapacityHyperParameters = Partial<CapacityHyperParameters> & {
4099
+ SHUFFLE_SEED?: number;
4100
+ DIRECTIVE_SEED?: number;
4101
+ FORCE_VIA_TRAVEL_CHANCE?: number;
4102
+ FAR_VIA_MIN_DISTANCE?: number;
4103
+ MAX_CLOSEST_VIA_SKIP?: number;
4104
+ MAX_FURTHEST_VIA_SKIP?: number;
4105
+ };
4106
+ type ConnectionNodePair = {
4107
+ start: CapacityMeshNode;
4108
+ end: CapacityMeshNode;
4109
+ connection: SimpleRouteConnection;
4110
+ };
4111
+ type SubpathNodePair = {
4112
+ start: CapacityMeshNode;
4113
+ end: CapacityMeshNode;
4114
+ solved: boolean;
4115
+ path?: CapacityMeshNode[];
4116
+ layer: number;
4117
+ };
4118
+ type ConnectionPathWithNodes = {
4119
+ connection: SimpleRouteConnection;
4120
+ path: CapacityMeshNode[];
4121
+ };
4115
4122
  /**
4116
- * Calculate the capacity of a node based on its width
4117
- *
4118
- * This capacity corresponds to how many vias the node can fit, tuned for two
4119
- * layers.
4120
- *
4121
- * @param nodeOrWidth The node or width to calculate capacity for
4122
- * @param maxCapacityFactor Optional multiplier to adjust capacity
4123
- * @returns The calculated capacity
4124
- */
4125
- declare const getTunedTotalCapacity1: (nodeOrWidth: CapacityMeshNode | {
4126
- width: number;
4127
- availableZ?: number[];
4128
- }, maxCapacityFactor?: number, opts?: {
4129
- viaDiameter?: number;
4130
- obstacleMargin?: number;
4131
- }) => number;
4132
- /**
4133
- * Calculate the optimal subdivision depth to reach a target minimum capacity
4134
- * @param initialWidth The initial width of the top-level node
4135
- * @param targetMinCapacity The minimum capacity target (default 0.5)
4136
- * @param maxDepth Maximum allowed depth (default 10)
4137
- * @returns The optimal capacity depth
4138
- */
4139
- declare const calculateOptimalCapacityDepth: (initialWidth: number, targetMinCapacity?: number, maxDepth?: number) => number;
4140
-
4141
- /**
4142
- * An in-memory implementation of the CacheProvider interface.
4143
- * Useful for testing or scenarios where persistence is not required.
4123
+ * See description in the prompt
4144
4124
  */
4145
- declare class InMemoryCache implements CacheProvider {
4146
- cacheHitsByPrefix: Record<string, number>;
4147
- cacheMissesByPrefix: Record<string, number>;
4148
- isSyncCache: boolean;
4149
- cacheHits: number;
4150
- cacheMisses: number;
4151
- cache: Map<string, any>;
4152
- /**
4153
- * Retrieves a cached solution synchronously based on the cache key.
4154
- * Increments cache hit/miss counters.
4155
- * @param cacheKey The key to look up in the cache.
4156
- * @returns The cached solution if found, otherwise undefined.
4157
- */
4158
- getCachedSolutionSync(cacheKey: string): any;
4159
- /**
4160
- * Retrieves a cached solution asynchronously. Wraps the synchronous method.
4161
- * @param cacheKey The key to look up in the cache.
4162
- * @returns A promise that resolves with the cached solution or undefined.
4163
- */
4164
- getCachedSolution(cacheKey: string): Promise<any>;
4125
+ declare class AssignableViaCapacityPathingSolver_DirectiveSubOptimal extends BaseSolver {
4126
+ private inputParams;
4165
4127
  /**
4166
- * Stores a solution in the cache synchronously.
4167
- * Uses structured cloning to store a copy, preventing external modifications.
4168
- * @param cacheKey The key under which to store the solution.
4169
- * @param cachedSolution The solution data to cache.
4128
+ * Bias toward greedier choices (f = g + GREEDY_MULTIPLIER * h)
4170
4129
  */
4171
- setCachedSolutionSync(cacheKey: string, cachedSolution: any): void;
4172
- /**
4173
- * Stores a solution in the cache asynchronously. Wraps the synchronous method.
4174
- * @param cacheKey The key under which to store the solution.
4175
- * @param cachedSolution The solution data to cache.
4176
- * @returns A promise that resolves when the solution is cached.
4177
- */
4178
- setCachedSolution(cacheKey: string, cachedSolution: any): Promise<void>;
4130
+ GREEDY_MULTIPLIER: number;
4131
+ simpleRouteJson: SimpleRouteJson;
4132
+ nodes: CapacityMeshNode[];
4133
+ edges: CapacityMeshEdge[];
4134
+ colorMap: Record<string, string>;
4135
+ MAX_ITERATIONS: number;
4136
+ hyperParameters: Partial<AssignableViaCapacityHyperParameters>;
4137
+ usedNodeMap: Map<CapacityMeshNodeId, true>;
4138
+ nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>;
4139
+ nodeEdgeMap: Map<CapacityMeshNodeId, CapacityMeshEdge[]>;
4140
+ unprocessedConnectionPairs: ConnectionNodePair[];
4141
+ solvedRoutes: ConnectionPathWithNodes[];
4142
+ activeConnectionPair: ConnectionNodePair | null;
4143
+ ogUnprocessedSubpaths: SubpathNodePair[] | null;
4144
+ unprocessedSubpaths: SubpathNodePair[] | null;
4145
+ solvedSubpaths: SubpathNodePair[] | null;
4146
+ activeSubpath: SubpathNodePair | null;
4147
+ viaNodes: CapacityMeshNode[];
4148
+ closestViaForConnectionStartMap: Map<ConnectionNodePair, CapacityMeshNode>;
4149
+ closestViaForConnectionEndMap: Map<ConnectionNodePair, CapacityMeshNode>;
4150
+ constructor(inputParams: {
4151
+ simpleRouteJson: SimpleRouteJson;
4152
+ nodes: CapacityMeshNode[];
4153
+ edges: CapacityMeshEdge[];
4154
+ colorMap?: Record<string, string>;
4155
+ MAX_ITERATIONS?: number;
4156
+ hyperParameters?: Partial<AssignableViaCapacityHyperParameters>;
4157
+ });
4158
+ getConstructorParams(): typeof this.inputParams;
4159
+ lastStepOperation: "none" | "dequeueConnectionPair" | "breakConnectionPairIntoSubpaths" | "dequeueSubpath" | "stepSolveSubpath" | "finishedSolvingSubpath" | "finishedSolvingConnectionPair";
4179
4160
  /**
4180
- * Clears the entire cache and resets hit/miss counters.
4161
+ * Computes and stores the closest via for both start and end of each unprocessed connection pair.
4162
+ * This is used to ensure we don't "steal" a via that's closest to another connection.
4181
4163
  */
4182
- clearCache(): void;
4183
- getAllCacheKeys(): string[];
4164
+ computeClosestViaForAllConnections(): void;
4165
+ _step(): void;
4166
+ queuedCandidateNodes: Candidate[];
4167
+ visitedNodes: Set<CapacityMeshNodeId>;
4168
+ private _dist;
4169
+ stepSolveSubpath(subpath: SubpathNodePair): void;
4170
+ getNeighbors(node: CapacityMeshNode): CapacityMeshNode[];
4171
+ clearCandidateNodes(): void;
4172
+ computeG(prevCandidate: Candidate, node: CapacityMeshNode, _endGoal: CapacityMeshNode): number;
4173
+ computeH(_prevCandidate: Candidate, node: CapacityMeshNode, endGoal: CapacityMeshNode): number;
4174
+ createSolvedRoute(subpaths: SubpathNodePair[], connectionPair: ConnectionNodePair): ConnectionPathWithNodes;
4175
+ breakConnectionPairIntoSubpaths(connectionPair: ConnectionNodePair): SubpathNodePair[];
4176
+ getClosestVia(node: CapacityMeshNode): CapacityMeshNode;
4177
+ getFarVia(closestVia: CapacityMeshNode, end: CapacityMeshNode): CapacityMeshNode;
4178
+ getCapacityPaths(): CapacityPath[];
4179
+ visualize(): GraphicsObject;
4184
4180
  }
4185
4181
 
4186
- /**
4187
- * A CacheProvider implementation using the browser's localStorage.
4188
- * Note: localStorage has size limits (typically 5-10MB) and stores data as strings.
4189
- * Complex objects will be JSON serialized/deserialized.
4190
- */
4191
- declare class LocalStorageCache implements CacheProvider {
4192
- isSyncCache: boolean;
4193
- cacheHits: number;
4194
- cacheMisses: number;
4195
- cacheHitsByPrefix: Record<string, number>;
4196
- cacheMissesByPrefix: Record<string, number>;
4197
- constructor();
4198
- private getKey;
4199
- /**
4200
- * Retrieves a cached solution synchronously from localStorage.
4201
- * Increments cache hit/miss counters.
4202
- * @param cacheKey The key to look up in the cache.
4203
- * @returns The cached solution if found and parsed correctly, otherwise undefined.
4204
- */
4205
- getCachedSolutionSync(cacheKey: string): any;
4206
- /**
4207
- * Retrieves a cached solution asynchronously. Wraps the synchronous method.
4208
- * @param cacheKey The key to look up in the cache.
4209
- * @returns A promise that resolves with the cached solution or undefined.
4210
- */
4211
- getCachedSolution(cacheKey: string): Promise<any>;
4212
- /**
4213
- * Stores a solution in localStorage synchronously.
4214
- * The solution is JSON stringified before storing.
4215
- * @param cacheKey The key under which to store the solution.
4216
- * @param cachedSolution The solution data to cache.
4217
- */
4218
- setCachedSolutionSync(cacheKey: string, cachedSolution: any): void;
4219
- /**
4220
- * Stores a solution in the cache asynchronously. Wraps the synchronous method.
4221
- * @param cacheKey The key under which to store the solution.
4222
- * @param cachedSolution The solution data to cache.
4223
- * @returns A promise that resolves when the solution is cached.
4224
- */
4225
- setCachedSolution(cacheKey: string, cachedSolution: any): Promise<void>;
4226
- /**
4227
- * Clears all cache entries created by this instance from localStorage
4228
- * and resets hit/miss counters.
4229
- */
4230
- clearCache(): void;
4231
- getAllCacheKeys(): string[];
4182
+ type AssignableViaCapacityPathingParams = ConstructorParameters<typeof AssignableViaCapacityPathingSolver_DirectiveSubOptimal>[0];
4183
+ type HyperParameterOverrides = Partial<CapacityHyperParameters> & {
4184
+ TRACE_ORDERING_SEED?: number;
4185
+ LAYER_TRAVERSAL_REWARD?: number;
4186
+ };
4187
+ declare class HyperAssignableViaCapacityPathingSolver extends HyperParameterSupervisorSolver<AssignableViaCapacityPathingSolver_DirectiveSubOptimal> {
4188
+ constructorParams: AssignableViaCapacityPathingParams;
4189
+ constructor(opts: AssignableViaCapacityPathingParams);
4190
+ getHyperParameterDefs(): ({
4191
+ name: string;
4192
+ possibleValues: {
4193
+ SHUFFLE_SEED: number;
4194
+ }[];
4195
+ } | {
4196
+ name: string;
4197
+ possibleValues: {
4198
+ FORCE_VIA_TRAVEL_CHANCE: number;
4199
+ }[];
4200
+ })[];
4201
+ computeG(solver: AssignableViaCapacityPathingSolver_DirectiveSubOptimal): number;
4202
+ computeH(solver: AssignableViaCapacityPathingSolver_DirectiveSubOptimal): number;
4203
+ generateSolver(hyperParameters: HyperParameterOverrides): AssignableViaCapacityPathingSolver_DirectiveSubOptimal;
4232
4204
  }
4233
4205
 
4234
- declare global {
4235
- var TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE: LocalStorageCache;
4236
- var TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE: InMemoryCache;
4206
+ /**
4207
+ * Creates offboard edges between assignable via obstacles that share
4208
+ * the same `offBoardConnectsTo` net name. These obstacles represent off-board
4209
+ * connection points (like edge connectors) that are logically connected
4210
+ * through external wiring.
4211
+ *
4212
+ * The solver finds all capacity nodes with `_assignedViaObstacle.offBoardConnectsTo`,
4213
+ * groups them by net name, and creates zero-cost offboard edges between
4214
+ * matching nodes. This allows the pathing solver to route through these virtual
4215
+ * connections as if the obstacles were directly connected.
4216
+ */
4217
+ declare class OffboardCapacityNodeSolver extends BaseSolver {
4218
+ capacityNodes: CapacityMeshNode[];
4219
+ capacityEdges: CapacityMeshEdge[];
4220
+ enhancedEdges: CapacityMeshEdge[];
4221
+ private animationState;
4222
+ private assignableNodes;
4223
+ private shownNodes;
4224
+ private pendingEdges;
4225
+ private createdEdges;
4226
+ private nextEdgeId;
4227
+ private nodeMap;
4228
+ constructor(solverParams: {
4229
+ capacityNodes: CapacityMeshNode[];
4230
+ capacityEdges: CapacityMeshEdge[];
4231
+ });
4232
+ private initializeAssignableNodes;
4233
+ private initializePendingEdges;
4234
+ _step(): void;
4235
+ private createOffboardEdge;
4236
+ visualize(): GraphicsObject;
4237
+ getVirtualOffboardNodes(): CapacityMeshNode[];
4238
+ getOffboardEdges(): CapacityMeshEdge[];
4237
4239
  }
4238
- declare function getGlobalLocalStorageCache(): LocalStorageCache;
4239
- declare function getGlobalInMemoryCache(): InMemoryCache;
4240
- declare function setupGlobalCaches(): void;
4241
4240
 
4242
- interface Target$1 {
4243
- x: number;
4244
- y: number;
4245
- bounds: {
4246
- minX: number;
4247
- minY: number;
4248
- maxX: number;
4249
- maxY: number;
4250
- };
4251
- connectionName: string;
4252
- availableZ: number[];
4253
- }
4254
- type BucketCoordinate = `${number}x${number}`;
4255
- declare class TargetTree {
4256
- targets: Target$1[];
4257
- buckets: Map<BucketCoordinate, [Target$1, number][]>;
4258
- CELL_SIZE: number;
4259
- constructor(targets: Target$1[]);
4260
- getBucketKey(x: number, y: number): BucketCoordinate;
4261
- getTargetsInArea(centerX: number, centerY: number, width: number, height: number): Target$1[];
4241
+ /**
4242
+ * Splits capacity paths at offboard edges into separate fragments.
4243
+ * When a path crosses an offboard edge (created by OffboardCapacityNodeSolver),
4244
+ * this solver breaks it into independent path segments.
4245
+ *
4246
+ * Each fragment becomes a separate connection with its own `connectionName`
4247
+ * (e.g., `AD_NET_frag_0`, `AD_NET_frag_1`). The solver also creates new
4248
+ * `SimpleRouteConnection` entries with appropriate `pointsToConnect` - the
4249
+ * original pad location plus a synthetic point at the offboard node.
4250
+ *
4251
+ * This enables downstream solvers to route each fragment independently,
4252
+ * treating them as separate traces that terminate at off-board connection points.
4253
+ */
4254
+ declare class OffboardPathFragmentSolver extends BaseSolver {
4255
+ private inputPaths;
4256
+ private capacityEdges;
4257
+ private originalConnections;
4258
+ fragmentedPaths: CapacityPath[];
4259
+ fragmentedConnections: SimpleRouteConnection[];
4260
+ fragmentedOriginalConnectionNames: Set<string>;
4261
+ private nextFragmentId;
4262
+ private animationState;
4263
+ private currentPath;
4264
+ private currentFragments;
4265
+ private currentFragmentIndex;
4266
+ private nodeMap;
4267
+ constructor({ capacityPaths, capacityEdges, capacityNodes, connections, }: {
4268
+ capacityPaths: CapacityPath[];
4269
+ capacityEdges: CapacityMeshEdge[];
4270
+ capacityNodes: CapacityMeshNode[];
4271
+ connections: SimpleRouteConnection[];
4272
+ });
4273
+ _step(): void;
4274
+ private createFragmentConnections;
4275
+ private splitPath;
4276
+ getFragmentedPaths(): CapacityPath[];
4277
+ getFragmentedConnections(): SimpleRouteConnection[];
4278
+ getFragmentedOriginalConnectionNames(): Set<string>;
4279
+ visualize(): GraphicsObject;
4280
+ private drawPath;
4262
4281
  }
4263
4282
 
4264
- interface CapacityMeshNodeSolverOptions$2 {
4283
+ interface CapacityMeshSolverOptions {
4265
4284
  capacityDepth?: number;
4285
+ targetMinCapacity?: number;
4286
+ cacheProvider?: CacheProvider | null;
4266
4287
  }
4267
- interface Target {
4268
- x: number;
4269
- y: number;
4270
- bounds: {
4271
- minX: number;
4272
- minY: number;
4273
- maxX: number;
4274
- maxY: number;
4275
- };
4276
- connectionName: string;
4277
- availableZ: number[];
4278
- }
4279
- declare class CapacityMeshNodeSolver extends BaseSolver {
4288
+ type AutoroutingPipelineSolverOptions = CapacityMeshSolverOptions;
4289
+ type PipelineStep<T extends new (...args: any[]) => BaseSolver> = {
4290
+ solverName: string;
4291
+ solverClass: T;
4292
+ getConstructorParams: (instance: AssignableAutoroutingPipeline1Solver) => ConstructorParameters<T>;
4293
+ onSolved?: (instance: AssignableAutoroutingPipeline1Solver) => void;
4294
+ };
4295
+ declare class AssignableAutoroutingPipeline1Solver extends BaseSolver {
4280
4296
  srj: SimpleRouteJson;
4281
- opts: CapacityMeshNodeSolverOptions$2;
4282
- unfinishedNodes: CapacityMeshNode[];
4283
- finishedNodes: CapacityMeshNode[];
4284
- nodeToXYOverlappingObstaclesMap: Map<CapacityMeshNodeId, Obstacle$1[]>;
4285
- layerCount: number;
4286
- protected outlinePolygon?: Polygon;
4287
- MAX_DEPTH: number;
4288
- targets: Target[];
4289
- targetTree: TargetTree;
4290
- obstacleTree: ObstacleSpatialHashIndex;
4291
- constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions$2);
4292
- computeTargets(): Target[];
4293
- protected getNodeBounds(node: CapacityMeshNode): {
4294
- minX: number;
4295
- maxX: number;
4296
- minY: number;
4297
- maxY: number;
4298
- };
4299
- protected getNodeRect(node: CapacityMeshNode): {
4300
- center: {
4301
- x: number;
4302
- y: number;
4303
- };
4304
- width: number;
4305
- height: number;
4306
- };
4307
- _nextNodeCounter: number;
4308
- getNextNodeId(): string;
4309
- getCapacityFromDepth(depth: number): number;
4310
- getTargetIfNodeContainsTarget(node: CapacityMeshNode): Target | null;
4311
- getXYOverlappingObstacles(node: CapacityMeshNode): Obstacle$1[];
4312
- getXYZOverlappingObstacles(node: CapacityMeshNode): Obstacle$1[];
4313
- /**
4314
- * Checks if the given mesh node overlaps with any obstacle.
4315
- * We treat both obstacles and nodes as axis‐aligned rectangles.
4316
- */
4317
- doesNodeOverlapObstacle(node: CapacityMeshNode): boolean;
4318
- /**
4319
- * Checks if the entire node is contained within any obstacle.
4320
- */
4321
- isNodeCompletelyInsideObstacle(node: CapacityMeshNode): boolean;
4322
- getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[];
4323
- shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean;
4297
+ opts: CapacityMeshSolverOptions;
4298
+ netToPointPairsSolver?: NetToPointPairsSolver;
4299
+ nodeSolver?: CapacityMeshNodeSolver;
4300
+ nodeTargetMerger?: CapacityNodeTargetMerger;
4301
+ edgeSolver?: CapacityMeshEdgeSolver;
4302
+ initialPathingSolver?: AssignableViaCapacityPathingSolver_DirectiveSubOptimal;
4303
+ initialPathingHyperSolver?: HyperAssignableViaCapacityPathingSolver;
4304
+ pathingOptimizer?: CapacityPathingMultiSectionSolver;
4305
+ edgeToPortSegmentSolver?: CapacityEdgeToPortSegmentSolver;
4306
+ colorMap: Record<string, string>;
4307
+ segmentToPointSolver?: CapacitySegmentToPointSolver;
4308
+ unravelMultiSectionSolver?: UnravelMultiSectionSolver;
4309
+ segmentToPointOptimizer?: CapacitySegmentPointOptimizer;
4310
+ highDensityRouteSolver?: HighDensitySolver;
4311
+ highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver;
4312
+ singleLayerNodeMerger?: SingleLayerNodeMergerSolver_OnlyMergeTargets;
4313
+ mergeAssignableViaNodes?: AssignableViaNodeMergerSolver;
4314
+ offboardCapacityNodeSolver?: OffboardCapacityNodeSolver;
4315
+ offboardPathFragmentSolver?: OffboardPathFragmentSolver;
4316
+ strawSolver?: StrawSolver;
4317
+ deadEndSolver?: DeadEndSolver;
4318
+ uselessViaRemovalSolver1?: UselessViaRemovalSolver;
4319
+ uselessViaRemovalSolver2?: UselessViaRemovalSolver;
4320
+ multiSimplifiedPathSolver1?: MultiSimplifiedPathSolver;
4321
+ multiSimplifiedPathSolver2?: MultiSimplifiedPathSolver;
4322
+ startTimeOfPhase: Record<string, number>;
4323
+ endTimeOfPhase: Record<string, number>;
4324
+ timeSpentOnPhase: Record<string, number>;
4325
+ activeSubSolver?: BaseSolver | null;
4326
+ connMap: ConnectivityMap;
4327
+ srjWithPointPairs?: SimpleRouteJson;
4328
+ capacityNodes: CapacityMeshNode[] | null;
4329
+ capacityEdges: CapacityMeshEdge[] | null;
4330
+ cacheProvider: CacheProvider | null;
4331
+ pipelineDef: (PipelineStep<typeof NetToPointPairsSolver> | PipelineStep<typeof CapacityMeshNodeSolver_OnlyTraverseLayersInAssignableObstacles> | PipelineStep<typeof AssignableViaNodeMergerSolver> | PipelineStep<typeof SingleLayerNodeMergerSolver_OnlyMergeTargets> | PipelineStep<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep<typeof OffboardCapacityNodeSolver> | PipelineStep<typeof DeadEndSolver> | PipelineStep<typeof HyperAssignableViaCapacityPathingSolver> | PipelineStep<typeof OffboardPathFragmentSolver> | PipelineStep<typeof CapacityEdgeToPortSegmentSolver> | PipelineStep<typeof CapacitySegmentToPointSolver> | PipelineStep<typeof UnravelMultiSectionSolver> | PipelineStep<typeof HighDensitySolver> | PipelineStep<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep<typeof UselessViaRemovalSolver> | PipelineStep<typeof MultiSimplifiedPathSolver>)[];
4332
+ constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions);
4333
+ getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions];
4334
+ currentPipelineStepIndex: number;
4324
4335
  _step(): void;
4325
- /**
4326
- * Creates a GraphicsObject to visualize the mesh, its nodes, obstacles, and connection points.
4327
- *
4328
- * - Mesh nodes are rendered as rectangles.
4329
- * - Nodes that have an obstacle intersection are outlined in red.
4330
- * - Other nodes are outlined in green.
4331
- * - Lines are drawn from a node to its parent.
4332
- * - Obstacles are drawn as semi-transparent red rectangles.
4333
- * - Points for each connection’s pointsToConnect are drawn in a unique color.
4334
- */
4336
+ solveUntilPhase(phase: string): void;
4337
+ getCurrentPhase(): string;
4335
4338
  visualize(): GraphicsObject;
4336
- }
4337
-
4338
- interface CapacityMeshNodeSolverOptions$1 {
4339
- capacityDepth?: number;
4340
- }
4341
- declare class CapacityMeshNodeSolver2_NodeUnderObstacle extends CapacityMeshNodeSolver {
4342
- srj: SimpleRouteJson;
4343
- opts: CapacityMeshNodeSolverOptions$1;
4344
- VIA_DIAMETER: number;
4345
- OBSTACLE_MARGIN: number;
4346
- /**
4347
- * The threshold for the percentage of a single-layer node that must be
4348
- * covered by obstacles to be considered "under an obstacle"
4349
- */
4350
- OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES: number;
4351
- constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions$1);
4352
- isNodeCompletelyOutsideBounds(node: CapacityMeshNode): boolean;
4353
- isNodePartiallyOutsideBounds(node: CapacityMeshNode): boolean;
4354
- /**
4355
- * Calculate the percentage of node area covered by obstacles
4356
- */
4357
- getObstacleCoveragePercentage(node: CapacityMeshNode): number;
4358
4339
  /**
4359
- * Check if a single-layer node should be filtered due to obstacle coverage
4340
+ * A lightweight version of the visualize method that can be used to stream
4341
+ * progress
4342
+ *
4343
+ * We return the most relevant graphic for the stage:
4344
+ * 1. netToPointPairs output
4345
+ * 2. Capacity Planning Output
4346
+ * 3. High Density Route Solver Output, max 200 lines
4360
4347
  */
4361
- shouldFilterSingleLayerNodeForObstacle(node: CapacityMeshNode): boolean;
4348
+ preview(): GraphicsObject;
4349
+ _getOutputHdRoutes(): HighDensityRoute$1[];
4362
4350
  /**
4363
- * Check if a node should be filtered due to obstacles.
4364
- * Single-layer nodes: filtered only if >20% covered
4365
- * Multi-layer nodes: filtered if any overlap
4351
+ * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces
4366
4352
  */
4367
- shouldFilterNodeForObstacle(node: CapacityMeshNode): boolean;
4368
- createChildNodeAtPosition(parent: CapacityMeshNode, opts: {
4369
- center: {
4370
- x: number;
4371
- y: number;
4372
- };
4373
- width: number;
4374
- height: number;
4375
- availableZ: number[];
4376
- _depth?: number;
4377
- }): CapacityMeshNode;
4378
- getZSubdivisionChildNodes(node: CapacityMeshNode): CapacityMeshNode[];
4379
- getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[];
4380
- shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean;
4381
- _step(): void;
4353
+ getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces;
4354
+ getOutputSimpleRouteJson(): SimpleRouteJson;
4382
4355
  }
4383
4356
 
4384
- interface CapacityMeshNodeSolverOptions {
4385
- capacityDepth?: number;
4386
- }
4357
+ declare const convertSrjToGraphicsObject: (srj: SimpleRouteJson) => {
4358
+ rects: Rect[];
4359
+ circles: Circle[];
4360
+ lines: Line[];
4361
+ points: Point$5[];
4362
+ };
4363
+
4364
+ type FutureConnection = {
4365
+ connectionName: string;
4366
+ points: {
4367
+ x: number;
4368
+ y: number;
4369
+ z: number;
4370
+ }[];
4371
+ };
4387
4372
  /**
4388
- * This capacity mesh node solver is meant to be used in contexts where vias
4389
- * aren't allowed, but there may be assignable vias on the PCB as obstacles.
4390
- *
4391
- * Behavior:
4392
- * - Outside assignable obstacles, multi-layer nodes are *always* Z-split into single-layer nodes.
4393
- * - During mesh subdivision, nodes overlapping with "assignable" obstacles
4394
- * (obstacle.netIsAssignable === true) are NOT filtered, allowing normal subdivision.
4395
- * - After the main mesh subdivision is complete:
4396
- * 1. All nodes overlapping with assignable obstacles are removed
4397
- * 2. Each assignable obstacle is replaced with a single multi-layer node spanning all layers
4398
- * - Single-layer nodes that are larger than MAX_SIZE_FOR_SINGLE_LAYER_NODES are XY-subdivided.
4399
- * - IMPORTANT: the multi-layer nodes created from assignable obstacles are **traversable**,
4400
- * so we mark `_containsObstacle = false` and `_completelyInsideObstacle = false` on them.
4373
+ * Components that make up the g (cost so far) calculation
4401
4374
  */
4402
- declare class CapacityMeshNodeSolver_OnlyTraverseLayersInAssignableObstacles extends CapacityMeshNodeSolver2_NodeUnderObstacle {
4403
- srj: SimpleRouteJson;
4404
- opts: CapacityMeshNodeSolverOptions;
4405
- MAX_SIZE_FOR_SINGLE_LAYER_NODES: number;
4406
- constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions);
4407
- private isObstacleAssignable;
4408
- private getOverlappingAssignableObstacles;
4409
- shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean;
4410
- /**
4411
- * Filter nodes for obstacles, but skip filtering for assignable obstacles.
4412
- * Assignable obstacles will be handled separately at the end.
4413
- */
4414
- shouldFilterNodeForObstacle(node: CapacityMeshNode): boolean;
4415
- /**
4416
- * Remove nodes inside assignable obstacles and replace with single multi-layer nodes.
4417
- * The new node's bounds are extended to cover all removed nodes' XY space.
4418
- */
4419
- private insertAssignableObstaclesAsNodes;
4420
- _step(): void;
4421
- }
4422
-
4375
+ type GComponents = {
4376
+ /** Total path distance traveled from start */
4377
+ distFromStart: number;
4378
+ /** Cumulative weighted penalty for being near obstacles */
4379
+ weightedMmNearObstacle: number;
4380
+ /** Cumulative weighted penalty for being near edges */
4381
+ weightedMmNearEdge: number;
4382
+ /** Cumulative weighted penalty for being near future connection start/end points */
4383
+ weightedMmNearFutureConnectionStartEnd: number;
4384
+ /** Cumulative weighted penalty for being near future connection lines */
4385
+ weightedMmNearFutureConnectionLine: number;
4386
+ /** Cumulative jumper penalty (includes jumper distance + penalty factor) */
4387
+ jumperPenalty: number;
4388
+ /** Cumulative penalty for jumper pads near future connections */
4389
+ jumperPadFutureConnectionPenalty: number;
4390
+ /** Total g value (sum of all components) */
4391
+ total: number;
4392
+ };
4423
4393
  /**
4424
- * Variant of SingleLayerNodeMergerSolver that only merges nodes containing targets.
4425
- * Nodes without targets are passed through unchanged.
4394
+ * Components that make up the h (heuristic) calculation
4426
4395
  */
4427
- declare class SingleLayerNodeMergerSolver_OnlyMergeTargets extends BaseSolver {
4428
- nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>;
4429
- currentBatchNodeIds: CapacityMeshNodeId[];
4430
- absorbedNodeIds: Set<CapacityMeshNodeId>;
4431
- nextBatchNodeIds: CapacityMeshNodeId[];
4432
- batchHadModifications: boolean;
4433
- hasComputedAdjacentNodeIds: boolean;
4434
- newNodes: CapacityMeshNode[];
4435
- constructor(nodes: CapacityMeshNode[]);
4436
- computeAdjacentNodeIdsForFirstBatch(nodes: CapacityMeshNode[]): void;
4437
- getAdjacentSameLayerUnprocessedNodes(rootNode: CapacityMeshNode): CapacityMeshNode[];
4438
- _step(): void;
4439
- visualize(): GraphicsObject;
4440
- }
4441
-
4396
+ type HComponents = {
4397
+ distanceToGoal: number;
4398
+ obstacleProximity: number;
4399
+ edgeProximity: number;
4400
+ futureConnectionStartEndProximityPenalty: number;
4401
+ futureConnectionLine: number;
4402
+ total: number;
4403
+ /** Stored rates (penalty per mm) for derivative computation */
4404
+ obstacleProximityRate: number;
4405
+ edgeProximityRate: number;
4406
+ futureConnectionStartEndProximityRate: number;
4407
+ futureConnectionLineRate: number;
4408
+ };
4442
4409
  /**
4443
- * This solver merges nodes that represent the same assignable obstacle into a single node.
4444
- *
4445
- * For each assignable obstacle:
4446
- * - Finds all nodes that have _assignedViaObstacle pointing to that obstacle
4447
- * - Replaces them with a single node representing the bounding box of all removed nodes
4448
- * - Each step handles one assignable obstacle
4410
+ * Extended node type that tracks jumper usage
4449
4411
  */
4450
- declare class AssignableViaNodeMergerSolver extends BaseSolver {
4451
- newNodes: CapacityMeshNode[];
4452
- obstacleToNodesMap: Map<Obstacle$1, CapacityMeshNode[]>;
4453
- obstaclesToProcess: Obstacle$1[];
4454
- mergedNodeIds: Set<CapacityMeshNodeId>;
4455
- constructor(nodes: CapacityMeshNode[]);
4456
- _step(): void;
4457
- visualize(): GraphicsObject;
4458
- }
4459
-
4460
- interface Point {
4461
- x: number;
4462
- y: number;
4463
- z: number;
4464
- }
4465
- declare class SingleSimplifiedPathSolver extends BaseSolver {
4466
- newRoute: HighDensityIntraNodeRoute$1["route"];
4467
- newVias: HighDensityIntraNodeRoute$1["vias"];
4468
- headIndex: number;
4469
- tailIndex: number;
4470
- inputRoute: HighDensityIntraNodeRoute$1;
4471
- otherHdRoutes: HighDensityIntraNodeRoute$1[];
4472
- obstacles: Obstacle$1[];
4473
- connMap: ConnectivityMap;
4474
- colorMap: Record<string, string>;
4475
- outline?: Array<{
4412
+ type JumperNode = Node & {
4413
+ /** If this node was reached via a jumper, this contains jumper info */
4414
+ jumperEntry?: {
4476
4415
  x: number;
4477
4416
  y: number;
4417
+ };
4418
+ /** Track if this movement is the exit of a jumper */
4419
+ isJumperExit?: boolean;
4420
+ /** Count of jumpers used to reach this node */
4421
+ jumperCount?: number;
4422
+ /** Stored g components for debugging/visualization */
4423
+ gComponents?: GComponents;
4424
+ /** Stored h components for debugging/visualization */
4425
+ hComponents?: HComponents;
4426
+ };
4427
+ declare class SingleHighDensityRouteWithJumpersSolver extends BaseSolver {
4428
+ obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[];
4429
+ bounds: {
4430
+ minX: number;
4431
+ maxX: number;
4432
+ minY: number;
4433
+ maxY: number;
4434
+ };
4435
+ boundsSize: {
4436
+ width: number;
4437
+ height: number;
4438
+ };
4439
+ boundsCenter: {
4440
+ x: number;
4441
+ y: number;
4442
+ };
4443
+ A: {
4444
+ x: number;
4445
+ y: number;
4446
+ z: number;
4447
+ };
4448
+ B: {
4449
+ x: number;
4450
+ y: number;
4451
+ z: number;
4452
+ };
4453
+ roundedGoalPosition: {
4454
+ x: number;
4455
+ y: number;
4456
+ z: number;
4457
+ };
4458
+ straightLineDistance: number;
4459
+ traceThickness: number;
4460
+ obstacleMargin: number;
4461
+ minCellSize: number;
4462
+ cellStep: number;
4463
+ GREEDY_MULTIPLER: number;
4464
+ numRoutes: number;
4465
+ /** Penalty factor for using a jumper (relative to distance) */
4466
+ JUMPER_PENALTY_FACTOR: number;
4467
+ /** Future connection proximity parameters */
4468
+ FUTURE_CONNECTION_START_END_PENALTY: number;
4469
+ FUTURE_CONNECTION_START_END_PROXIMITY: number;
4470
+ /** Future connection jumper pad penalty parameters */
4471
+ FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY: number;
4472
+ FUTURE_CONNECTION_JUMPER_PAD_PENALTY: number;
4473
+ /** Jumper-to-jumper pad proximity penalty parameters */
4474
+ JUMPER_JUMPER_PAD_PROXIMITY: number;
4475
+ JUMPER_JUMPER_PAD_PENALTY: number;
4476
+ /** Future connection line proximity penalty parameters */
4477
+ FUTURE_CONNECTION_LINE_PROXIMITY: number;
4478
+ FUTURE_CONNECTION_LINE_PENALTY: number;
4479
+ /** Obstacle proximity penalty parameters (repulsive field) */
4480
+ OBSTACLE_PROX_PENALTY_FACTOR: number;
4481
+ OBSTACLE_PROX_SIGMA: number;
4482
+ /** Edge proximity penalty parameters */
4483
+ EDGE_PROX_PENALTY_FACTOR: number;
4484
+ EDGE_PROX_SIGMA: number;
4485
+ /** Whether to allow diagonal movement in pathfinding */
4486
+ ALLOW_DIAGONAL: boolean;
4487
+ /** Minimum distance traveled before allowing jumper neighbors */
4488
+ MIN_TRAVEL_BEFORE_JUMPER: number;
4489
+ CELL_SIZE_FACTOR: number;
4490
+ exploredNodes: Set<string>;
4491
+ candidates: SingleRouteCandidatePriorityQueue<JumperNode>;
4492
+ connectionName: string;
4493
+ rootConnectionName?: string;
4494
+ solvedPath: HighDensityIntraNodeRouteWithJumpers | null;
4495
+ futureConnections: FutureConnection[];
4496
+ hyperParameters: Partial<HighDensityHyperParameters>;
4497
+ connMap?: ConnectivityMap;
4498
+ /** For debugging/animating the exploration */
4499
+ debug_exploredNodesOrdered: string[];
4500
+ debug_exploredNodeValues: Map<string, {
4501
+ g: number;
4502
+ h: number;
4503
+ f: number;
4504
+ gComponents?: GComponents;
4505
+ hComponents?: HComponents;
4478
4506
  }>;
4479
- constructor(params: {
4480
- inputRoute: HighDensityIntraNodeRoute$1;
4481
- otherHdRoutes: HighDensityIntraNodeRoute$1[];
4482
- obstacles: Obstacle$1[];
4483
- connMap: ConnectivityMap;
4484
- colorMap: Record<string, string>;
4485
- outline?: Array<{
4507
+ debug_nodesTooCloseToObstacle: Set<string>;
4508
+ debug_nodePathToParentIntersectsObstacle: Set<string>;
4509
+ debugEnabled: boolean;
4510
+ initialNodeGridOffset: {
4511
+ x: number;
4512
+ y: number;
4513
+ };
4514
+ /** Existing jumpers that act as obstacles */
4515
+ existingJumpers: Jumper[];
4516
+ constructor(opts: {
4517
+ connectionName: string;
4518
+ rootConnectionName?: string;
4519
+ obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[];
4520
+ minDistBetweenEnteringPoints: number;
4521
+ bounds: {
4522
+ minX: number;
4523
+ maxX: number;
4524
+ minY: number;
4525
+ maxY: number;
4526
+ };
4527
+ A: {
4486
4528
  x: number;
4487
4529
  y: number;
4488
- }>;
4489
- });
4490
- getConstructorParams(): {
4491
- inputRoute: HighDensityIntraNodeRoute$1;
4492
- otherHdRoutes: HighDensityIntraNodeRoute$1[];
4493
- obstacles: Obstacle$1[];
4494
- connMap: Record<string, string[]>;
4495
- colorMap: Record<string, string>;
4496
- outline: {
4530
+ z: number;
4531
+ };
4532
+ B: {
4497
4533
  x: number;
4498
4534
  y: number;
4499
- }[] | undefined;
4500
- };
4501
- get simplifiedRoute(): HighDensityIntraNodeRoute$1;
4502
- isValidPath(pointsInRoute: Point[]): boolean;
4503
- _step(): void;
4504
- getVisualsForNewRouteAndObstacles(): GraphicsObject & Pick<Required<GraphicsObject>, "points" | "lines" | "rects" | "circles">;
4505
- }
4506
-
4507
- declare class MultiSimplifiedPathSolver extends BaseSolver {
4508
- simplifiedHdRoutes: HighDensityIntraNodeRoute$1[];
4509
- currentUnsimplifiedHdRouteIndex: number;
4510
- activeSubSolver: SingleSimplifiedPathSolver | null;
4511
- unsimplifiedHdRoutes: HighDensityIntraNodeRoute$1[];
4512
- obstacles: Obstacle$1[];
4513
- connMap: ConnectivityMap;
4514
- colorMap: Record<string, string>;
4515
- outline?: Array<{
4535
+ z: number;
4536
+ };
4537
+ traceThickness?: number;
4538
+ obstacleMargin?: number;
4539
+ futureConnections?: FutureConnection[];
4540
+ hyperParameters?: Partial<HighDensityHyperParameters>;
4541
+ connMap?: ConnectivityMap;
4542
+ });
4543
+ handleSimpleCases(): void;
4544
+ get jumperPenaltyDistance(): number;
4545
+ /**
4546
+ * Check if a node is too close to an obstacle trace or jumper
4547
+ */
4548
+ isNodeTooCloseToObstacle(node: JumperNode, margin?: number): boolean;
4549
+ /**
4550
+ * Check if a node is too close to a jumper's pads
4551
+ * Traces CAN route under the body of the jumper, just not under the pads
4552
+ */
4553
+ isNodeTooCloseToJumper(node: {
4516
4554
  x: number;
4517
4555
  y: number;
4518
- }>;
4519
- defaultViaDiameter: number;
4520
- constructor(params: {
4521
- unsimplifiedHdRoutes: HighDensityIntraNodeRoute$1[];
4522
- obstacles: Obstacle$1[];
4523
- connMap?: ConnectivityMap;
4524
- colorMap?: Record<string, string>;
4525
- outline?: Array<{
4556
+ }, jumper: Jumper, margin: number): boolean;
4557
+ isNodeTooCloseToEdge(node: JumperNode): boolean;
4558
+ doesPathToParentIntersectObstacle(node: JumperNode): boolean;
4559
+ /**
4560
+ * Check if a line segment intersects with a jumper's pads
4561
+ * Segments CAN pass under the jumper body, just not through the pads
4562
+ */
4563
+ doesSegmentIntersectJumperPads(p1: {
4564
+ x: number;
4565
+ y: number;
4566
+ }, p2: {
4567
+ x: number;
4568
+ y: number;
4569
+ }, jumper: Jumper): boolean;
4570
+ /**
4571
+ * Check if a line segment intersects with an axis-aligned rectangle
4572
+ */
4573
+ doesSegmentIntersectRect(p1: {
4574
+ x: number;
4575
+ y: number;
4576
+ }, p2: {
4577
+ x: number;
4578
+ y: number;
4579
+ }, center: {
4580
+ x: number;
4581
+ y: number;
4582
+ }, halfWidth: number, halfHeight: number): boolean;
4583
+ /**
4584
+ * Find obstacles between current node and a target position
4585
+ * Returns the obstacle segment(s) that block the direct path
4586
+ */
4587
+ findObstaclesBetween(from: {
4588
+ x: number;
4589
+ y: number;
4590
+ }, to: {
4591
+ x: number;
4592
+ y: number;
4593
+ }): Array<{
4594
+ A: {
4526
4595
  x: number;
4527
4596
  y: number;
4528
- }>;
4529
- defaultViaDiameter?: number;
4530
- });
4531
- _step(): void;
4532
- visualize(): GraphicsObject;
4533
- }
4534
-
4535
- interface RouteSection {
4536
- startIndex: number;
4537
- endIndex: number;
4538
- z: number;
4539
- points: HighDensityRoute["route"];
4540
- }
4541
- declare class SingleRouteUselessViaRemovalSolver extends BaseSolver {
4542
- obstacleSHI: ObstacleSpatialHashIndex;
4543
- hdRouteSHI: HighDensityRouteSpatialIndex;
4544
- unsimplifiedRoute: HighDensityRoute;
4545
- routeSections: Array<RouteSection>;
4546
- currentSectionIndex: number;
4547
- TRACE_THICKNESS: number;
4548
- OBSTACLE_MARGIN: number;
4549
- constructor(params: {
4550
- obstacleSHI: ObstacleSpatialHashIndex;
4551
- hdRouteSHI: HighDensityRouteSpatialIndex;
4552
- unsimplifiedRoute: HighDensityRoute;
4553
- });
4554
- breakRouteIntoSections(route: HighDensityRoute): never[] | this["routeSections"];
4555
- _step(): void;
4597
+ };
4598
+ B: {
4599
+ x: number;
4600
+ y: number;
4601
+ };
4602
+ }>;
4603
+ computeHComponents(node: JumperNode): HComponents;
4604
+ computeH(node: JumperNode): number;
4605
+ computeGComponents(node: JumperNode): GComponents;
4606
+ computeG(node: JumperNode): number;
4607
+ computeF(g: number, h: number): number;
4608
+ getClosestFutureConnectionPoint(node: JumperNode): {
4609
+ x: number;
4610
+ y: number;
4611
+ z: number;
4612
+ } | null;
4613
+ getFutureConnectionStartEndPenalty(node: JumperNode): number;
4556
4614
  /**
4557
- * Check if an endpoint (first or last point of the route) can connect
4558
- * to a different layer. This is only allowed if the obstacles the endpoint
4559
- * connects to support that layer.
4615
+ * Calculate penalty for being close to future connection line segments.
4616
+ * This penalty is computed by summing the segment-to-point distance between
4617
+ * the node and all unrouted future connection start-to-end segments.
4618
+ * The penalty helps routes avoid crossing directly over future connection paths.
4560
4619
  */
4561
- canEndpointConnectOnLayer(endpointX: number, endpointY: number, targetZ: number): boolean;
4562
- canSectionMoveToLayer({ currentSection, targetZ, }: {
4563
- currentSection: RouteSection;
4564
- targetZ: number;
4565
- }): boolean;
4566
- getConstructorParams(): {
4567
- obstacleSHI: ObstacleSpatialHashIndex;
4568
- hdRouteSHI: HighDensityRouteSpatialIndex;
4569
- unsimplifiedRoute: HighDensityIntraNodeRoute;
4570
- };
4571
- getOptimizedHdRoute(): HighDensityRoute;
4572
- visualize(): GraphicsObject;
4573
- }
4574
-
4575
- interface UselessViaRemovalSolverInput {
4576
- unsimplifiedHdRoutes: HighDensityRoute$1[];
4577
- obstacles: Obstacle$1[];
4578
- colorMap: Record<string, string>;
4579
- layerCount: number;
4580
- }
4581
- declare class UselessViaRemovalSolver extends BaseSolver {
4582
- private input;
4583
- unsimplifiedHdRoutes: HighDensityRoute$1[];
4584
- optimizedHdRoutes: HighDensityRoute$1[];
4585
- unprocessedRoutes: HighDensityRoute$1[];
4586
- activeSubSolver?: SingleRouteUselessViaRemovalSolver | null | undefined;
4587
- obstacleSHI: ObstacleSpatialHashIndex | null;
4588
- hdRouteSHI: HighDensityRouteSpatialIndex | null;
4589
- constructor(input: UselessViaRemovalSolverInput);
4590
- _step(): void;
4591
- getOptimizedHdRoutes(): HighDensityRoute$1[] | null;
4592
- visualize(): GraphicsObject;
4593
- }
4594
-
4595
- type Candidate = {
4596
- prevCandidate: Candidate | null;
4597
- node: CapacityMeshNode;
4598
- f: number;
4599
- g: number;
4600
- h: number;
4601
- };
4602
- type AssignableViaCapacityHyperParameters = Partial<CapacityHyperParameters> & {
4603
- SHUFFLE_SEED?: number;
4604
- DIRECTIVE_SEED?: number;
4605
- FORCE_VIA_TRAVEL_CHANCE?: number;
4606
- FAR_VIA_MIN_DISTANCE?: number;
4607
- MAX_CLOSEST_VIA_SKIP?: number;
4608
- MAX_FURTHEST_VIA_SKIP?: number;
4609
- };
4610
- type ConnectionNodePair = {
4611
- start: CapacityMeshNode;
4612
- end: CapacityMeshNode;
4613
- connection: SimpleRouteConnection;
4614
- };
4615
- type SubpathNodePair = {
4616
- start: CapacityMeshNode;
4617
- end: CapacityMeshNode;
4618
- solved: boolean;
4619
- path?: CapacityMeshNode[];
4620
- layer: number;
4621
- };
4622
- type ConnectionPathWithNodes = {
4623
- connection: SimpleRouteConnection;
4624
- path: CapacityMeshNode[];
4625
- };
4626
- /**
4627
- * See description in the prompt
4628
- */
4629
- declare class AssignableViaCapacityPathingSolver_DirectiveSubOptimal extends BaseSolver {
4630
- private inputParams;
4620
+ getFutureConnectionLinePenalty(node: JumperNode): number;
4631
4621
  /**
4632
- * Bias toward greedier choices (f = g + GREEDY_MULTIPLIER * h)
4622
+ * Calculate penalty for jumper pads placed near future connection start/end points.
4623
+ * This disincentivizes placing jumper pads in areas that will be needed for future routing.
4624
+ * The distance is calculated as the minimum distance from either jumper pad to any future connection point.
4633
4625
  */
4634
- GREEDY_MULTIPLIER: number;
4635
- simpleRouteJson: SimpleRouteJson;
4636
- nodes: CapacityMeshNode[];
4637
- edges: CapacityMeshEdge[];
4638
- colorMap: Record<string, string>;
4639
- MAX_ITERATIONS: number;
4640
- hyperParameters: Partial<AssignableViaCapacityHyperParameters>;
4641
- usedNodeMap: Map<CapacityMeshNodeId, true>;
4642
- nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>;
4643
- nodeEdgeMap: Map<CapacityMeshNodeId, CapacityMeshEdge[]>;
4644
- unprocessedConnectionPairs: ConnectionNodePair[];
4645
- solvedRoutes: ConnectionPathWithNodes[];
4646
- activeConnectionPair: ConnectionNodePair | null;
4647
- ogUnprocessedSubpaths: SubpathNodePair[] | null;
4648
- unprocessedSubpaths: SubpathNodePair[] | null;
4649
- solvedSubpaths: SubpathNodePair[] | null;
4650
- activeSubpath: SubpathNodePair | null;
4651
- viaNodes: CapacityMeshNode[];
4652
- closestViaForConnectionStartMap: Map<ConnectionNodePair, CapacityMeshNode>;
4653
- closestViaForConnectionEndMap: Map<ConnectionNodePair, CapacityMeshNode>;
4654
- constructor(inputParams: {
4655
- simpleRouteJson: SimpleRouteJson;
4656
- nodes: CapacityMeshNode[];
4657
- edges: CapacityMeshEdge[];
4658
- colorMap?: Record<string, string>;
4659
- MAX_ITERATIONS?: number;
4660
- hyperParameters?: Partial<AssignableViaCapacityHyperParameters>;
4661
- });
4662
- getConstructorParams(): typeof this.inputParams;
4663
- lastStepOperation: "none" | "dequeueConnectionPair" | "breakConnectionPairIntoSubpaths" | "dequeueSubpath" | "stepSolveSubpath" | "finishedSolvingSubpath" | "finishedSolvingConnectionPair";
4626
+ getJumperPadFutureConnectionPenalty(node: JumperNode): number;
4627
+ /**
4628
+ * Compute the minimum distance from a node to any obstacle (trace segments and jumper pads)
4629
+ */
4630
+ getClearanceToObstacles(node: {
4631
+ x: number;
4632
+ y: number;
4633
+ }): number;
4634
+ /**
4635
+ * Compute distance from a point to the nearest jumper pad
4636
+ */
4637
+ distanceToJumperPads(p: {
4638
+ x: number;
4639
+ y: number;
4640
+ }, j: Jumper): number;
4641
+ /**
4642
+ * Compute distance from a point to an axis-aligned rectangle (0 if inside)
4643
+ */
4644
+ pointToRectDistance(p: {
4645
+ x: number;
4646
+ y: number;
4647
+ }, c: {
4648
+ x: number;
4649
+ y: number;
4650
+ }, halfW: number, halfH: number): number;
4651
+ /**
4652
+ * Compute minimum distance from a node to the nearest boundary edge
4653
+ */
4654
+ getClearanceToEdge(node: {
4655
+ x: number;
4656
+ y: number;
4657
+ }): number;
4658
+ /**
4659
+ * Compute the obstacle proximity penalty (repulsive field)
4660
+ * Returns a high value near obstacles, ~0 far away
4661
+ */
4662
+ getObstacleProximityPenalty(node: JumperNode): number;
4663
+ /**
4664
+ * Compute the edge proximity penalty (repulsive field near boundaries)
4665
+ * Returns a high value near edges, ~0 far away
4666
+ * Penalty is reduced as we approach the goal (which is always on an edge)
4667
+ */
4668
+ getEdgeProximityPenalty(node: JumperNode): number;
4669
+ getNodeKey(node: JumperNode): string;
4670
+ /**
4671
+ * Calculate potential jumper positions to cross an obstacle
4672
+ */
4673
+ getJumperNeighbors(node: JumperNode): JumperNode[];
4674
+ /**
4675
+ * Calculate the exit position for a jumper that clears an obstacle
4676
+ */
4677
+ calculateJumperExit(entry: JumperNode, obstacle: {
4678
+ A: {
4679
+ x: number;
4680
+ y: number;
4681
+ };
4682
+ B: {
4683
+ x: number;
4684
+ y: number;
4685
+ };
4686
+ }, direction: {
4687
+ dx: number;
4688
+ dy: number;
4689
+ }): JumperNode | null;
4690
+ /**
4691
+ * Check if a jumper's pads are too close to obstacle traces
4692
+ */
4693
+ isJumperTooCloseToTraces(entry: {
4694
+ x: number;
4695
+ y: number;
4696
+ }, exit: {
4697
+ x: number;
4698
+ y: number;
4699
+ }): boolean;
4664
4700
  /**
4665
- * Computes and stores the closest via for both start and end of each unprocessed connection pair.
4666
- * This is used to ensure we don't "steal" a via that's closest to another connection.
4701
+ * Verify that a jumper placement is valid (doesn't overlap with existing jumpers or traces)
4667
4702
  */
4668
- computeClosestViaForAllConnections(): void;
4669
- _step(): void;
4670
- queuedCandidateNodes: Candidate[];
4671
- visitedNodes: Set<CapacityMeshNodeId>;
4672
- private _dist;
4673
- stepSolveSubpath(subpath: SubpathNodePair): void;
4674
- getNeighbors(node: CapacityMeshNode): CapacityMeshNode[];
4675
- clearCandidateNodes(): void;
4676
- computeG(prevCandidate: Candidate, node: CapacityMeshNode, _endGoal: CapacityMeshNode): number;
4677
- computeH(_prevCandidate: Candidate, node: CapacityMeshNode, endGoal: CapacityMeshNode): number;
4678
- createSolvedRoute(subpaths: SubpathNodePair[], connectionPair: ConnectionNodePair): ConnectionPathWithNodes;
4679
- breakConnectionPairIntoSubpaths(connectionPair: ConnectionNodePair): SubpathNodePair[];
4680
- getClosestVia(node: CapacityMeshNode): CapacityMeshNode;
4681
- getFarVia(closestVia: CapacityMeshNode, end: CapacityMeshNode): CapacityMeshNode;
4682
- getCapacityPaths(): CapacityPath[];
4683
- visualize(): GraphicsObject;
4684
- }
4685
-
4686
- type AssignableViaCapacityPathingParams = ConstructorParameters<typeof AssignableViaCapacityPathingSolver_DirectiveSubOptimal>[0];
4687
- type HyperParameterOverrides = Partial<CapacityHyperParameters> & {
4688
- TRACE_ORDERING_SEED?: number;
4689
- LAYER_TRAVERSAL_REWARD?: number;
4690
- };
4691
- declare class HyperAssignableViaCapacityPathingSolver extends HyperParameterSupervisorSolver<AssignableViaCapacityPathingSolver_DirectiveSubOptimal> {
4692
- constructorParams: AssignableViaCapacityPathingParams;
4693
- constructor(opts: AssignableViaCapacityPathingParams);
4694
- getHyperParameterDefs(): ({
4695
- name: string;
4696
- possibleValues: {
4697
- SHUFFLE_SEED: number;
4698
- }[];
4699
- } | {
4700
- name: string;
4701
- possibleValues: {
4702
- FORCE_VIA_TRAVEL_CHANCE: number;
4703
- }[];
4704
- })[];
4705
- computeG(solver: AssignableViaCapacityPathingSolver_DirectiveSubOptimal): number;
4706
- computeH(solver: AssignableViaCapacityPathingSolver_DirectiveSubOptimal): number;
4707
- generateSolver(hyperParameters: HyperParameterOverrides): AssignableViaCapacityPathingSolver_DirectiveSubOptimal;
4708
- }
4709
-
4710
- /**
4711
- * Creates offboard edges between assignable via obstacles that share
4712
- * the same `offBoardConnectsTo` net name. These obstacles represent off-board
4713
- * connection points (like edge connectors) that are logically connected
4714
- * through external wiring.
4715
- *
4716
- * The solver finds all capacity nodes with `_assignedViaObstacle.offBoardConnectsTo`,
4717
- * groups them by net name, and creates zero-cost offboard edges between
4718
- * matching nodes. This allows the pathing solver to route through these virtual
4719
- * connections as if the obstacles were directly connected.
4720
- */
4721
- declare class OffboardCapacityNodeSolver extends BaseSolver {
4722
- capacityNodes: CapacityMeshNode[];
4723
- capacityEdges: CapacityMeshEdge[];
4724
- enhancedEdges: CapacityMeshEdge[];
4725
- private animationState;
4726
- private assignableNodes;
4727
- private shownNodes;
4728
- private pendingEdges;
4729
- private createdEdges;
4730
- private nextEdgeId;
4731
- private nodeMap;
4732
- constructor(solverParams: {
4733
- capacityNodes: CapacityMeshNode[];
4734
- capacityEdges: CapacityMeshEdge[];
4735
- });
4736
- private initializeAssignableNodes;
4737
- private initializePendingEdges;
4703
+ isJumperPlacementValid(entry: JumperNode, exit: JumperNode): boolean;
4704
+ /**
4705
+ * Check if two jumpers overlap
4706
+ */
4707
+ doJumpersOverlap(j1: Jumper, j2: Jumper): boolean;
4708
+ /**
4709
+ * Get all jumpers in the path to a node
4710
+ */
4711
+ getJumpersInPath(node: JumperNode): Jumper[];
4712
+ getNeighbors(node: JumperNode): JumperNode[];
4713
+ getNodePath(node: JumperNode): JumperNode[];
4714
+ setSolvedPath(node: JumperNode): void;
4715
+ computeProgress(currentNode: JumperNode, goalDist: number): number;
4738
4716
  _step(): void;
4739
- private createOffboardEdge;
4717
+ /**
4718
+ * Draw the two pads of an 0603 jumper
4719
+ * Pad dimensions are rotated based on jumper orientation
4720
+ */
4721
+ private drawJumperPads;
4740
4722
  visualize(): GraphicsObject;
4741
- getVirtualOffboardNodes(): CapacityMeshNode[];
4742
- getOffboardEdges(): CapacityMeshEdge[];
4743
4723
  }
4744
4724
 
4745
4725
  /**
4746
- * Splits capacity paths at offboard edges into separate fragments.
4747
- * When a path crosses an offboard edge (created by OffboardCapacityNodeSolver),
4748
- * this solver breaks it into independent path segments.
4749
- *
4750
- * Each fragment becomes a separate connection with its own `connectionName`
4751
- * (e.g., `AD_NET_frag_0`, `AD_NET_frag_1`). The solver also creates new
4752
- * `SimpleRouteConnection` entries with appropriate `pointsToConnect` - the
4753
- * original pad location plus a synthetic point at the offboard node.
4726
+ * IntraNodeSolverWithJumpers is designed for single-layer nodes that use
4727
+ * 0603 jumpers to allow traces to jump over each other.
4754
4728
  *
4755
- * This enables downstream solvers to route each fragment independently,
4756
- * treating them as separate traces that terminate at off-board connection points.
4729
+ * Unlike the standard IntraNodeRouteSolver which uses vias to change layers,
4730
+ * this solver operates on a single layer and uses physical jumper components
4731
+ * to handle trace crossings.
4757
4732
  */
4758
- declare class OffboardPathFragmentSolver extends BaseSolver {
4759
- private inputPaths;
4760
- private capacityEdges;
4761
- private originalConnections;
4762
- fragmentedPaths: CapacityPath[];
4763
- fragmentedConnections: SimpleRouteConnection[];
4764
- fragmentedOriginalConnectionNames: Set<string>;
4765
- private nextFragmentId;
4766
- private animationState;
4767
- private currentPath;
4768
- private currentFragments;
4769
- private currentFragmentIndex;
4770
- private nodeMap;
4771
- constructor({ capacityPaths, capacityEdges, capacityNodes, connections, }: {
4772
- capacityPaths: CapacityPath[];
4773
- capacityEdges: CapacityMeshEdge[];
4774
- capacityNodes: CapacityMeshNode[];
4775
- connections: SimpleRouteConnection[];
4776
- });
4777
- _step(): void;
4778
- private createFragmentConnections;
4779
- private splitPath;
4780
- getFragmentedPaths(): CapacityPath[];
4781
- getFragmentedConnections(): SimpleRouteConnection[];
4782
- getFragmentedOriginalConnectionNames(): Set<string>;
4783
- visualize(): GraphicsObject;
4784
- private drawPath;
4785
- }
4786
-
4787
- interface CapacityMeshSolverOptions {
4788
- capacityDepth?: number;
4789
- targetMinCapacity?: number;
4790
- cacheProvider?: CacheProvider | null;
4791
- }
4792
- type AutoroutingPipelineSolverOptions = CapacityMeshSolverOptions;
4793
- type PipelineStep<T extends new (...args: any[]) => BaseSolver> = {
4794
- solverName: string;
4795
- solverClass: T;
4796
- getConstructorParams: (instance: AssignableAutoroutingPipeline1Solver) => ConstructorParameters<T>;
4797
- onSolved?: (instance: AssignableAutoroutingPipeline1Solver) => void;
4798
- };
4799
- declare class AssignableAutoroutingPipeline1Solver extends BaseSolver {
4800
- srj: SimpleRouteJson;
4801
- opts: CapacityMeshSolverOptions;
4802
- netToPointPairsSolver?: NetToPointPairsSolver;
4803
- nodeSolver?: CapacityMeshNodeSolver;
4804
- nodeTargetMerger?: CapacityNodeTargetMerger;
4805
- edgeSolver?: CapacityMeshEdgeSolver;
4806
- initialPathingSolver?: AssignableViaCapacityPathingSolver_DirectiveSubOptimal;
4807
- initialPathingHyperSolver?: HyperAssignableViaCapacityPathingSolver;
4808
- pathingOptimizer?: CapacityPathingMultiSectionSolver;
4809
- edgeToPortSegmentSolver?: CapacityEdgeToPortSegmentSolver;
4733
+ declare class IntraNodeSolverWithJumpers extends BaseSolver {
4734
+ nodeWithPortPoints: NodeWithPortPoints;
4810
4735
  colorMap: Record<string, string>;
4811
- segmentToPointSolver?: CapacitySegmentToPointSolver;
4812
- unravelMultiSectionSolver?: UnravelMultiSectionSolver;
4813
- segmentToPointOptimizer?: CapacitySegmentPointOptimizer;
4814
- highDensityRouteSolver?: HighDensitySolver;
4815
- highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver;
4816
- singleLayerNodeMerger?: SingleLayerNodeMergerSolver_OnlyMergeTargets;
4817
- mergeAssignableViaNodes?: AssignableViaNodeMergerSolver;
4818
- offboardCapacityNodeSolver?: OffboardCapacityNodeSolver;
4819
- offboardPathFragmentSolver?: OffboardPathFragmentSolver;
4820
- strawSolver?: StrawSolver;
4821
- deadEndSolver?: DeadEndSolver;
4822
- uselessViaRemovalSolver1?: UselessViaRemovalSolver;
4823
- uselessViaRemovalSolver2?: UselessViaRemovalSolver;
4824
- multiSimplifiedPathSolver1?: MultiSimplifiedPathSolver;
4825
- multiSimplifiedPathSolver2?: MultiSimplifiedPathSolver;
4826
- startTimeOfPhase: Record<string, number>;
4827
- endTimeOfPhase: Record<string, number>;
4828
- timeSpentOnPhase: Record<string, number>;
4829
- activeSubSolver?: BaseSolver | null;
4830
- connMap: ConnectivityMap;
4831
- srjWithPointPairs?: SimpleRouteJson;
4832
- capacityNodes: CapacityMeshNode[] | null;
4833
- capacityEdges: CapacityMeshEdge[] | null;
4834
- cacheProvider: CacheProvider | null;
4835
- pipelineDef: (PipelineStep<typeof NetToPointPairsSolver> | PipelineStep<typeof CapacityMeshNodeSolver_OnlyTraverseLayersInAssignableObstacles> | PipelineStep<typeof AssignableViaNodeMergerSolver> | PipelineStep<typeof SingleLayerNodeMergerSolver_OnlyMergeTargets> | PipelineStep<typeof CapacityMeshEdgeSolver2_NodeTreeOptimization> | PipelineStep<typeof OffboardCapacityNodeSolver> | PipelineStep<typeof DeadEndSolver> | PipelineStep<typeof HyperAssignableViaCapacityPathingSolver> | PipelineStep<typeof OffboardPathFragmentSolver> | PipelineStep<typeof CapacityEdgeToPortSegmentSolver> | PipelineStep<typeof CapacitySegmentToPointSolver> | PipelineStep<typeof UnravelMultiSectionSolver> | PipelineStep<typeof HighDensitySolver> | PipelineStep<typeof MultipleHighDensityRouteStitchSolver> | PipelineStep<typeof UselessViaRemovalSolver> | PipelineStep<typeof MultiSimplifiedPathSolver>)[];
4836
- constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions);
4837
- getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions];
4838
- currentPipelineStepIndex: number;
4736
+ unsolvedConnections: {
4737
+ connectionName: string;
4738
+ rootConnectionName?: string;
4739
+ points: {
4740
+ x: number;
4741
+ y: number;
4742
+ z: number;
4743
+ }[];
4744
+ }[];
4745
+ totalConnections: number;
4746
+ solvedRoutes: HighDensityIntraNodeRouteWithJumpers[];
4747
+ failedSubSolvers: SingleHighDensityRouteWithJumpersSolver[];
4748
+ hyperParameters: Partial<HighDensityHyperParameters>;
4749
+ minDistBetweenEnteringPoints: number;
4750
+ traceWidth: number;
4751
+ activeSubSolver: SingleHighDensityRouteWithJumpersSolver | null;
4752
+ lastActiveSubSolver: SingleHighDensityRouteWithJumpersSolver | null;
4753
+ connMap?: ConnectivityMap;
4754
+ get failedSolvers(): SingleHighDensityRouteWithJumpersSolver[];
4755
+ get activeSolver(): SingleHighDensityRouteWithJumpersSolver | null;
4756
+ constructor(params: {
4757
+ nodeWithPortPoints: NodeWithPortPoints;
4758
+ colorMap?: Record<string, string>;
4759
+ hyperParameters?: Partial<HighDensityHyperParameters>;
4760
+ connMap?: ConnectivityMap;
4761
+ traceWidth?: number;
4762
+ });
4763
+ getConstructorParams(): {
4764
+ nodeWithPortPoints: NodeWithPortPoints;
4765
+ colorMap: Record<string, string>;
4766
+ hyperParameters: Partial<HighDensityHyperParameters>;
4767
+ connMap: ConnectivityMap | undefined;
4768
+ traceWidth: number;
4769
+ };
4770
+ computeProgress(): number;
4839
4771
  _step(): void;
4840
- solveUntilPhase(phase: string): void;
4841
- getCurrentPhase(): string;
4842
- visualize(): GraphicsObject;
4843
- /**
4844
- * A lightweight version of the visualize method that can be used to stream
4845
- * progress
4846
- *
4847
- * We return the most relevant graphic for the stage:
4848
- * 1. netToPointPairs output
4849
- * 2. Capacity Planning Output
4850
- * 3. High Density Route Solver Output, max 200 lines
4851
- */
4852
- preview(): GraphicsObject;
4853
- _getOutputHdRoutes(): HighDensityRoute$1[];
4854
4772
  /**
4855
- * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces
4773
+ * Draw the two pads of an 0603 jumper
4774
+ * Pad dimensions are rotated based on jumper orientation
4856
4775
  */
4857
- getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces;
4858
- getOutputSimpleRouteJson(): SimpleRouteJson;
4776
+ private drawJumperPads;
4777
+ visualize(): GraphicsObject;
4859
4778
  }
4860
4779
 
4861
- declare const convertSrjToGraphicsObject: (srj: SimpleRouteJson) => {
4862
- rects: Rect[];
4863
- circles: Circle[];
4864
- lines: Line[];
4865
- points: Point$5[];
4866
- };
4867
-
4868
4780
  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 };