@tscircuit/capacity-autorouter 0.0.237 → 0.0.238

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