@tscircuit/schematic-trace-solver 0.0.136 → 0.0.140
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/.github/workflows/bun-pver-release.yml +7 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +333 -45
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationObstacleIndex.ts +182 -0
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +67 -25
- package/lib/solvers/AvailableNetOrientationSolver/constants.ts +2 -0
- package/lib/solvers/Example28Solver/labelMovement.ts +71 -0
- package/lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts +5 -2
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +93 -14
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +12 -4
- package/package.json +5 -1
- package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +4 -4
- package/tests/bug-reports/bug-report-20260721T221026Z/bug-report-20260721T221026Z.test.ts +11 -0
- package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +3 -3
- package/tests/bug-reports/bug-report-20260815T073240Z/bug-report-20260815T073240Z.test.ts +39 -0
- package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +237 -0
- package/tests/bug-reports/bug-report-20260819T091818Z/bug-report-20260819T091818Z.json +1052 -0
- package/tests/bug-reports/bug-report-20260819T091818Z/bug-report-20260819T091818Z.test.ts +33 -0
- package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +4 -4
- package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +124 -0
- package/tests/repros/assets/repro-board-648-esp12f-section.input.json +537 -0
- package/tests/repros/repro-board-589-regulator-section.test.ts +23 -1
- package/tests/repros/repro-board-648-esp12f-section.test.ts +13 -0
- package/tests/repros/repro161-power-section-autolayout.test.ts +7 -0
- package/tests/solvers/AvailableNetOrientationSolver/AvailableNetOrientationObstacleIndex.test.ts +122 -0
|
@@ -7,6 +7,10 @@ on:
|
|
|
7
7
|
paths:
|
|
8
8
|
- 'lib/**'
|
|
9
9
|
workflow_dispatch:
|
|
10
|
+
permissions:
|
|
11
|
+
contents: write
|
|
12
|
+
id-token: write
|
|
13
|
+
pull-requests: write
|
|
10
14
|
jobs:
|
|
11
15
|
publish:
|
|
12
16
|
runs-on: ubuntu-latest
|
|
@@ -18,14 +22,14 @@ jobs:
|
|
|
18
22
|
uses: oven-sh/setup-bun@v2
|
|
19
23
|
with:
|
|
20
24
|
bun-version: 1.3.1
|
|
21
|
-
- uses: actions/setup-node@
|
|
25
|
+
- uses: actions/setup-node@v6
|
|
22
26
|
with:
|
|
23
|
-
node-version:
|
|
27
|
+
node-version: 24
|
|
24
28
|
registry-url: https://registry.npmjs.org/
|
|
29
|
+
package-manager-cache: false
|
|
25
30
|
- run: npm install -g pver
|
|
26
31
|
- run: bun install --frozen-lockfile
|
|
27
32
|
- run: bun run build
|
|
28
33
|
- run: pver release
|
|
29
34
|
env:
|
|
30
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
31
35
|
GITHUB_TOKEN: ${{ secrets.TSCIRCUIT_BOT_GITHUB_TOKEN }}
|
package/dist/index.d.ts
CHANGED
|
@@ -787,6 +787,7 @@ declare class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
787
787
|
private chipObstacleSpatialIndex;
|
|
788
788
|
private maxSearchDistance;
|
|
789
789
|
private pinMap;
|
|
790
|
+
private obstacleIndex;
|
|
790
791
|
constructor(params: AvailableNetOrientationSolverParams);
|
|
791
792
|
getConstructorParams(): ConstructorParameters<typeof AvailableNetOrientationSolver>[0];
|
|
792
793
|
_step(): void;
|
|
@@ -824,6 +825,7 @@ declare class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
824
825
|
private findValidLateralShiftedCandidate;
|
|
825
826
|
private findValidCandidateInShiftColumn;
|
|
826
827
|
private evaluateCandidate;
|
|
828
|
+
private recordCandidateResult;
|
|
827
829
|
private getCandidateConnectorTrace;
|
|
828
830
|
private isStandaloneSinglePinNetLabel;
|
|
829
831
|
private labelIntersectsDifferentNetTrace;
|
|
@@ -1117,6 +1119,7 @@ interface SameNetJunctionAlignmentSolverInput {
|
|
|
1117
1119
|
declare class SameNetJunctionAlignmentSolver extends BaseSolver {
|
|
1118
1120
|
private input;
|
|
1119
1121
|
outputTraces: SolvedTracePath[];
|
|
1122
|
+
outputNetLabelPlacements: NetLabelPlacement[];
|
|
1120
1123
|
constructor(input: SameNetJunctionAlignmentSolverInput);
|
|
1121
1124
|
_step(): void;
|
|
1122
1125
|
getOutput(): {
|
package/dist/index.js
CHANGED
|
@@ -7159,6 +7159,65 @@ var moveAttachedLabelsToReroutedTrace = ({
|
|
|
7159
7159
|
}
|
|
7160
7160
|
};
|
|
7161
7161
|
});
|
|
7162
|
+
var moveNetLabelConnectorsToReroutedTraces = ({
|
|
7163
|
+
originalTraces,
|
|
7164
|
+
reroutedTraces,
|
|
7165
|
+
netLabelPlacements
|
|
7166
|
+
}) => {
|
|
7167
|
+
const traces = [...reroutedTraces];
|
|
7168
|
+
const reroutedTraceMap = new Map(
|
|
7169
|
+
reroutedTraces.map((trace) => [trace.mspPairId, trace])
|
|
7170
|
+
);
|
|
7171
|
+
const labels = netLabelPlacements.map((label) => {
|
|
7172
|
+
const originalHostTrace = originalTraces.find((trace) => {
|
|
7173
|
+
if (!label.mspConnectionPairIds.includes(trace.mspPairId)) return false;
|
|
7174
|
+
const reroutedTrace = reroutedTraceMap.get(trace.mspPairId);
|
|
7175
|
+
if (!reroutedTrace) return false;
|
|
7176
|
+
return reroutedTrace.tracePath !== trace.tracePath;
|
|
7177
|
+
});
|
|
7178
|
+
if (!originalHostTrace) return label;
|
|
7179
|
+
const reroutedHostTrace = reroutedTraceMap.get(originalHostTrace.mspPairId);
|
|
7180
|
+
const connectorIndex = originalTraces.findIndex((trace) => {
|
|
7181
|
+
if (trace.mspPairId === originalHostTrace.mspPairId) return false;
|
|
7182
|
+
if (trace.globalConnNetId !== label.globalConnNetId) return false;
|
|
7183
|
+
if (!tracePathContainsPoint(trace.tracePath, label.anchorPoint)) {
|
|
7184
|
+
return false;
|
|
7185
|
+
}
|
|
7186
|
+
return label.pinIds.every((pinId) => trace.pinIds.includes(pinId));
|
|
7187
|
+
});
|
|
7188
|
+
if (connectorIndex < 0) return label;
|
|
7189
|
+
const connector = originalTraces[connectorIndex];
|
|
7190
|
+
const originalJunction = connector.tracePath.find(
|
|
7191
|
+
(point) => tracePathContainsPoint(originalHostTrace.tracePath, point)
|
|
7192
|
+
);
|
|
7193
|
+
if (!originalJunction) return label;
|
|
7194
|
+
const reroutedJunction = getMovedAnchorPointForReroute(
|
|
7195
|
+
originalJunction,
|
|
7196
|
+
originalHostTrace.tracePath,
|
|
7197
|
+
reroutedHostTrace.tracePath
|
|
7198
|
+
);
|
|
7199
|
+
if (!reroutedJunction) return label;
|
|
7200
|
+
const delta = {
|
|
7201
|
+
x: reroutedJunction.x - originalJunction.x,
|
|
7202
|
+
y: reroutedJunction.y - originalJunction.y
|
|
7203
|
+
};
|
|
7204
|
+
const movedConnector = {
|
|
7205
|
+
...connector,
|
|
7206
|
+
tracePath: connector.tracePath.map((point) => ({
|
|
7207
|
+
x: point.x + delta.x,
|
|
7208
|
+
y: point.y + delta.y
|
|
7209
|
+
}))
|
|
7210
|
+
};
|
|
7211
|
+
traces[connectorIndex] = movedConnector;
|
|
7212
|
+
return moveAttachedLabelsToReroutedTrace({
|
|
7213
|
+
trace: connector,
|
|
7214
|
+
originalTracePath: connector.tracePath,
|
|
7215
|
+
reroutedTracePath: movedConnector.tracePath,
|
|
7216
|
+
netLabelPlacements: [label]
|
|
7217
|
+
})[0];
|
|
7218
|
+
});
|
|
7219
|
+
return { traces, netLabelPlacements: labels };
|
|
7220
|
+
};
|
|
7162
7221
|
|
|
7163
7222
|
// lib/solvers/Example28Solver/doesPathRunAlongChipBoundary.ts
|
|
7164
7223
|
var doesPathRunAlongChipBoundary = (path, chipObstacles) => {
|
|
@@ -7951,6 +8010,7 @@ var createPortOnlyLabelConnectorTrace = ({
|
|
|
7951
8010
|
|
|
7952
8011
|
// lib/solvers/AvailableNetOrientationSolver/constants.ts
|
|
7953
8012
|
var LABEL_SEARCH_STEP = 0.05;
|
|
8013
|
+
var MAX_RECORDED_CANDIDATES = 2e3;
|
|
7954
8014
|
var WICK_CLEARANCE = 1e-3;
|
|
7955
8015
|
var EPS12 = 1e-9;
|
|
7956
8016
|
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS12;
|
|
@@ -8007,14 +8067,6 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
8007
8067
|
}
|
|
8008
8068
|
return false;
|
|
8009
8069
|
};
|
|
8010
|
-
var tracePathCrossesAnyBounds = (tracePath, bounds) => {
|
|
8011
|
-
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
8012
|
-
if (segmentCrossesBoundsInterior(tracePath[i], tracePath[i + 1], bounds)) {
|
|
8013
|
-
return true;
|
|
8014
|
-
}
|
|
8015
|
-
}
|
|
8016
|
-
return false;
|
|
8017
|
-
};
|
|
8018
8070
|
var tracePathIntersectsBounds = (tracePath, bounds) => {
|
|
8019
8071
|
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
8020
8072
|
if (segmentIntersectsRect2(tracePath[i], tracePath[i + 1], bounds)) {
|
|
@@ -8184,6 +8236,145 @@ var ensureGraphicsArrays = (graphics) => {
|
|
|
8184
8236
|
if (!graphics.texts) graphics.texts = [];
|
|
8185
8237
|
};
|
|
8186
8238
|
|
|
8239
|
+
// lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationObstacleIndex.ts
|
|
8240
|
+
import Flatbush2 from "flatbush";
|
|
8241
|
+
var AvailableNetOrientationObstacleIndex = class {
|
|
8242
|
+
chipObstacleSpatialIndex;
|
|
8243
|
+
labelIndex = null;
|
|
8244
|
+
traceSegmentIndex = null;
|
|
8245
|
+
traceSegments = [];
|
|
8246
|
+
constructor(params) {
|
|
8247
|
+
this.chipObstacleSpatialIndex = params.chipObstacleSpatialIndex;
|
|
8248
|
+
this.rebuild(params);
|
|
8249
|
+
}
|
|
8250
|
+
rebuild(params) {
|
|
8251
|
+
this.labelIndex = this.buildLabelIndex(params.netLabelPlacements);
|
|
8252
|
+
this.traceSegments = this.getTraceSegments(params.traces);
|
|
8253
|
+
this.traceSegmentIndex = this.buildTraceSegmentIndex(this.traceSegments);
|
|
8254
|
+
}
|
|
8255
|
+
getLabelIndicesInBounds(bounds) {
|
|
8256
|
+
if (!this.labelIndex) return [];
|
|
8257
|
+
return this.labelIndex.search(
|
|
8258
|
+
bounds.minX,
|
|
8259
|
+
bounds.minY,
|
|
8260
|
+
bounds.maxX,
|
|
8261
|
+
bounds.maxY
|
|
8262
|
+
);
|
|
8263
|
+
}
|
|
8264
|
+
getTraceSegmentsInBounds(bounds) {
|
|
8265
|
+
if (!this.traceSegmentIndex) return [];
|
|
8266
|
+
const searchBounds = getPaddedBounds(bounds, EPS12);
|
|
8267
|
+
return this.traceSegmentIndex.search(
|
|
8268
|
+
searchBounds.minX,
|
|
8269
|
+
searchBounds.minY,
|
|
8270
|
+
searchBounds.maxX,
|
|
8271
|
+
searchBounds.maxY
|
|
8272
|
+
).map((segmentIndex) => this.traceSegments[segmentIndex]);
|
|
8273
|
+
}
|
|
8274
|
+
getLabelIndicesNearTracePath(tracePath) {
|
|
8275
|
+
const labelIndices = /* @__PURE__ */ new Set();
|
|
8276
|
+
for (let pointIndex = 0; pointIndex < tracePath.length - 1; pointIndex++) {
|
|
8277
|
+
const segmentBounds = getPaddedBounds(
|
|
8278
|
+
getSegmentBounds(tracePath[pointIndex], tracePath[pointIndex + 1]),
|
|
8279
|
+
EPS12
|
|
8280
|
+
);
|
|
8281
|
+
for (const labelIndex of this.getLabelIndicesInBounds(segmentBounds)) {
|
|
8282
|
+
labelIndices.add(labelIndex);
|
|
8283
|
+
}
|
|
8284
|
+
}
|
|
8285
|
+
return [...labelIndices].sort((a, b) => a - b);
|
|
8286
|
+
}
|
|
8287
|
+
doesTracePathCrossChip(tracePath) {
|
|
8288
|
+
for (let pointIndex = 0; pointIndex < tracePath.length - 1; pointIndex++) {
|
|
8289
|
+
const start = tracePath[pointIndex];
|
|
8290
|
+
const end = tracePath[pointIndex + 1];
|
|
8291
|
+
const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(
|
|
8292
|
+
getPaddedBounds(getSegmentBounds(start, end), EPS12)
|
|
8293
|
+
);
|
|
8294
|
+
for (const chip of nearbyChips) {
|
|
8295
|
+
if (segmentCrossesBoundsInterior(start, end, chip.bounds)) return true;
|
|
8296
|
+
}
|
|
8297
|
+
}
|
|
8298
|
+
return false;
|
|
8299
|
+
}
|
|
8300
|
+
doesTraceCrossBoundsInterior(bounds) {
|
|
8301
|
+
for (const segment of this.getTraceSegmentsInBounds(bounds)) {
|
|
8302
|
+
if (segmentCrossesBoundsInterior(segment.start, segment.end, bounds)) {
|
|
8303
|
+
return true;
|
|
8304
|
+
}
|
|
8305
|
+
}
|
|
8306
|
+
return false;
|
|
8307
|
+
}
|
|
8308
|
+
doesTraceIntersectBounds(params) {
|
|
8309
|
+
for (const segment of this.getTraceSegmentsInBounds(params.bounds)) {
|
|
8310
|
+
if (segment.trace.globalConnNetId === params.excludedGlobalConnNetId) {
|
|
8311
|
+
continue;
|
|
8312
|
+
}
|
|
8313
|
+
if (segmentIntersectsRect2(segment.start, segment.end, params.bounds)) {
|
|
8314
|
+
return true;
|
|
8315
|
+
}
|
|
8316
|
+
}
|
|
8317
|
+
return false;
|
|
8318
|
+
}
|
|
8319
|
+
buildLabelIndex(netLabelPlacements) {
|
|
8320
|
+
if (netLabelPlacements.length === 0) return null;
|
|
8321
|
+
const labelIndex = new Flatbush2(netLabelPlacements.length);
|
|
8322
|
+
for (const label of netLabelPlacements) {
|
|
8323
|
+
labelIndex.add(
|
|
8324
|
+
label.center.x - label.width / 2,
|
|
8325
|
+
label.center.y - label.height / 2,
|
|
8326
|
+
label.center.x + label.width / 2,
|
|
8327
|
+
label.center.y + label.height / 2
|
|
8328
|
+
);
|
|
8329
|
+
}
|
|
8330
|
+
labelIndex.finish();
|
|
8331
|
+
return labelIndex;
|
|
8332
|
+
}
|
|
8333
|
+
getTraceSegments(traces) {
|
|
8334
|
+
const traceSegments = [];
|
|
8335
|
+
for (const trace of traces) {
|
|
8336
|
+
for (let pointIndex = 0; pointIndex < trace.tracePath.length - 1; pointIndex++) {
|
|
8337
|
+
traceSegments.push({
|
|
8338
|
+
trace,
|
|
8339
|
+
start: trace.tracePath[pointIndex],
|
|
8340
|
+
end: trace.tracePath[pointIndex + 1]
|
|
8341
|
+
});
|
|
8342
|
+
}
|
|
8343
|
+
}
|
|
8344
|
+
return traceSegments;
|
|
8345
|
+
}
|
|
8346
|
+
buildTraceSegmentIndex(traceSegments) {
|
|
8347
|
+
if (traceSegments.length === 0) return null;
|
|
8348
|
+
const traceSegmentIndex = new Flatbush2(traceSegments.length);
|
|
8349
|
+
for (const segment of traceSegments) {
|
|
8350
|
+
traceSegmentIndex.add(
|
|
8351
|
+
Math.min(segment.start.x, segment.end.x),
|
|
8352
|
+
Math.min(segment.start.y, segment.end.y),
|
|
8353
|
+
Math.max(segment.start.x, segment.end.x),
|
|
8354
|
+
Math.max(segment.start.y, segment.end.y)
|
|
8355
|
+
);
|
|
8356
|
+
}
|
|
8357
|
+
traceSegmentIndex.finish();
|
|
8358
|
+
return traceSegmentIndex;
|
|
8359
|
+
}
|
|
8360
|
+
};
|
|
8361
|
+
function getSegmentBounds(start, end) {
|
|
8362
|
+
return {
|
|
8363
|
+
minX: Math.min(start.x, end.x),
|
|
8364
|
+
minY: Math.min(start.y, end.y),
|
|
8365
|
+
maxX: Math.max(start.x, end.x),
|
|
8366
|
+
maxY: Math.max(start.y, end.y)
|
|
8367
|
+
};
|
|
8368
|
+
}
|
|
8369
|
+
function getPaddedBounds(bounds, padding) {
|
|
8370
|
+
return {
|
|
8371
|
+
minX: bounds.minX - padding,
|
|
8372
|
+
minY: bounds.minY - padding,
|
|
8373
|
+
maxX: bounds.maxX + padding,
|
|
8374
|
+
maxY: bounds.maxY + padding
|
|
8375
|
+
};
|
|
8376
|
+
}
|
|
8377
|
+
|
|
8187
8378
|
// lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts
|
|
8188
8379
|
var LABEL_TRACE_CLEARANCE2 = 0.1;
|
|
8189
8380
|
var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
@@ -8202,6 +8393,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8202
8393
|
chipObstacleSpatialIndex;
|
|
8203
8394
|
maxSearchDistance;
|
|
8204
8395
|
pinMap;
|
|
8396
|
+
obstacleIndex;
|
|
8205
8397
|
constructor(params) {
|
|
8206
8398
|
super();
|
|
8207
8399
|
this.inputProblem = params.inputProblem;
|
|
@@ -8214,6 +8406,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8214
8406
|
this.pinMap = getPinMap(params.inputProblem);
|
|
8215
8407
|
this.chipObstacleSpatialIndex = params.inputProblem._chipObstacleSpatialIndex ?? new ChipObstacleSpatialIndex(params.inputProblem.chips);
|
|
8216
8408
|
this.maxSearchDistance = getMaxSearchDistance(params.inputProblem);
|
|
8409
|
+
this.obstacleIndex = new AvailableNetOrientationObstacleIndex({
|
|
8410
|
+
chipObstacleSpatialIndex: this.chipObstacleSpatialIndex,
|
|
8411
|
+
netLabelPlacements: this.outputNetLabelPlacements,
|
|
8412
|
+
traces: this.traces
|
|
8413
|
+
});
|
|
8217
8414
|
this.crowdedPortOnlyLabelIndices = this.getCrowdedPortOnlyLabelIndices();
|
|
8218
8415
|
this.queuedLabelIndices = this.getProcessableLabelIndices();
|
|
8219
8416
|
this.setCurrentLabel(this.queuedLabelIndices[0] ?? null);
|
|
@@ -8395,6 +8592,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8395
8592
|
...toNetLabelPlacementPatch(candidate)
|
|
8396
8593
|
};
|
|
8397
8594
|
this.addConnectorTrace(label, candidate, labelIndex);
|
|
8595
|
+
this.obstacleIndex.rebuild({
|
|
8596
|
+
netLabelPlacements: this.outputNetLabelPlacements,
|
|
8597
|
+
traces: this.traces
|
|
8598
|
+
});
|
|
8398
8599
|
}
|
|
8399
8600
|
addConnectorTrace(label, candidate, labelIndex) {
|
|
8400
8601
|
if (candidate.phase === "trace-anchor") return;
|
|
@@ -8557,7 +8758,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8557
8758
|
anchorY - label.anchorPoint.y,
|
|
8558
8759
|
anchorX - label.anchorPoint.x
|
|
8559
8760
|
);
|
|
8560
|
-
this.
|
|
8761
|
+
this.recordCandidateResult(result);
|
|
8561
8762
|
if (result.status !== "valid") continue;
|
|
8562
8763
|
result.selected = true;
|
|
8563
8764
|
return result;
|
|
@@ -8592,7 +8793,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8592
8793
|
labelIndex,
|
|
8593
8794
|
"rotate"
|
|
8594
8795
|
);
|
|
8595
|
-
this.
|
|
8796
|
+
this.recordCandidateResult(result);
|
|
8596
8797
|
if (result.status === "valid") {
|
|
8597
8798
|
result.selected = true;
|
|
8598
8799
|
return result;
|
|
@@ -8617,7 +8818,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8617
8818
|
labelIndex,
|
|
8618
8819
|
"trace-anchor"
|
|
8619
8820
|
);
|
|
8620
|
-
this.
|
|
8821
|
+
this.recordCandidateResult(result);
|
|
8621
8822
|
if (result.status === "valid") {
|
|
8622
8823
|
result.selected = true;
|
|
8623
8824
|
return result;
|
|
@@ -8654,7 +8855,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8654
8855
|
labelIndex,
|
|
8655
8856
|
"outward-trace-anchor"
|
|
8656
8857
|
);
|
|
8657
|
-
this.
|
|
8858
|
+
this.recordCandidateResult(preservedColumnResult);
|
|
8658
8859
|
if (preservedColumnResult.status === "valid") {
|
|
8659
8860
|
preservedColumnResult.selected = true;
|
|
8660
8861
|
return preservedColumnResult;
|
|
@@ -8682,7 +8883,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8682
8883
|
"outward-trace-anchor",
|
|
8683
8884
|
distance5
|
|
8684
8885
|
);
|
|
8685
|
-
this.
|
|
8886
|
+
this.recordCandidateResult(result);
|
|
8686
8887
|
if (result.status === "valid") {
|
|
8687
8888
|
result.selected = true;
|
|
8688
8889
|
return result;
|
|
@@ -8807,7 +9008,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8807
9008
|
distance5,
|
|
8808
9009
|
outwardDistance
|
|
8809
9010
|
);
|
|
8810
|
-
this.
|
|
9011
|
+
this.recordCandidateResult(result);
|
|
8811
9012
|
if (result.status === "valid") {
|
|
8812
9013
|
result.selected = true;
|
|
8813
9014
|
return result;
|
|
@@ -8831,6 +9032,18 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8831
9032
|
})
|
|
8832
9033
|
};
|
|
8833
9034
|
}
|
|
9035
|
+
recordCandidateResult(candidate) {
|
|
9036
|
+
this.stats.candidateEvaluations = (this.stats.candidateEvaluations ?? 0) + 1;
|
|
9037
|
+
if (this.currentCandidateResults.length < MAX_RECORDED_CANDIDATES) {
|
|
9038
|
+
this.currentCandidateResults.push(candidate);
|
|
9039
|
+
} else if (candidate.status === "valid") {
|
|
9040
|
+
this.currentCandidateResults[MAX_RECORDED_CANDIDATES - 1] = candidate;
|
|
9041
|
+
}
|
|
9042
|
+
this.stats.maxRecordedCandidates = Math.max(
|
|
9043
|
+
this.stats.maxRecordedCandidates ?? 0,
|
|
9044
|
+
this.currentCandidateResults.length
|
|
9045
|
+
);
|
|
9046
|
+
}
|
|
8834
9047
|
getCandidateConnectorTrace(label, candidate, labelIndex) {
|
|
8835
9048
|
if (this.crowdedPortOnlyLabelIndices.has(labelIndex) && this.getChipSideForPoint(label.anchorPoint) === "top" && isYOrientation(candidate.orientation)) {
|
|
8836
9049
|
return simplifyOrthogonalPath([
|
|
@@ -9070,12 +9283,12 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9070
9283
|
},
|
|
9071
9284
|
labelIndex
|
|
9072
9285
|
);
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
return "chip-collision";
|
|
9076
|
-
}
|
|
9286
|
+
if (this.obstacleIndex.doesTracePathCrossChip(connectorTrace)) {
|
|
9287
|
+
return "chip-collision";
|
|
9077
9288
|
}
|
|
9078
|
-
for (
|
|
9289
|
+
for (const i of this.obstacleIndex.getLabelIndicesNearTracePath(
|
|
9290
|
+
connectorTrace
|
|
9291
|
+
)) {
|
|
9079
9292
|
if (i === labelIndex) continue;
|
|
9080
9293
|
if (this.shouldIgnorePendingCrowdedLabel(labelIndex, i)) continue;
|
|
9081
9294
|
const otherLabel = this.outputNetLabelPlacements[i];
|
|
@@ -9117,7 +9330,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9117
9330
|
if (rectIntersectsAnyTextBox(bounds, this.inputProblem)) {
|
|
9118
9331
|
return "text-collision";
|
|
9119
9332
|
}
|
|
9120
|
-
if (
|
|
9333
|
+
if (this.obstacleIndex.doesTraceCrossBoundsInterior(bounds)) {
|
|
9121
9334
|
return "trace-collision";
|
|
9122
9335
|
}
|
|
9123
9336
|
if (this.isTraceTooCloseToLabel(bounds, label)) {
|
|
@@ -9131,13 +9344,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9131
9344
|
isTraceTooCloseToLabel(bounds, label) {
|
|
9132
9345
|
if (!this.shouldCheckTraceClearanceForLabel(label)) return false;
|
|
9133
9346
|
const clearanceBounds = this.getLabelTraceClearanceBounds(bounds);
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
}
|
|
9139
|
-
}
|
|
9140
|
-
return false;
|
|
9347
|
+
return this.obstacleIndex.doesTraceIntersectBounds({
|
|
9348
|
+
bounds: clearanceBounds,
|
|
9349
|
+
excludedGlobalConnNetId: label.globalConnNetId
|
|
9350
|
+
});
|
|
9141
9351
|
}
|
|
9142
9352
|
getLabelTraceClearanceBounds(bounds) {
|
|
9143
9353
|
return {
|
|
@@ -9220,7 +9430,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9220
9430
|
return this.crowdedPortOnlyLabelIndices.has(labelIndex) && this.crowdedPortOnlyLabelIndices.has(otherLabelIndex) && this.queuedLabelIndices.includes(otherLabelIndex);
|
|
9221
9431
|
}
|
|
9222
9432
|
intersectsAnyOtherNetLabel(bounds, labelIndex) {
|
|
9223
|
-
|
|
9433
|
+
const searchBounds = {
|
|
9434
|
+
minX: bounds.minX - LABEL_SEARCH_STEP,
|
|
9435
|
+
minY: bounds.minY - LABEL_SEARCH_STEP,
|
|
9436
|
+
maxX: bounds.maxX + LABEL_SEARCH_STEP,
|
|
9437
|
+
maxY: bounds.maxY + LABEL_SEARCH_STEP
|
|
9438
|
+
};
|
|
9439
|
+
const nearbyLabelIndices = this.obstacleIndex.getLabelIndicesInBounds(searchBounds).sort((a, b) => a - b);
|
|
9440
|
+
for (const i of nearbyLabelIndices) {
|
|
9224
9441
|
if (i === labelIndex) continue;
|
|
9225
9442
|
if (this.shouldIgnorePendingCrowdedLabel(labelIndex, i)) continue;
|
|
9226
9443
|
const label = this.outputNetLabelPlacements[i];
|
|
@@ -9234,7 +9451,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9234
9451
|
return false;
|
|
9235
9452
|
}
|
|
9236
9453
|
sharesChipBoundary(bounds) {
|
|
9237
|
-
|
|
9454
|
+
const boundarySearchBounds = {
|
|
9455
|
+
minX: bounds.minX - WICK_CLEARANCE - EPS12,
|
|
9456
|
+
minY: bounds.minY - WICK_CLEARANCE - EPS12,
|
|
9457
|
+
maxX: bounds.maxX + WICK_CLEARANCE + EPS12,
|
|
9458
|
+
maxY: bounds.maxY + WICK_CLEARANCE + EPS12
|
|
9459
|
+
};
|
|
9460
|
+
const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(boundarySearchBounds);
|
|
9461
|
+
for (const chip of nearbyChips) {
|
|
9238
9462
|
const chipBounds = chip.bounds;
|
|
9239
9463
|
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS12 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS12;
|
|
9240
9464
|
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS12 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS12;
|
|
@@ -11749,6 +11973,35 @@ var railIsOnFacingSide = ({
|
|
|
11749
11973
|
if (pin._facingDirection === "y+") return railY > pin.y;
|
|
11750
11974
|
return false;
|
|
11751
11975
|
};
|
|
11976
|
+
var getAttachedLabelIndexes = (trace, netLabelPlacements) => netLabelPlacements.flatMap((label, index) => {
|
|
11977
|
+
const labelOwnsTrace = label.mspConnectionPairIds.includes(trace.mspPairId) || label.mspConnectionPairIds.length === 0 && label.globalConnNetId === trace.globalConnNetId;
|
|
11978
|
+
return labelOwnsTrace && tracePathContainsPoint(trace.tracePath, label.anchorPoint) ? [index] : [];
|
|
11979
|
+
});
|
|
11980
|
+
var moveAttachedLabels = ({
|
|
11981
|
+
trace,
|
|
11982
|
+
reroutedTracePath,
|
|
11983
|
+
netLabelPlacements,
|
|
11984
|
+
attachedLabelIndexes
|
|
11985
|
+
}) => {
|
|
11986
|
+
const attachedLabels = attachedLabelIndexes.map(
|
|
11987
|
+
(index) => netLabelPlacements[index]
|
|
11988
|
+
);
|
|
11989
|
+
const movedAttachedLabels = moveAttachedLabelsToReroutedTrace({
|
|
11990
|
+
trace,
|
|
11991
|
+
originalTracePath: trace.tracePath,
|
|
11992
|
+
reroutedTracePath,
|
|
11993
|
+
netLabelPlacements: attachedLabels
|
|
11994
|
+
});
|
|
11995
|
+
const movedLabelByIndex = new Map(
|
|
11996
|
+
attachedLabelIndexes.map((labelIndex, index) => [
|
|
11997
|
+
labelIndex,
|
|
11998
|
+
movedAttachedLabels[index]
|
|
11999
|
+
])
|
|
12000
|
+
);
|
|
12001
|
+
return netLabelPlacements.map(
|
|
12002
|
+
(label, index) => movedLabelByIndex.get(index) ?? label
|
|
12003
|
+
);
|
|
12004
|
+
};
|
|
11752
12005
|
var getAlignedBranchPath = ({
|
|
11753
12006
|
donorTrace,
|
|
11754
12007
|
branchTrace
|
|
@@ -11789,7 +12042,8 @@ var candidateIsClear = ({
|
|
|
11789
12042
|
originalTrace,
|
|
11790
12043
|
traces,
|
|
11791
12044
|
inputProblem,
|
|
11792
|
-
|
|
12045
|
+
candidateNetLabelPlacements,
|
|
12046
|
+
attachedLabelIndexes
|
|
11793
12047
|
}) => {
|
|
11794
12048
|
const obstacles = getObstacleRects(inputProblem);
|
|
11795
12049
|
if (isPathCollidingWithObstacles(candidateTrace.tracePath, obstacles)) {
|
|
@@ -11801,14 +12055,15 @@ var candidateIsClear = ({
|
|
|
11801
12055
|
if (doesPathCoincideWithTraces(candidateTrace.tracePath, otherNetTraces)) {
|
|
11802
12056
|
return false;
|
|
11803
12057
|
}
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
12058
|
+
if (!attachedLabelIndexes.every(
|
|
12059
|
+
(index) => tracePathContainsPoint(
|
|
12060
|
+
candidateTrace.tracePath,
|
|
12061
|
+
candidateNetLabelPlacements[index].anchorPoint
|
|
12062
|
+
)
|
|
12063
|
+
)) {
|
|
11809
12064
|
return false;
|
|
11810
12065
|
}
|
|
11811
|
-
const otherNetLabelPlacements =
|
|
12066
|
+
const otherNetLabelPlacements = candidateNetLabelPlacements.filter(
|
|
11812
12067
|
(label) => label.globalConnNetId !== candidateTrace.globalConnNetId
|
|
11813
12068
|
);
|
|
11814
12069
|
if (pathIntersectsAnyNetLabel({
|
|
@@ -11817,7 +12072,7 @@ var candidateIsClear = ({
|
|
|
11817
12072
|
})) {
|
|
11818
12073
|
return false;
|
|
11819
12074
|
}
|
|
11820
|
-
const sameNetLabelPlacements =
|
|
12075
|
+
const sameNetLabelPlacements = candidateNetLabelPlacements.filter(
|
|
11821
12076
|
(label) => label.globalConnNetId === candidateTrace.globalConnNetId
|
|
11822
12077
|
);
|
|
11823
12078
|
if (!pathIntersectsAnyNetLabel({
|
|
@@ -11843,9 +12098,14 @@ var alignSameNetJunctions = ({
|
|
|
11843
12098
|
netLabelPlacements
|
|
11844
12099
|
}) => {
|
|
11845
12100
|
let outputTraces = [...traces];
|
|
12101
|
+
let outputNetLabelPlacements = [...netLabelPlacements];
|
|
11846
12102
|
const alignedBranchTraceIds = /* @__PURE__ */ new Set();
|
|
11847
12103
|
let alignedJunctionCount = 0;
|
|
11848
|
-
|
|
12104
|
+
const donorTraceIds = traces.map((trace) => trace.mspPairId);
|
|
12105
|
+
const pendingDonorTraceIds = new Set(donorTraceIds);
|
|
12106
|
+
for (let donorIndex = 0; donorIndex < donorTraceIds.length; donorIndex++) {
|
|
12107
|
+
const donorTraceId = donorTraceIds[donorIndex];
|
|
12108
|
+
pendingDonorTraceIds.delete(donorTraceId);
|
|
11849
12109
|
const donorTrace = outputTraces.find(
|
|
11850
12110
|
(trace) => trace.mspPairId === donorTraceId
|
|
11851
12111
|
);
|
|
@@ -11866,12 +12126,23 @@ var alignSameNetJunctions = ({
|
|
|
11866
12126
|
if (!removesVisibleSegment && !shortensVisibleTrace) {
|
|
11867
12127
|
continue;
|
|
11868
12128
|
}
|
|
12129
|
+
const attachedLabelIndexes = getAttachedLabelIndexes(
|
|
12130
|
+
branchTrace,
|
|
12131
|
+
outputNetLabelPlacements
|
|
12132
|
+
);
|
|
12133
|
+
const candidateNetLabelPlacements = moveAttachedLabels({
|
|
12134
|
+
trace: branchTrace,
|
|
12135
|
+
reroutedTracePath: candidatePath,
|
|
12136
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
12137
|
+
attachedLabelIndexes
|
|
12138
|
+
});
|
|
11869
12139
|
if (!candidateIsClear({
|
|
11870
12140
|
candidateTrace,
|
|
11871
12141
|
originalTrace: branchTrace,
|
|
11872
12142
|
traces: outputTraces,
|
|
11873
12143
|
inputProblem,
|
|
11874
|
-
|
|
12144
|
+
candidateNetLabelPlacements,
|
|
12145
|
+
attachedLabelIndexes
|
|
11875
12146
|
})) {
|
|
11876
12147
|
continue;
|
|
11877
12148
|
}
|
|
@@ -11879,32 +12150,44 @@ var alignSameNetJunctions = ({
|
|
|
11879
12150
|
if (trace.mspPairId === branchTrace.mspPairId) return candidateTrace;
|
|
11880
12151
|
return trace;
|
|
11881
12152
|
});
|
|
12153
|
+
outputNetLabelPlacements = candidateNetLabelPlacements;
|
|
11882
12154
|
alignedBranchTraceIds.add(branchTrace.mspPairId);
|
|
11883
12155
|
alignedJunctionCount++;
|
|
12156
|
+
if (!pendingDonorTraceIds.has(branchTrace.mspPairId)) {
|
|
12157
|
+
donorTraceIds.push(branchTrace.mspPairId);
|
|
12158
|
+
pendingDonorTraceIds.add(branchTrace.mspPairId);
|
|
12159
|
+
}
|
|
11884
12160
|
}
|
|
11885
12161
|
}
|
|
11886
|
-
return {
|
|
12162
|
+
return {
|
|
12163
|
+
traces: outputTraces,
|
|
12164
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
12165
|
+
alignedJunctionCount
|
|
12166
|
+
};
|
|
11887
12167
|
};
|
|
11888
12168
|
|
|
11889
12169
|
// lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts
|
|
11890
12170
|
var SameNetJunctionAlignmentSolver = class extends BaseSolver {
|
|
11891
12171
|
input;
|
|
11892
12172
|
outputTraces;
|
|
12173
|
+
outputNetLabelPlacements;
|
|
11893
12174
|
constructor(input) {
|
|
11894
12175
|
super();
|
|
11895
12176
|
this.input = input;
|
|
11896
12177
|
this.outputTraces = input.traces;
|
|
12178
|
+
this.outputNetLabelPlacements = input.netLabelPlacements;
|
|
11897
12179
|
}
|
|
11898
12180
|
_step() {
|
|
11899
12181
|
const result = alignSameNetJunctions(this.input);
|
|
11900
12182
|
this.outputTraces = result.traces;
|
|
12183
|
+
this.outputNetLabelPlacements = result.netLabelPlacements;
|
|
11901
12184
|
this.stats.alignedJunctionCount = result.alignedJunctionCount;
|
|
11902
12185
|
this.solved = true;
|
|
11903
12186
|
}
|
|
11904
12187
|
getOutput() {
|
|
11905
12188
|
return {
|
|
11906
12189
|
traces: this.outputTraces,
|
|
11907
|
-
netLabelPlacements: this.
|
|
12190
|
+
netLabelPlacements: this.outputNetLabelPlacements
|
|
11908
12191
|
};
|
|
11909
12192
|
}
|
|
11910
12193
|
visualize() {
|
|
@@ -11918,7 +12201,7 @@ var SameNetJunctionAlignmentSolver = class extends BaseSolver {
|
|
|
11918
12201
|
strokeColor: "purple"
|
|
11919
12202
|
});
|
|
11920
12203
|
}
|
|
11921
|
-
for (const label of this.
|
|
12204
|
+
for (const label of this.outputNetLabelPlacements) {
|
|
11922
12205
|
const labelRect = {
|
|
11923
12206
|
center: label.center,
|
|
11924
12207
|
width: label.width,
|
|
@@ -12904,11 +13187,16 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
12904
13187
|
(instance) => {
|
|
12905
13188
|
const previousOutput = instance.preAlignmentNetLabelTraceCollisionSolver.getOutput();
|
|
12906
13189
|
const alignmentOutput = instance.traceCleanupSolver2.getOutput();
|
|
13190
|
+
const connectorMovement = moveNetLabelConnectorsToReroutedTraces({
|
|
13191
|
+
originalTraces: previousOutput.traces,
|
|
13192
|
+
reroutedTraces: alignmentOutput.traces,
|
|
13193
|
+
netLabelPlacements: previousOutput.netLabelPlacements
|
|
13194
|
+
});
|
|
12907
13195
|
const previousTraceMap = new Map(
|
|
12908
13196
|
previousOutput.traces.map((trace) => [trace.mspPairId, trace])
|
|
12909
13197
|
);
|
|
12910
|
-
let netLabelPlacements =
|
|
12911
|
-
for (const trace of
|
|
13198
|
+
let netLabelPlacements = connectorMovement.netLabelPlacements;
|
|
13199
|
+
for (const trace of connectorMovement.traces) {
|
|
12912
13200
|
const previousTrace = previousTraceMap.get(trace.mspPairId);
|
|
12913
13201
|
if (!previousTrace || previousTrace.tracePath === trace.tracePath) {
|
|
12914
13202
|
continue;
|
|
@@ -12928,7 +13216,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
12928
13216
|
return [
|
|
12929
13217
|
{
|
|
12930
13218
|
inputProblem: instance.inputProblem,
|
|
12931
|
-
traces:
|
|
13219
|
+
traces: connectorMovement.traces,
|
|
12932
13220
|
netLabelPlacements
|
|
12933
13221
|
}
|
|
12934
13222
|
];
|