@tscircuit/schematic-trace-solver 0.0.183 → 0.0.184
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 +231 -20
- 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/package.json +1 -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-20260707T020342Z/bug-report-20260707T020342Z.test.ts +10 -0
- 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-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/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/dist/index.js
CHANGED
|
@@ -13230,24 +13230,228 @@ var findNearestSharedPinExitRail = ({
|
|
|
13230
13230
|
return nearestRail;
|
|
13231
13231
|
};
|
|
13232
13232
|
|
|
13233
|
+
// lib/solvers/SameNetJunctionAlignmentSolver/getSharedPin.ts
|
|
13234
|
+
var getSharedPin = ({
|
|
13235
|
+
donorTrace,
|
|
13236
|
+
branchTrace
|
|
13237
|
+
}) => {
|
|
13238
|
+
const branchPinIds = new Set(branchTrace.pins.map((pin) => pin.pinId));
|
|
13239
|
+
return donorTrace.pins.find((pin) => branchPinIds.has(pin.pinId)) ?? null;
|
|
13240
|
+
};
|
|
13241
|
+
|
|
13242
|
+
// lib/solvers/SameNetJunctionAlignmentSolver/collapseRedundantSharedEndpointStubs.ts
|
|
13243
|
+
var getSegmentAxis3 = (start, end) => {
|
|
13244
|
+
if (nearlyEqual(start.x, end.x)) return "y";
|
|
13245
|
+
if (nearlyEqual(start.y, end.y)) return "x";
|
|
13246
|
+
return null;
|
|
13247
|
+
};
|
|
13248
|
+
var getPathFromSharedPin = ({
|
|
13249
|
+
trace,
|
|
13250
|
+
sharedPinId
|
|
13251
|
+
}) => {
|
|
13252
|
+
const tracePath = simplifyPath(trace.tracePath);
|
|
13253
|
+
if (trace.pins[0]?.pinId === sharedPinId) return tracePath;
|
|
13254
|
+
return tracePath.reverse();
|
|
13255
|
+
};
|
|
13256
|
+
var traceCanLoseSharedPrefix = ({
|
|
13257
|
+
trace,
|
|
13258
|
+
sharedPrefix,
|
|
13259
|
+
netLabelPlacements
|
|
13260
|
+
}) => {
|
|
13261
|
+
return !netLabelPlacements.some(
|
|
13262
|
+
(label) => label.mspConnectionPairIds.includes(trace.mspPairId) && tracePathContainsPoint(sharedPrefix, label.anchorPoint)
|
|
13263
|
+
);
|
|
13264
|
+
};
|
|
13265
|
+
var getTraceWithoutSharedPrefix = ({
|
|
13266
|
+
trace,
|
|
13267
|
+
pathFromSharedPin,
|
|
13268
|
+
sharedPinId,
|
|
13269
|
+
branchPoint
|
|
13270
|
+
}) => {
|
|
13271
|
+
const branchSegmentIndex = pathFromSharedPin.findIndex((point, index) => {
|
|
13272
|
+
const nextPoint = pathFromSharedPin[index + 1];
|
|
13273
|
+
if (!nextPoint) return false;
|
|
13274
|
+
return tracePathContainsPoint([point, nextPoint], branchPoint);
|
|
13275
|
+
});
|
|
13276
|
+
if (branchSegmentIndex < 0) return null;
|
|
13277
|
+
const pathFromJunction = simplifyPath([
|
|
13278
|
+
branchPoint,
|
|
13279
|
+
...pathFromSharedPin.slice(branchSegmentIndex + 1)
|
|
13280
|
+
]);
|
|
13281
|
+
let tracePath = pathFromJunction;
|
|
13282
|
+
if (trace.pins[0]?.pinId !== sharedPinId) {
|
|
13283
|
+
tracePath = pathFromJunction.reverse();
|
|
13284
|
+
}
|
|
13285
|
+
return { ...trace, tracePath };
|
|
13286
|
+
};
|
|
13287
|
+
var collapseRedundantSharedEndpointStubs = ({
|
|
13288
|
+
traces,
|
|
13289
|
+
netLabelPlacements,
|
|
13290
|
+
netLabelConnectorTraceIds,
|
|
13291
|
+
multiPinNetPinIds
|
|
13292
|
+
}) => {
|
|
13293
|
+
const outputTraces = [...traces];
|
|
13294
|
+
for (let firstIndex = 0; firstIndex < outputTraces.length; firstIndex++) {
|
|
13295
|
+
const firstTrace = outputTraces[firstIndex];
|
|
13296
|
+
if (netLabelConnectorTraceIds.has(firstTrace.mspPairId)) continue;
|
|
13297
|
+
for (let secondIndex = firstIndex + 1; secondIndex < outputTraces.length; secondIndex++) {
|
|
13298
|
+
const secondTrace = outputTraces[secondIndex];
|
|
13299
|
+
if (netLabelConnectorTraceIds.has(secondTrace.mspPairId) || firstTrace.globalConnNetId !== secondTrace.globalConnNetId) {
|
|
13300
|
+
continue;
|
|
13301
|
+
}
|
|
13302
|
+
const sharedPin = getSharedPin({
|
|
13303
|
+
donorTrace: firstTrace,
|
|
13304
|
+
branchTrace: secondTrace
|
|
13305
|
+
});
|
|
13306
|
+
if (!sharedPin || !multiPinNetPinIds.has(sharedPin.pinId)) continue;
|
|
13307
|
+
const firstPath = getPathFromSharedPin({
|
|
13308
|
+
trace: firstTrace,
|
|
13309
|
+
sharedPinId: sharedPin.pinId
|
|
13310
|
+
});
|
|
13311
|
+
const secondPath = getPathFromSharedPin({
|
|
13312
|
+
trace: secondTrace,
|
|
13313
|
+
sharedPinId: sharedPin.pinId
|
|
13314
|
+
});
|
|
13315
|
+
if (firstPath.length < 2 || secondPath.length < 2) continue;
|
|
13316
|
+
const departureAxis = getSegmentAxis3(firstPath[0], firstPath[1]);
|
|
13317
|
+
const secondDepartureAxis = getSegmentAxis3(secondPath[0], secondPath[1]);
|
|
13318
|
+
if (!departureAxis || departureAxis !== secondDepartureAxis) continue;
|
|
13319
|
+
const firstDepartureDirection = firstPath[1][departureAxis] - firstPath[0][departureAxis];
|
|
13320
|
+
const secondDepartureDirection = secondPath[1][departureAxis] - secondPath[0][departureAxis];
|
|
13321
|
+
if (!pointsEqual2(firstPath[1], secondPath[1]) && Math.sign(firstDepartureDirection) === Math.sign(secondDepartureDirection)) {
|
|
13322
|
+
let traceIndexToCollapse2 = secondIndex;
|
|
13323
|
+
let traceToCollapse2 = secondTrace;
|
|
13324
|
+
let pathToCollapse2 = secondPath;
|
|
13325
|
+
if (Math.abs(firstDepartureDirection) < Math.abs(secondDepartureDirection)) {
|
|
13326
|
+
traceIndexToCollapse2 = firstIndex;
|
|
13327
|
+
traceToCollapse2 = firstTrace;
|
|
13328
|
+
pathToCollapse2 = firstPath;
|
|
13329
|
+
}
|
|
13330
|
+
const branchPoint2 = pathToCollapse2[1];
|
|
13331
|
+
if (!traceCanLoseSharedPrefix({
|
|
13332
|
+
trace: traceToCollapse2,
|
|
13333
|
+
sharedPrefix: [pathToCollapse2[0], branchPoint2],
|
|
13334
|
+
netLabelPlacements
|
|
13335
|
+
})) {
|
|
13336
|
+
if (traceIndexToCollapse2 === firstIndex) {
|
|
13337
|
+
traceIndexToCollapse2 = secondIndex;
|
|
13338
|
+
traceToCollapse2 = secondTrace;
|
|
13339
|
+
pathToCollapse2 = secondPath;
|
|
13340
|
+
} else {
|
|
13341
|
+
traceIndexToCollapse2 = firstIndex;
|
|
13342
|
+
traceToCollapse2 = firstTrace;
|
|
13343
|
+
pathToCollapse2 = firstPath;
|
|
13344
|
+
}
|
|
13345
|
+
}
|
|
13346
|
+
if (!traceCanLoseSharedPrefix({
|
|
13347
|
+
trace: traceToCollapse2,
|
|
13348
|
+
sharedPrefix: [pathToCollapse2[0], branchPoint2],
|
|
13349
|
+
netLabelPlacements
|
|
13350
|
+
})) {
|
|
13351
|
+
continue;
|
|
13352
|
+
}
|
|
13353
|
+
const collapsedTrace2 = getTraceWithoutSharedPrefix({
|
|
13354
|
+
trace: traceToCollapse2,
|
|
13355
|
+
pathFromSharedPin: pathToCollapse2,
|
|
13356
|
+
sharedPinId: sharedPin.pinId,
|
|
13357
|
+
branchPoint: branchPoint2
|
|
13358
|
+
});
|
|
13359
|
+
if (!collapsedTrace2) continue;
|
|
13360
|
+
outputTraces[traceIndexToCollapse2] = collapsedTrace2;
|
|
13361
|
+
break;
|
|
13362
|
+
}
|
|
13363
|
+
if (firstPath.length < 3 || secondPath.length < 3) continue;
|
|
13364
|
+
if (!pointsEqual2(firstPath[1], secondPath[1])) continue;
|
|
13365
|
+
const railAxis = getSegmentAxis3(firstPath[1], firstPath[2]);
|
|
13366
|
+
const secondRailAxis = getSegmentAxis3(secondPath[1], secondPath[2]);
|
|
13367
|
+
if (!railAxis || railAxis !== secondRailAxis || railAxis === departureAxis) {
|
|
13368
|
+
continue;
|
|
13369
|
+
}
|
|
13370
|
+
const firstRailDirection = firstPath[2][railAxis] - firstPath[1][railAxis];
|
|
13371
|
+
const secondRailDirection = secondPath[2][railAxis] - secondPath[1][railAxis];
|
|
13372
|
+
const railsHaveSameDirection = Math.sign(firstRailDirection) === Math.sign(secondRailDirection);
|
|
13373
|
+
const sharedStub = firstPath.slice(0, 2);
|
|
13374
|
+
if (!railsHaveSameDirection && !nearlyEqual(
|
|
13375
|
+
Math.abs(firstRailDirection),
|
|
13376
|
+
Math.abs(secondRailDirection)
|
|
13377
|
+
) && netLabelPlacements.some(
|
|
13378
|
+
(label) => label.globalConnNetId === firstTrace.globalConnNetId && tracePathContainsPoint(sharedStub, label.anchorPoint)
|
|
13379
|
+
)) {
|
|
13380
|
+
continue;
|
|
13381
|
+
}
|
|
13382
|
+
let traceIndexToCollapse = secondIndex;
|
|
13383
|
+
let traceToCollapse = secondTrace;
|
|
13384
|
+
let pathToCollapse = secondPath;
|
|
13385
|
+
let branchPoint = firstPath[1];
|
|
13386
|
+
if (railsHaveSameDirection && Math.abs(firstRailDirection) < Math.abs(secondRailDirection)) {
|
|
13387
|
+
traceIndexToCollapse = firstIndex;
|
|
13388
|
+
traceToCollapse = firstTrace;
|
|
13389
|
+
pathToCollapse = firstPath;
|
|
13390
|
+
branchPoint = firstPath[2];
|
|
13391
|
+
} else if (railsHaveSameDirection) {
|
|
13392
|
+
branchPoint = secondPath[2];
|
|
13393
|
+
}
|
|
13394
|
+
const sharedPrefix = [pathToCollapse[0], pathToCollapse[1], branchPoint];
|
|
13395
|
+
if (!traceCanLoseSharedPrefix({
|
|
13396
|
+
trace: traceToCollapse,
|
|
13397
|
+
sharedPrefix,
|
|
13398
|
+
netLabelPlacements
|
|
13399
|
+
})) {
|
|
13400
|
+
if (traceIndexToCollapse === firstIndex) {
|
|
13401
|
+
traceIndexToCollapse = secondIndex;
|
|
13402
|
+
traceToCollapse = secondTrace;
|
|
13403
|
+
pathToCollapse = secondPath;
|
|
13404
|
+
} else {
|
|
13405
|
+
traceIndexToCollapse = firstIndex;
|
|
13406
|
+
traceToCollapse = firstTrace;
|
|
13407
|
+
pathToCollapse = firstPath;
|
|
13408
|
+
}
|
|
13409
|
+
}
|
|
13410
|
+
if (!traceCanLoseSharedPrefix({
|
|
13411
|
+
trace: traceToCollapse,
|
|
13412
|
+
sharedPrefix: [pathToCollapse[0], pathToCollapse[1], branchPoint],
|
|
13413
|
+
netLabelPlacements
|
|
13414
|
+
})) {
|
|
13415
|
+
continue;
|
|
13416
|
+
}
|
|
13417
|
+
const collapsedTrace = getTraceWithoutSharedPrefix({
|
|
13418
|
+
trace: traceToCollapse,
|
|
13419
|
+
pathFromSharedPin: pathToCollapse,
|
|
13420
|
+
sharedPinId: sharedPin.pinId,
|
|
13421
|
+
branchPoint
|
|
13422
|
+
});
|
|
13423
|
+
if (!collapsedTrace) continue;
|
|
13424
|
+
outputTraces[traceIndexToCollapse] = collapsedTrace;
|
|
13425
|
+
break;
|
|
13426
|
+
}
|
|
13427
|
+
}
|
|
13428
|
+
return outputTraces;
|
|
13429
|
+
};
|
|
13430
|
+
|
|
13233
13431
|
// lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
|
|
13234
13432
|
var MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2;
|
|
13235
13433
|
var MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2;
|
|
13236
13434
|
var MAX_SHARED_PIN_RAIL_OFFSET = 0.05;
|
|
13237
13435
|
var MAX_SHARED_ENDPOINT_RAIL_OFFSET = 0.8;
|
|
13238
13436
|
var MIN_RETURN_STEM_LENGTH = 0.05;
|
|
13239
|
-
var
|
|
13437
|
+
var getMultiPinNetPinIds = (inputProblem) => {
|
|
13438
|
+
const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
13439
|
+
const inputPinIds = new Set(
|
|
13440
|
+
inputProblem.chips.flatMap((chip) => chip.pins.map((pin) => pin.pinId))
|
|
13441
|
+
);
|
|
13442
|
+
return new Set(
|
|
13443
|
+
[...inputPinIds].filter((pinId) => {
|
|
13444
|
+
const globalNetId = netConnMap.getNetConnectedToId(pinId);
|
|
13445
|
+
if (!globalNetId) return false;
|
|
13446
|
+
return netConnMap.getIdsConnectedToNet(globalNetId).filter((connectedId) => inputPinIds.has(connectedId)).length > 2;
|
|
13447
|
+
})
|
|
13448
|
+
);
|
|
13449
|
+
};
|
|
13450
|
+
var getSegmentAxis4 = (start, end) => {
|
|
13240
13451
|
if (isHorizontal2(start, end)) return "x";
|
|
13241
13452
|
if (isVertical2(start, end)) return "y";
|
|
13242
13453
|
return null;
|
|
13243
13454
|
};
|
|
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
13455
|
var getOtherPin = ({
|
|
13252
13456
|
trace,
|
|
13253
13457
|
sharedPin
|
|
@@ -13473,8 +13677,8 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13473
13677
|
const donorPath = pathFromShared(donorTrace);
|
|
13474
13678
|
const branchPath = pathFromShared(branchTrace);
|
|
13475
13679
|
if (donorPath.length < 3 || branchPath.length < 4) return null;
|
|
13476
|
-
const donorDepartureAxis =
|
|
13477
|
-
const branchDepartureAxis =
|
|
13680
|
+
const donorDepartureAxis = getSegmentAxis4(donorPath[0], donorPath[1]);
|
|
13681
|
+
const branchDepartureAxis = getSegmentAxis4(branchPath[0], branchPath[1]);
|
|
13478
13682
|
if (!donorDepartureAxis || donorDepartureAxis !== branchDepartureAxis) {
|
|
13479
13683
|
return null;
|
|
13480
13684
|
}
|
|
@@ -13482,8 +13686,8 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13482
13686
|
const branchDeparture = branchPath[1][branchDepartureAxis] - branchPath[0][branchDepartureAxis];
|
|
13483
13687
|
if (Math.sign(donorDeparture) !== Math.sign(branchDeparture)) return null;
|
|
13484
13688
|
let railIndex = 1;
|
|
13485
|
-
let donorRailAxis =
|
|
13486
|
-
let branchRailAxis =
|
|
13689
|
+
let donorRailAxis = getSegmentAxis4(donorPath[1], donorPath[2]);
|
|
13690
|
+
let branchRailAxis = getSegmentAxis4(branchPath[1], branchPath[2]);
|
|
13487
13691
|
if (!donorRailAxis || donorRailAxis !== branchRailAxis || donorRailAxis === donorDepartureAxis) {
|
|
13488
13692
|
return null;
|
|
13489
13693
|
}
|
|
@@ -13491,11 +13695,11 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13491
13695
|
if (firstRailsAreAligned) {
|
|
13492
13696
|
railIndex++;
|
|
13493
13697
|
if (!donorPath[railIndex + 2] || !branchPath[railIndex + 2]) return null;
|
|
13494
|
-
donorRailAxis =
|
|
13698
|
+
donorRailAxis = getSegmentAxis4(
|
|
13495
13699
|
donorPath[railIndex],
|
|
13496
13700
|
donorPath[railIndex + 1]
|
|
13497
13701
|
);
|
|
13498
|
-
branchRailAxis =
|
|
13702
|
+
branchRailAxis = getSegmentAxis4(
|
|
13499
13703
|
branchPath[railIndex],
|
|
13500
13704
|
branchPath[railIndex + 1]
|
|
13501
13705
|
);
|
|
@@ -13503,7 +13707,7 @@ var getAlignedSharedEndpointRailPath = ({
|
|
|
13503
13707
|
}
|
|
13504
13708
|
let branchParallelRailCount = 0;
|
|
13505
13709
|
for (let index = 1; index < branchPath.length - 2; index++) {
|
|
13506
|
-
if (
|
|
13710
|
+
if (getSegmentAxis4(branchPath[index], branchPath[index + 1]) === branchRailAxis) {
|
|
13507
13711
|
branchParallelRailCount++;
|
|
13508
13712
|
}
|
|
13509
13713
|
}
|
|
@@ -13545,13 +13749,13 @@ var getAlignedAttachedLabelConnectorPath = ({
|
|
|
13545
13749
|
const junction = connectorPath[0];
|
|
13546
13750
|
const turn = connectorPath[1];
|
|
13547
13751
|
const railEnd = connectorPath[2];
|
|
13548
|
-
const departureAxis =
|
|
13549
|
-
const railAxis =
|
|
13752
|
+
const departureAxis = getSegmentAxis4(junction, turn);
|
|
13753
|
+
const railAxis = getSegmentAxis4(turn, railEnd);
|
|
13550
13754
|
if (!departureAxis || !railAxis || departureAxis === railAxis) return null;
|
|
13551
13755
|
const donorSegmentIndex = donorTrace.tracePath.findIndex(
|
|
13552
13756
|
(point, index, path) => {
|
|
13553
13757
|
const next = path[index + 1];
|
|
13554
|
-
return next &&
|
|
13758
|
+
return next && getSegmentAxis4(point, next) === departureAxis && tracePathContainsPoint([point, next], junction) && tracePathContainsPoint([point, next], turn);
|
|
13555
13759
|
}
|
|
13556
13760
|
);
|
|
13557
13761
|
if (donorSegmentIndex < 0) return null;
|
|
@@ -13564,7 +13768,7 @@ var getAlignedAttachedLabelConnectorPath = ({
|
|
|
13564
13768
|
donorSegmentIndex > 0 ? [donorTrace.tracePath[donorSegmentIndex - 1], donorSegmentStart] : null,
|
|
13565
13769
|
donorSegmentIndex + 2 < donorTrace.tracePath.length ? [donorSegmentEnd, donorTrace.tracePath[donorSegmentIndex + 2]] : null
|
|
13566
13770
|
].flatMap(
|
|
13567
|
-
(segment) => segment &&
|
|
13771
|
+
(segment) => segment && getSegmentAxis4(segment[0], segment[1]) === railAxis ? [segment] : []
|
|
13568
13772
|
);
|
|
13569
13773
|
if (adjacentDonorRails.length === 0) return null;
|
|
13570
13774
|
const railCoordinateAxis = railAxis === "x" ? "y" : "x";
|
|
@@ -13647,7 +13851,7 @@ var preserveAttachedLabelConnectorJunctions = ({
|
|
|
13647
13851
|
if (!movedJunction) return null;
|
|
13648
13852
|
const neighborIndex = endpointIndex === 0 ? 1 : endpointIndex - 1;
|
|
13649
13853
|
const neighbor = connector.tracePath[neighborIndex];
|
|
13650
|
-
if (!neighbor ||
|
|
13854
|
+
if (!neighbor || getSegmentAxis4(originalJunction, neighbor) !== getSegmentAxis4(movedJunction, neighbor)) {
|
|
13651
13855
|
return null;
|
|
13652
13856
|
}
|
|
13653
13857
|
const movedConnector = {
|
|
@@ -14070,6 +14274,13 @@ var alignSameNetJunctions = ({
|
|
|
14070
14274
|
}
|
|
14071
14275
|
}
|
|
14072
14276
|
}
|
|
14277
|
+
const collapsedSharedEndpointStubs = collapseRedundantSharedEndpointStubs({
|
|
14278
|
+
traces: outputTraces,
|
|
14279
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
14280
|
+
netLabelConnectorTraceIds,
|
|
14281
|
+
multiPinNetPinIds: getMultiPinNetPinIds(inputProblem)
|
|
14282
|
+
});
|
|
14283
|
+
outputTraces = collapsedSharedEndpointStubs;
|
|
14073
14284
|
return {
|
|
14074
14285
|
traces: outputTraces,
|
|
14075
14286
|
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,
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import type { Point } from "@tscircuit/math-utils"
|
|
2
|
+
import type { PinId } from "lib/types/InputProblem"
|
|
3
|
+
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
4
|
+
import type { MspConnectionPairId } from "lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver"
|
|
5
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
6
|
+
import {
|
|
7
|
+
nearlyEqual,
|
|
8
|
+
pointsEqual,
|
|
9
|
+
} from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
|
|
10
|
+
import { simplifyPath } from "lib/solvers/TraceCleanupSolver/simplifyPath"
|
|
11
|
+
import { tracePathContainsPoint } from "lib/solvers/RailNetLabelCornerPlacementSolver/geometry"
|
|
12
|
+
import { getSharedPin } from "./getSharedPin"
|
|
13
|
+
|
|
14
|
+
const getSegmentAxis = (start: Point, end: Point) => {
|
|
15
|
+
if (nearlyEqual(start.x, end.x)) return "y" as const
|
|
16
|
+
if (nearlyEqual(start.y, end.y)) return "x" as const
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getPathFromSharedPin = ({
|
|
21
|
+
trace,
|
|
22
|
+
sharedPinId,
|
|
23
|
+
}: {
|
|
24
|
+
trace: SolvedTracePath
|
|
25
|
+
sharedPinId: PinId
|
|
26
|
+
}) => {
|
|
27
|
+
const tracePath = simplifyPath(trace.tracePath)
|
|
28
|
+
if (trace.pins[0]?.pinId === sharedPinId) return tracePath
|
|
29
|
+
return tracePath.reverse()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const traceCanLoseSharedPrefix = ({
|
|
33
|
+
trace,
|
|
34
|
+
sharedPrefix,
|
|
35
|
+
netLabelPlacements,
|
|
36
|
+
}: {
|
|
37
|
+
trace: SolvedTracePath
|
|
38
|
+
sharedPrefix: Point[]
|
|
39
|
+
netLabelPlacements: NetLabelPlacement[]
|
|
40
|
+
}) => {
|
|
41
|
+
return !netLabelPlacements.some(
|
|
42
|
+
(label) =>
|
|
43
|
+
label.mspConnectionPairIds.includes(trace.mspPairId) &&
|
|
44
|
+
tracePathContainsPoint(sharedPrefix, label.anchorPoint),
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const getTraceWithoutSharedPrefix = ({
|
|
49
|
+
trace,
|
|
50
|
+
pathFromSharedPin,
|
|
51
|
+
sharedPinId,
|
|
52
|
+
branchPoint,
|
|
53
|
+
}: {
|
|
54
|
+
trace: SolvedTracePath
|
|
55
|
+
pathFromSharedPin: Point[]
|
|
56
|
+
sharedPinId: PinId
|
|
57
|
+
branchPoint: Point
|
|
58
|
+
}) => {
|
|
59
|
+
const branchSegmentIndex = pathFromSharedPin.findIndex((point, index) => {
|
|
60
|
+
const nextPoint = pathFromSharedPin[index + 1]
|
|
61
|
+
if (!nextPoint) return false
|
|
62
|
+
return tracePathContainsPoint([point, nextPoint], branchPoint)
|
|
63
|
+
})
|
|
64
|
+
if (branchSegmentIndex < 0) return null
|
|
65
|
+
const pathFromJunction = simplifyPath([
|
|
66
|
+
branchPoint,
|
|
67
|
+
...pathFromSharedPin.slice(branchSegmentIndex + 1),
|
|
68
|
+
])
|
|
69
|
+
let tracePath = pathFromJunction
|
|
70
|
+
if (trace.pins[0]?.pinId !== sharedPinId) {
|
|
71
|
+
tracePath = pathFromJunction.reverse()
|
|
72
|
+
}
|
|
73
|
+
return { ...trace, tracePath }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const collapseRedundantSharedEndpointStubs = ({
|
|
77
|
+
traces,
|
|
78
|
+
netLabelPlacements,
|
|
79
|
+
netLabelConnectorTraceIds,
|
|
80
|
+
multiPinNetPinIds,
|
|
81
|
+
}: {
|
|
82
|
+
traces: SolvedTracePath[]
|
|
83
|
+
netLabelPlacements: NetLabelPlacement[]
|
|
84
|
+
netLabelConnectorTraceIds: ReadonlySet<MspConnectionPairId>
|
|
85
|
+
multiPinNetPinIds: ReadonlySet<PinId>
|
|
86
|
+
}) => {
|
|
87
|
+
const outputTraces = [...traces]
|
|
88
|
+
|
|
89
|
+
for (let firstIndex = 0; firstIndex < outputTraces.length; firstIndex++) {
|
|
90
|
+
const firstTrace = outputTraces[firstIndex]!
|
|
91
|
+
if (netLabelConnectorTraceIds.has(firstTrace.mspPairId)) continue
|
|
92
|
+
for (
|
|
93
|
+
let secondIndex = firstIndex + 1;
|
|
94
|
+
secondIndex < outputTraces.length;
|
|
95
|
+
secondIndex++
|
|
96
|
+
) {
|
|
97
|
+
const secondTrace = outputTraces[secondIndex]!
|
|
98
|
+
if (
|
|
99
|
+
netLabelConnectorTraceIds.has(secondTrace.mspPairId) ||
|
|
100
|
+
firstTrace.globalConnNetId !== secondTrace.globalConnNetId
|
|
101
|
+
) {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
const sharedPin = getSharedPin({
|
|
105
|
+
donorTrace: firstTrace,
|
|
106
|
+
branchTrace: secondTrace,
|
|
107
|
+
})
|
|
108
|
+
if (!sharedPin || !multiPinNetPinIds.has(sharedPin.pinId)) continue
|
|
109
|
+
const firstPath = getPathFromSharedPin({
|
|
110
|
+
trace: firstTrace,
|
|
111
|
+
sharedPinId: sharedPin.pinId,
|
|
112
|
+
})
|
|
113
|
+
const secondPath = getPathFromSharedPin({
|
|
114
|
+
trace: secondTrace,
|
|
115
|
+
sharedPinId: sharedPin.pinId,
|
|
116
|
+
})
|
|
117
|
+
if (firstPath.length < 2 || secondPath.length < 2) continue
|
|
118
|
+
|
|
119
|
+
const departureAxis = getSegmentAxis(firstPath[0]!, firstPath[1]!)
|
|
120
|
+
const secondDepartureAxis = getSegmentAxis(secondPath[0]!, secondPath[1]!)
|
|
121
|
+
if (!departureAxis || departureAxis !== secondDepartureAxis) continue
|
|
122
|
+
|
|
123
|
+
const firstDepartureDirection =
|
|
124
|
+
firstPath[1]![departureAxis] - firstPath[0]![departureAxis]
|
|
125
|
+
const secondDepartureDirection =
|
|
126
|
+
secondPath[1]![departureAxis] - secondPath[0]![departureAxis]
|
|
127
|
+
if (
|
|
128
|
+
!pointsEqual(firstPath[1]!, secondPath[1]!) &&
|
|
129
|
+
Math.sign(firstDepartureDirection) ===
|
|
130
|
+
Math.sign(secondDepartureDirection)
|
|
131
|
+
) {
|
|
132
|
+
let traceIndexToCollapse = secondIndex
|
|
133
|
+
let traceToCollapse = secondTrace
|
|
134
|
+
let pathToCollapse = secondPath
|
|
135
|
+
if (
|
|
136
|
+
Math.abs(firstDepartureDirection) < Math.abs(secondDepartureDirection)
|
|
137
|
+
) {
|
|
138
|
+
traceIndexToCollapse = firstIndex
|
|
139
|
+
traceToCollapse = firstTrace
|
|
140
|
+
pathToCollapse = firstPath
|
|
141
|
+
}
|
|
142
|
+
const branchPoint = pathToCollapse[1]!
|
|
143
|
+
if (
|
|
144
|
+
!traceCanLoseSharedPrefix({
|
|
145
|
+
trace: traceToCollapse,
|
|
146
|
+
sharedPrefix: [pathToCollapse[0]!, branchPoint],
|
|
147
|
+
netLabelPlacements,
|
|
148
|
+
})
|
|
149
|
+
) {
|
|
150
|
+
if (traceIndexToCollapse === firstIndex) {
|
|
151
|
+
traceIndexToCollapse = secondIndex
|
|
152
|
+
traceToCollapse = secondTrace
|
|
153
|
+
pathToCollapse = secondPath
|
|
154
|
+
} else {
|
|
155
|
+
traceIndexToCollapse = firstIndex
|
|
156
|
+
traceToCollapse = firstTrace
|
|
157
|
+
pathToCollapse = firstPath
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (
|
|
161
|
+
!traceCanLoseSharedPrefix({
|
|
162
|
+
trace: traceToCollapse,
|
|
163
|
+
sharedPrefix: [pathToCollapse[0]!, branchPoint],
|
|
164
|
+
netLabelPlacements,
|
|
165
|
+
})
|
|
166
|
+
) {
|
|
167
|
+
continue
|
|
168
|
+
}
|
|
169
|
+
const collapsedTrace = getTraceWithoutSharedPrefix({
|
|
170
|
+
trace: traceToCollapse,
|
|
171
|
+
pathFromSharedPin: pathToCollapse,
|
|
172
|
+
sharedPinId: sharedPin.pinId,
|
|
173
|
+
branchPoint,
|
|
174
|
+
})
|
|
175
|
+
if (!collapsedTrace) continue
|
|
176
|
+
outputTraces[traceIndexToCollapse] = collapsedTrace
|
|
177
|
+
break
|
|
178
|
+
}
|
|
179
|
+
if (firstPath.length < 3 || secondPath.length < 3) continue
|
|
180
|
+
if (!pointsEqual(firstPath[1]!, secondPath[1]!)) continue
|
|
181
|
+
|
|
182
|
+
const railAxis = getSegmentAxis(firstPath[1]!, firstPath[2]!)
|
|
183
|
+
const secondRailAxis = getSegmentAxis(secondPath[1]!, secondPath[2]!)
|
|
184
|
+
if (
|
|
185
|
+
!railAxis ||
|
|
186
|
+
railAxis !== secondRailAxis ||
|
|
187
|
+
railAxis === departureAxis
|
|
188
|
+
) {
|
|
189
|
+
continue
|
|
190
|
+
}
|
|
191
|
+
const firstRailDirection =
|
|
192
|
+
firstPath[2]![railAxis] - firstPath[1]![railAxis]
|
|
193
|
+
const secondRailDirection =
|
|
194
|
+
secondPath[2]![railAxis] - secondPath[1]![railAxis]
|
|
195
|
+
const railsHaveSameDirection =
|
|
196
|
+
Math.sign(firstRailDirection) === Math.sign(secondRailDirection)
|
|
197
|
+
const sharedStub = firstPath.slice(0, 2)
|
|
198
|
+
if (
|
|
199
|
+
!railsHaveSameDirection &&
|
|
200
|
+
!nearlyEqual(
|
|
201
|
+
Math.abs(firstRailDirection),
|
|
202
|
+
Math.abs(secondRailDirection),
|
|
203
|
+
) &&
|
|
204
|
+
netLabelPlacements.some(
|
|
205
|
+
(label) =>
|
|
206
|
+
label.globalConnNetId === firstTrace.globalConnNetId &&
|
|
207
|
+
tracePathContainsPoint(sharedStub, label.anchorPoint),
|
|
208
|
+
)
|
|
209
|
+
) {
|
|
210
|
+
continue
|
|
211
|
+
}
|
|
212
|
+
let traceIndexToCollapse = secondIndex
|
|
213
|
+
let traceToCollapse = secondTrace
|
|
214
|
+
let pathToCollapse = secondPath
|
|
215
|
+
let branchPoint = firstPath[1]!
|
|
216
|
+
if (
|
|
217
|
+
railsHaveSameDirection &&
|
|
218
|
+
Math.abs(firstRailDirection) < Math.abs(secondRailDirection)
|
|
219
|
+
) {
|
|
220
|
+
traceIndexToCollapse = firstIndex
|
|
221
|
+
traceToCollapse = firstTrace
|
|
222
|
+
pathToCollapse = firstPath
|
|
223
|
+
branchPoint = firstPath[2]!
|
|
224
|
+
} else if (railsHaveSameDirection) {
|
|
225
|
+
branchPoint = secondPath[2]!
|
|
226
|
+
}
|
|
227
|
+
const sharedPrefix = [pathToCollapse[0]!, pathToCollapse[1]!, branchPoint]
|
|
228
|
+
if (
|
|
229
|
+
!traceCanLoseSharedPrefix({
|
|
230
|
+
trace: traceToCollapse,
|
|
231
|
+
sharedPrefix,
|
|
232
|
+
netLabelPlacements,
|
|
233
|
+
})
|
|
234
|
+
) {
|
|
235
|
+
if (traceIndexToCollapse === firstIndex) {
|
|
236
|
+
traceIndexToCollapse = secondIndex
|
|
237
|
+
traceToCollapse = secondTrace
|
|
238
|
+
pathToCollapse = secondPath
|
|
239
|
+
} else {
|
|
240
|
+
traceIndexToCollapse = firstIndex
|
|
241
|
+
traceToCollapse = firstTrace
|
|
242
|
+
pathToCollapse = firstPath
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (
|
|
246
|
+
!traceCanLoseSharedPrefix({
|
|
247
|
+
trace: traceToCollapse,
|
|
248
|
+
sharedPrefix: [pathToCollapse[0]!, pathToCollapse[1]!, branchPoint],
|
|
249
|
+
netLabelPlacements,
|
|
250
|
+
})
|
|
251
|
+
) {
|
|
252
|
+
continue
|
|
253
|
+
}
|
|
254
|
+
const collapsedTrace = getTraceWithoutSharedPrefix({
|
|
255
|
+
trace: traceToCollapse,
|
|
256
|
+
pathFromSharedPin: pathToCollapse,
|
|
257
|
+
sharedPinId: sharedPin.pinId,
|
|
258
|
+
branchPoint,
|
|
259
|
+
})
|
|
260
|
+
if (!collapsedTrace) continue
|
|
261
|
+
outputTraces[traceIndexToCollapse] = collapsedTrace
|
|
262
|
+
break
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return outputTraces
|
|
267
|
+
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
pointsEqual,
|
|
12
12
|
} from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
|
|
13
13
|
import { simplifyPath } from "lib/solvers/TraceCleanupSolver/simplifyPath"
|
|
14
|
-
import { getSharedPin } from "./
|
|
14
|
+
import { getSharedPin } from "./getSharedPin"
|
|
15
15
|
import {
|
|
16
16
|
pathEntersAnyNetLabel,
|
|
17
17
|
pathIntersectsAnyNetLabel,
|