@tscircuit/schematic-trace-solver 0.0.156 → 0.0.158
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 +2 -0
- package/dist/index.js +151 -57
- package/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +10 -2
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +196 -67
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260826T072956Z.page.tsx +4 -0
- package/site/components/PipelineDebugger.tsx +4 -2
- package/site/examples/example51.page.tsx +3 -1
- package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T020342Z/__snapshots__/bug-report-20260707T020342Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T134722Z/__snapshots__/bug-report-20260707T134722Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T141421Z/__snapshots__/bug-report-20260707T141421Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260708T053736Z/__snapshots__/bug-report-20260708T053736Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260708T055430Z/__snapshots__/bug-report-20260708T055430Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260716T144856Z/__snapshots__/bug-report-20260716T144856Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260717T022934Z/__snapshots__/bug-report-20260717T022934Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260717T031704Z/__snapshots__/bug-report-20260717T031704Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260724T175257Z/__snapshots__/bug-report-20260724T175257Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260728T144234Z/__snapshots__/bug-report-20260728T144234Z.snap.svg +4 -4
- package/tests/bug-reports/bug-report-20260728T225606Z/__snapshots__/bug-report-20260728T225606Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260731T052229Z/__snapshots__/bug-report-20260731T052229Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260804T095800Z/__snapshots__/bug-report-20260804T095800Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260804T225912Z/__snapshots__/bug-report-20260804T225912Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260811T075142Z/__snapshots__/bug-report-20260811T075142Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +4 -4
- package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +842 -0
- package/tests/bug-reports/bug-report-20260826T072956Z/bug-report-20260826T072956Z.json +2452 -0
- package/tests/bug-reports/bug-report-20260826T072956Z/bug-report-20260826T072956Z.test.ts +12 -0
- package/tests/examples/__snapshots__/example01.snap.svg +2 -2
- package/tests/examples/__snapshots__/example02.snap.svg +12 -12
- package/tests/examples/__snapshots__/example03.snap.svg +2 -2
- package/tests/examples/__snapshots__/example04.snap.svg +2 -2
- package/tests/examples/__snapshots__/example05.snap.svg +2 -2
- package/tests/examples/__snapshots__/example06.snap.svg +2 -2
- package/tests/examples/__snapshots__/example07.snap.svg +2 -2
- package/tests/examples/__snapshots__/example08.snap.svg +2 -2
- package/tests/examples/__snapshots__/example09.snap.svg +2 -2
- package/tests/examples/__snapshots__/example10.snap.svg +2 -2
- package/tests/examples/__snapshots__/example11.snap.svg +2 -2
- package/tests/examples/__snapshots__/example12.snap.svg +2 -2
- package/tests/examples/__snapshots__/example13.snap.svg +2 -2
- package/tests/examples/__snapshots__/example14.snap.svg +2 -2
- package/tests/examples/__snapshots__/example15.snap.svg +2 -2
- package/tests/examples/__snapshots__/example16.snap.svg +2 -2
- package/tests/examples/__snapshots__/example17.snap.svg +2 -2
- package/tests/examples/__snapshots__/example18.snap.svg +2 -2
- package/tests/examples/__snapshots__/example19.snap.svg +2 -2
- package/tests/examples/__snapshots__/example20.snap.svg +2 -2
- package/tests/examples/__snapshots__/example21.snap.svg +2 -2
- package/tests/examples/__snapshots__/example22.snap.svg +2 -2
- package/tests/examples/__snapshots__/example23.snap.svg +2 -2
- package/tests/examples/__snapshots__/example24.snap.svg +2 -2
- package/tests/examples/__snapshots__/example25.snap.svg +2 -2
- package/tests/examples/__snapshots__/example26.snap.svg +2 -2
- package/tests/examples/__snapshots__/example27.snap.svg +2 -2
- package/tests/examples/__snapshots__/example28.snap.svg +2 -2
- package/tests/examples/__snapshots__/example29.snap.svg +2 -2
- package/tests/examples/__snapshots__/example30.snap.svg +2 -2
- package/tests/examples/__snapshots__/example31.snap.svg +2 -2
- package/tests/examples/__snapshots__/example32.snap.svg +2 -2
- package/tests/examples/__snapshots__/example33.snap.svg +2 -2
- package/tests/examples/__snapshots__/example34.snap.svg +2 -2
- package/tests/examples/__snapshots__/example35.snap.svg +2 -2
- package/tests/examples/__snapshots__/example36.snap.svg +2 -2
- package/tests/examples/__snapshots__/example37.snap.svg +2 -2
- package/tests/examples/__snapshots__/example38.snap.svg +2 -2
- package/tests/examples/__snapshots__/example39.snap.svg +2 -2
- package/tests/examples/__snapshots__/example40.snap.svg +2 -2
- package/tests/examples/__snapshots__/example41.snap.svg +2 -2
- package/tests/examples/__snapshots__/example42.snap.svg +2 -2
- package/tests/examples/__snapshots__/example43.snap.svg +2 -2
- package/tests/examples/__snapshots__/example44.snap.svg +2 -2
- package/tests/examples/__snapshots__/example45.snap.svg +2 -2
- package/tests/examples/__snapshots__/example46.snap.svg +2 -2
- package/tests/examples/__snapshots__/example47.snap.svg +2 -2
- package/tests/examples/__snapshots__/example48.snap.svg +2 -2
- package/tests/examples/__snapshots__/example49.snap.svg +2 -2
- package/tests/examples/__snapshots__/example50.snap.svg +2 -2
- package/tests/examples/__snapshots__/example51.snap.svg +4 -4
- package/tests/fixtures/matcher.ts +3 -3
- package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +73 -82
- package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +12 -12
- package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +5 -5
- package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/manufacturePartNumber-text-box.snap.svg +2 -2
- package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-atmega328p-fault-pullup.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-atmega328p-missing-gnd-netlabel.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bq24074-battery-charger.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-core-555-power-cross-net-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-core-subcircuit-missing-ground.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-core-tb67s579ftg-inline-label-routing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-dc-power-isolated-routing.snap.svg +129 -0
- package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ground-label-on-lower-rail-end.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ina237-current-monitor.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-missing-trace-netlabel.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-mspm0l1306-capacitor-symmetry.snap.svg +182 -0
- package/tests/repros/__snapshots__/repro-netlabel-collision-687.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-netlabel-overlap-trace.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-nrf52810-clock-routing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-pga300-c6-trace-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-pga300-redundant-ground-traces.snap.svg +288 -0
- package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +1290 -0
- package/tests/repros/__snapshots__/repro-power-group-rail-labels.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rectifier-trace-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rp2040-usb-cc2-ground-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rp2040-v3v3-label-placement.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rp2040-zero-crystal-fallback-netlabels.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +4 -4
- package/tests/repros/__snapshots__/repro-tida00553-j4-cell-divider.snap.svg +130 -0
- package/tests/repros/__snapshots__/repro-tida010076-j4-ground-bus.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +4 -4
- package/tests/repros/__snapshots__/repro-type-c-16pin-self-connection.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-type-c-16pin-to-resistor.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-type-c-vbus-led-ground-label.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +12 -12
- package/tests/repros/__snapshots__/repro-vcc-pin1-detour.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro129-host-custom-symbol-passives.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +4 -4
- package/tests/repros/__snapshots__/repro47-endpoint-obstacle-detour.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro5-escape-padded-text-obstacles.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro51-overlap-junction-crossing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro84-stacked-gnd-label-orientation.snap.svg +2 -2
- package/tests/repros/__snapshots__/small-variant-resistor-facing-direction.snap.svg +2 -2
- package/tests/repros/__snapshots__/trace-overlap-box-resistor.snap.svg +2 -2
- package/tests/repros/assets/repro-dc-power-isolated-routing.input.json +193 -0
- package/tests/repros/assets/repro-mspm0l1306-capacitor-symmetry.input.json +537 -0
- package/tests/repros/assets/repro-pga300-redundant-ground-traces.input.json +858 -0
- package/tests/repros/assets/repro-pmp11282-isolated-dcdc.input.json +4570 -0
- package/tests/repros/board-1273-trace-overlap-cycle.test.ts +1 -1
- package/tests/repros/repro-dc-power-isolated-routing.test.ts +13 -0
- package/tests/repros/repro-mspm0l1306-capacitor-symmetry.test.ts +54 -0
- package/tests/repros/repro-pga300-redundant-ground-traces.test.ts +33 -0
- package/tests/repros/repro-pmp11282-isolated-dcdc.test.ts +77 -0
- package/tests/repros/repro-tida00553-j4-cell-divider.test.ts +111 -0
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/anchored-net-label-width.snap.svg +2 -2
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-anchored-label-clearance.snap.svg +2 -2
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-port-stub.snap.svg +2 -2
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-two-pin-net.snap.svg +2 -2
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label01.snap.svg +2 -2
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label02.snap.svg +2 -2
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/terminal-stub-trace-clearance.snap.svg +2 -2
- package/tests/solvers/SameNetJunctionAlignmentSolver/parallel-load-rails.test.ts +291 -0
- package/tests/solvers/SchematicTraceSingleLineSolver2/__snapshots__/SchematicTraceSingleLineSolver2_01-example17-d1_1-u1_1.snap.svg +2 -2
- package/tests/solvers/SchematicTraceSingleLineSolver2/__snapshots__/SchematicTraceSingleLineSolver2_repro47-short-opposing-pins.snap.svg +2 -2
- package/tests/solvers/TraceCleanupSolver/__snapshots__/TraceCleanupSolver.snap.svg +2 -2
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/__snapshots__/TraceLabelOverlapAvoidanceSolver.snap.svg +2 -2
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/MergedNetLabelObstacles.snap.svg +2 -2
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/OverlapAvoidanceStepSolver.snap.svg +2 -2
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/SingleOverlapSolver.snap.svg +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -191,6 +191,7 @@ type MspConnectionPair = {
|
|
|
191
191
|
declare class MspConnectionPairSolver extends BaseSolver {
|
|
192
192
|
inputProblem: InputProblem;
|
|
193
193
|
mspConnectionPairs: MspConnectionPair[];
|
|
194
|
+
mspConnectionPairIds: Set<string>;
|
|
194
195
|
dcConnMap: ConnectivityMap;
|
|
195
196
|
globalConnMap: ConnectivityMap;
|
|
196
197
|
queuedDcNetIds: string[];
|
|
@@ -205,6 +206,7 @@ declare class MspConnectionPairSolver extends BaseSolver {
|
|
|
205
206
|
inputProblem: InputProblem;
|
|
206
207
|
});
|
|
207
208
|
getConstructorParams(): ConstructorParameters<typeof MspConnectionPairSolver>[0];
|
|
209
|
+
private addMspConnectionPair;
|
|
208
210
|
_step(): void;
|
|
209
211
|
visualize(): GraphicsObject;
|
|
210
212
|
}
|
package/dist/index.js
CHANGED
|
@@ -503,6 +503,7 @@ var getPinPairKey = (pinIds) => [...pinIds].sort().join("::");
|
|
|
503
503
|
var MspConnectionPairSolver = class extends BaseSolver {
|
|
504
504
|
inputProblem;
|
|
505
505
|
mspConnectionPairs = [];
|
|
506
|
+
mspConnectionPairIds = /* @__PURE__ */ new Set();
|
|
506
507
|
dcConnMap;
|
|
507
508
|
globalConnMap;
|
|
508
509
|
queuedDcNetIds;
|
|
@@ -550,6 +551,11 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
550
551
|
inputProblem: this.inputProblem
|
|
551
552
|
};
|
|
552
553
|
}
|
|
554
|
+
addMspConnectionPair(pair) {
|
|
555
|
+
if (this.mspConnectionPairIds.has(pair.mspPairId)) return;
|
|
556
|
+
this.mspConnectionPairIds.add(pair.mspPairId);
|
|
557
|
+
this.mspConnectionPairs.push(pair);
|
|
558
|
+
}
|
|
553
559
|
_step() {
|
|
554
560
|
if (this.queuedDcNetIds.length === 0) {
|
|
555
561
|
this.solved = true;
|
|
@@ -594,7 +600,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
594
600
|
const globalConnNetId = this.globalConnMap.getNetConnectedToId(pin1);
|
|
595
601
|
const userNetId = this.userNetIdByPinId[pin1] ?? this.userNetIdByPinId[pin2];
|
|
596
602
|
const suppressNetLabel = pairDistance > this.maxMspPairDistance && labeledConnectionRouteReason === "overlapping-fallback-labels";
|
|
597
|
-
this.
|
|
603
|
+
this.addMspConnectionPair({
|
|
598
604
|
mspPairId: `${pin1}-${pin2}`,
|
|
599
605
|
dcConnNetId: dcNetId,
|
|
600
606
|
globalConnNetId,
|
|
@@ -639,7 +645,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
639
645
|
}
|
|
640
646
|
const globalConnNetId = this.globalConnMap.getNetConnectedToId(pin1);
|
|
641
647
|
const userNetId = this.userNetIdByPinId[pin1] ?? this.userNetIdByPinId[pin2];
|
|
642
|
-
this.
|
|
648
|
+
this.addMspConnectionPair({
|
|
643
649
|
mspPairId: `${pin1}-${pin2}`,
|
|
644
650
|
dcConnNetId: dcNetId,
|
|
645
651
|
globalConnNetId,
|
|
@@ -12316,6 +12322,9 @@ var UnroutedTraceRecoverySolver = class extends BaseSolver {
|
|
|
12316
12322
|
}
|
|
12317
12323
|
};
|
|
12318
12324
|
|
|
12325
|
+
// lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
|
|
12326
|
+
import { getSegmentIntersection as getSegmentIntersection3 } from "@tscircuit/math-utils/line-intersections";
|
|
12327
|
+
|
|
12319
12328
|
// lib/solvers/SameNetJunctionAlignmentSolver/pathIntersectsAnyNetLabel.ts
|
|
12320
12329
|
var NET_LABEL_INTERIOR_INSET = 1e-6;
|
|
12321
12330
|
var pathIntersectsAnyNetLabel = ({
|
|
@@ -12357,6 +12366,7 @@ var pathEntersAnyNetLabel = ({
|
|
|
12357
12366
|
var MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2;
|
|
12358
12367
|
var MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2;
|
|
12359
12368
|
var MAX_SHARED_PIN_RAIL_OFFSET = 0.05;
|
|
12369
|
+
var MIN_RETURN_STEM_LENGTH = 0.05;
|
|
12360
12370
|
var getSharedPin = ({
|
|
12361
12371
|
donorTrace,
|
|
12362
12372
|
branchTrace
|
|
@@ -12394,6 +12404,7 @@ var railIsOnFacingSide = ({
|
|
|
12394
12404
|
pin
|
|
12395
12405
|
}) => {
|
|
12396
12406
|
if (pin._facingDirection === "y+") return railY > pin.y;
|
|
12407
|
+
if (pin._facingDirection === "y-") return railY < pin.y;
|
|
12397
12408
|
return false;
|
|
12398
12409
|
};
|
|
12399
12410
|
var railIsOnSharedPinFacingSide = ({
|
|
@@ -12526,6 +12537,27 @@ var candidateIsClear = ({
|
|
|
12526
12537
|
if (doesPathCoincideWithTraces(candidateTrace.tracePath, otherNetTraces)) {
|
|
12527
12538
|
return false;
|
|
12528
12539
|
}
|
|
12540
|
+
for (const otherTrace of otherNetTraces) {
|
|
12541
|
+
const countIntersections = (path) => {
|
|
12542
|
+
const intersections = /* @__PURE__ */ new Set();
|
|
12543
|
+
for (let i = 1; i < path.length; i++) {
|
|
12544
|
+
for (let j = 1; j < otherTrace.tracePath.length; j++) {
|
|
12545
|
+
const point = getSegmentIntersection3(
|
|
12546
|
+
path[i - 1],
|
|
12547
|
+
path[i],
|
|
12548
|
+
otherTrace.tracePath[j - 1],
|
|
12549
|
+
otherTrace.tracePath[j]
|
|
12550
|
+
);
|
|
12551
|
+
if (point)
|
|
12552
|
+
intersections.add(`${point.x.toFixed(6)},${point.y.toFixed(6)}`);
|
|
12553
|
+
}
|
|
12554
|
+
}
|
|
12555
|
+
return intersections.size;
|
|
12556
|
+
};
|
|
12557
|
+
if (countIntersections(candidateTrace.tracePath) > countIntersections(originalTrace.tracePath)) {
|
|
12558
|
+
return false;
|
|
12559
|
+
}
|
|
12560
|
+
}
|
|
12529
12561
|
if (!attachedLabelIndexes.every(
|
|
12530
12562
|
(index) => tracePathContainsPoint(
|
|
12531
12563
|
candidateTrace.tracePath,
|
|
@@ -12563,6 +12595,57 @@ var candidateIsClear = ({
|
|
|
12563
12595
|
if (!originalRail || !candidateRail) return false;
|
|
12564
12596
|
return Math.abs(originalRail.start.y - candidateRail.start.y) <= MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET;
|
|
12565
12597
|
};
|
|
12598
|
+
var getAlignedReturnBranchPath = ({
|
|
12599
|
+
donorTrace,
|
|
12600
|
+
branchTrace,
|
|
12601
|
+
returnStemScale = 1
|
|
12602
|
+
}) => {
|
|
12603
|
+
const sharedPin = getSharedPin({ donorTrace, branchTrace });
|
|
12604
|
+
if (!sharedPin) return null;
|
|
12605
|
+
const railPin = getOtherPin({ trace: donorTrace, sharedPin });
|
|
12606
|
+
const returnPin = getOtherPin({ trace: branchTrace, sharedPin });
|
|
12607
|
+
if (!railPin || !returnPin) return null;
|
|
12608
|
+
const facing = sharedPin._facingDirection;
|
|
12609
|
+
if (facing !== "y+" && facing !== "y-") return null;
|
|
12610
|
+
if (railPin._facingDirection !== facing || returnPin._facingDirection !== facing)
|
|
12611
|
+
return null;
|
|
12612
|
+
if (!nearlyEqual(sharedPin.y, railPin.y)) return null;
|
|
12613
|
+
const donorPath = simplifyPath(donorTrace.tracePath);
|
|
12614
|
+
if (donorPath.length !== 4) return null;
|
|
12615
|
+
const rail = getLongestHorizontalSegment(donorTrace);
|
|
12616
|
+
if (!rail || !railIsOnFacingSide({ railY: rail.start.y, pin: sharedPin }))
|
|
12617
|
+
return null;
|
|
12618
|
+
if (!isVertical2(donorPath[0], donorPath[1]) || !isVertical2(donorPath[2], donorPath[3]))
|
|
12619
|
+
return null;
|
|
12620
|
+
const sharedFirst = branchTrace.pins[0].pinId === sharedPin.pinId;
|
|
12621
|
+
const path = simplifyPath(
|
|
12622
|
+
sharedFirst ? branchTrace.tracePath : [...branchTrace.tracePath].reverse()
|
|
12623
|
+
);
|
|
12624
|
+
if (path.length !== 6) return null;
|
|
12625
|
+
if (!isVertical2(path[0], path[1]) || !isHorizontal2(path[1], path[2]) || !isVertical2(path[2], path[3]) || !isHorizontal2(path[3], path[4]) || !isVertical2(path[4], path[5]))
|
|
12626
|
+
return null;
|
|
12627
|
+
if (!railIsOnFacingSide({ railY: path[1].y, pin: sharedPin }) || !railIsOnFacingSide({ railY: path[4].y, pin: returnPin }))
|
|
12628
|
+
return null;
|
|
12629
|
+
const direction = facing === "y+" ? 1 : -1;
|
|
12630
|
+
if (direction * (returnPin.y - rail.start.y) <= 0) return null;
|
|
12631
|
+
const minX = Math.min(sharedPin.x, railPin.x);
|
|
12632
|
+
const maxX = Math.max(sharedPin.x, railPin.x);
|
|
12633
|
+
if (path[2].x < minX || path[2].x > maxX) return null;
|
|
12634
|
+
if (nearlyEqual(path[2].x, railPin.x) && nearlyEqual(path[1].y, rail.start.y))
|
|
12635
|
+
return null;
|
|
12636
|
+
const returnRailY = returnPin.y + (path[4].y - returnPin.y) * returnStemScale;
|
|
12637
|
+
if (Math.abs(returnRailY - returnPin.y) < MIN_RETURN_STEM_LENGTH - 1e-6)
|
|
12638
|
+
return null;
|
|
12639
|
+
const candidate = simplifyPath([
|
|
12640
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
12641
|
+
{ x: sharedPin.x, y: rail.start.y },
|
|
12642
|
+
{ x: railPin.x, y: rail.start.y },
|
|
12643
|
+
{ x: railPin.x, y: returnRailY },
|
|
12644
|
+
{ x: returnPin.x, y: returnRailY },
|
|
12645
|
+
{ x: returnPin.x, y: returnPin.y }
|
|
12646
|
+
]);
|
|
12647
|
+
return sharedFirst ? candidate : candidate.reverse();
|
|
12648
|
+
};
|
|
12566
12649
|
var alignSameNetJunctions = ({
|
|
12567
12650
|
inputProblem,
|
|
12568
12651
|
traces,
|
|
@@ -12570,63 +12653,74 @@ var alignSameNetJunctions = ({
|
|
|
12570
12653
|
}) => {
|
|
12571
12654
|
let outputTraces = [...traces];
|
|
12572
12655
|
let outputNetLabelPlacements = [...netLabelPlacements];
|
|
12573
|
-
const alignedBranchTraceIds = /* @__PURE__ */ new Set();
|
|
12574
12656
|
let alignedJunctionCount = 0;
|
|
12575
|
-
const
|
|
12576
|
-
|
|
12577
|
-
|
|
12578
|
-
const
|
|
12579
|
-
|
|
12580
|
-
|
|
12581
|
-
(
|
|
12582
|
-
|
|
12583
|
-
|
|
12584
|
-
if (alignedBranchTraceIds.has(branchTrace.mspPairId)) continue;
|
|
12585
|
-
if (donorTrace.mspPairId === branchTrace.mspPairId) continue;
|
|
12586
|
-
if (donorTrace.globalConnNetId !== branchTrace.globalConnNetId) continue;
|
|
12587
|
-
const candidatePath = getAlignedBranchPath({ donorTrace, branchTrace });
|
|
12588
|
-
if (!candidatePath) continue;
|
|
12589
|
-
const candidateTrace = { ...branchTrace, tracePath: candidatePath };
|
|
12590
|
-
const originalPair = [donorTrace, branchTrace];
|
|
12591
|
-
const candidatePair = [donorTrace, candidateTrace];
|
|
12592
|
-
const removesVisibleSegment = getVisibleTraceSegmentCount(candidatePair) < getVisibleTraceSegmentCount(originalPair);
|
|
12593
|
-
const shortensVisibleTrace = getVisibleTraceLength(candidatePair) < getVisibleTraceLength(originalPair) && !nearlyEqual(
|
|
12594
|
-
getVisibleTraceLength(candidatePair),
|
|
12595
|
-
getVisibleTraceLength(originalPair)
|
|
12596
|
-
);
|
|
12597
|
-
if (!removesVisibleSegment && !shortensVisibleTrace) {
|
|
12598
|
-
continue;
|
|
12599
|
-
}
|
|
12600
|
-
const attachedLabelIndexes = getAttachedLabelIndexes(
|
|
12601
|
-
branchTrace,
|
|
12602
|
-
outputNetLabelPlacements
|
|
12657
|
+
for (const alignReturnBranches of [false, true]) {
|
|
12658
|
+
const alignedBranchTraceIds = /* @__PURE__ */ new Set();
|
|
12659
|
+
const donorTraceIds = traces.map((trace) => trace.mspPairId);
|
|
12660
|
+
const pendingDonorTraceIds = new Set(donorTraceIds);
|
|
12661
|
+
for (let donorIndex = 0; donorIndex < donorTraceIds.length; donorIndex++) {
|
|
12662
|
+
const donorTraceId = donorTraceIds[donorIndex];
|
|
12663
|
+
pendingDonorTraceIds.delete(donorTraceId);
|
|
12664
|
+
const donorTrace = outputTraces.find(
|
|
12665
|
+
(trace) => trace.mspPairId === donorTraceId
|
|
12603
12666
|
);
|
|
12604
|
-
const
|
|
12605
|
-
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
-
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
|
|
12628
|
-
|
|
12629
|
-
|
|
12667
|
+
for (const branchTrace of outputTraces) {
|
|
12668
|
+
if (alignedBranchTraceIds.has(branchTrace.mspPairId)) continue;
|
|
12669
|
+
if (donorTrace.mspPairId === branchTrace.mspPairId) continue;
|
|
12670
|
+
if (donorTrace.globalConnNetId !== branchTrace.globalConnNetId) continue;
|
|
12671
|
+
const candidatePaths = alignReturnBranches ? [1, 0.5, 0.25].map(
|
|
12672
|
+
(returnStemScale) => getAlignedReturnBranchPath({
|
|
12673
|
+
donorTrace,
|
|
12674
|
+
branchTrace,
|
|
12675
|
+
returnStemScale
|
|
12676
|
+
})
|
|
12677
|
+
) : [getAlignedBranchPath({ donorTrace, branchTrace })];
|
|
12678
|
+
for (const candidatePath of candidatePaths) {
|
|
12679
|
+
if (!candidatePath) continue;
|
|
12680
|
+
const candidateTrace = { ...branchTrace, tracePath: candidatePath };
|
|
12681
|
+
const originalPair = [donorTrace, branchTrace];
|
|
12682
|
+
const candidatePair = [donorTrace, candidateTrace];
|
|
12683
|
+
const removesVisibleSegment = getVisibleTraceSegmentCount(candidatePair) < getVisibleTraceSegmentCount(originalPair);
|
|
12684
|
+
const shortensVisibleTrace = getVisibleTraceLength(candidatePair) < getVisibleTraceLength(originalPair) && !nearlyEqual(
|
|
12685
|
+
getVisibleTraceLength(candidatePair),
|
|
12686
|
+
getVisibleTraceLength(originalPair)
|
|
12687
|
+
);
|
|
12688
|
+
if (!removesVisibleSegment && !shortensVisibleTrace) {
|
|
12689
|
+
continue;
|
|
12690
|
+
}
|
|
12691
|
+
const attachedLabelIndexes = getAttachedLabelIndexes(
|
|
12692
|
+
branchTrace,
|
|
12693
|
+
outputNetLabelPlacements
|
|
12694
|
+
);
|
|
12695
|
+
const candidateNetLabelPlacements = moveAttachedLabels({
|
|
12696
|
+
trace: branchTrace,
|
|
12697
|
+
reroutedTracePath: candidatePath,
|
|
12698
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
12699
|
+
attachedLabelIndexes
|
|
12700
|
+
});
|
|
12701
|
+
if (!candidateIsClear({
|
|
12702
|
+
candidateTrace,
|
|
12703
|
+
originalTrace: branchTrace,
|
|
12704
|
+
traces: outputTraces,
|
|
12705
|
+
inputProblem,
|
|
12706
|
+
candidateNetLabelPlacements,
|
|
12707
|
+
attachedLabelIndexes
|
|
12708
|
+
})) {
|
|
12709
|
+
continue;
|
|
12710
|
+
}
|
|
12711
|
+
outputTraces = outputTraces.map((trace) => {
|
|
12712
|
+
if (trace.mspPairId === branchTrace.mspPairId) return candidateTrace;
|
|
12713
|
+
return trace;
|
|
12714
|
+
});
|
|
12715
|
+
outputNetLabelPlacements = candidateNetLabelPlacements;
|
|
12716
|
+
alignedBranchTraceIds.add(branchTrace.mspPairId);
|
|
12717
|
+
alignedJunctionCount++;
|
|
12718
|
+
if (!pendingDonorTraceIds.has(branchTrace.mspPairId)) {
|
|
12719
|
+
donorTraceIds.push(branchTrace.mspPairId);
|
|
12720
|
+
pendingDonorTraceIds.add(branchTrace.mspPairId);
|
|
12721
|
+
}
|
|
12722
|
+
break;
|
|
12723
|
+
}
|
|
12630
12724
|
}
|
|
12631
12725
|
}
|
|
12632
12726
|
}
|
|
@@ -35,6 +35,7 @@ export class MspConnectionPairSolver extends BaseSolver {
|
|
|
35
35
|
inputProblem: InputProblem
|
|
36
36
|
|
|
37
37
|
mspConnectionPairs: MspConnectionPair[] = []
|
|
38
|
+
mspConnectionPairIds = new Set<MspConnectionPairId>()
|
|
38
39
|
dcConnMap: ConnectivityMap
|
|
39
40
|
globalConnMap: ConnectivityMap
|
|
40
41
|
queuedDcNetIds: string[]
|
|
@@ -97,6 +98,13 @@ export class MspConnectionPairSolver extends BaseSolver {
|
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
private addMspConnectionPair(pair: MspConnectionPair) {
|
|
102
|
+
if (this.mspConnectionPairIds.has(pair.mspPairId)) return
|
|
103
|
+
|
|
104
|
+
this.mspConnectionPairIds.add(pair.mspPairId)
|
|
105
|
+
this.mspConnectionPairs.push(pair)
|
|
106
|
+
}
|
|
107
|
+
|
|
100
108
|
override _step() {
|
|
101
109
|
if (this.queuedDcNetIds.length === 0) {
|
|
102
110
|
this.solved = true
|
|
@@ -164,7 +172,7 @@ export class MspConnectionPairSolver extends BaseSolver {
|
|
|
164
172
|
pairDistance > this.maxMspPairDistance &&
|
|
165
173
|
labeledConnectionRouteReason === "overlapping-fallback-labels"
|
|
166
174
|
|
|
167
|
-
this.
|
|
175
|
+
this.addMspConnectionPair({
|
|
168
176
|
mspPairId: `${pin1}-${pin2}`,
|
|
169
177
|
dcConnNetId: dcNetId,
|
|
170
178
|
globalConnNetId,
|
|
@@ -226,7 +234,7 @@ export class MspConnectionPairSolver extends BaseSolver {
|
|
|
226
234
|
const globalConnNetId = this.globalConnMap.getNetConnectedToId(pin1!)!
|
|
227
235
|
const userNetId =
|
|
228
236
|
this.userNetIdByPinId[pin1!] ?? this.userNetIdByPinId[pin2!]
|
|
229
|
-
this.
|
|
237
|
+
this.addMspConnectionPair({
|
|
230
238
|
mspPairId: `${pin1}-${pin2}`,
|
|
231
239
|
dcConnNetId: dcNetId,
|
|
232
240
|
globalConnNetId,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Point } from "@tscircuit/math-utils"
|
|
2
|
+
import { getSegmentIntersection } from "@tscircuit/math-utils/line-intersections"
|
|
2
3
|
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
3
4
|
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
4
5
|
import { isPathCollidingWithObstacles } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
getVisibleTraceLength,
|
|
11
12
|
getVisibleTraceSegmentCount,
|
|
12
13
|
isHorizontal,
|
|
14
|
+
isVertical,
|
|
13
15
|
nearlyEqual,
|
|
14
16
|
} from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
|
|
15
17
|
import type { InputPin, InputProblem } from "lib/types/InputProblem"
|
|
@@ -37,6 +39,7 @@ const MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2
|
|
|
37
39
|
// A shared vertical pin can anchor an existing rail when the rail is only a
|
|
38
40
|
// symbol-stem correction away from the pin itself.
|
|
39
41
|
const MAX_SHARED_PIN_RAIL_OFFSET = 0.05
|
|
42
|
+
const MIN_RETURN_STEM_LENGTH = 0.05
|
|
40
43
|
|
|
41
44
|
const getSharedPin = ({
|
|
42
45
|
donorTrace,
|
|
@@ -96,6 +99,7 @@ const railIsOnFacingSide = ({
|
|
|
96
99
|
pin: InputPin
|
|
97
100
|
}) => {
|
|
98
101
|
if (pin._facingDirection === "y+") return railY > pin.y
|
|
102
|
+
if (pin._facingDirection === "y-") return railY < pin.y
|
|
99
103
|
return false
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -287,6 +291,33 @@ const candidateIsClear = ({
|
|
|
287
291
|
return false
|
|
288
292
|
}
|
|
289
293
|
|
|
294
|
+
// Moving a junction must not introduce an extra crossing on another net,
|
|
295
|
+
// including single-segment traces and intersections at a bend.
|
|
296
|
+
for (const otherTrace of otherNetTraces) {
|
|
297
|
+
const countIntersections = (path: Point[]) => {
|
|
298
|
+
const intersections = new Set<string>()
|
|
299
|
+
for (let i = 1; i < path.length; i++) {
|
|
300
|
+
for (let j = 1; j < otherTrace.tracePath.length; j++) {
|
|
301
|
+
const point = getSegmentIntersection(
|
|
302
|
+
path[i - 1]!,
|
|
303
|
+
path[i]!,
|
|
304
|
+
otherTrace.tracePath[j - 1]!,
|
|
305
|
+
otherTrace.tracePath[j]!,
|
|
306
|
+
)
|
|
307
|
+
if (point)
|
|
308
|
+
intersections.add(`${point.x.toFixed(6)},${point.y.toFixed(6)}`)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return intersections.size
|
|
312
|
+
}
|
|
313
|
+
if (
|
|
314
|
+
countIntersections(candidateTrace.tracePath) >
|
|
315
|
+
countIntersections(originalTrace.tracePath)
|
|
316
|
+
) {
|
|
317
|
+
return false
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
290
321
|
if (
|
|
291
322
|
!attachedLabelIndexes.every((index) =>
|
|
292
323
|
tracePathContainsPoint(
|
|
@@ -340,6 +371,87 @@ const candidateIsClear = ({
|
|
|
340
371
|
)
|
|
341
372
|
}
|
|
342
373
|
|
|
374
|
+
/** Extend the outer load's stem instead of adding a return trunk between loads. */
|
|
375
|
+
const getAlignedReturnBranchPath = ({
|
|
376
|
+
donorTrace,
|
|
377
|
+
branchTrace,
|
|
378
|
+
returnStemScale = 1,
|
|
379
|
+
}: {
|
|
380
|
+
donorTrace: SolvedTracePath
|
|
381
|
+
branchTrace: SolvedTracePath
|
|
382
|
+
returnStemScale?: number
|
|
383
|
+
}): Point[] | null => {
|
|
384
|
+
const sharedPin = getSharedPin({ donorTrace, branchTrace })
|
|
385
|
+
if (!sharedPin) return null
|
|
386
|
+
const railPin = getOtherPin({ trace: donorTrace, sharedPin })
|
|
387
|
+
const returnPin = getOtherPin({ trace: branchTrace, sharedPin })
|
|
388
|
+
if (!railPin || !returnPin) return null
|
|
389
|
+
const facing = sharedPin._facingDirection
|
|
390
|
+
if (facing !== "y+" && facing !== "y-") return null
|
|
391
|
+
if (
|
|
392
|
+
railPin._facingDirection !== facing ||
|
|
393
|
+
returnPin._facingDirection !== facing
|
|
394
|
+
)
|
|
395
|
+
return null
|
|
396
|
+
if (!nearlyEqual(sharedPin.y, railPin.y)) return null
|
|
397
|
+
|
|
398
|
+
const donorPath = simplifyPath(donorTrace.tracePath)
|
|
399
|
+
if (donorPath.length !== 4) return null
|
|
400
|
+
const rail = getLongestHorizontalSegment(donorTrace)
|
|
401
|
+
if (!rail || !railIsOnFacingSide({ railY: rail.start.y, pin: sharedPin }))
|
|
402
|
+
return null
|
|
403
|
+
if (
|
|
404
|
+
!isVertical(donorPath[0]!, donorPath[1]!) ||
|
|
405
|
+
!isVertical(donorPath[2]!, donorPath[3]!)
|
|
406
|
+
)
|
|
407
|
+
return null
|
|
408
|
+
|
|
409
|
+
const sharedFirst = branchTrace.pins[0].pinId === sharedPin.pinId
|
|
410
|
+
const path = simplifyPath(
|
|
411
|
+
sharedFirst ? branchTrace.tracePath : [...branchTrace.tracePath].reverse(),
|
|
412
|
+
)
|
|
413
|
+
// A return branch leaves the shared stem, detours beside the loads, and
|
|
414
|
+
// approaches the remote parallel pin from its facing side.
|
|
415
|
+
if (path.length !== 6) return null
|
|
416
|
+
if (
|
|
417
|
+
!isVertical(path[0]!, path[1]!) ||
|
|
418
|
+
!isHorizontal(path[1]!, path[2]!) ||
|
|
419
|
+
!isVertical(path[2]!, path[3]!) ||
|
|
420
|
+
!isHorizontal(path[3]!, path[4]!) ||
|
|
421
|
+
!isVertical(path[4]!, path[5]!)
|
|
422
|
+
)
|
|
423
|
+
return null
|
|
424
|
+
if (
|
|
425
|
+
!railIsOnFacingSide({ railY: path[1]!.y, pin: sharedPin }) ||
|
|
426
|
+
!railIsOnFacingSide({ railY: path[4]!.y, pin: returnPin })
|
|
427
|
+
)
|
|
428
|
+
return null
|
|
429
|
+
const direction = facing === "y+" ? 1 : -1
|
|
430
|
+
if (direction * (returnPin.y - rail.start.y) <= 0) return null
|
|
431
|
+
|
|
432
|
+
const minX = Math.min(sharedPin.x, railPin.x)
|
|
433
|
+
const maxX = Math.max(sharedPin.x, railPin.x)
|
|
434
|
+
if (path[2]!.x < minX || path[2]!.x > maxX) return null
|
|
435
|
+
if (
|
|
436
|
+
nearlyEqual(path[2]!.x, railPin.x) &&
|
|
437
|
+
nearlyEqual(path[1]!.y, rail.start.y)
|
|
438
|
+
)
|
|
439
|
+
return null
|
|
440
|
+
|
|
441
|
+
const returnRailY = returnPin.y + (path[4]!.y - returnPin.y) * returnStemScale
|
|
442
|
+
if (Math.abs(returnRailY - returnPin.y) < MIN_RETURN_STEM_LENGTH - 1e-6)
|
|
443
|
+
return null
|
|
444
|
+
const candidate = simplifyPath([
|
|
445
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
446
|
+
{ x: sharedPin.x, y: rail.start.y },
|
|
447
|
+
{ x: railPin.x, y: rail.start.y },
|
|
448
|
+
{ x: railPin.x, y: returnRailY },
|
|
449
|
+
{ x: returnPin.x, y: returnRailY },
|
|
450
|
+
{ x: returnPin.x, y: returnPin.y },
|
|
451
|
+
])
|
|
452
|
+
return sharedFirst ? candidate : candidate.reverse()
|
|
453
|
+
}
|
|
454
|
+
|
|
343
455
|
export const alignSameNetJunctions = ({
|
|
344
456
|
inputProblem,
|
|
345
457
|
traces,
|
|
@@ -347,76 +459,93 @@ export const alignSameNetJunctions = ({
|
|
|
347
459
|
}: AlignSameNetJunctionsInput) => {
|
|
348
460
|
let outputTraces = [...traces]
|
|
349
461
|
let outputNetLabelPlacements = [...netLabelPlacements]
|
|
350
|
-
const alignedBranchTraceIds = new Set<string>()
|
|
351
462
|
let alignedJunctionCount = 0
|
|
352
463
|
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
464
|
+
// First level the load rails, then attach return branches to those final
|
|
465
|
+
// rails. Doing this in one pass could attach a branch to a rail that moves later.
|
|
466
|
+
for (const alignReturnBranches of [false, true]) {
|
|
467
|
+
const alignedBranchTraceIds = new Set<string>()
|
|
468
|
+
// Reuse each aligned branch as the rail for the next load in the chain. An
|
|
469
|
+
// aligned branch may already have had its donor turn, so queue it again when
|
|
470
|
+
// its geometry changes.
|
|
471
|
+
const donorTraceIds = traces.map((trace) => trace.mspPairId)
|
|
472
|
+
const pendingDonorTraceIds = new Set(donorTraceIds)
|
|
473
|
+
for (let donorIndex = 0; donorIndex < donorTraceIds.length; donorIndex++) {
|
|
474
|
+
const donorTraceId = donorTraceIds[donorIndex]!
|
|
475
|
+
pendingDonorTraceIds.delete(donorTraceId)
|
|
476
|
+
const donorTrace = outputTraces.find(
|
|
477
|
+
(trace) => trace.mspPairId === donorTraceId,
|
|
478
|
+
)!
|
|
479
|
+
for (const branchTrace of outputTraces) {
|
|
480
|
+
if (alignedBranchTraceIds.has(branchTrace.mspPairId)) continue
|
|
481
|
+
if (donorTrace.mspPairId === branchTrace.mspPairId) continue
|
|
482
|
+
if (donorTrace.globalConnNetId !== branchTrace.globalConnNetId) continue
|
|
483
|
+
|
|
484
|
+
// Prefer the existing return stem. If extending the outer column
|
|
485
|
+
// meets another net, try shorter escapes without moving any pins.
|
|
486
|
+
const candidatePaths = alignReturnBranches
|
|
487
|
+
? [1, 0.5, 0.25].map((returnStemScale) =>
|
|
488
|
+
getAlignedReturnBranchPath({
|
|
489
|
+
donorTrace,
|
|
490
|
+
branchTrace,
|
|
491
|
+
returnStemScale,
|
|
492
|
+
}),
|
|
493
|
+
)
|
|
494
|
+
: [getAlignedBranchPath({ donorTrace, branchTrace })]
|
|
495
|
+
for (const candidatePath of candidatePaths) {
|
|
496
|
+
if (!candidatePath) continue
|
|
497
|
+
const candidateTrace = { ...branchTrace, tracePath: candidatePath }
|
|
498
|
+
const originalPair = [donorTrace, branchTrace]
|
|
499
|
+
const candidatePair = [donorTrace, candidateTrace]
|
|
500
|
+
const removesVisibleSegment =
|
|
501
|
+
getVisibleTraceSegmentCount(candidatePair) <
|
|
502
|
+
getVisibleTraceSegmentCount(originalPair)
|
|
503
|
+
const shortensVisibleTrace =
|
|
504
|
+
getVisibleTraceLength(candidatePair) <
|
|
505
|
+
getVisibleTraceLength(originalPair) &&
|
|
506
|
+
!nearlyEqual(
|
|
507
|
+
getVisibleTraceLength(candidatePair),
|
|
508
|
+
getVisibleTraceLength(originalPair),
|
|
509
|
+
)
|
|
510
|
+
if (!removesVisibleSegment && !shortensVisibleTrace) {
|
|
511
|
+
continue
|
|
512
|
+
}
|
|
513
|
+
const attachedLabelIndexes = getAttachedLabelIndexes(
|
|
514
|
+
branchTrace,
|
|
515
|
+
outputNetLabelPlacements,
|
|
516
|
+
)
|
|
517
|
+
const candidateNetLabelPlacements = moveAttachedLabels({
|
|
518
|
+
trace: branchTrace,
|
|
519
|
+
reroutedTracePath: candidatePath,
|
|
520
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
521
|
+
attachedLabelIndexes,
|
|
522
|
+
})
|
|
523
|
+
if (
|
|
524
|
+
!candidateIsClear({
|
|
525
|
+
candidateTrace,
|
|
526
|
+
originalTrace: branchTrace,
|
|
527
|
+
traces: outputTraces,
|
|
528
|
+
inputProblem,
|
|
529
|
+
candidateNetLabelPlacements,
|
|
530
|
+
attachedLabelIndexes,
|
|
531
|
+
})
|
|
532
|
+
) {
|
|
533
|
+
continue
|
|
534
|
+
}
|
|
409
535
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
536
|
+
outputTraces = outputTraces.map((trace) => {
|
|
537
|
+
if (trace.mspPairId === branchTrace.mspPairId) return candidateTrace
|
|
538
|
+
return trace
|
|
539
|
+
})
|
|
540
|
+
outputNetLabelPlacements = candidateNetLabelPlacements
|
|
541
|
+
alignedBranchTraceIds.add(branchTrace.mspPairId)
|
|
542
|
+
alignedJunctionCount++
|
|
543
|
+
if (!pendingDonorTraceIds.has(branchTrace.mspPairId)) {
|
|
544
|
+
donorTraceIds.push(branchTrace.mspPairId)
|
|
545
|
+
pendingDonorTraceIds.add(branchTrace.mspPairId)
|
|
546
|
+
}
|
|
547
|
+
break
|
|
548
|
+
}
|
|
420
549
|
}
|
|
421
550
|
}
|
|
422
551
|
}
|
package/package.json
CHANGED