@tscircuit/rectdiff 0.0.30 → 0.0.32
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 +381 -0
- package/dist/index.js +2764 -0
- package/lib/fixtures/twoNodeExpansionFixture.ts +1 -1
- package/lib/solvers/GapFillSolver/ExpandEdgesToEmptySpaceSolver.ts +2 -4
- package/lib/solvers/GapFillSolver/FindSegmentsWithAdjacentEmptySpaceSolver.ts +1 -3
- package/lib/solvers/GapFillSolver/GapFillSolverPipeline.ts +2 -6
- package/lib/solvers/RectDiffExpansionSolver/RectDiffExpansionSolver.ts +2 -5
- package/lib/solvers/RectDiffGridSolverPipeline/RectDiffGridSolverPipeline.ts +5 -8
- package/lib/solvers/RectDiffGridSolverPipeline/buildObstacleIndexes.ts +6 -6
- package/lib/solvers/RectDiffSeedingSolver/RectDiffSeedingSolver.ts +4 -4
- package/lib/solvers/RectDiffSeedingSolver/computeCandidates3D.ts +1 -1
- package/lib/solvers/RectDiffSeedingSolver/computeEdgeCandidates3D.ts +1 -1
- package/lib/solvers/RectDiffSeedingSolver/longestFreeSpanAroundZ.ts +1 -1
- package/lib/types/capacity-mesh-types.ts +1 -1
- package/lib/utils/expandRectFromSeed.ts +1 -1
- package/lib/utils/finalizeRects.ts +1 -1
- package/lib/utils/isFullyOccupiedAtPoint.ts +1 -1
- package/lib/utils/isSelfRect.ts +1 -1
- package/lib/utils/rectToTree.ts +2 -2
- package/lib/utils/renderObstacleClearance.ts +1 -1
- package/lib/utils/resizeSoftOverlaps.ts +1 -1
- package/lib/utils/sameTreeRect.ts +1 -1
- package/lib/utils/searchStrip.ts +1 -1
- package/package.json +7 -12
- package/pages/arduino-uno/inner2-ground-bottom-power.page.tsx +16 -0
- package/pages/arduino-uno/inner2-ground-inner1-power.page.tsx +16 -0
- package/test-assets/arduino-uno-inner2-ground-bottom-power.json +9687 -0
- package/test-assets/arduino-uno-inner2-ground-inner1-power.json +9687 -0
- package/tests/solver/arduino-uno-inner2-ground-bottom-power/__snapshots__/arduino-uno-inner2-ground-bottom-power.snap.svg +44 -0
- package/tests/solver/arduino-uno-inner2-ground-bottom-power/arduino-uno-inner2-ground-bottom-power.test.ts +94 -0
- package/tests/solver/arduino-uno-inner2-ground-inner1-power/__snapshots__/arduino-uno-inner2-ground-inner1-power.snap.svg +44 -0
- package/tests/solver/arduino-uno-inner2-ground-inner1-power/arduino-uno-inner2-ground-inner1-power.test.ts +94 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { BaseSolver, BasePipelineSolver, PipelineStep } from '@tscircuit/solver-utils';
|
|
2
|
+
import { GraphicsObject } from 'graphics-debug';
|
|
3
|
+
import Flatbush from 'flatbush';
|
|
4
|
+
import RBush from 'rbush';
|
|
5
|
+
import { Bounds } from '@tscircuit/math-utils';
|
|
6
|
+
|
|
7
|
+
type TraceId = string;
|
|
8
|
+
interface SimpleRouteJson {
|
|
9
|
+
layerCount: number;
|
|
10
|
+
minTraceWidth: number;
|
|
11
|
+
minViaDiameter?: number;
|
|
12
|
+
obstacles: Obstacle[];
|
|
13
|
+
connections: Array<SimpleRouteConnection>;
|
|
14
|
+
bounds: {
|
|
15
|
+
minX: number;
|
|
16
|
+
maxX: number;
|
|
17
|
+
minY: number;
|
|
18
|
+
maxY: number;
|
|
19
|
+
};
|
|
20
|
+
outline?: Array<{
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
interface Obstacle {
|
|
26
|
+
type: "rect";
|
|
27
|
+
layers: string[];
|
|
28
|
+
zLayers?: number[];
|
|
29
|
+
center: {
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
};
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
connectedTo: TraceId[];
|
|
36
|
+
netIsAssignable?: boolean;
|
|
37
|
+
offBoardConnectsTo?: TraceId[];
|
|
38
|
+
}
|
|
39
|
+
interface SimpleRouteConnection {
|
|
40
|
+
name: string;
|
|
41
|
+
netConnectionName?: string;
|
|
42
|
+
nominalTraceWidth?: number;
|
|
43
|
+
pointsToConnect: Array<{
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
layer: string;
|
|
47
|
+
pointId?: string;
|
|
48
|
+
pcb_port_id?: string;
|
|
49
|
+
}>;
|
|
50
|
+
externallyConnectedPointIds?: string[][];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type XYRect = {
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
};
|
|
59
|
+
type GridFill3DOptions = {
|
|
60
|
+
gridSizes?: number[];
|
|
61
|
+
initialCellRatio?: number;
|
|
62
|
+
maxAspectRatio?: number | null;
|
|
63
|
+
minSingle: {
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
};
|
|
67
|
+
minMulti: {
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
minLayers: number;
|
|
71
|
+
};
|
|
72
|
+
preferMultiLayer?: boolean;
|
|
73
|
+
maxMultiLayerSpan?: number;
|
|
74
|
+
};
|
|
75
|
+
type Candidate3D = {
|
|
76
|
+
x: number;
|
|
77
|
+
y: number;
|
|
78
|
+
z: number;
|
|
79
|
+
distance: number;
|
|
80
|
+
/** Larger values mean more multi-layer potential at this seed. */
|
|
81
|
+
zSpanLen?: number;
|
|
82
|
+
/** Marked when the seed came from the edge analysis pass. */
|
|
83
|
+
isEdgeSeed?: boolean;
|
|
84
|
+
};
|
|
85
|
+
type Placed3D = {
|
|
86
|
+
rect: XYRect;
|
|
87
|
+
zLayers: number[];
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
type CapacityMeshNodeId = string;
|
|
91
|
+
interface CapacityMeshNode {
|
|
92
|
+
capacityMeshNodeId: string;
|
|
93
|
+
center: {
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
};
|
|
97
|
+
width: number;
|
|
98
|
+
height: number;
|
|
99
|
+
layer: string;
|
|
100
|
+
availableZ: number[];
|
|
101
|
+
_depth?: number;
|
|
102
|
+
_completelyInsideObstacle?: boolean;
|
|
103
|
+
_containsObstacle?: boolean;
|
|
104
|
+
_containsTarget?: boolean;
|
|
105
|
+
_targetConnectionName?: string;
|
|
106
|
+
_strawNode?: boolean;
|
|
107
|
+
_strawParentCapacityMeshNodeId?: CapacityMeshNodeId;
|
|
108
|
+
_adjacentNodeIds?: CapacityMeshNodeId[];
|
|
109
|
+
_parent?: CapacityMeshNode;
|
|
110
|
+
}
|
|
111
|
+
type RTreeRect = XYRect & {
|
|
112
|
+
minX: number;
|
|
113
|
+
minY: number;
|
|
114
|
+
maxX: number;
|
|
115
|
+
maxY: number;
|
|
116
|
+
zLayers: number[];
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
interface SegmentWithAdjacentEmptySpace {
|
|
120
|
+
parent: CapacityMeshNode;
|
|
121
|
+
start: {
|
|
122
|
+
x: number;
|
|
123
|
+
y: number;
|
|
124
|
+
};
|
|
125
|
+
end: {
|
|
126
|
+
x: number;
|
|
127
|
+
y: number;
|
|
128
|
+
};
|
|
129
|
+
z: number;
|
|
130
|
+
facingDirection: "x+" | "x-" | "y+" | "y-";
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Find edges with adjacent empty space in the mesh
|
|
134
|
+
*
|
|
135
|
+
* Do this by iterating over each edge of the rect (each step is one edge)
|
|
136
|
+
* and checking if the is completely covered by any other edge
|
|
137
|
+
*
|
|
138
|
+
* If it is completely covered, then it doesn't have an adjacent empty space,
|
|
139
|
+
* continue
|
|
140
|
+
*
|
|
141
|
+
* If it is partially uncovered, then divide it into uncovered segments and add
|
|
142
|
+
* each uncovered segment as a new edge with an adjacent empty space
|
|
143
|
+
*/
|
|
144
|
+
declare class FindSegmentsWithAdjacentEmptySpaceSolver extends BaseSolver {
|
|
145
|
+
private input;
|
|
146
|
+
allEdges: Array<SegmentWithAdjacentEmptySpace>;
|
|
147
|
+
unprocessedEdges: Array<SegmentWithAdjacentEmptySpace>;
|
|
148
|
+
segmentsWithAdjacentEmptySpace: Array<SegmentWithAdjacentEmptySpace>;
|
|
149
|
+
edgeSpatialIndex: Flatbush;
|
|
150
|
+
lastCandidateEdge: SegmentWithAdjacentEmptySpace | null;
|
|
151
|
+
lastOverlappingEdges: Array<SegmentWithAdjacentEmptySpace> | null;
|
|
152
|
+
lastUncoveredSegments: Array<SegmentWithAdjacentEmptySpace> | null;
|
|
153
|
+
constructor(input: {
|
|
154
|
+
meshNodes: CapacityMeshNode[];
|
|
155
|
+
});
|
|
156
|
+
_step(): void;
|
|
157
|
+
getOutput(): {
|
|
158
|
+
segmentsWithAdjacentEmptySpace: Array<SegmentWithAdjacentEmptySpace>;
|
|
159
|
+
};
|
|
160
|
+
visualize(): Required<GraphicsObject>;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
type ExpandEdgesToEmptySpaceSolverInput = {
|
|
164
|
+
inputMeshNodes: CapacityMeshNode[];
|
|
165
|
+
segmentsWithAdjacentEmptySpace: Array<SegmentWithAdjacentEmptySpace>;
|
|
166
|
+
boardVoid?: {
|
|
167
|
+
boardVoidRects: XYRect[];
|
|
168
|
+
layerCount: number;
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
interface ExpandedSegment {
|
|
172
|
+
segment: SegmentWithAdjacentEmptySpace;
|
|
173
|
+
newNode: CapacityMeshNode;
|
|
174
|
+
}
|
|
175
|
+
declare class ExpandEdgesToEmptySpaceSolver extends BaseSolver {
|
|
176
|
+
private input;
|
|
177
|
+
unprocessedSegments: Array<SegmentWithAdjacentEmptySpace>;
|
|
178
|
+
expandedSegments: Array<ExpandedSegment>;
|
|
179
|
+
lastSegment: SegmentWithAdjacentEmptySpace | null;
|
|
180
|
+
lastSearchBounds: Bounds | null;
|
|
181
|
+
lastCollidingNodes: CapacityMeshNode[] | null;
|
|
182
|
+
lastSearchCorner1: {
|
|
183
|
+
x: number;
|
|
184
|
+
y: number;
|
|
185
|
+
} | null;
|
|
186
|
+
lastSearchCorner2: {
|
|
187
|
+
x: number;
|
|
188
|
+
y: number;
|
|
189
|
+
} | null;
|
|
190
|
+
lastExpandedSegment: ExpandedSegment | null;
|
|
191
|
+
rectSpatialIndex: RBush<CapacityMeshNode>;
|
|
192
|
+
constructor(input: ExpandEdgesToEmptySpaceSolverInput);
|
|
193
|
+
_step(): void;
|
|
194
|
+
getOutput(): {
|
|
195
|
+
expandedSegments: ExpandedSegment[];
|
|
196
|
+
};
|
|
197
|
+
visualize(): Required<GraphicsObject>;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
type GapFillSolverInput = {
|
|
201
|
+
meshNodes: CapacityMeshNode[];
|
|
202
|
+
boardVoid?: {
|
|
203
|
+
boardVoidRects: XYRect[];
|
|
204
|
+
layerCount: number;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
declare class GapFillSolverPipeline extends BasePipelineSolver<GapFillSolverInput> {
|
|
208
|
+
findSegmentsWithAdjacentEmptySpaceSolver?: FindSegmentsWithAdjacentEmptySpaceSolver;
|
|
209
|
+
expandEdgesToEmptySpaceSolver?: ExpandEdgesToEmptySpaceSolver;
|
|
210
|
+
pipelineDef: PipelineStep<any>[];
|
|
211
|
+
getOutput(): {
|
|
212
|
+
outputNodes: CapacityMeshNode[];
|
|
213
|
+
};
|
|
214
|
+
initialVisualize(): GraphicsObject;
|
|
215
|
+
finalVisualize(): GraphicsObject;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
type RectDiffSeedingSolverInput = {
|
|
219
|
+
simpleRouteJson: SimpleRouteJson;
|
|
220
|
+
obstacleIndexByLayer: Array<RBush<RTreeRect>>;
|
|
221
|
+
gridOptions?: Partial<GridFill3DOptions>;
|
|
222
|
+
boardVoidRects?: XYRect[];
|
|
223
|
+
layerNames: string[];
|
|
224
|
+
zIndexByName: Map<string, number>;
|
|
225
|
+
obstacleClearance?: number;
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* First phase of RectDiff: grid-based seeding and placement.
|
|
229
|
+
*
|
|
230
|
+
* This solver is responsible for walking all grid sizes and producing
|
|
231
|
+
* an initial set of placed rectangles.
|
|
232
|
+
*/
|
|
233
|
+
declare class RectDiffSeedingSolver extends BaseSolver {
|
|
234
|
+
private input;
|
|
235
|
+
private srj;
|
|
236
|
+
private layerNames;
|
|
237
|
+
private layerCount;
|
|
238
|
+
private bounds;
|
|
239
|
+
private options;
|
|
240
|
+
private boardVoidRects?;
|
|
241
|
+
private gridIndex;
|
|
242
|
+
private candidates;
|
|
243
|
+
private placed;
|
|
244
|
+
private placedIndexByLayer;
|
|
245
|
+
private hardPlacedByLayer;
|
|
246
|
+
private expansionIndex;
|
|
247
|
+
private edgeAnalysisDone;
|
|
248
|
+
private totalSeedsThisGrid;
|
|
249
|
+
private consumedSeedsThisGrid;
|
|
250
|
+
constructor(input: RectDiffSeedingSolverInput);
|
|
251
|
+
_setup(): void;
|
|
252
|
+
/** Exactly ONE grid candidate step per call. */
|
|
253
|
+
_step(): void;
|
|
254
|
+
/**
|
|
255
|
+
* One micro-step during the GRID phase: handle exactly one candidate.
|
|
256
|
+
*/
|
|
257
|
+
private _stepGrid;
|
|
258
|
+
/** Compute solver progress (0 to 1) during GRID phase. */
|
|
259
|
+
computeProgress(): number;
|
|
260
|
+
/**
|
|
261
|
+
* Output the intermediate RectDiff engine data to feed into the
|
|
262
|
+
* expansion phase solver.
|
|
263
|
+
*/
|
|
264
|
+
getOutput(): {
|
|
265
|
+
layerNames: string[];
|
|
266
|
+
layerCount: number;
|
|
267
|
+
bounds: XYRect;
|
|
268
|
+
options: Required<Omit<GridFill3DOptions, "gridSizes" | "maxMultiLayerSpan">> & {
|
|
269
|
+
gridSizes: number[];
|
|
270
|
+
maxMultiLayerSpan: number | undefined;
|
|
271
|
+
};
|
|
272
|
+
boardVoidRects: XYRect[] | undefined;
|
|
273
|
+
gridIndex: number;
|
|
274
|
+
candidates: Candidate3D[];
|
|
275
|
+
placed: Placed3D[];
|
|
276
|
+
expansionIndex: number;
|
|
277
|
+
edgeAnalysisDone: boolean;
|
|
278
|
+
totalSeedsThisGrid: number;
|
|
279
|
+
consumedSeedsThisGrid: number;
|
|
280
|
+
obstacles: Obstacle[];
|
|
281
|
+
obstacleClearance: number | undefined;
|
|
282
|
+
};
|
|
283
|
+
/** Visualization focused on the grid seeding phase. */
|
|
284
|
+
visualize(): GraphicsObject;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
type RectDiffExpansionSolverInput = {
|
|
288
|
+
layerNames: string[];
|
|
289
|
+
layerCount: number;
|
|
290
|
+
bounds: XYRect;
|
|
291
|
+
options: {
|
|
292
|
+
gridSizes: number[];
|
|
293
|
+
[key: string]: any;
|
|
294
|
+
};
|
|
295
|
+
boardVoidRects: XYRect[];
|
|
296
|
+
gridIndex: number;
|
|
297
|
+
candidates: Candidate3D[];
|
|
298
|
+
placed: Placed3D[];
|
|
299
|
+
expansionIndex: number;
|
|
300
|
+
edgeAnalysisDone: boolean;
|
|
301
|
+
totalSeedsThisGrid: number;
|
|
302
|
+
consumedSeedsThisGrid: number;
|
|
303
|
+
obstacleIndexByLayer: Array<RBush<RTreeRect>>;
|
|
304
|
+
zIndexByName: Map<string, number>;
|
|
305
|
+
layerNamesCanonical: string[];
|
|
306
|
+
obstacles: Obstacle[];
|
|
307
|
+
obstacleClearance?: number;
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Second phase of RectDiff: expand placed rects to their maximal extents.
|
|
311
|
+
*
|
|
312
|
+
* This solver takes the intermediate data produced by RectDiffSeedingSolver
|
|
313
|
+
* and runs the EXPANSION phase, then finalizes to capacity mesh nodes.
|
|
314
|
+
*/
|
|
315
|
+
declare class RectDiffExpansionSolver extends BaseSolver {
|
|
316
|
+
private input;
|
|
317
|
+
placedIndexByLayer: Array<RBush<RTreeRect>>;
|
|
318
|
+
_meshNodes: CapacityMeshNode[];
|
|
319
|
+
constructor(input: RectDiffExpansionSolverInput);
|
|
320
|
+
_setup(): void;
|
|
321
|
+
_step(): void;
|
|
322
|
+
private _stepExpansion;
|
|
323
|
+
private finalizeIfNeeded;
|
|
324
|
+
computeProgress(): number;
|
|
325
|
+
getOutput(): {
|
|
326
|
+
meshNodes: CapacityMeshNode[];
|
|
327
|
+
};
|
|
328
|
+
/** Simple visualization of expanded placements. */
|
|
329
|
+
visualize(): GraphicsObject;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
type RectDiffGridSolverPipelineInput = {
|
|
333
|
+
bounds: Bounds;
|
|
334
|
+
obstacles: Obstacle[];
|
|
335
|
+
connections: SimpleRouteConnection[];
|
|
336
|
+
outline?: Pick<SimpleRouteJson, "outline">;
|
|
337
|
+
layerCount: number;
|
|
338
|
+
minTraceWidth: number;
|
|
339
|
+
obstacleClearance?: number;
|
|
340
|
+
gridOptions?: Partial<GridFill3DOptions>;
|
|
341
|
+
boardVoidRects?: XYRect[];
|
|
342
|
+
layerNames?: string[];
|
|
343
|
+
zIndexByName?: Map<string, number>;
|
|
344
|
+
};
|
|
345
|
+
declare class RectDiffGridSolverPipeline extends BasePipelineSolver<RectDiffGridSolverPipelineInput> {
|
|
346
|
+
rectDiffSeedingSolver?: RectDiffSeedingSolver;
|
|
347
|
+
rectDiffExpansionSolver?: RectDiffExpansionSolver;
|
|
348
|
+
private obstacleIndexByLayer;
|
|
349
|
+
private layerNames;
|
|
350
|
+
private zIndexByName;
|
|
351
|
+
constructor(inputProblem: RectDiffGridSolverPipelineInput);
|
|
352
|
+
pipelineDef: PipelineStep<any>[];
|
|
353
|
+
getConstructorParams(): RectDiffGridSolverPipelineInput[];
|
|
354
|
+
getOutput(): {
|
|
355
|
+
meshNodes: CapacityMeshNode[];
|
|
356
|
+
};
|
|
357
|
+
visualize(): GraphicsObject;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
interface RectDiffPipelineInput {
|
|
361
|
+
simpleRouteJson: SimpleRouteJson;
|
|
362
|
+
gridOptions?: Partial<GridFill3DOptions>;
|
|
363
|
+
obstacleClearance?: number;
|
|
364
|
+
}
|
|
365
|
+
declare class RectDiffPipeline extends BasePipelineSolver<RectDiffPipelineInput> {
|
|
366
|
+
rectDiffGridSolverPipeline?: RectDiffGridSolverPipeline;
|
|
367
|
+
gapFillSolver?: GapFillSolverPipeline;
|
|
368
|
+
boardVoidRects: XYRect[] | undefined;
|
|
369
|
+
zIndexByName?: Map<string, number>;
|
|
370
|
+
layerNames?: string[];
|
|
371
|
+
pipelineDef: PipelineStep<any>[];
|
|
372
|
+
_setup(): void;
|
|
373
|
+
getConstructorParams(): RectDiffPipelineInput[];
|
|
374
|
+
getOutput(): {
|
|
375
|
+
meshNodes: CapacityMeshNode[];
|
|
376
|
+
};
|
|
377
|
+
initialVisualize(): GraphicsObject;
|
|
378
|
+
finalVisualize(): GraphicsObject;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export { RectDiffPipeline, type RectDiffPipelineInput };
|