@tscircuit/schematic-trace-solver 0.0.158 → 0.0.160
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 +41 -9
- package/dist/index.js +762 -110
- package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +536 -94
- package/lib/solvers/InlineNetLabelSolver/pushAnchoredNetLabelsAwayFromInlineLabels.ts +9 -7
- package/lib/solvers/InlineNetLabelSolver/pushInlineTerminalLabelsAwayFromAnchoredLabels.ts +295 -0
- package/lib/solvers/LongDistancePairSolver/LongDistancePairSolver.ts +15 -8
- package/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +5 -0
- package/lib/solvers/MspConnectionPairSolver/getGroundConnectionPolicy.ts +83 -0
- package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +7 -35
- package/lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts +6 -1
- package/lib/solvers/SameNetJunctionAlignmentSolver/placeGroundRailLabelsAtOuterEnd.ts +122 -0
- package/lib/solvers/SchematicTraceLinesSolver/getTraceConnectedPinComponents.ts +60 -0
- package/lib/types/InputProblem.ts +5 -4
- package/package.json +1 -1
- package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +600 -783
- package/tests/bug-reports/bug-report-20260826T072956Z/bug-report-20260826T072956Z.test.ts +66 -1
- package/tests/fixtures/parallel-ground-rail.ts +53 -0
- package/tests/repros/__snapshots__/repro-mspm0l1306-capacitor-symmetry.snap.svg +34 -16
- package/tests/repros/repro-mspm0l1306-capacitor-symmetry.test.ts +40 -7
- package/tests/repros/repro-usb-power-vbus-label-detour.test.ts +14 -0
- package/tests/solvers/InlineNetLabelSolver/multi-pin-connected-components.test.ts +252 -0
- package/tests/solvers/InlineNetLabelSolver/opposite-side-placement.test.ts +71 -0
- package/tests/solvers/InlineNetLabelSolver/push-anchored-net-labels-away.test.ts +8 -2
- package/tests/solvers/InlineNetLabelSolver/push-inline-terminal-labels-away.test.ts +91 -0
- package/tests/solvers/InlineNetLabelSolver/two-pin-terminal-stubs-atomic.test.ts +7 -1
- package/tests/solvers/MspConnectionPairSolver/local-ground-branches.test.ts +105 -0
- package/tests/solvers/SameNetJunctionAlignmentSolver/ground-rail-label.test.ts +188 -0
package/dist/index.js
CHANGED
|
@@ -363,6 +363,48 @@ var getConnectivityMapsFromInputProblem = (inputProblem) => {
|
|
|
363
363
|
return { directConnMap, netConnMap };
|
|
364
364
|
};
|
|
365
365
|
|
|
366
|
+
// lib/solvers/MspConnectionPairSolver/getGroundConnectionPolicy.ts
|
|
367
|
+
import { ConnectivityMap as ConnectivityMap2 } from "connectivity-map";
|
|
368
|
+
var MAX_LOCAL_GROUND_BRANCH_OFFSET = 1;
|
|
369
|
+
var getGroundConnectionPolicy = (inputProblem) => {
|
|
370
|
+
const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
371
|
+
const groundNetId = netConnMap.getNetConnectedToId("GND");
|
|
372
|
+
if (!groundNetId) return () => true;
|
|
373
|
+
const physicalConnMap = new ConnectivityMap2({});
|
|
374
|
+
for (const connection of inputProblem.directConnections) {
|
|
375
|
+
physicalConnMap.addConnections([connection.pinIds]);
|
|
376
|
+
}
|
|
377
|
+
const pins = new Map(
|
|
378
|
+
inputProblem.chips.flatMap(
|
|
379
|
+
(chip) => chip.pins.map((pin) => [pin.pinId, { pin, chip }])
|
|
380
|
+
)
|
|
381
|
+
);
|
|
382
|
+
const groundFacingPins = [...pins.values()].filter(
|
|
383
|
+
({ pin, chip }) => chip.pins.length === 2 && netConnMap.getNetConnectedToId(pin.pinId) === groundNetId && (pin._facingDirection ?? getPinDirection(pin, chip)) === "y-"
|
|
384
|
+
);
|
|
385
|
+
const hasExplicitParallelGroundRail = groundFacingPins.some(({ pin: a }) => {
|
|
386
|
+
const group = physicalConnMap.getNetConnectedToId(a.pinId);
|
|
387
|
+
return group !== void 0 && groundFacingPins.some(
|
|
388
|
+
({ pin: b }) => a.pinId !== b.pinId && Math.abs(a.y - b.y) < 1e-6 && Math.abs(a.x - b.x) > 1e-6 && physicalConnMap.getNetConnectedToId(b.pinId) === group
|
|
389
|
+
);
|
|
390
|
+
});
|
|
391
|
+
if (!hasExplicitParallelGroundRail) return () => true;
|
|
392
|
+
const isGroundFacingTerminal = (pinId) => {
|
|
393
|
+
const entry = pins.get(pinId);
|
|
394
|
+
return entry?.chip.pins.length === 2 && !physicalConnMap.getNetConnectedToId(pinId) && (entry.pin._facingDirection ?? getPinDirection(entry.pin, entry.chip)) === "y-";
|
|
395
|
+
};
|
|
396
|
+
return (firstPinId, secondPinId) => {
|
|
397
|
+
if (!groundNetId || netConnMap.getNetConnectedToId(firstPinId) !== groundNetId || netConnMap.getNetConnectedToId(secondPinId) !== groundNetId) {
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
if (!isGroundFacingTerminal(firstPinId) && !isGroundFacingTerminal(secondPinId))
|
|
401
|
+
return true;
|
|
402
|
+
const first = pins.get(firstPinId)?.pin;
|
|
403
|
+
const second = pins.get(secondPinId)?.pin;
|
|
404
|
+
return !first || !second || Math.abs(first.y - second.y) <= MAX_LOCAL_GROUND_BRANCH_OFFSET + 1e-6;
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
|
|
366
408
|
// lib/solvers/MspConnectionPairSolver/getMspConnectionPairsFromPins.ts
|
|
367
409
|
function getOrthogonalMinimumSpanningTree(pins, opts = {}) {
|
|
368
410
|
const n = pins.length;
|
|
@@ -512,9 +554,11 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
512
554
|
pinMap;
|
|
513
555
|
userNetIdByPinId;
|
|
514
556
|
directConnectionPinPairKeys;
|
|
557
|
+
canRouteGroundPair;
|
|
515
558
|
constructor({ inputProblem }) {
|
|
516
559
|
super();
|
|
517
560
|
this.inputProblem = inputProblem;
|
|
561
|
+
this.canRouteGroundPair = getGroundConnectionPolicy(inputProblem);
|
|
518
562
|
this.maxMspPairDistance = inputProblem.maxMspPairDistance ?? DEFAULT_MAX_MSP_PAIR_DISTANCE;
|
|
519
563
|
const { directConnMap, netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
520
564
|
this.dcConnMap = directConnMap;
|
|
@@ -571,6 +615,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
571
615
|
const [pin1, pin2] = directlyConnectedPins;
|
|
572
616
|
const p1 = this.pinMap[pin1];
|
|
573
617
|
const p2 = this.pinMap[pin2];
|
|
618
|
+
if (!this.canRouteGroundPair(pin1, pin2)) return;
|
|
574
619
|
const pinPairKey = getPinPairKey([pin1, pin2]);
|
|
575
620
|
let pairDistance = Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
|
|
576
621
|
if (this.directConnectionPinPairKeys.has(pinPairKey)) {
|
|
@@ -615,7 +660,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
615
660
|
directlyConnectedPins.map((p) => this.pinMap[p]).filter(Boolean),
|
|
616
661
|
{
|
|
617
662
|
maxDistance: this.maxMspPairDistance,
|
|
618
|
-
forbidEdge: (a, b) => arePinsInDifferentSchematicSections(
|
|
663
|
+
forbidEdge: (a, b) => !this.canRouteGroundPair(a.pinId, b.pinId) || arePinsInDifferentSchematicSections(
|
|
619
664
|
this.inputProblem,
|
|
620
665
|
a,
|
|
621
666
|
b
|
|
@@ -3136,6 +3181,50 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
3136
3181
|
}
|
|
3137
3182
|
};
|
|
3138
3183
|
|
|
3184
|
+
// lib/solvers/SchematicTraceLinesSolver/getTraceConnectedPinComponents.ts
|
|
3185
|
+
var getTraceConnectedPinComponents = ({
|
|
3186
|
+
pinIds,
|
|
3187
|
+
traces
|
|
3188
|
+
}) => {
|
|
3189
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
3190
|
+
for (const pinId of pinIds) adjacency.set(pinId, /* @__PURE__ */ new Set());
|
|
3191
|
+
const relevantTraces = traces.filter((trace) => {
|
|
3192
|
+
if (trace.pins.length !== 2) return false;
|
|
3193
|
+
const [firstPin, secondPin] = trace.pins;
|
|
3194
|
+
return adjacency.has(firstPin.pinId) && adjacency.has(secondPin.pinId);
|
|
3195
|
+
});
|
|
3196
|
+
for (const trace of relevantTraces) {
|
|
3197
|
+
const [firstPin, secondPin] = trace.pins;
|
|
3198
|
+
adjacency.get(firstPin.pinId).add(secondPin.pinId);
|
|
3199
|
+
adjacency.get(secondPin.pinId).add(firstPin.pinId);
|
|
3200
|
+
}
|
|
3201
|
+
const components = [];
|
|
3202
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3203
|
+
for (const pinId of pinIds) {
|
|
3204
|
+
if (visited.has(pinId)) continue;
|
|
3205
|
+
const componentPinIds = [];
|
|
3206
|
+
const pending = [pinId];
|
|
3207
|
+
visited.add(pinId);
|
|
3208
|
+
while (pending.length > 0) {
|
|
3209
|
+
const currentPinId = pending.pop();
|
|
3210
|
+
componentPinIds.push(currentPinId);
|
|
3211
|
+
for (const adjacentPinId of adjacency.get(currentPinId) ?? []) {
|
|
3212
|
+
if (visited.has(adjacentPinId)) continue;
|
|
3213
|
+
visited.add(adjacentPinId);
|
|
3214
|
+
pending.push(adjacentPinId);
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
const componentPinIdSet = new Set(componentPinIds);
|
|
3218
|
+
components.push({
|
|
3219
|
+
pinIds: componentPinIds,
|
|
3220
|
+
traces: relevantTraces.filter(
|
|
3221
|
+
(trace) => trace.pins.every((pin) => componentPinIdSet.has(pin.pinId))
|
|
3222
|
+
)
|
|
3223
|
+
});
|
|
3224
|
+
}
|
|
3225
|
+
return components;
|
|
3226
|
+
};
|
|
3227
|
+
|
|
3139
3228
|
// lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts
|
|
3140
3229
|
var NetLabelPlacementSolver = class extends BaseSolver {
|
|
3141
3230
|
inputProblem;
|
|
@@ -3209,35 +3298,12 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
3209
3298
|
globalConnNetId
|
|
3210
3299
|
);
|
|
3211
3300
|
const pinsInNet = allIdsInNet.filter((id) => pinIdToPinMap.has(id));
|
|
3212
|
-
const
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
const
|
|
3217
|
-
|
|
3218
|
-
adj[a].add(b);
|
|
3219
|
-
adj[b].add(a);
|
|
3220
|
-
}
|
|
3221
|
-
}
|
|
3222
|
-
const visited = /* @__PURE__ */ new Set();
|
|
3223
|
-
for (const pid of pinsInNet) {
|
|
3224
|
-
if (visited.has(pid)) continue;
|
|
3225
|
-
const stack = [pid];
|
|
3226
|
-
const component = /* @__PURE__ */ new Set();
|
|
3227
|
-
visited.add(pid);
|
|
3228
|
-
while (stack.length > 0) {
|
|
3229
|
-
const u = stack.pop();
|
|
3230
|
-
component.add(u);
|
|
3231
|
-
for (const v of adj[u] ?? []) {
|
|
3232
|
-
if (!visited.has(v)) {
|
|
3233
|
-
visited.add(v);
|
|
3234
|
-
stack.push(v);
|
|
3235
|
-
}
|
|
3236
|
-
}
|
|
3237
|
-
}
|
|
3238
|
-
const compTraces = (byGlobal[globalConnNetId] ?? []).filter(
|
|
3239
|
-
(t) => component.has(t.pins[0].pinId) && component.has(t.pins[1].pinId)
|
|
3240
|
-
);
|
|
3301
|
+
for (const traceConnectedComponent of getTraceConnectedPinComponents({
|
|
3302
|
+
pinIds: pinsInNet,
|
|
3303
|
+
traces: byGlobal[globalConnNetId] ?? []
|
|
3304
|
+
})) {
|
|
3305
|
+
const component = new Set(traceConnectedComponent.pinIds);
|
|
3306
|
+
const compTraces = traceConnectedComponent.traces;
|
|
3241
3307
|
if (compTraces.length > 0) {
|
|
3242
3308
|
if (compTraces.some((trace) => trace.suppressNetLabel)) continue;
|
|
3243
3309
|
const lengthOf = (path) => {
|
|
@@ -4827,6 +4893,7 @@ var LongDistancePairSolver = class extends BaseSolver {
|
|
|
4827
4893
|
super();
|
|
4828
4894
|
this.params = params;
|
|
4829
4895
|
const { inputProblem, primaryMspConnectionPairs, alreadySolvedTraces } = this.params;
|
|
4896
|
+
const canRouteGroundPair = getGroundConnectionPolicy(inputProblem);
|
|
4830
4897
|
this.inputProblem = inputProblem;
|
|
4831
4898
|
this.allSolvedTraces = [...alreadySolvedTraces];
|
|
4832
4899
|
this.maxMspPairDistance = inputProblem.maxMspPairDistance ?? DEFAULT_MAX_MSP_PAIR_DISTANCE;
|
|
@@ -4845,7 +4912,10 @@ var LongDistancePairSolver = class extends BaseSolver {
|
|
|
4845
4912
|
}
|
|
4846
4913
|
}
|
|
4847
4914
|
this.queuedFailedConnectionPairs = this.params.failedConnectionPairs.filter(
|
|
4848
|
-
(connectionPair) =>
|
|
4915
|
+
(connectionPair) => canRouteGroundPair(
|
|
4916
|
+
connectionPair.pins[0].pinId,
|
|
4917
|
+
connectionPair.pins[1].pinId
|
|
4918
|
+
) && isLabeledPeripheralConnection({
|
|
4849
4919
|
inputProblem: this.inputProblem,
|
|
4850
4920
|
chipMap: this.chipMap,
|
|
4851
4921
|
pins: connectionPair.pins
|
|
@@ -4865,6 +4935,7 @@ var LongDistancePairSolver = class extends BaseSolver {
|
|
|
4865
4935
|
const neighbors = allPinIdsInNet.filter((otherPinId) => otherPinId !== unconnectedPinId).flatMap((otherPinId) => {
|
|
4866
4936
|
const targetPin = pinMap.get(otherPinId);
|
|
4867
4937
|
if (!targetPin) return [];
|
|
4938
|
+
if (!canRouteGroundPair(sourcePin.pinId, targetPin.pinId)) return [];
|
|
4868
4939
|
const isNamedTwoPinConnection = inputProblem.netConnections.some(
|
|
4869
4940
|
(connection) => connection.pinIds.length === 2 && connection.pinIds.includes(sourcePin.pinId) && connection.pinIds.includes(targetPin.pinId)
|
|
4870
4941
|
);
|
|
@@ -12731,6 +12802,75 @@ var alignSameNetJunctions = ({
|
|
|
12731
12802
|
};
|
|
12732
12803
|
};
|
|
12733
12804
|
|
|
12805
|
+
// lib/solvers/SameNetJunctionAlignmentSolver/placeGroundRailLabelsAtOuterEnd.ts
|
|
12806
|
+
var placeGroundRailLabelsAtOuterEnd = ({
|
|
12807
|
+
inputProblem,
|
|
12808
|
+
traces,
|
|
12809
|
+
netLabelPlacements
|
|
12810
|
+
}) => {
|
|
12811
|
+
const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
12812
|
+
const groundNetId = netConnMap.getNetConnectedToId("GND");
|
|
12813
|
+
if (!groundNetId) return netLabelPlacements;
|
|
12814
|
+
const chipMap = new Map(inputProblem.chips.map((chip) => [chip.chipId, chip]));
|
|
12815
|
+
const traceMap = Object.fromEntries(
|
|
12816
|
+
traces.map((trace) => [trace.mspPairId, trace])
|
|
12817
|
+
);
|
|
12818
|
+
const obstacles = getObstacleRects(inputProblem);
|
|
12819
|
+
const output = [...netLabelPlacements];
|
|
12820
|
+
for (const rail of traces) {
|
|
12821
|
+
if (rail.globalConnNetId !== groundNetId) continue;
|
|
12822
|
+
const [a, b] = rail.pins;
|
|
12823
|
+
if (a.chipId === b.chipId || !nearlyEqual(a.y, b.y) || ![a, b].every(
|
|
12824
|
+
(pin) => pin._facingDirection === "y-" && chipMap.get(pin.chipId)?.pins.length === 2
|
|
12825
|
+
))
|
|
12826
|
+
continue;
|
|
12827
|
+
const path = simplifyPath(rail.tracePath);
|
|
12828
|
+
if (path.length !== 4 || !isVertical2(path[0], path[1]) || !isHorizontal2(path[1], path[2]) || !isVertical2(path[2], path[3]) || path[1].y >= a.y)
|
|
12829
|
+
continue;
|
|
12830
|
+
for (const feed of traces) {
|
|
12831
|
+
if (feed.globalConnNetId !== groundNetId) continue;
|
|
12832
|
+
const shared = feed.pins.find((pin) => rail.pinIds.includes(pin.pinId));
|
|
12833
|
+
const icPin = feed.pins.find(
|
|
12834
|
+
(pin) => !rail.pinIds.includes(pin.pinId) && (chipMap.get(pin.chipId)?.pins.length ?? 0) > 2
|
|
12835
|
+
);
|
|
12836
|
+
if (!shared || !icPin || !nearlyEqual(icPin.y, path[1].y)) continue;
|
|
12837
|
+
const outer = shared.pinId === a.pinId ? b : a;
|
|
12838
|
+
if (Math.abs(outer.x - icPin.x) <= Math.abs(shared.x - icPin.x)) continue;
|
|
12839
|
+
const anchorPoint = { x: outer.x, y: path[1].y };
|
|
12840
|
+
if (!tracePathContainsPoint(rail.tracePath, anchorPoint)) continue;
|
|
12841
|
+
for (let index = 0; index < output.length; index++) {
|
|
12842
|
+
const label = output[index];
|
|
12843
|
+
if (label.globalConnNetId !== groundNetId || label.orientation !== "y-" || !label.mspConnectionPairIds.some(
|
|
12844
|
+
(id) => id === feed.mspPairId || id === rail.mspPairId
|
|
12845
|
+
) || !tracePathContainsPoint(feed.tracePath, label.anchorPoint) && !tracePathContainsPoint(rail.tracePath, label.anchorPoint))
|
|
12846
|
+
continue;
|
|
12847
|
+
const center = getCenterFromAnchor(
|
|
12848
|
+
anchorPoint,
|
|
12849
|
+
label.orientation,
|
|
12850
|
+
label.width,
|
|
12851
|
+
label.height
|
|
12852
|
+
);
|
|
12853
|
+
const bounds = getRectBounds(center, label.width, label.height);
|
|
12854
|
+
if (obstacles.some((obstacle) => rectsOverlap(bounds, obstacle)) || traceCrossesBoundsInterior(bounds, traceMap) || output.some(
|
|
12855
|
+
(other, otherIndex) => otherIndex !== index && rectsOverlap(
|
|
12856
|
+
bounds,
|
|
12857
|
+
getRectBounds(other.center, other.width, other.height)
|
|
12858
|
+
)
|
|
12859
|
+
))
|
|
12860
|
+
continue;
|
|
12861
|
+
output[index] = {
|
|
12862
|
+
...label,
|
|
12863
|
+
anchorPoint,
|
|
12864
|
+
center,
|
|
12865
|
+
mspConnectionPairIds: [rail.mspPairId],
|
|
12866
|
+
pinIds: [...rail.pinIds]
|
|
12867
|
+
};
|
|
12868
|
+
}
|
|
12869
|
+
}
|
|
12870
|
+
}
|
|
12871
|
+
return output;
|
|
12872
|
+
};
|
|
12873
|
+
|
|
12734
12874
|
// lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts
|
|
12735
12875
|
var SameNetJunctionAlignmentSolver = class extends BaseSolver {
|
|
12736
12876
|
input;
|
|
@@ -12745,7 +12885,11 @@ var SameNetJunctionAlignmentSolver = class extends BaseSolver {
|
|
|
12745
12885
|
_step() {
|
|
12746
12886
|
const result = alignSameNetJunctions(this.input);
|
|
12747
12887
|
this.outputTraces = result.traces;
|
|
12748
|
-
this.outputNetLabelPlacements =
|
|
12888
|
+
this.outputNetLabelPlacements = placeGroundRailLabelsAtOuterEnd({
|
|
12889
|
+
inputProblem: this.input.inputProblem,
|
|
12890
|
+
traces: result.traces,
|
|
12891
|
+
netLabelPlacements: result.netLabelPlacements
|
|
12892
|
+
});
|
|
12749
12893
|
this.stats.alignedJunctionCount = result.alignedJunctionCount;
|
|
12750
12894
|
this.solved = true;
|
|
12751
12895
|
}
|
|
@@ -13572,7 +13716,7 @@ var pushAnchoredNetLabelsAwayFromInlineLabels = ({
|
|
|
13572
13716
|
const connectorObstructed = inlineBounds.some(
|
|
13573
13717
|
(bounds) => pathIntersectsBounds(connector.tracePath, bounds)
|
|
13574
13718
|
) || inputProblem.chips.some(
|
|
13575
|
-
(chip) => pathIntersectsBounds(connector.tracePath, {
|
|
13719
|
+
(chip) => !ownerChipIds.has(chip.chipId) && pathIntersectsBounds(connector.tracePath, {
|
|
13576
13720
|
minX: chip.center.x - chip.width / 2,
|
|
13577
13721
|
maxX: chip.center.x + chip.width / 2,
|
|
13578
13722
|
minY: chip.center.y - chip.height / 2,
|
|
@@ -13609,20 +13753,247 @@ var pushAnchoredNetLabelsAwayFromInlineLabels = ({
|
|
|
13609
13753
|
};
|
|
13610
13754
|
};
|
|
13611
13755
|
|
|
13756
|
+
// lib/solvers/InlineNetLabelSolver/pushInlineTerminalLabelsAwayFromAnchoredLabels.ts
|
|
13757
|
+
var LABEL_CLEARANCE3 = 0.05;
|
|
13758
|
+
var MAX_OUTWARD_DISTANCE2 = 5;
|
|
13759
|
+
var getStubDirection2 = (path) => {
|
|
13760
|
+
const [start, end] = path;
|
|
13761
|
+
if (Math.abs(end.x - start.x) >= Math.abs(end.y - start.y)) {
|
|
13762
|
+
return end.x >= start.x ? "x+" : "x-";
|
|
13763
|
+
}
|
|
13764
|
+
return end.y >= start.y ? "y+" : "y-";
|
|
13765
|
+
};
|
|
13766
|
+
var getLabelBounds3 = (placement) => {
|
|
13767
|
+
const renderedWidth = placement.axis === "y" ? placement.height : placement.width;
|
|
13768
|
+
const renderedHeight = placement.axis === "y" ? placement.width : placement.height;
|
|
13769
|
+
return {
|
|
13770
|
+
minX: placement.center.x - renderedWidth / 2,
|
|
13771
|
+
maxX: placement.center.x + renderedWidth / 2,
|
|
13772
|
+
minY: placement.center.y - renderedHeight / 2,
|
|
13773
|
+
maxY: placement.center.y + renderedHeight / 2
|
|
13774
|
+
};
|
|
13775
|
+
};
|
|
13776
|
+
var getPathBounds2 = (path) => ({
|
|
13777
|
+
minX: Math.min(...path.map((point) => point.x)),
|
|
13778
|
+
maxX: Math.max(...path.map((point) => point.x)),
|
|
13779
|
+
minY: Math.min(...path.map((point) => point.y)),
|
|
13780
|
+
maxY: Math.max(...path.map((point) => point.y))
|
|
13781
|
+
});
|
|
13782
|
+
var doesPathIntersectBounds2 = (path, bounds) => {
|
|
13783
|
+
for (let index = 0; index < path.length - 1; index++) {
|
|
13784
|
+
if (boundsOverlap(getPathBounds2([path[index], path[index + 1]]), bounds)) {
|
|
13785
|
+
return true;
|
|
13786
|
+
}
|
|
13787
|
+
}
|
|
13788
|
+
return false;
|
|
13789
|
+
};
|
|
13790
|
+
var shiftPoint = (point, direction, distance7) => {
|
|
13791
|
+
switch (direction) {
|
|
13792
|
+
case "x+":
|
|
13793
|
+
return { x: point.x + distance7, y: point.y };
|
|
13794
|
+
case "x-":
|
|
13795
|
+
return { x: point.x - distance7, y: point.y };
|
|
13796
|
+
case "y+":
|
|
13797
|
+
return { x: point.x, y: point.y + distance7 };
|
|
13798
|
+
case "y-":
|
|
13799
|
+
return { x: point.x, y: point.y - distance7 };
|
|
13800
|
+
}
|
|
13801
|
+
};
|
|
13802
|
+
var shiftTerminalPlacement = (placement, direction, distance7) => {
|
|
13803
|
+
const [start, end] = placement.stubTracePath;
|
|
13804
|
+
const shiftedEnd = shiftPoint(end, direction, distance7);
|
|
13805
|
+
return {
|
|
13806
|
+
...placement,
|
|
13807
|
+
stubTracePath: [start, shiftedEnd],
|
|
13808
|
+
anchorPoint: shiftPoint(placement.anchorPoint, direction, distance7),
|
|
13809
|
+
center: shiftPoint(placement.center, direction, distance7)
|
|
13810
|
+
};
|
|
13811
|
+
};
|
|
13812
|
+
var getRequiredOutwardDistance2 = (movingBounds, obstacleBounds, direction) => {
|
|
13813
|
+
switch (direction) {
|
|
13814
|
+
case "x+":
|
|
13815
|
+
return obstacleBounds.maxX - movingBounds.minX + LABEL_CLEARANCE3;
|
|
13816
|
+
case "x-":
|
|
13817
|
+
return movingBounds.maxX - obstacleBounds.minX + LABEL_CLEARANCE3;
|
|
13818
|
+
case "y+":
|
|
13819
|
+
return obstacleBounds.maxY - movingBounds.minY + LABEL_CLEARANCE3;
|
|
13820
|
+
case "y-":
|
|
13821
|
+
return movingBounds.maxY - obstacleBounds.minY + LABEL_CLEARANCE3;
|
|
13822
|
+
}
|
|
13823
|
+
};
|
|
13824
|
+
var pushInlineTerminalLabelsAwayFromAnchoredLabels = ({
|
|
13825
|
+
inputProblem,
|
|
13826
|
+
traces,
|
|
13827
|
+
anchoredNetLabelPlacements,
|
|
13828
|
+
inlineNetLabelPlacements
|
|
13829
|
+
}) => {
|
|
13830
|
+
const chipIdByPinId = /* @__PURE__ */ new Map();
|
|
13831
|
+
for (const chip of inputProblem.chips) {
|
|
13832
|
+
for (const pin of chip.pins) chipIdByPinId.set(pin.pinId, chip.chipId);
|
|
13833
|
+
}
|
|
13834
|
+
const groups = /* @__PURE__ */ new Map();
|
|
13835
|
+
for (const [
|
|
13836
|
+
placementIndex,
|
|
13837
|
+
placement
|
|
13838
|
+
] of inlineNetLabelPlacements.entries()) {
|
|
13839
|
+
if (!placement.stubTracePath || placement.pinIds.length !== 1) continue;
|
|
13840
|
+
const direction = getStubDirection2(placement.stubTracePath);
|
|
13841
|
+
const ownerChipId = chipIdByPinId.get(placement.pinIds[0]);
|
|
13842
|
+
const groupKey = `${ownerChipId ?? placement.pinIds[0]}::${direction}`;
|
|
13843
|
+
const group = groups.get(groupKey) ?? [];
|
|
13844
|
+
group.push({ placementIndex, placement, direction, ownerChipId });
|
|
13845
|
+
groups.set(groupKey, group);
|
|
13846
|
+
}
|
|
13847
|
+
const outputPlacements = [...inlineNetLabelPlacements];
|
|
13848
|
+
let movedGroupCount = 0;
|
|
13849
|
+
for (const group of groups.values()) {
|
|
13850
|
+
const groupPlacementIndices = new Set(
|
|
13851
|
+
group.map(({ placementIndex }) => placementIndex)
|
|
13852
|
+
);
|
|
13853
|
+
const fixedInlinePlacements = outputPlacements.filter(
|
|
13854
|
+
(_, placementIndex) => !groupPlacementIndices.has(placementIndex)
|
|
13855
|
+
);
|
|
13856
|
+
const direction = group[0].direction;
|
|
13857
|
+
let distance7 = 0;
|
|
13858
|
+
for (let iteration = 0; iteration <= anchoredNetLabelPlacements.length; iteration++) {
|
|
13859
|
+
let requiredAdditionalDistance = 0;
|
|
13860
|
+
for (const { placement } of group) {
|
|
13861
|
+
const shiftedPlacement = shiftTerminalPlacement(
|
|
13862
|
+
placement,
|
|
13863
|
+
direction,
|
|
13864
|
+
distance7
|
|
13865
|
+
);
|
|
13866
|
+
const shiftedBounds = getLabelBounds3(shiftedPlacement);
|
|
13867
|
+
for (const anchoredPlacement of anchoredNetLabelPlacements) {
|
|
13868
|
+
if (anchoredPlacement.globalConnNetId === placement.globalConnNetId) {
|
|
13869
|
+
continue;
|
|
13870
|
+
}
|
|
13871
|
+
const anchoredBounds = getLabelBounds3(anchoredPlacement);
|
|
13872
|
+
if (!boundsOverlap(shiftedBounds, anchoredBounds)) continue;
|
|
13873
|
+
requiredAdditionalDistance = Math.max(
|
|
13874
|
+
requiredAdditionalDistance,
|
|
13875
|
+
getRequiredOutwardDistance2(
|
|
13876
|
+
shiftedBounds,
|
|
13877
|
+
anchoredBounds,
|
|
13878
|
+
direction
|
|
13879
|
+
)
|
|
13880
|
+
);
|
|
13881
|
+
}
|
|
13882
|
+
}
|
|
13883
|
+
if (requiredAdditionalDistance <= 0) break;
|
|
13884
|
+
distance7 += requiredAdditionalDistance;
|
|
13885
|
+
}
|
|
13886
|
+
if (distance7 <= 0 || distance7 > MAX_OUTWARD_DISTANCE2) continue;
|
|
13887
|
+
const proposals = group.map(
|
|
13888
|
+
({ placement }) => shiftTerminalPlacement(placement, direction, distance7)
|
|
13889
|
+
);
|
|
13890
|
+
const hasConflict = proposals.some((proposal, proposalIndex) => {
|
|
13891
|
+
const originalPlacement = group[proposalIndex].placement;
|
|
13892
|
+
const originalEnd = originalPlacement.stubTracePath[1];
|
|
13893
|
+
const shiftedEnd = proposal.stubTracePath[1];
|
|
13894
|
+
const addedStubSegment = [originalEnd, shiftedEnd];
|
|
13895
|
+
const labelBounds = getLabelBounds3(proposal);
|
|
13896
|
+
const ownerChipId = group[proposalIndex].ownerChipId;
|
|
13897
|
+
if (anchoredNetLabelPlacements.some((anchoredPlacement) => {
|
|
13898
|
+
if (anchoredPlacement.globalConnNetId === proposal.globalConnNetId) {
|
|
13899
|
+
return false;
|
|
13900
|
+
}
|
|
13901
|
+
const anchoredBounds = getLabelBounds3(anchoredPlacement);
|
|
13902
|
+
return boundsOverlap(labelBounds, anchoredBounds) || doesPathIntersectBounds2(addedStubSegment, anchoredBounds);
|
|
13903
|
+
})) {
|
|
13904
|
+
return true;
|
|
13905
|
+
}
|
|
13906
|
+
for (const chip of inputProblem.chips) {
|
|
13907
|
+
if (chip.chipId === ownerChipId) continue;
|
|
13908
|
+
const chipBounds = {
|
|
13909
|
+
minX: chip.center.x - chip.width / 2,
|
|
13910
|
+
maxX: chip.center.x + chip.width / 2,
|
|
13911
|
+
minY: chip.center.y - chip.height / 2,
|
|
13912
|
+
maxY: chip.center.y + chip.height / 2
|
|
13913
|
+
};
|
|
13914
|
+
if (boundsOverlap(labelBounds, chipBounds) || doesPathIntersectBounds2(addedStubSegment, chipBounds)) {
|
|
13915
|
+
return true;
|
|
13916
|
+
}
|
|
13917
|
+
}
|
|
13918
|
+
for (const textBox of inputProblem.textBoxes ?? []) {
|
|
13919
|
+
const textBounds = getTextBoxBounds(textBox);
|
|
13920
|
+
if (boundsOverlap(labelBounds, textBounds) || doesPathIntersectBounds2(addedStubSegment, textBounds)) {
|
|
13921
|
+
return true;
|
|
13922
|
+
}
|
|
13923
|
+
}
|
|
13924
|
+
for (const trace of traces) {
|
|
13925
|
+
if (trace.globalConnNetId === proposal.globalConnNetId) continue;
|
|
13926
|
+
if (doesPathIntersectBounds2(trace.tracePath, labelBounds) || doesPathIntersectBounds2(
|
|
13927
|
+
trace.tracePath,
|
|
13928
|
+
getPathBounds2(addedStubSegment)
|
|
13929
|
+
)) {
|
|
13930
|
+
return true;
|
|
13931
|
+
}
|
|
13932
|
+
}
|
|
13933
|
+
for (const fixedPlacement of fixedInlinePlacements) {
|
|
13934
|
+
const fixedBounds = getLabelBounds3(fixedPlacement);
|
|
13935
|
+
if (boundsOverlap(labelBounds, fixedBounds) || doesPathIntersectBounds2(addedStubSegment, fixedBounds) || fixedPlacement.stubTracePath && doesPathIntersectBounds2(fixedPlacement.stubTracePath, labelBounds)) {
|
|
13936
|
+
return true;
|
|
13937
|
+
}
|
|
13938
|
+
}
|
|
13939
|
+
return false;
|
|
13940
|
+
});
|
|
13941
|
+
if (hasConflict) continue;
|
|
13942
|
+
for (const [groupIndex, { placementIndex }] of group.entries()) {
|
|
13943
|
+
outputPlacements[placementIndex] = proposals[groupIndex];
|
|
13944
|
+
}
|
|
13945
|
+
movedGroupCount++;
|
|
13946
|
+
}
|
|
13947
|
+
return {
|
|
13948
|
+
inlineNetLabelPlacements: outputPlacements,
|
|
13949
|
+
movedGroupCount
|
|
13950
|
+
};
|
|
13951
|
+
};
|
|
13952
|
+
|
|
13612
13953
|
// lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts
|
|
13613
13954
|
var DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18;
|
|
13614
13955
|
var INLINE_NET_LABEL_TRACE_MARGIN = 0.05;
|
|
13615
13956
|
var INLINE_NET_LABEL_STUB_TRACE_CLEARANCE = 0.05;
|
|
13616
13957
|
var INLINE_NET_LABEL_MAX_SPAN_JOG = 0.4;
|
|
13958
|
+
var AVAILABLE_NET_ORIENTATION_TRACE_PREFIX = "available-net-orientation-";
|
|
13959
|
+
var isGeneratedAnchoredLabelConnector = (trace) => trace.mspPairId.startsWith(AVAILABLE_NET_ORIENTATION_TRACE_PREFIX);
|
|
13617
13960
|
var getPinPairKey2 = (pinIds) => [...pinIds].sort().join("::");
|
|
13961
|
+
var getTraceLength2 = (trace) => {
|
|
13962
|
+
let length = 0;
|
|
13963
|
+
for (let index = 0; index < trace.tracePath.length - 1; index++) {
|
|
13964
|
+
const start = trace.tracePath[index];
|
|
13965
|
+
const end = trace.tracePath[index + 1];
|
|
13966
|
+
length += Math.abs(end.x - start.x) + Math.abs(end.y - start.y);
|
|
13967
|
+
}
|
|
13968
|
+
return length;
|
|
13969
|
+
};
|
|
13970
|
+
var setsEqual = (first, second) => first.size === second.size && [...first].every((value) => second.has(value));
|
|
13971
|
+
var getInlinePlacementBounds = (placement) => {
|
|
13972
|
+
const renderedWidth = placement.axis === "y" ? placement.height : placement.width;
|
|
13973
|
+
const renderedHeight = placement.axis === "y" ? placement.width : placement.height;
|
|
13974
|
+
return {
|
|
13975
|
+
minX: placement.center.x - renderedWidth / 2,
|
|
13976
|
+
maxX: placement.center.x + renderedWidth / 2,
|
|
13977
|
+
minY: placement.center.y - renderedHeight / 2,
|
|
13978
|
+
maxY: placement.center.y + renderedHeight / 2
|
|
13979
|
+
};
|
|
13980
|
+
};
|
|
13981
|
+
var getAnchoredPlacementBounds = (placement) => ({
|
|
13982
|
+
minX: placement.center.x - placement.width / 2,
|
|
13983
|
+
maxX: placement.center.x + placement.width / 2,
|
|
13984
|
+
minY: placement.center.y - placement.height / 2,
|
|
13985
|
+
maxY: placement.center.y + placement.height / 2
|
|
13986
|
+
});
|
|
13618
13987
|
var InlineNetLabelSolver = class extends BaseSolver {
|
|
13619
13988
|
inputProblem;
|
|
13620
13989
|
traces;
|
|
13621
13990
|
inputNetLabelPlacements;
|
|
13622
13991
|
inlineNetLabelPlacements = [];
|
|
13623
|
-
/** Eligible
|
|
13992
|
+
/** Eligible connections still waiting to be processed. */
|
|
13624
13993
|
queuedConnections;
|
|
13625
13994
|
tracesByPinPairKey;
|
|
13995
|
+
globalConnMap;
|
|
13996
|
+
supersededTraceIdsByGlobalConnNetId = /* @__PURE__ */ new Map();
|
|
13626
13997
|
hasAlignedPortOnlyStubs = false;
|
|
13627
13998
|
postProcessedOutput;
|
|
13628
13999
|
constructor(input) {
|
|
@@ -13630,16 +14001,26 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13630
14001
|
this.inputProblem = input.inputProblem;
|
|
13631
14002
|
this.traces = input.traces;
|
|
13632
14003
|
this.inputNetLabelPlacements = input.netLabelPlacements;
|
|
14004
|
+
this.globalConnMap = getConnectivityMapsFromInputProblem(
|
|
14005
|
+
this.inputProblem
|
|
14006
|
+
).netConnMap;
|
|
13633
14007
|
this.queuedConnections = [
|
|
13634
14008
|
...this.inputProblem.directConnections.filter(
|
|
13635
14009
|
(connection) => connection.allowInlineNetLabel && connection.netId
|
|
13636
|
-
)
|
|
14010
|
+
).map((connection) => ({
|
|
14011
|
+
kind: "direct_connection",
|
|
14012
|
+
connection
|
|
14013
|
+
})),
|
|
13637
14014
|
...this.inputProblem.netConnections.filter(
|
|
13638
|
-
(connection) => connection.allowInlineNetLabel && connection.pinIds.length >= 1 && connection.
|
|
13639
|
-
)
|
|
14015
|
+
(connection) => connection.allowInlineNetLabel && connection.pinIds.length >= 1 && connection.netId
|
|
14016
|
+
).map((connection) => ({
|
|
14017
|
+
kind: "net_connection",
|
|
14018
|
+
connection
|
|
14019
|
+
}))
|
|
13640
14020
|
];
|
|
13641
14021
|
this.tracesByPinPairKey = /* @__PURE__ */ new Map();
|
|
13642
14022
|
for (const trace of this.traces) {
|
|
14023
|
+
if (isGeneratedAnchoredLabelConnector(trace)) continue;
|
|
13643
14024
|
const key = getPinPairKey2(trace.pins.map((p) => p.pinId));
|
|
13644
14025
|
const existing = this.tracesByPinPairKey.get(key);
|
|
13645
14026
|
if (existing) {
|
|
@@ -13659,11 +14040,43 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13659
14040
|
];
|
|
13660
14041
|
}
|
|
13661
14042
|
_step() {
|
|
13662
|
-
const
|
|
13663
|
-
if (
|
|
14043
|
+
const queuedConnection = this.queuedConnections.shift();
|
|
14044
|
+
if (queuedConnection) {
|
|
14045
|
+
if (queuedConnection.kind === "net_connection" && queuedConnection.connection.pinIds.length > 2) {
|
|
14046
|
+
const netConnections = [
|
|
14047
|
+
queuedConnection.connection,
|
|
14048
|
+
...this.queuedConnections.filter(
|
|
14049
|
+
(queued) => queued.kind === "net_connection" && queued.connection.pinIds.length > 2
|
|
14050
|
+
).map((queued) => queued.connection)
|
|
14051
|
+
];
|
|
14052
|
+
this.queuedConnections = this.queuedConnections.filter(
|
|
14053
|
+
(queued) => queued.kind !== "net_connection" || queued.connection.pinIds.length <= 2
|
|
14054
|
+
);
|
|
14055
|
+
for (const conversion of this.computeNetConnectionInlineConversions(
|
|
14056
|
+
netConnections
|
|
14057
|
+
)) {
|
|
14058
|
+
this.inlineNetLabelPlacements.push(...conversion.placements);
|
|
14059
|
+
const supersededTraceIds = this.supersededTraceIdsByGlobalConnNetId.get(
|
|
14060
|
+
conversion.globalConnNetId
|
|
14061
|
+
) ?? /* @__PURE__ */ new Set();
|
|
14062
|
+
for (const traceId of conversion.supersededTraceIds) {
|
|
14063
|
+
supersededTraceIds.add(traceId);
|
|
14064
|
+
}
|
|
14065
|
+
this.supersededTraceIdsByGlobalConnNetId.set(
|
|
14066
|
+
conversion.globalConnNetId,
|
|
14067
|
+
supersededTraceIds
|
|
14068
|
+
);
|
|
14069
|
+
}
|
|
14070
|
+
return;
|
|
14071
|
+
}
|
|
14072
|
+
const { connection } = queuedConnection;
|
|
13664
14073
|
const routedTraces = connection.pinIds.length === 2 ? this.tracesByPinPairKey.get(getPinPairKey2(connection.pinIds)) ?? [] : [];
|
|
13665
14074
|
if (routedTraces.length > 0) {
|
|
13666
|
-
const placement = this.computeInlinePlacement(
|
|
14075
|
+
const placement = this.computeInlinePlacement({
|
|
14076
|
+
connection,
|
|
14077
|
+
trace: routedTraces[0],
|
|
14078
|
+
pinIds: connection.pinIds
|
|
14079
|
+
});
|
|
13667
14080
|
if (placement) this.inlineNetLabelPlacements.push(placement);
|
|
13668
14081
|
} else {
|
|
13669
14082
|
const terminalPlacements = connection.pinIds.map(
|
|
@@ -13692,18 +14105,181 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13692
14105
|
this.solved = true;
|
|
13693
14106
|
this.stats.inlineNetLabelCount = this.inlineNetLabelPlacements.length;
|
|
13694
14107
|
}
|
|
14108
|
+
/**
|
|
14109
|
+
* Plans all opted-in multi-pin nets together. Short routed components can
|
|
14110
|
+
* mutually block the outward endpoint stubs that replace them, so tentative
|
|
14111
|
+
* replacements are ignored as obstacles only while their owning net still
|
|
14112
|
+
* converts successfully. Failed conversions retain both their traces and
|
|
14113
|
+
* their conventional labels, and the remaining conversions are retried.
|
|
14114
|
+
*/
|
|
14115
|
+
computeNetConnectionInlineConversions(connections) {
|
|
14116
|
+
const prospectiveTraceIdsByConnection = /* @__PURE__ */ new Map();
|
|
14117
|
+
for (const connection of connections) {
|
|
14118
|
+
const prospectiveTraceIds = /* @__PURE__ */ new Set();
|
|
14119
|
+
for (const component of this.getNetConnectionComponents(connection)) {
|
|
14120
|
+
if (component.traces.length === 0) continue;
|
|
14121
|
+
const hasInlinePlacement = component.traces.some(
|
|
14122
|
+
(trace) => Boolean(
|
|
14123
|
+
this.computeInlinePlacement({
|
|
14124
|
+
connection,
|
|
14125
|
+
trace,
|
|
14126
|
+
pinIds: component.pinIds
|
|
14127
|
+
})
|
|
14128
|
+
)
|
|
14129
|
+
);
|
|
14130
|
+
if (!hasInlinePlacement) {
|
|
14131
|
+
for (const trace of component.traces) {
|
|
14132
|
+
prospectiveTraceIds.add(trace.mspPairId);
|
|
14133
|
+
}
|
|
14134
|
+
}
|
|
14135
|
+
}
|
|
14136
|
+
prospectiveTraceIdsByConnection.set(connection, prospectiveTraceIds);
|
|
14137
|
+
}
|
|
14138
|
+
let ignoredTraceIds = new Set(
|
|
14139
|
+
[...prospectiveTraceIdsByConnection.values()].flatMap((ids) => [...ids])
|
|
14140
|
+
);
|
|
14141
|
+
while (true) {
|
|
14142
|
+
const conversions = connections.map((connection) => ({
|
|
14143
|
+
connection,
|
|
14144
|
+
conversion: this.computeNetConnectionInlinePlacements(
|
|
14145
|
+
connection,
|
|
14146
|
+
ignoredTraceIds,
|
|
14147
|
+
prospectiveTraceIdsByConnection.get(connection) ?? /* @__PURE__ */ new Set()
|
|
14148
|
+
)
|
|
14149
|
+
}));
|
|
14150
|
+
const nextIgnoredTraceIds = new Set(
|
|
14151
|
+
conversions.flatMap(
|
|
14152
|
+
({ conversion }) => conversion ? [...conversion.supersededTraceIds] : []
|
|
14153
|
+
)
|
|
14154
|
+
);
|
|
14155
|
+
if (setsEqual(ignoredTraceIds, nextIgnoredTraceIds)) {
|
|
14156
|
+
return conversions.flatMap(
|
|
14157
|
+
({ conversion }) => conversion ? [conversion] : []
|
|
14158
|
+
);
|
|
14159
|
+
}
|
|
14160
|
+
ignoredTraceIds = nextIgnoredTraceIds;
|
|
14161
|
+
}
|
|
14162
|
+
}
|
|
14163
|
+
/**
|
|
14164
|
+
* Splits an input net into the connected components created by its solved
|
|
14165
|
+
* traces. This intentionally does not depend on anchored-label placement:
|
|
14166
|
+
* a group whose anchored label failed still has the same routing topology.
|
|
14167
|
+
*/
|
|
14168
|
+
getNetConnectionComponents(connection) {
|
|
14169
|
+
const firstPinId = connection.pinIds[0];
|
|
14170
|
+
if (!firstPinId) return [];
|
|
14171
|
+
const canonicalGlobalConnNetId = this.globalConnMap.getNetConnectedToId(firstPinId);
|
|
14172
|
+
if (!canonicalGlobalConnNetId) return [];
|
|
14173
|
+
const inputPinIds = new Set(
|
|
14174
|
+
this.inputProblem.chips.flatMap(
|
|
14175
|
+
(chip) => chip.pins.map((pin) => pin.pinId)
|
|
14176
|
+
)
|
|
14177
|
+
);
|
|
14178
|
+
const pinIdsInGlobalNet = this.globalConnMap.getIdsConnectedToNet(
|
|
14179
|
+
canonicalGlobalConnNetId
|
|
14180
|
+
).filter((id) => inputPinIds.has(id));
|
|
14181
|
+
const labeledPinIds = new Set(connection.pinIds);
|
|
14182
|
+
return getTraceConnectedPinComponents({
|
|
14183
|
+
pinIds: pinIdsInGlobalNet,
|
|
14184
|
+
// Available-net-orientation traces only connect a pin to its generated
|
|
14185
|
+
// anchored label. They are removed when that label becomes inline, so
|
|
14186
|
+
// treating them as routed circuitry would leave text on a deleted wire.
|
|
14187
|
+
traces: this.traces.filter(
|
|
14188
|
+
(trace) => !isGeneratedAnchoredLabelConnector(trace)
|
|
14189
|
+
)
|
|
14190
|
+
}).map((component) => ({
|
|
14191
|
+
pinIds: component.pinIds,
|
|
14192
|
+
labeledPinIds: component.pinIds.filter(
|
|
14193
|
+
(pinId) => labeledPinIds.has(pinId)
|
|
14194
|
+
),
|
|
14195
|
+
traces: component.traces.sort(
|
|
14196
|
+
(a, b) => getTraceLength2(b) - getTraceLength2(a)
|
|
14197
|
+
)
|
|
14198
|
+
})).filter((component) => component.labeledPinIds.length > 0);
|
|
14199
|
+
}
|
|
14200
|
+
getGlobalConnNetId(connection) {
|
|
14201
|
+
const firstPinId = connection.pinIds[0];
|
|
14202
|
+
if (!firstPinId) return void 0;
|
|
14203
|
+
const connectionPinIds = new Set(connection.pinIds);
|
|
14204
|
+
return this.traces.find(
|
|
14205
|
+
(trace) => trace.pins.some((pin) => connectionPinIds.has(pin.pinId))
|
|
14206
|
+
)?.globalConnNetId ?? this.inputNetLabelPlacements.find(
|
|
14207
|
+
(placement) => placement.netId === connection.netId
|
|
14208
|
+
)?.globalConnNetId ?? this.globalConnMap.getNetConnectedToId(firstPinId) ?? void 0;
|
|
14209
|
+
}
|
|
14210
|
+
/**
|
|
14211
|
+
* Converts every conventional label representation for an opted-in named
|
|
14212
|
+
* net. Routed connected components become labels on their representative
|
|
14213
|
+
* trace; disconnected pins become outward terminal stubs. The conversion is
|
|
14214
|
+
* atomic so one blocked candidate cannot leave mixed label styles on a net.
|
|
14215
|
+
*/
|
|
14216
|
+
computeNetConnectionInlinePlacements(connection, ignoredTraceIds, forcedTerminalTraceIds) {
|
|
14217
|
+
const components = this.getNetConnectionComponents(connection);
|
|
14218
|
+
const globalConnNetId = this.getGlobalConnNetId(connection);
|
|
14219
|
+
if (!globalConnNetId) return null;
|
|
14220
|
+
const inlinePlacements = [];
|
|
14221
|
+
const supersededTraceIds = /* @__PURE__ */ new Set();
|
|
14222
|
+
for (const component of components) {
|
|
14223
|
+
const shouldUseTerminalStubs = component.traces.some(
|
|
14224
|
+
(trace) => forcedTerminalTraceIds.has(trace.mspPairId)
|
|
14225
|
+
);
|
|
14226
|
+
let inlinePlacement = null;
|
|
14227
|
+
if (!shouldUseTerminalStubs) {
|
|
14228
|
+
for (const trace of component.traces) {
|
|
14229
|
+
inlinePlacement = this.computeInlinePlacement({
|
|
14230
|
+
connection,
|
|
14231
|
+
trace,
|
|
14232
|
+
pinIds: component.pinIds,
|
|
14233
|
+
ignoredTraceIds
|
|
14234
|
+
});
|
|
14235
|
+
if (inlinePlacement) break;
|
|
14236
|
+
}
|
|
14237
|
+
}
|
|
14238
|
+
if (inlinePlacement) {
|
|
14239
|
+
inlinePlacements.push(inlinePlacement);
|
|
14240
|
+
continue;
|
|
14241
|
+
}
|
|
14242
|
+
if (component.traces.length > 0 && !shouldUseTerminalStubs) {
|
|
14243
|
+
return null;
|
|
14244
|
+
}
|
|
14245
|
+
if (component.labeledPinIds.length !== component.pinIds.length) {
|
|
14246
|
+
return null;
|
|
14247
|
+
}
|
|
14248
|
+
const terminalPlacements = component.pinIds.map(
|
|
14249
|
+
(pinId) => this.computeTerminalInlinePlacement(
|
|
14250
|
+
connection,
|
|
14251
|
+
pinId,
|
|
14252
|
+
globalConnNetId,
|
|
14253
|
+
ignoredTraceIds
|
|
14254
|
+
)
|
|
14255
|
+
);
|
|
14256
|
+
if (terminalPlacements.some((placement) => placement === null)) {
|
|
14257
|
+
return null;
|
|
14258
|
+
}
|
|
14259
|
+
inlinePlacements.push(
|
|
14260
|
+
...terminalPlacements.filter(
|
|
14261
|
+
(placement) => placement !== null
|
|
14262
|
+
)
|
|
14263
|
+
);
|
|
14264
|
+
for (const trace of component.traces) {
|
|
14265
|
+
supersededTraceIds.add(trace.mspPairId);
|
|
14266
|
+
}
|
|
14267
|
+
}
|
|
14268
|
+
return { globalConnNetId, placements: inlinePlacements, supersededTraceIds };
|
|
14269
|
+
}
|
|
13695
14270
|
/**
|
|
13696
14271
|
* Converts one conventional endpoint placement into an inline label on a
|
|
13697
14272
|
* generated outward stub. The stub follows the pin's true facing direction;
|
|
13698
14273
|
* an anchored label may finish in another direction after an elbow, which is
|
|
13699
14274
|
* not the direction a terminal stub should leave the pin.
|
|
13700
14275
|
*/
|
|
13701
|
-
computeTerminalInlinePlacement(connection, pinId) {
|
|
14276
|
+
computeTerminalInlinePlacement(connection, pinId, knownGlobalConnNetId, ignoredTraceIds = /* @__PURE__ */ new Set()) {
|
|
13702
14277
|
if (!connection.netId) return null;
|
|
13703
14278
|
const anchoredPlacement = this.inputNetLabelPlacements.find(
|
|
13704
14279
|
(placement) => placement.netId === connection.netId && placement.pinIds.length === 1 && placement.pinIds[0] === pinId
|
|
13705
14280
|
);
|
|
13706
|
-
|
|
14281
|
+
const globalConnNetId = knownGlobalConnNetId ?? anchoredPlacement?.globalConnNetId;
|
|
14282
|
+
if (!globalConnNetId) return null;
|
|
13707
14283
|
const inputChip = this.inputProblem.chips.find(
|
|
13708
14284
|
(chip) => chip.pins.some((pin) => pin.pinId === pinId)
|
|
13709
14285
|
);
|
|
@@ -13712,6 +14288,7 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13712
14288
|
const netLabelText = connection.netLabelText?.trim() || void 0;
|
|
13713
14289
|
const width = connection.inlineNetLabelWidth ?? connection.netLabelWidth ?? estimateInlineNetLabelWidth(netLabelText ?? connection.netId, height);
|
|
13714
14290
|
const stubLength = Math.max(width + 0.2, 0.6);
|
|
14291
|
+
if (!inputPin && !anchoredPlacement) return null;
|
|
13715
14292
|
const start = inputPin ? { x: inputPin.x, y: inputPin.y } : anchoredPlacement.anchorPoint;
|
|
13716
14293
|
const direction = inputPin && inputChip ? inputPin._facingDirection ?? getPinDirection(inputPin, inputChip) : anchoredPlacement.orientation;
|
|
13717
14294
|
const intendedEnd = direction === "x+" ? { x: start.x + stubLength, y: start.y } : direction === "x-" ? { x: start.x - stubLength, y: start.y } : direction === "y+" ? { x: start.x, y: start.y + stubLength } : { x: start.x, y: start.y - stubLength };
|
|
@@ -13720,53 +14297,60 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13720
14297
|
intendedEnd,
|
|
13721
14298
|
minimumLength: width + 2 * INLINE_NET_LABEL_TRACE_MARGIN,
|
|
13722
14299
|
traces: this.traces,
|
|
13723
|
-
ownGlobalConnNetId:
|
|
14300
|
+
ownGlobalConnNetId: globalConnNetId,
|
|
14301
|
+
ignoredTraceIds
|
|
13724
14302
|
});
|
|
13725
14303
|
if (!end) return null;
|
|
13726
14304
|
const axis = direction === "x+" || direction === "x-" ? "x" : "y";
|
|
13727
|
-
const side = axis === "x" ? "y+" : "x-";
|
|
13728
14305
|
const anchorPoint = {
|
|
13729
14306
|
x: (start.x + end.x) / 2,
|
|
13730
14307
|
y: (start.y + end.y) / 2
|
|
13731
14308
|
};
|
|
13732
14309
|
const offset = height / 2 + INLINE_NET_LABEL_TRACE_MARGIN;
|
|
13733
|
-
const
|
|
13734
|
-
const
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
14310
|
+
const sides = axis === "x" ? ["y+", "y-"] : ["x-", "x+"];
|
|
14311
|
+
for (const side of sides) {
|
|
14312
|
+
const center = side === "y+" ? { x: anchorPoint.x, y: anchorPoint.y + offset } : side === "y-" ? { x: anchorPoint.x, y: anchorPoint.y - offset } : side === "x-" ? { x: anchorPoint.x - offset, y: anchorPoint.y } : { x: anchorPoint.x + offset, y: anchorPoint.y };
|
|
14313
|
+
const halfAlong = width / 2;
|
|
14314
|
+
const halfAcross = height / 2;
|
|
14315
|
+
const bounds = axis === "x" ? {
|
|
14316
|
+
minX: center.x - halfAlong,
|
|
14317
|
+
maxX: center.x + halfAlong,
|
|
14318
|
+
minY: center.y - halfAcross,
|
|
14319
|
+
maxY: center.y + halfAcross
|
|
14320
|
+
} : {
|
|
14321
|
+
minX: center.x - halfAcross,
|
|
14322
|
+
maxX: center.x + halfAcross,
|
|
14323
|
+
minY: center.y - halfAlong,
|
|
14324
|
+
maxY: center.y + halfAlong
|
|
14325
|
+
};
|
|
14326
|
+
if (this.isObstructed(bounds, {
|
|
14327
|
+
ownGlobalConnNetId: globalConnNetId,
|
|
14328
|
+
ignoredTraceIds
|
|
14329
|
+
})) {
|
|
14330
|
+
continue;
|
|
14331
|
+
}
|
|
14332
|
+
return {
|
|
14333
|
+
globalConnNetId,
|
|
14334
|
+
netId: connection.netId,
|
|
14335
|
+
netLabelText,
|
|
14336
|
+
pinIds: [pinId],
|
|
14337
|
+
stubTracePath: [start, end],
|
|
14338
|
+
axis,
|
|
14339
|
+
anchorPoint,
|
|
14340
|
+
center,
|
|
14341
|
+
width,
|
|
14342
|
+
height,
|
|
14343
|
+
side
|
|
14344
|
+
};
|
|
13751
14345
|
}
|
|
13752
|
-
return
|
|
13753
|
-
globalConnNetId: anchoredPlacement.globalConnNetId,
|
|
13754
|
-
netId: connection.netId,
|
|
13755
|
-
netLabelText,
|
|
13756
|
-
pinIds: [pinId],
|
|
13757
|
-
stubTracePath: [start, end],
|
|
13758
|
-
axis,
|
|
13759
|
-
anchorPoint,
|
|
13760
|
-
center,
|
|
13761
|
-
width,
|
|
13762
|
-
height,
|
|
13763
|
-
side
|
|
13764
|
-
};
|
|
14346
|
+
return null;
|
|
13765
14347
|
}
|
|
13766
|
-
computeInlinePlacement(
|
|
13767
|
-
|
|
13768
|
-
|
|
13769
|
-
|
|
14348
|
+
computeInlinePlacement({
|
|
14349
|
+
connection,
|
|
14350
|
+
trace,
|
|
14351
|
+
pinIds,
|
|
14352
|
+
ignoredTraceIds = /* @__PURE__ */ new Set()
|
|
14353
|
+
}) {
|
|
13770
14354
|
const segments = getAxisAlignedSegments(trace.tracePath);
|
|
13771
14355
|
if (segments.length === 0) return null;
|
|
13772
14356
|
const height = connection.inlineNetLabelHeight ?? DEFAULT_INLINE_NET_LABEL_HEIGHT;
|
|
@@ -13794,7 +14378,8 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13794
14378
|
};
|
|
13795
14379
|
if (this.isObstructed(bounds, {
|
|
13796
14380
|
ownTrace: trace,
|
|
13797
|
-
ownGlobalConnNetId: trace.globalConnNetId
|
|
14381
|
+
ownGlobalConnNetId: trace.globalConnNetId,
|
|
14382
|
+
ignoredTraceIds
|
|
13798
14383
|
}))
|
|
13799
14384
|
continue;
|
|
13800
14385
|
return {
|
|
@@ -13802,7 +14387,7 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13802
14387
|
netId: connection.netId,
|
|
13803
14388
|
netLabelText,
|
|
13804
14389
|
mspPairId: trace.mspPairId,
|
|
13805
|
-
pinIds: [...
|
|
14390
|
+
pinIds: [...pinIds],
|
|
13806
14391
|
axis: segment.axis,
|
|
13807
14392
|
anchorPoint,
|
|
13808
14393
|
center,
|
|
@@ -13819,7 +14404,9 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13819
14404
|
netLabelText,
|
|
13820
14405
|
width,
|
|
13821
14406
|
height,
|
|
13822
|
-
offset
|
|
14407
|
+
offset,
|
|
14408
|
+
pinIds,
|
|
14409
|
+
ignoredTraceIds
|
|
13823
14410
|
});
|
|
13824
14411
|
if (spanPlacement) return spanPlacement;
|
|
13825
14412
|
return null;
|
|
@@ -13836,7 +14423,9 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13836
14423
|
netLabelText,
|
|
13837
14424
|
width,
|
|
13838
14425
|
height,
|
|
13839
|
-
offset
|
|
14426
|
+
offset,
|
|
14427
|
+
pinIds,
|
|
14428
|
+
ignoredTraceIds
|
|
13840
14429
|
}) {
|
|
13841
14430
|
const path = trace.tracePath;
|
|
13842
14431
|
if (path.length < 2) return null;
|
|
@@ -13886,7 +14475,8 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13886
14475
|
};
|
|
13887
14476
|
if (this.isObstructed(bounds, {
|
|
13888
14477
|
ownTrace: trace,
|
|
13889
|
-
ownGlobalConnNetId: trace.globalConnNetId
|
|
14478
|
+
ownGlobalConnNetId: trace.globalConnNetId,
|
|
14479
|
+
ignoredTraceIds
|
|
13890
14480
|
}))
|
|
13891
14481
|
continue;
|
|
13892
14482
|
const anchorPoint = axis === "x" ? { x: along, y: side === "y+" ? maxY : minY } : { x: side === "x-" ? minX : maxX, y: along };
|
|
@@ -13895,7 +14485,7 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13895
14485
|
netId: connection.netId,
|
|
13896
14486
|
netLabelText,
|
|
13897
14487
|
mspPairId: trace.mspPairId,
|
|
13898
|
-
pinIds: [...
|
|
14488
|
+
pinIds: [...pinIds],
|
|
13899
14489
|
axis,
|
|
13900
14490
|
anchorPoint,
|
|
13901
14491
|
center,
|
|
@@ -13913,7 +14503,8 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13913
14503
|
*/
|
|
13914
14504
|
isObstructed(bounds, {
|
|
13915
14505
|
ownTrace,
|
|
13916
|
-
ownGlobalConnNetId
|
|
14506
|
+
ownGlobalConnNetId,
|
|
14507
|
+
ignoredTraceIds = /* @__PURE__ */ new Set()
|
|
13917
14508
|
}) {
|
|
13918
14509
|
for (const chip of this.inputProblem.chips) {
|
|
13919
14510
|
const chipBounds = {
|
|
@@ -13928,9 +14519,10 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13928
14519
|
if (boundsOverlap(bounds, getTextBoxBounds(textBox))) return true;
|
|
13929
14520
|
}
|
|
13930
14521
|
for (const trace of this.traces) {
|
|
14522
|
+
if (ignoredTraceIds.has(trace.mspPairId)) continue;
|
|
13931
14523
|
if (ownTrace && trace.mspPairId === ownTrace.mspPairId) continue;
|
|
13932
14524
|
if (trace.globalConnNetId === ownGlobalConnNetId) continue;
|
|
13933
|
-
if (
|
|
14525
|
+
if (doesPathIntersectBounds3(trace.tracePath, bounds)) return true;
|
|
13934
14526
|
}
|
|
13935
14527
|
return false;
|
|
13936
14528
|
}
|
|
@@ -13938,36 +14530,94 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13938
14530
|
* Net label placements superseded by an inline label. A net gets one label or
|
|
13939
14531
|
* the other, never both.
|
|
13940
14532
|
*/
|
|
13941
|
-
getSupersededNetLabelKeys() {
|
|
14533
|
+
getSupersededNetLabelKeys(placements = this.inlineNetLabelPlacements) {
|
|
13942
14534
|
const keys = /* @__PURE__ */ new Set();
|
|
13943
|
-
for (const placement of
|
|
14535
|
+
for (const placement of placements) {
|
|
13944
14536
|
keys.add(placement.globalConnNetId);
|
|
13945
14537
|
}
|
|
13946
14538
|
return keys;
|
|
13947
14539
|
}
|
|
13948
|
-
getOutputTraces(supersededNetLabelKeys) {
|
|
14540
|
+
getOutputTraces(supersededNetLabelKeys, supersededTraceIds) {
|
|
13949
14541
|
return this.traces.filter(
|
|
13950
|
-
(trace) => !(supersededNetLabelKeys.has(trace.globalConnNetId) && trace
|
|
14542
|
+
(trace) => !supersededTraceIds.has(trace.mspPairId) && !(supersededNetLabelKeys.has(trace.globalConnNetId) && isGeneratedAnchoredLabelConnector(trace))
|
|
13951
14543
|
);
|
|
13952
14544
|
}
|
|
14545
|
+
getInlineGlobalsOverlappingAnchoredLabels({
|
|
14546
|
+
inlineNetLabelPlacements,
|
|
14547
|
+
anchoredNetLabelPlacements
|
|
14548
|
+
}) {
|
|
14549
|
+
const blockedGlobalConnNetIds = /* @__PURE__ */ new Set();
|
|
14550
|
+
for (const inlinePlacement of inlineNetLabelPlacements) {
|
|
14551
|
+
const inlineBounds = getInlinePlacementBounds(inlinePlacement);
|
|
14552
|
+
for (const anchoredPlacement of anchoredNetLabelPlacements) {
|
|
14553
|
+
if (anchoredPlacement.globalConnNetId === inlinePlacement.globalConnNetId) {
|
|
14554
|
+
continue;
|
|
14555
|
+
}
|
|
14556
|
+
const anchoredBounds = getAnchoredPlacementBounds(anchoredPlacement);
|
|
14557
|
+
if (boundsOverlap(inlineBounds, anchoredBounds) || inlinePlacement.stubTracePath && doesPathIntersectBounds3(
|
|
14558
|
+
inlinePlacement.stubTracePath,
|
|
14559
|
+
anchoredBounds
|
|
14560
|
+
)) {
|
|
14561
|
+
blockedGlobalConnNetIds.add(inlinePlacement.globalConnNetId);
|
|
14562
|
+
break;
|
|
14563
|
+
}
|
|
14564
|
+
}
|
|
14565
|
+
}
|
|
14566
|
+
return blockedGlobalConnNetIds;
|
|
14567
|
+
}
|
|
13953
14568
|
buildPostProcessedOutput() {
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
14569
|
+
let activeInlinePlacements = this.inlineNetLabelPlacements;
|
|
14570
|
+
while (true) {
|
|
14571
|
+
const supersededNetLabelKeys = this.getSupersededNetLabelKeys(
|
|
14572
|
+
activeInlinePlacements
|
|
14573
|
+
);
|
|
14574
|
+
const supersededTraceIds = new Set(
|
|
14575
|
+
[...supersededNetLabelKeys].flatMap((globalConnNetId) => [
|
|
14576
|
+
...this.supersededTraceIdsByGlobalConnNetId.get(globalConnNetId) ?? []
|
|
14577
|
+
])
|
|
14578
|
+
);
|
|
14579
|
+
const retainedNetLabelPlacements = this.inputNetLabelPlacements.filter(
|
|
14580
|
+
(placement) => !supersededNetLabelKeys.has(placement.globalConnNetId)
|
|
14581
|
+
);
|
|
14582
|
+
const outputTraces = this.getOutputTraces(
|
|
14583
|
+
supersededNetLabelKeys,
|
|
14584
|
+
supersededTraceIds
|
|
14585
|
+
);
|
|
14586
|
+
const pushed = pushAnchoredNetLabelsAwayFromInlineLabels({
|
|
14587
|
+
inputProblem: this.inputProblem,
|
|
14588
|
+
traces: outputTraces,
|
|
14589
|
+
netLabelPlacements: retainedNetLabelPlacements,
|
|
14590
|
+
inlineNetLabelPlacements: activeInlinePlacements
|
|
14591
|
+
});
|
|
14592
|
+
const blockedGlobalConnNetIds = this.getInlineGlobalsOverlappingAnchoredLabels({
|
|
14593
|
+
inlineNetLabelPlacements: activeInlinePlacements,
|
|
14594
|
+
anchoredNetLabelPlacements: pushed.netLabelPlacements
|
|
14595
|
+
});
|
|
14596
|
+
if (blockedGlobalConnNetIds.size > 0) {
|
|
14597
|
+
const shiftedInlineTerminalLabels = pushInlineTerminalLabelsAwayFromAnchoredLabels({
|
|
14598
|
+
inputProblem: this.inputProblem,
|
|
14599
|
+
traces: pushed.traces,
|
|
14600
|
+
anchoredNetLabelPlacements: pushed.netLabelPlacements,
|
|
14601
|
+
inlineNetLabelPlacements: activeInlinePlacements
|
|
14602
|
+
});
|
|
14603
|
+
if (shiftedInlineTerminalLabels.movedGroupCount > 0) {
|
|
14604
|
+
activeInlinePlacements = shiftedInlineTerminalLabels.inlineNetLabelPlacements;
|
|
14605
|
+
continue;
|
|
14606
|
+
}
|
|
14607
|
+
}
|
|
14608
|
+
if (blockedGlobalConnNetIds.size === 0) {
|
|
14609
|
+
this.inlineNetLabelPlacements = activeInlinePlacements;
|
|
14610
|
+
this.stats.pushedAnchoredNetLabelCount = pushed.movedLabelCount;
|
|
14611
|
+
return {
|
|
14612
|
+
traces: pushed.traces,
|
|
14613
|
+
netLabelPlacements: pushed.netLabelPlacements,
|
|
14614
|
+
inlineNetLabelPlacements: activeInlinePlacements
|
|
14615
|
+
};
|
|
14616
|
+
}
|
|
14617
|
+
activeInlinePlacements = activeInlinePlacements.filter(
|
|
14618
|
+
(placement) => !blockedGlobalConnNetIds.has(placement.globalConnNetId)
|
|
14619
|
+
);
|
|
14620
|
+
}
|
|
13971
14621
|
}
|
|
13972
14622
|
getOutput() {
|
|
13973
14623
|
if (this.postProcessedOutput) return this.postProcessedOutput;
|
|
@@ -14102,7 +14752,7 @@ var getAnchorCandidates = (segment, labelWidth, step = 0.1) => {
|
|
|
14102
14752
|
offsets.push(slack / 2, -slack / 2);
|
|
14103
14753
|
return offsets.map((offset) => pointAt(mid + offset * direction));
|
|
14104
14754
|
};
|
|
14105
|
-
var
|
|
14755
|
+
var doesPathIntersectBounds3 = (path, bounds) => {
|
|
14106
14756
|
for (let i = 0; i < path.length - 1; i++) {
|
|
14107
14757
|
const a = path[i];
|
|
14108
14758
|
const b = path[i + 1];
|
|
@@ -14122,7 +14772,8 @@ var getCollisionLimitedTerminalStubEnd = ({
|
|
|
14122
14772
|
intendedEnd,
|
|
14123
14773
|
minimumLength,
|
|
14124
14774
|
traces,
|
|
14125
|
-
ownGlobalConnNetId
|
|
14775
|
+
ownGlobalConnNetId,
|
|
14776
|
+
ignoredTraceIds
|
|
14126
14777
|
}) => {
|
|
14127
14778
|
const isHorizontal4 = Math.abs(intendedEnd.x - start.x) >= Math.abs(intendedEnd.y - start.y);
|
|
14128
14779
|
const alongAxis = isHorizontal4 ? "x" : "y";
|
|
@@ -14131,6 +14782,7 @@ var getCollisionLimitedTerminalStubEnd = ({
|
|
|
14131
14782
|
const intendedLength = Math.abs(intendedEnd[alongAxis] - start[alongAxis]);
|
|
14132
14783
|
let availableLength = intendedLength;
|
|
14133
14784
|
for (const trace of traces) {
|
|
14785
|
+
if (ignoredTraceIds.has(trace.mspPairId)) continue;
|
|
14134
14786
|
if (trace.globalConnNetId === ownGlobalConnNetId) continue;
|
|
14135
14787
|
for (let segmentIndex = 0; segmentIndex < trace.tracePath.length - 1; segmentIndex++) {
|
|
14136
14788
|
const segmentStart = trace.tracePath[segmentIndex];
|