@tscircuit/schematic-trace-solver 0.0.183 → 0.0.185
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.js +242 -24
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +30 -12
- package/lib/solvers/SameNetJunctionAlignmentSolver/collapseRedundantSharedEndpointStubs.ts +267 -0
- package/lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts +1 -1
- package/lib/solvers/SameNetJunctionAlignmentSolver/getSharedPin.ts +13 -0
- package/lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts +12 -4
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260905T041712Z.page.tsx +4 -0
- 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-20260707T020342Z/bug-report-20260707T020342Z.test.ts +10 -0
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +524 -533
- package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.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-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-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 +2 -2
- package/tests/bug-reports/bug-report-20260728T144234Z/bug-report-20260728T144234Z.test.ts +2 -0
- package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260730T061837Z/bug-report-20260730T061837Z.test.ts +1 -1
- package/tests/bug-reports/bug-report-20260731T052229Z/__snapshots__/bug-report-20260731T052229Z.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-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 +2 -2
- 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 +2 -2
- package/tests/bug-reports/bug-report-20260901T055358Z/__snapshots__/bug-report-20260901T055358Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260901T064117Z/__snapshots__/bug-report-20260901T064117Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260901T134241Z/__snapshots__/bug-report-20260901T134241Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260902T092425Z/__snapshots__/bug-report-20260902T092425Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260905T041712Z/__snapshots__/bug-report-20260905T041712Z.snap.svg +546 -0
- package/tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.json +2023 -0
- package/tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.test.ts +33 -0
- package/tests/examples/__snapshots__/example02.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__/example18.snap.svg +2 -2
- package/tests/examples/__snapshots__/example19.snap.svg +2 -2
- package/tests/examples/__snapshots__/example21.snap.svg +2 -2
- package/tests/examples/__snapshots__/example27.snap.svg +2 -2
- package/tests/examples/__snapshots__/example29.snap.svg +2 -2
- package/tests/examples/__snapshots__/example42.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__/example51.snap.svg +2 -2
- package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +2 -2
- package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +2 -2
- package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +2 -2
- package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-battery-management-bq24073.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bc107a-common-emitter-routing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bluetooth-controller-ground-decoupling-groups.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-board-8090-power-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-bq40z60-current-sense.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-core-ground-inline-label-fallback.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-esp12f-section.snap.svg +508 -0
- package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-hdc2080-ground-label-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-hdc3020-ground-label-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-hub-usb-sheet.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ina237-current-monitor.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-isolated-rs485-isow7841.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-mspm0l1306-capacitor-symmetry.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 +2 -2
- package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +18 -18
- package/tests/repros/__snapshots__/repro-power-group-rail-labels.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-powerbank-3v-system-power.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-smartwatch-power-sheet.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tida-01389-hbridge.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tida00553-j4-cell-divider.snap.svg +2 -2
- 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-tmp1075-ground-label-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-trellis-core-gnd-net-label-overlap.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 +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 +2 -2
- package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +2 -2
- package/tests/repros/assets/repro-esp12f-status-section.input.json +1394 -0
- package/tests/repros/repro-esp12f-section.test.ts +12 -0
- package/tests/solvers/SameNetJunctionAlignmentSolver/collapse-redundant-shared-endpoint-stubs.test.ts +101 -0
- package/tests/solvers/UnroutedTraceRecoverySolver/local-elbow-obstacles.test.ts +74 -0
package/dist/index.js
CHANGED
|
@@ -12659,6 +12659,7 @@ ${c.status}`
|
|
|
12659
12659
|
|
|
12660
12660
|
// lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts
|
|
12661
12661
|
import { distance as distance6, doSegmentsIntersect as doSegmentsIntersect3 } from "@tscircuit/math-utils";
|
|
12662
|
+
import { calculateElbow as calculateElbow3 } from "calculate-elbow";
|
|
12662
12663
|
var ROUTE_CLEARANCE = 0.2;
|
|
12663
12664
|
var COORDINATE_TOLERANCE = 1e-9;
|
|
12664
12665
|
var GROUND_NET_ID = "GND";
|
|
@@ -12711,7 +12712,7 @@ var getOuterBounds = (obstacles) => {
|
|
|
12711
12712
|
maxY: Math.max(...obstacles.map((obstacle) => obstacle.maxY))
|
|
12712
12713
|
};
|
|
12713
12714
|
};
|
|
12714
|
-
var
|
|
12715
|
+
var getPinConnectionCandidates = ({
|
|
12715
12716
|
connectionPair,
|
|
12716
12717
|
obstacles
|
|
12717
12718
|
}) => {
|
|
@@ -12733,7 +12734,13 @@ var getPerimeterCandidates = ({
|
|
|
12733
12734
|
outerBounds.minX - ROUTE_CLEARANCE,
|
|
12734
12735
|
outerBounds.maxX + ROUTE_CLEARANCE
|
|
12735
12736
|
];
|
|
12736
|
-
const candidates = [
|
|
12737
|
+
const candidates = [
|
|
12738
|
+
calculateElbow3(
|
|
12739
|
+
{ ...firstPin, facingDirection: firstPin._facingDirection },
|
|
12740
|
+
{ ...secondPin, facingDirection: secondPin._facingDirection },
|
|
12741
|
+
{ overshoot: ROUTE_CLEARANCE }
|
|
12742
|
+
)
|
|
12743
|
+
];
|
|
12737
12744
|
for (const channelY of horizontalChannels) {
|
|
12738
12745
|
candidates.push(
|
|
12739
12746
|
removeConsecutiveDuplicatePoints([
|
|
@@ -13053,11 +13060,11 @@ var UnroutedTraceRecoverySolver = class extends BaseSolver {
|
|
|
13053
13060
|
obstacles,
|
|
13054
13061
|
maxConnectionDistance: this.maxConnectionDistance
|
|
13055
13062
|
});
|
|
13056
|
-
const
|
|
13063
|
+
const pinConnectionCandidates = getPinConnectionCandidates({
|
|
13057
13064
|
connectionPair,
|
|
13058
13065
|
obstacles
|
|
13059
13066
|
});
|
|
13060
|
-
const candidates = [...junctionCandidates, ...
|
|
13067
|
+
const candidates = [...junctionCandidates, ...pinConnectionCandidates];
|
|
13061
13068
|
const rejectComponentBoundaryTravel = hasParallelFailedConnection({
|
|
13062
13069
|
connectionPair,
|
|
13063
13070
|
failedConnectionPairs: this.failedConnectionPairs
|
|
@@ -13230,24 +13237,228 @@ var findNearestSharedPinExitRail = ({
|
|
|
13230
13237
|
return nearestRail;
|
|
13231
13238
|
};
|
|
13232
13239
|
|
|
13240
|
+
// lib/solvers/SameNetJunctionAlignmentSolver/getSharedPin.ts
|
|
13241
|
+
var getSharedPin = ({
|
|
13242
|
+
donorTrace,
|
|
13243
|
+
branchTrace
|
|
13244
|
+
}) => {
|
|
13245
|
+
const branchPinIds = new Set(branchTrace.pins.map((pin) => pin.pinId));
|
|
13246
|
+
return donorTrace.pins.find((pin) => branchPinIds.has(pin.pinId)) ?? null;
|
|
13247
|
+
};
|
|
13248
|
+
|
|
13249
|
+
// lib/solvers/SameNetJunctionAlignmentSolver/collapseRedundantSharedEndpointStubs.ts
|
|
13250
|
+
var getSegmentAxis3 = (start, end) => {
|
|
13251
|
+
if (nearlyEqual(start.x, end.x)) return "y";
|
|
13252
|
+
if (nearlyEqual(start.y, end.y)) return "x";
|
|
13253
|
+
return null;
|
|
13254
|
+
};
|
|
13255
|
+
var getPathFromSharedPin = ({
|
|
13256
|
+
trace,
|
|
13257
|
+
sharedPinId
|
|
13258
|
+
}) => {
|
|
13259
|
+
const tracePath = simplifyPath(trace.tracePath);
|
|
13260
|
+
if (trace.pins[0]?.pinId === sharedPinId) return tracePath;
|
|
13261
|
+
return tracePath.reverse();
|
|
13262
|
+
};
|
|
13263
|
+
var traceCanLoseSharedPrefix = ({
|
|
13264
|
+
trace,
|
|
13265
|
+
sharedPrefix,
|
|
13266
|
+
netLabelPlacements
|
|
13267
|
+
}) => {
|
|
13268
|
+
return !netLabelPlacements.some(
|
|
13269
|
+
(label) => label.mspConnectionPairIds.includes(trace.mspPairId) && tracePathContainsPoint(sharedPrefix, label.anchorPoint)
|
|
13270
|
+
);
|
|
13271
|
+
};
|
|
13272
|
+
var getTraceWithoutSharedPrefix = ({
|
|
13273
|
+
trace,
|
|
13274
|
+
pathFromSharedPin,
|
|
13275
|
+
sharedPinId,
|
|
13276
|
+
branchPoint
|
|
13277
|
+
}) => {
|
|
13278
|
+
const branchSegmentIndex = pathFromSharedPin.findIndex((point, index) => {
|
|
13279
|
+
const nextPoint = pathFromSharedPin[index + 1];
|
|
13280
|
+
if (!nextPoint) return false;
|
|
13281
|
+
return tracePathContainsPoint([point, nextPoint], branchPoint);
|
|
13282
|
+
});
|
|
13283
|
+
if (branchSegmentIndex < 0) return null;
|
|
13284
|
+
const pathFromJunction = simplifyPath([
|
|
13285
|
+
branchPoint,
|
|
13286
|
+
...pathFromSharedPin.slice(branchSegmentIndex + 1)
|
|
13287
|
+
]);
|
|
13288
|
+
let tracePath = pathFromJunction;
|
|
13289
|
+
if (trace.pins[0]?.pinId !== sharedPinId) {
|
|
13290
|
+
tracePath = pathFromJunction.reverse();
|
|
13291
|
+
}
|
|
13292
|
+
return { ...trace, tracePath };
|
|
13293
|
+
};
|
|
13294
|
+
var collapseRedundantSharedEndpointStubs = ({
|
|
13295
|
+
traces,
|
|
13296
|
+
netLabelPlacements,
|
|
13297
|
+
netLabelConnectorTraceIds,
|
|
13298
|
+
multiPinNetPinIds
|
|
13299
|
+
}) => {
|
|
13300
|
+
const outputTraces = [...traces];
|
|
13301
|
+
for (let firstIndex = 0; firstIndex < outputTraces.length; firstIndex++) {
|
|
13302
|
+
const firstTrace = outputTraces[firstIndex];
|
|
13303
|
+
if (netLabelConnectorTraceIds.has(firstTrace.mspPairId)) continue;
|
|
13304
|
+
for (let secondIndex = firstIndex + 1; secondIndex < outputTraces.length; secondIndex++) {
|
|
13305
|
+
const secondTrace = outputTraces[secondIndex];
|
|
13306
|
+
if (netLabelConnectorTraceIds.has(secondTrace.mspPairId) || firstTrace.globalConnNetId !== secondTrace.globalConnNetId) {
|
|
13307
|
+
continue;
|
|
13308
|
+
}
|
|
13309
|
+
const sharedPin = getSharedPin({
|
|
13310
|
+
donorTrace: firstTrace,
|
|
13311
|
+
branchTrace: secondTrace
|
|
13312
|
+
});
|
|
13313
|
+
if (!sharedPin || !multiPinNetPinIds.has(sharedPin.pinId)) continue;
|
|
13314
|
+
const firstPath = getPathFromSharedPin({
|
|
13315
|
+
trace: firstTrace,
|
|
13316
|
+
sharedPinId: sharedPin.pinId
|
|
13317
|
+
});
|
|
13318
|
+
const secondPath = getPathFromSharedPin({
|
|
13319
|
+
trace: secondTrace,
|
|
13320
|
+
sharedPinId: sharedPin.pinId
|
|
13321
|
+
});
|
|
13322
|
+
if (firstPath.length < 2 || secondPath.length < 2) continue;
|
|
13323
|
+
const departureAxis = getSegmentAxis3(firstPath[0], firstPath[1]);
|
|
13324
|
+
const secondDepartureAxis = getSegmentAxis3(secondPath[0], secondPath[1]);
|
|
13325
|
+
if (!departureAxis || departureAxis !== secondDepartureAxis) continue;
|
|
13326
|
+
const firstDepartureDirection = firstPath[1][departureAxis] - firstPath[0][departureAxis];
|
|
13327
|
+
const secondDepartureDirection = secondPath[1][departureAxis] - secondPath[0][departureAxis];
|
|
13328
|
+
if (!pointsEqual2(firstPath[1], secondPath[1]) && Math.sign(firstDepartureDirection) === Math.sign(secondDepartureDirection)) {
|
|
13329
|
+
let traceIndexToCollapse2 = secondIndex;
|
|
13330
|
+
let traceToCollapse2 = secondTrace;
|
|
13331
|
+
let pathToCollapse2 = secondPath;
|
|
13332
|
+
if (Math.abs(firstDepartureDirection) < Math.abs(secondDepartureDirection)) {
|
|
13333
|
+
traceIndexToCollapse2 = firstIndex;
|
|
13334
|
+
traceToCollapse2 = firstTrace;
|
|
13335
|
+
pathToCollapse2 = firstPath;
|
|
13336
|
+
}
|
|
13337
|
+
const branchPoint2 = pathToCollapse2[1];
|
|
13338
|
+
if (!traceCanLoseSharedPrefix({
|
|
13339
|
+
trace: traceToCollapse2,
|
|
13340
|
+
sharedPrefix: [pathToCollapse2[0], branchPoint2],
|
|
13341
|
+
netLabelPlacements
|
|
13342
|
+
})) {
|
|
13343
|
+
if (traceIndexToCollapse2 === firstIndex) {
|
|
13344
|
+
traceIndexToCollapse2 = secondIndex;
|
|
13345
|
+
traceToCollapse2 = secondTrace;
|
|
13346
|
+
pathToCollapse2 = secondPath;
|
|
13347
|
+
} else {
|
|
13348
|
+
traceIndexToCollapse2 = firstIndex;
|
|
13349
|
+
traceToCollapse2 = firstTrace;
|
|
13350
|
+
pathToCollapse2 = firstPath;
|
|
13351
|
+
}
|
|
13352
|
+
}
|
|
13353
|
+
if (!traceCanLoseSharedPrefix({
|
|
13354
|
+
trace: traceToCollapse2,
|
|
13355
|
+
sharedPrefix: [pathToCollapse2[0], branchPoint2],
|
|
13356
|
+
netLabelPlacements
|
|
13357
|
+
})) {
|
|
13358
|
+
continue;
|
|
13359
|
+
}
|
|
13360
|
+
const collapsedTrace2 = getTraceWithoutSharedPrefix({
|
|
13361
|
+
trace: traceToCollapse2,
|
|
13362
|
+
pathFromSharedPin: pathToCollapse2,
|
|
13363
|
+
sharedPinId: sharedPin.pinId,
|
|
13364
|
+
branchPoint: branchPoint2
|
|
13365
|
+
});
|
|
13366
|
+
if (!collapsedTrace2) continue;
|
|
13367
|
+
outputTraces[traceIndexToCollapse2] = collapsedTrace2;
|
|
13368
|
+
break;
|
|
13369
|
+
}
|
|
13370
|
+
if (firstPath.length < 3 || secondPath.length < 3) continue;
|
|
13371
|
+
if (!pointsEqual2(firstPath[1], secondPath[1])) continue;
|
|
13372
|
+
const railAxis = getSegmentAxis3(firstPath[1], firstPath[2]);
|
|
13373
|
+
const secondRailAxis = getSegmentAxis3(secondPath[1], secondPath[2]);
|
|
13374
|
+
if (!railAxis || railAxis !== secondRailAxis || railAxis === departureAxis) {
|
|
13375
|
+
continue;
|
|
13376
|
+
}
|
|
13377
|
+
const firstRailDirection = firstPath[2][railAxis] - firstPath[1][railAxis];
|
|
13378
|
+
const secondRailDirection = secondPath[2][railAxis] - secondPath[1][railAxis];
|
|
13379
|
+
const railsHaveSameDirection = Math.sign(firstRailDirection) === Math.sign(secondRailDirection);
|
|
13380
|
+
const sharedStub = firstPath.slice(0, 2);
|
|
13381
|
+
if (!railsHaveSameDirection && !nearlyEqual(
|
|
13382
|
+
Math.abs(firstRailDirection),
|
|
13383
|
+
Math.abs(secondRailDirection)
|
|
13384
|
+
) && netLabelPlacements.some(
|
|
13385
|
+
(label) => label.globalConnNetId === firstTrace.globalConnNetId && tracePathContainsPoint(sharedStub, label.anchorPoint)
|
|
13386
|
+
)) {
|
|
13387
|
+
continue;
|
|
13388
|
+
}
|
|
13389
|
+
let traceIndexToCollapse = secondIndex;
|
|
13390
|
+
let traceToCollapse = secondTrace;
|
|
13391
|
+
let pathToCollapse = secondPath;
|
|
13392
|
+
let branchPoint = firstPath[1];
|
|
13393
|
+
if (railsHaveSameDirection && Math.abs(firstRailDirection) < Math.abs(secondRailDirection)) {
|
|
13394
|
+
traceIndexToCollapse = firstIndex;
|
|
13395
|
+
traceToCollapse = firstTrace;
|
|
13396
|
+
pathToCollapse = firstPath;
|
|
13397
|
+
branchPoint = firstPath[2];
|
|
13398
|
+
} else if (railsHaveSameDirection) {
|
|
13399
|
+
branchPoint = secondPath[2];
|
|
13400
|
+
}
|
|
13401
|
+
const sharedPrefix = [pathToCollapse[0], pathToCollapse[1], branchPoint];
|
|
13402
|
+
if (!traceCanLoseSharedPrefix({
|
|
13403
|
+
trace: traceToCollapse,
|
|
13404
|
+
sharedPrefix,
|
|
13405
|
+
netLabelPlacements
|
|
13406
|
+
})) {
|
|
13407
|
+
if (traceIndexToCollapse === firstIndex) {
|
|
13408
|
+
traceIndexToCollapse = secondIndex;
|
|
13409
|
+
traceToCollapse = secondTrace;
|
|
13410
|
+
pathToCollapse = secondPath;
|
|
13411
|
+
} else {
|
|
13412
|
+
traceIndexToCollapse = firstIndex;
|
|
13413
|
+
traceToCollapse = firstTrace;
|
|
13414
|
+
pathToCollapse = firstPath;
|
|
13415
|
+
}
|
|
13416
|
+
}
|
|
13417
|
+
if (!traceCanLoseSharedPrefix({
|
|
13418
|
+
trace: traceToCollapse,
|
|
13419
|
+
sharedPrefix: [pathToCollapse[0], pathToCollapse[1], branchPoint],
|
|
13420
|
+
netLabelPlacements
|
|
13421
|
+
})) {
|
|
13422
|
+
continue;
|
|
13423
|
+
}
|
|
13424
|
+
const collapsedTrace = getTraceWithoutSharedPrefix({
|
|
13425
|
+
trace: traceToCollapse,
|
|
13426
|
+
pathFromSharedPin: pathToCollapse,
|
|
13427
|
+
sharedPinId: sharedPin.pinId,
|
|
13428
|
+
branchPoint
|
|
13429
|
+
});
|
|
13430
|
+
if (!collapsedTrace) continue;
|
|
13431
|
+
outputTraces[traceIndexToCollapse] = collapsedTrace;
|
|
13432
|
+
break;
|
|
13433
|
+
}
|
|
13434
|
+
}
|
|
13435
|
+
return outputTraces;
|
|
13436
|
+
};
|
|
13437
|
+
|
|
13233
13438
|
// lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
|
|
13234
13439
|
var MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2;
|
|
13235
13440
|
var MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2;
|
|
13236
13441
|
var MAX_SHARED_PIN_RAIL_OFFSET = 0.05;
|
|
13237
13442
|
var MAX_SHARED_ENDPOINT_RAIL_OFFSET = 0.8;
|
|
13238
13443
|
var MIN_RETURN_STEM_LENGTH = 0.05;
|
|
13239
|
-
var
|
|
13444
|
+
var getMultiPinNetPinIds = (inputProblem) => {
|
|
13445
|
+
const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
13446
|
+
const inputPinIds = new Set(
|
|
13447
|
+
inputProblem.chips.flatMap((chip) => chip.pins.map((pin) => pin.pinId))
|
|
13448
|
+
);
|
|
13449
|
+
return new Set(
|
|
13450
|
+
[...inputPinIds].filter((pinId) => {
|
|
13451
|
+
const globalNetId = netConnMap.getNetConnectedToId(pinId);
|
|
13452
|
+
if (!globalNetId) return false;
|
|
13453
|
+
return netConnMap.getIdsConnectedToNet(globalNetId).filter((connectedId) => inputPinIds.has(connectedId)).length > 2;
|
|
13454
|
+
})
|
|
13455
|
+
);
|
|
13456
|
+
};
|
|
13457
|
+
var getSegmentAxis4 = (start, end) => {
|
|
13240
13458
|
if (isHorizontal2(start, end)) return "x";
|
|
13241
13459
|
if (isVertical2(start, end)) return "y";
|
|
13242
13460
|
return null;
|
|
13243
13461
|
};
|
|
13244
|
-
var getSharedPin = ({
|
|
13245
|
-
donorTrace,
|
|
13246
|
-
branchTrace
|
|
13247
|
-
}) => {
|
|
13248
|
-
const branchPinIds = new Set(branchTrace.pins.map((pin) => pin.pinId));
|
|
13249
|
-
return donorTrace.pins.find((pin) => branchPinIds.has(pin.pinId)) ?? null;
|
|
13250
|
-
};
|
|
13251
13462
|
var getOtherPin = ({
|
|
13252
13463
|
trace,
|
|
13253
13464
|
sharedPin
|
|
@@ -13473,8 +13684,8 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13473
13684
|
const donorPath = pathFromShared(donorTrace);
|
|
13474
13685
|
const branchPath = pathFromShared(branchTrace);
|
|
13475
13686
|
if (donorPath.length < 3 || branchPath.length < 4) return null;
|
|
13476
|
-
const donorDepartureAxis =
|
|
13477
|
-
const branchDepartureAxis =
|
|
13687
|
+
const donorDepartureAxis = getSegmentAxis4(donorPath[0], donorPath[1]);
|
|
13688
|
+
const branchDepartureAxis = getSegmentAxis4(branchPath[0], branchPath[1]);
|
|
13478
13689
|
if (!donorDepartureAxis || donorDepartureAxis !== branchDepartureAxis) {
|
|
13479
13690
|
return null;
|
|
13480
13691
|
}
|
|
@@ -13482,8 +13693,8 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13482
13693
|
const branchDeparture = branchPath[1][branchDepartureAxis] - branchPath[0][branchDepartureAxis];
|
|
13483
13694
|
if (Math.sign(donorDeparture) !== Math.sign(branchDeparture)) return null;
|
|
13484
13695
|
let railIndex = 1;
|
|
13485
|
-
let donorRailAxis =
|
|
13486
|
-
let branchRailAxis =
|
|
13696
|
+
let donorRailAxis = getSegmentAxis4(donorPath[1], donorPath[2]);
|
|
13697
|
+
let branchRailAxis = getSegmentAxis4(branchPath[1], branchPath[2]);
|
|
13487
13698
|
if (!donorRailAxis || donorRailAxis !== branchRailAxis || donorRailAxis === donorDepartureAxis) {
|
|
13488
13699
|
return null;
|
|
13489
13700
|
}
|
|
@@ -13491,11 +13702,11 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13491
13702
|
if (firstRailsAreAligned) {
|
|
13492
13703
|
railIndex++;
|
|
13493
13704
|
if (!donorPath[railIndex + 2] || !branchPath[railIndex + 2]) return null;
|
|
13494
|
-
donorRailAxis =
|
|
13705
|
+
donorRailAxis = getSegmentAxis4(
|
|
13495
13706
|
donorPath[railIndex],
|
|
13496
13707
|
donorPath[railIndex + 1]
|
|
13497
13708
|
);
|
|
13498
|
-
branchRailAxis =
|
|
13709
|
+
branchRailAxis = getSegmentAxis4(
|
|
13499
13710
|
branchPath[railIndex],
|
|
13500
13711
|
branchPath[railIndex + 1]
|
|
13501
13712
|
);
|
|
@@ -13503,7 +13714,7 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13503
13714
|
}
|
|
13504
13715
|
let branchParallelRailCount = 0;
|
|
13505
13716
|
for (let index = 1; index < branchPath.length - 2; index++) {
|
|
13506
|
-
if (
|
|
13717
|
+
if (getSegmentAxis4(branchPath[index], branchPath[index + 1]) === branchRailAxis) {
|
|
13507
13718
|
branchParallelRailCount++;
|
|
13508
13719
|
}
|
|
13509
13720
|
}
|
|
@@ -13545,13 +13756,13 @@ var getAlignedAttachedLabelConnectorPath = ({
|
|
|
13545
13756
|
const junction = connectorPath[0];
|
|
13546
13757
|
const turn = connectorPath[1];
|
|
13547
13758
|
const railEnd = connectorPath[2];
|
|
13548
|
-
const departureAxis =
|
|
13549
|
-
const railAxis =
|
|
13759
|
+
const departureAxis = getSegmentAxis4(junction, turn);
|
|
13760
|
+
const railAxis = getSegmentAxis4(turn, railEnd);
|
|
13550
13761
|
if (!departureAxis || !railAxis || departureAxis === railAxis) return null;
|
|
13551
13762
|
const donorSegmentIndex = donorTrace.tracePath.findIndex(
|
|
13552
13763
|
(point, index, path) => {
|
|
13553
13764
|
const next = path[index + 1];
|
|
13554
|
-
return next &&
|
|
13765
|
+
return next && getSegmentAxis4(point, next) === departureAxis && tracePathContainsPoint([point, next], junction) && tracePathContainsPoint([point, next], turn);
|
|
13555
13766
|
}
|
|
13556
13767
|
);
|
|
13557
13768
|
if (donorSegmentIndex < 0) return null;
|
|
@@ -13564,7 +13775,7 @@ var getAlignedAttachedLabelConnectorPath = ({
|
|
|
13564
13775
|
donorSegmentIndex > 0 ? [donorTrace.tracePath[donorSegmentIndex - 1], donorSegmentStart] : null,
|
|
13565
13776
|
donorSegmentIndex + 2 < donorTrace.tracePath.length ? [donorSegmentEnd, donorTrace.tracePath[donorSegmentIndex + 2]] : null
|
|
13566
13777
|
].flatMap(
|
|
13567
|
-
(segment) => segment &&
|
|
13778
|
+
(segment) => segment && getSegmentAxis4(segment[0], segment[1]) === railAxis ? [segment] : []
|
|
13568
13779
|
);
|
|
13569
13780
|
if (adjacentDonorRails.length === 0) return null;
|
|
13570
13781
|
const railCoordinateAxis = railAxis === "x" ? "y" : "x";
|
|
@@ -13647,7 +13858,7 @@ var preserveAttachedLabelConnectorJunctions = ({
|
|
|
13647
13858
|
if (!movedJunction) return null;
|
|
13648
13859
|
const neighborIndex = endpointIndex === 0 ? 1 : endpointIndex - 1;
|
|
13649
13860
|
const neighbor = connector.tracePath[neighborIndex];
|
|
13650
|
-
if (!neighbor ||
|
|
13861
|
+
if (!neighbor || getSegmentAxis4(originalJunction, neighbor) !== getSegmentAxis4(movedJunction, neighbor)) {
|
|
13651
13862
|
return null;
|
|
13652
13863
|
}
|
|
13653
13864
|
const movedConnector = {
|
|
@@ -14070,6 +14281,13 @@ var alignSameNetJunctions = ({
|
|
|
14070
14281
|
}
|
|
14071
14282
|
}
|
|
14072
14283
|
}
|
|
14284
|
+
const collapsedSharedEndpointStubs = collapseRedundantSharedEndpointStubs({
|
|
14285
|
+
traces: outputTraces,
|
|
14286
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
14287
|
+
netLabelConnectorTraceIds,
|
|
14288
|
+
multiPinNetPinIds: getMultiPinNetPinIds(inputProblem)
|
|
14289
|
+
});
|
|
14290
|
+
outputTraces = collapsedSharedEndpointStubs;
|
|
14073
14291
|
return {
|
|
14074
14292
|
traces: outputTraces,
|
|
14075
14293
|
netLabelPlacements: outputNetLabelPlacements,
|
|
@@ -2,6 +2,7 @@ import type { Point } from "@tscircuit/math-utils"
|
|
|
2
2
|
import { getSegmentIntersection } from "@tscircuit/math-utils/line-intersections"
|
|
3
3
|
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
4
4
|
import type { MspConnectionPairId } from "lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver"
|
|
5
|
+
import { getConnectivityMapsFromInputProblem } from "lib/solvers/MspConnectionPairSolver/getConnectivityMapFromInputProblem"
|
|
5
6
|
import { getRectBounds } from "lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry"
|
|
6
7
|
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
7
8
|
import { isPathCollidingWithObstacles } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
|
|
@@ -20,7 +21,7 @@ import {
|
|
|
20
21
|
isVertical,
|
|
21
22
|
nearlyEqual,
|
|
22
23
|
} from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
|
|
23
|
-
import type { InputPin, InputProblem } from "lib/types/InputProblem"
|
|
24
|
+
import type { InputPin, InputProblem, PinId } from "lib/types/InputProblem"
|
|
24
25
|
import { doesPathCoincideWithTraces } from "lib/utils/doesPathCoincideWithTraces"
|
|
25
26
|
import {
|
|
26
27
|
pathEntersAnyNetLabel,
|
|
@@ -31,6 +32,8 @@ import {
|
|
|
31
32
|
getPinFacingAxis,
|
|
32
33
|
isCoordinateOnPinFacingSide,
|
|
33
34
|
} from "./findNearestSharedPinExitRail"
|
|
35
|
+
import { collapseRedundantSharedEndpointStubs } from "./collapseRedundantSharedEndpointStubs"
|
|
36
|
+
import { getSharedPin } from "./getSharedPin"
|
|
34
37
|
|
|
35
38
|
interface AlignSameNetJunctionsInput {
|
|
36
39
|
inputProblem: InputProblem
|
|
@@ -57,23 +60,30 @@ const MAX_SHARED_PIN_RAIL_OFFSET = 0.05
|
|
|
57
60
|
const MAX_SHARED_ENDPOINT_RAIL_OFFSET = 0.8
|
|
58
61
|
const MIN_RETURN_STEM_LENGTH = 0.05
|
|
59
62
|
|
|
63
|
+
const getMultiPinNetPinIds = (inputProblem: InputProblem) => {
|
|
64
|
+
const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem)
|
|
65
|
+
const inputPinIds = new Set<PinId>(
|
|
66
|
+
inputProblem.chips.flatMap((chip) => chip.pins.map((pin) => pin.pinId)),
|
|
67
|
+
)
|
|
68
|
+
return new Set(
|
|
69
|
+
[...inputPinIds].filter((pinId) => {
|
|
70
|
+
const globalNetId = netConnMap.getNetConnectedToId(pinId)
|
|
71
|
+
if (!globalNetId) return false
|
|
72
|
+
return (
|
|
73
|
+
netConnMap
|
|
74
|
+
.getIdsConnectedToNet(globalNetId)
|
|
75
|
+
.filter((connectedId) => inputPinIds.has(connectedId)).length > 2
|
|
76
|
+
)
|
|
77
|
+
}),
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
60
81
|
const getSegmentAxis = (start: Point, end: Point) => {
|
|
61
82
|
if (isHorizontal(start, end)) return "x" as const
|
|
62
83
|
if (isVertical(start, end)) return "y" as const
|
|
63
84
|
return null
|
|
64
85
|
}
|
|
65
86
|
|
|
66
|
-
export const getSharedPin = ({
|
|
67
|
-
donorTrace,
|
|
68
|
-
branchTrace,
|
|
69
|
-
}: {
|
|
70
|
-
donorTrace: SolvedTracePath
|
|
71
|
-
branchTrace: SolvedTracePath
|
|
72
|
-
}): (InputPin & { chipId: string }) | null => {
|
|
73
|
-
const branchPinIds = new Set(branchTrace.pins.map((pin) => pin.pinId))
|
|
74
|
-
return donorTrace.pins.find((pin) => branchPinIds.has(pin.pinId)) ?? null
|
|
75
|
-
}
|
|
76
|
-
|
|
77
87
|
const getOtherPin = ({
|
|
78
88
|
trace,
|
|
79
89
|
sharedPin,
|
|
@@ -1301,6 +1311,14 @@ export const alignSameNetJunctions = ({
|
|
|
1301
1311
|
}
|
|
1302
1312
|
}
|
|
1303
1313
|
|
|
1314
|
+
const collapsedSharedEndpointStubs = collapseRedundantSharedEndpointStubs({
|
|
1315
|
+
traces: outputTraces,
|
|
1316
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
1317
|
+
netLabelConnectorTraceIds,
|
|
1318
|
+
multiPinNetPinIds: getMultiPinNetPinIds(inputProblem),
|
|
1319
|
+
})
|
|
1320
|
+
outputTraces = collapsedSharedEndpointStubs
|
|
1321
|
+
|
|
1304
1322
|
return {
|
|
1305
1323
|
traces: outputTraces,
|
|
1306
1324
|
netLabelPlacements: outputNetLabelPlacements,
|