@tscircuit/schematic-trace-solver 0.0.149 → 0.0.151
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/.agents/skills/schematic-trace-visualization/SKILL.md +7 -2
- package/README.md +6 -4
- package/dist/index.d.ts +64 -3
- package/dist/index.js +383 -66
- package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +123 -84
- package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +17 -1
- package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/SingleNetLabelPlacementSolver.ts +2 -0
- package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/solvePortOnlyPin.ts +2 -0
- package/lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts +338 -0
- package/lib/solvers/NetLabelTraceRecovery/getTraceRecoveryConnectivityMaps.ts +33 -0
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +15 -0
- package/lib/types/InputProblem.ts +27 -1
- package/package.json +8 -1
- package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +751 -5
- package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +660 -5
- package/tests/bug-reports/bug-report-20260707T020342Z/__snapshots__/bug-report-20260707T020342Z.snap.svg +44 -5
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +394 -5
- package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +170 -5
- package/tests/bug-reports/bug-report-20260707T134722Z/__snapshots__/bug-report-20260707T134722Z.snap.svg +79 -5
- package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +219 -5
- package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +65 -5
- package/tests/bug-reports/bug-report-20260707T141421Z/__snapshots__/bug-report-20260707T141421Z.snap.svg +142 -5
- package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +100 -5
- package/tests/bug-reports/bug-report-20260708T053736Z/__snapshots__/bug-report-20260708T053736Z.snap.svg +23 -5
- package/tests/bug-reports/bug-report-20260708T055430Z/__snapshots__/bug-report-20260708T055430Z.snap.svg +58 -5
- package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +86 -5
- package/tests/bug-reports/bug-report-20260716T144856Z/__snapshots__/bug-report-20260716T144856Z.snap.svg +226 -5
- package/tests/bug-reports/bug-report-20260717T022934Z/__snapshots__/bug-report-20260717T022934Z.snap.svg +191 -5
- package/tests/bug-reports/bug-report-20260717T031704Z/__snapshots__/bug-report-20260717T031704Z.snap.svg +30 -5
- package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +37 -5
- package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +580 -2
- package/tests/bug-reports/bug-report-20260724T175257Z/__snapshots__/bug-report-20260724T175257Z.snap.svg +44 -5
- package/tests/bug-reports/bug-report-20260728T144234Z/__snapshots__/bug-report-20260728T144234Z.snap.svg +107 -5
- package/tests/bug-reports/bug-report-20260728T225606Z/__snapshots__/bug-report-20260728T225606Z.snap.svg +114 -5
- package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +121 -5
- package/tests/bug-reports/bug-report-20260731T052229Z/__snapshots__/bug-report-20260731T052229Z.snap.svg +51 -5
- package/tests/bug-reports/bug-report-20260804T095800Z/__snapshots__/bug-report-20260804T095800Z.snap.svg +212 -5
- package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +569 -5
- package/tests/bug-reports/bug-report-20260804T225912Z/__snapshots__/bug-report-20260804T225912Z.snap.svg +37 -5
- package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +289 -5
- package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +289 -5
- package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +149 -5
- package/tests/bug-reports/bug-report-20260811T075142Z/__snapshots__/bug-report-20260811T075142Z.snap.svg +93 -5
- package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +79 -5
- package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +244 -2
- package/tests/examples/__snapshots__/example01.snap.svg +44 -5
- package/tests/examples/__snapshots__/example02.snap.svg +51 -5
- package/tests/examples/__snapshots__/example03.snap.svg +86 -5
- package/tests/examples/__snapshots__/example04.snap.svg +30 -5
- package/tests/examples/__snapshots__/example05.snap.svg +30 -5
- package/tests/examples/__snapshots__/example06.snap.svg +30 -5
- package/tests/examples/__snapshots__/example07.snap.svg +58 -5
- package/tests/examples/__snapshots__/example08.snap.svg +37 -5
- package/tests/examples/__snapshots__/example09.snap.svg +149 -5
- package/tests/examples/__snapshots__/example10.snap.svg +65 -5
- package/tests/examples/__snapshots__/example11.snap.svg +51 -5
- package/tests/examples/__snapshots__/example12.snap.svg +51 -5
- package/tests/examples/__snapshots__/example13.snap.svg +72 -5
- package/tests/examples/__snapshots__/example14.snap.svg +79 -5
- package/tests/examples/__snapshots__/example15.snap.svg +86 -5
- package/tests/examples/__snapshots__/example16.snap.svg +51 -5
- package/tests/examples/__snapshots__/example17.snap.svg +51 -5
- package/tests/examples/__snapshots__/example18.snap.svg +58 -5
- package/tests/examples/__snapshots__/example19.snap.svg +44 -5
- package/tests/examples/__snapshots__/example20.snap.svg +44 -5
- package/tests/examples/__snapshots__/example21.snap.svg +72 -5
- package/tests/examples/__snapshots__/example22.snap.svg +51 -5
- package/tests/examples/__snapshots__/example23.snap.svg +51 -5
- package/tests/examples/__snapshots__/example24.snap.svg +51 -5
- package/tests/examples/__snapshots__/example25.snap.svg +86 -5
- package/tests/examples/__snapshots__/example26.snap.svg +51 -5
- package/tests/examples/__snapshots__/example27.snap.svg +72 -5
- package/tests/examples/__snapshots__/example28.snap.svg +44 -5
- package/tests/examples/__snapshots__/example29.snap.svg +324 -5
- package/tests/examples/__snapshots__/example30.snap.svg +107 -5
- package/tests/examples/__snapshots__/example31.snap.svg +37 -5
- package/tests/examples/__snapshots__/example32.snap.svg +149 -5
- package/tests/examples/__snapshots__/example33.snap.svg +93 -5
- package/tests/examples/__snapshots__/example34.snap.svg +51 -5
- package/tests/examples/__snapshots__/example35.snap.svg +58 -5
- package/tests/examples/__snapshots__/example36.snap.svg +44 -5
- package/tests/examples/__snapshots__/example37.snap.svg +72 -5
- package/tests/examples/__snapshots__/example38.snap.svg +30 -5
- package/tests/examples/__snapshots__/example39.snap.svg +37 -5
- package/tests/examples/__snapshots__/example40.snap.svg +100 -5
- package/tests/examples/__snapshots__/example41.snap.svg +44 -5
- package/tests/examples/__snapshots__/example42.snap.svg +65 -5
- package/tests/examples/__snapshots__/example43.snap.svg +58 -5
- package/tests/examples/__snapshots__/example44.snap.svg +107 -5
- package/tests/examples/__snapshots__/example45.snap.svg +51 -5
- package/tests/examples/__snapshots__/example46.snap.svg +93 -5
- package/tests/examples/__snapshots__/example47.snap.svg +93 -5
- package/tests/examples/__snapshots__/example48.snap.svg +65 -5
- package/tests/examples/__snapshots__/example49.snap.svg +177 -5
- package/tests/examples/__snapshots__/example50.snap.svg +93 -5
- package/tests/examples/__snapshots__/example51.snap.svg +594 -21
- package/tests/fixtures/convertSolverOutputToCircuitJson.test.ts +219 -0
- package/tests/fixtures/convertSolverOutputToCircuitJson.ts +1058 -0
- package/tests/fixtures/matcher.ts +45 -8
- package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +762 -2
- package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +111 -2
- package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +170 -5
- package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +65 -5
- package/tests/repros/__snapshots__/manufacturePartNumber-text-box.snap.svg +30 -5
- package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +79 -5
- package/tests/repros/__snapshots__/repro-atmega328p-fault-pullup.snap.svg +65 -5
- package/tests/repros/__snapshots__/repro-atmega328p-missing-gnd-netlabel.snap.svg +149 -5
- package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +55 -2
- package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +160 -2
- package/tests/repros/__snapshots__/repro-bq24074-battery-charger.snap.svg +135 -5
- package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +69 -2
- package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +86 -5
- package/tests/repros/__snapshots__/repro-core-555-power-cross-net-overlap.snap.svg +44 -5
- package/tests/repros/__snapshots__/repro-core-subcircuit-missing-ground.snap.svg +44 -5
- package/tests/repros/__snapshots__/repro-core-tb67s579ftg-inline-label-routing.snap.svg +30 -5
- package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +335 -2
- package/tests/repros/__snapshots__/repro-ground-label-on-lower-rail-end.snap.svg +48 -2
- package/tests/repros/__snapshots__/repro-ina237-current-monitor.snap.svg +149 -5
- package/tests/repros/__snapshots__/repro-missing-trace-netlabel.snap.svg +72 -5
- package/tests/repros/__snapshots__/repro-netlabel-collision-687.snap.svg +100 -5
- package/tests/repros/__snapshots__/repro-netlabel-overlap-trace.snap.svg +51 -5
- package/tests/repros/__snapshots__/repro-nrf52810-clock-routing.snap.svg +90 -2
- package/tests/repros/__snapshots__/repro-power-group-rail-labels.snap.svg +37 -5
- package/tests/repros/__snapshots__/repro-rectifier-trace-overlap.snap.svg +44 -5
- package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +237 -2
- package/tests/repros/__snapshots__/repro-rp2040-usb-cc2-ground-overlap.snap.svg +72 -5
- package/tests/repros/__snapshots__/repro-rp2040-v3v3-label-placement.snap.svg +51 -5
- package/tests/repros/__snapshots__/repro-rp2040-zero-crystal-fallback-netlabels.snap.svg +30 -5
- package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +79 -5
- package/tests/repros/__snapshots__/repro-tida010076-j4-ground-bus.snap.svg +27 -2
- package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +1150 -5
- package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +51 -5
- package/tests/repros/__snapshots__/repro-type-c-16pin-self-connection.snap.svg +30 -5
- package/tests/repros/__snapshots__/repro-type-c-16pin-to-resistor.snap.svg +30 -5
- package/tests/repros/__snapshots__/repro-type-c-vbus-led-ground-label.snap.svg +44 -5
- package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +685 -2
- package/tests/repros/__snapshots__/repro-vcc-pin1-detour.snap.svg +27 -2
- package/tests/repros/__snapshots__/repro129-host-custom-symbol-passives.snap.svg +51 -5
- package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +100 -5
- package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +107 -5
- package/tests/repros/__snapshots__/repro47-endpoint-obstacle-detour.snap.svg +51 -5
- package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +104 -2
- package/tests/repros/__snapshots__/repro5-escape-padded-text-obstacles.snap.svg +30 -5
- package/tests/repros/__snapshots__/repro51-overlap-junction-crossing.snap.svg +65 -5
- package/tests/repros/__snapshots__/repro84-stacked-gnd-label-orientation.snap.svg +27 -2
- package/tests/repros/__snapshots__/small-variant-resistor-facing-direction.snap.svg +58 -5
- package/tests/repros/__snapshots__/trace-overlap-box-resistor.snap.svg +37 -5
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/fallback-net-label-width.snap.svg +25 -7
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-anchored-label-clearance.snap.svg +34 -2
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-port-stub.snap.svg +23 -5
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-two-pin-net.snap.svg +23 -5
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label01.snap.svg +23 -5
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label02.snap.svg +23 -5
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/terminal-stub-trace-clearance.snap.svg +23 -5
- package/tests/solvers/InlineNetLabelSolver/fallback-net-label-width.test.ts +10 -1
- package/tests/solvers/SchematicTraceSingleLineSolver2/__snapshots__/SchematicTraceSingleLineSolver2_01-example17-d1_1-u1_1.snap.svg +23 -5
- package/tests/solvers/SchematicTraceSingleLineSolver2/__snapshots__/SchematicTraceSingleLineSolver2_repro47-short-opposing-pins.snap.svg +20 -2
- package/tests/solvers/TraceCleanupSolver/__snapshots__/TraceCleanupSolver.snap.svg +44 -5
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/__snapshots__/TraceLabelOverlapAvoidanceSolver.snap.svg +79 -5
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/MergedNetLabelObstacles.snap.svg +44 -5
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/OverlapAvoidanceStepSolver.snap.svg +23 -5
- package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/SingleOverlapSolver.snap.svg +30 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Bounds, Point } from "@tscircuit/math-utils"
|
|
2
|
-
import type { GraphicsObject, Rect } from "graphics-debug"
|
|
2
|
+
import type { GraphicsObject, Rect, Text } from "graphics-debug"
|
|
3
3
|
import { BaseSolver } from "lib/solvers/BaseSolver/BaseSolver"
|
|
4
4
|
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
5
5
|
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
@@ -52,6 +52,8 @@ export const INLINE_NET_LABEL_MAX_SPAN_JOG = 0.4
|
|
|
52
52
|
export interface InlineNetLabelPlacement {
|
|
53
53
|
globalConnNetId: string
|
|
54
54
|
netId?: string
|
|
55
|
+
/** User-facing label content, separate from the connectivity identifier. */
|
|
56
|
+
netLabelText?: string
|
|
55
57
|
mspPairId?: string
|
|
56
58
|
pinIds: PinId[]
|
|
57
59
|
|
|
@@ -90,6 +92,13 @@ interface InlineNetLabelSolverInput {
|
|
|
90
92
|
netLabelPlacements: NetLabelPlacement[]
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
export interface InlineNetLabelOutput {
|
|
96
|
+
inputProblem: InputProblem
|
|
97
|
+
traces: SolvedTracePath[]
|
|
98
|
+
netLabelPlacements: NetLabelPlacement[]
|
|
99
|
+
inlineNetLabelPlacements: InlineNetLabelPlacement[]
|
|
100
|
+
}
|
|
101
|
+
|
|
93
102
|
type InlineEligibleConnection = InputDirectConnection | InputNetConnection
|
|
94
103
|
|
|
95
104
|
const getPinPairKey = (pinIds: readonly string[]) =>
|
|
@@ -236,10 +245,11 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
236
245
|
|
|
237
246
|
const height =
|
|
238
247
|
connection.inlineNetLabelHeight ?? DEFAULT_INLINE_NET_LABEL_HEIGHT
|
|
248
|
+
const netLabelText = connection.netLabelText?.trim() || undefined
|
|
239
249
|
const width =
|
|
240
250
|
connection.inlineNetLabelWidth ??
|
|
241
251
|
connection.netLabelWidth ??
|
|
242
|
-
estimateInlineNetLabelWidth(connection.netId, height)
|
|
252
|
+
estimateInlineNetLabelWidth(netLabelText ?? connection.netId, height)
|
|
243
253
|
|
|
244
254
|
// Leave a small wire tail at both ends of the text so it unmistakably
|
|
245
255
|
// reads as a label on a trace rather than free-standing text.
|
|
@@ -310,6 +320,7 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
310
320
|
return {
|
|
311
321
|
globalConnNetId: anchoredPlacement.globalConnNetId,
|
|
312
322
|
netId: connection.netId,
|
|
323
|
+
netLabelText,
|
|
313
324
|
pinIds: [pinId],
|
|
314
325
|
stubTracePath: [start, end],
|
|
315
326
|
axis,
|
|
@@ -336,10 +347,11 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
336
347
|
|
|
337
348
|
const height =
|
|
338
349
|
connection.inlineNetLabelHeight ?? DEFAULT_INLINE_NET_LABEL_HEIGHT
|
|
350
|
+
const netLabelText = connection.netLabelText?.trim() || undefined
|
|
339
351
|
const width =
|
|
340
352
|
connection.inlineNetLabelWidth ??
|
|
341
353
|
connection.netLabelWidth ??
|
|
342
|
-
estimateInlineNetLabelWidth(connection.netId!, height)
|
|
354
|
+
estimateInlineNetLabelWidth(netLabelText ?? connection.netId!, height)
|
|
343
355
|
|
|
344
356
|
const offset = height / 2 + INLINE_NET_LABEL_TRACE_MARGIN
|
|
345
357
|
|
|
@@ -397,6 +409,7 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
397
409
|
return {
|
|
398
410
|
globalConnNetId: trace.globalConnNetId,
|
|
399
411
|
netId: connection.netId,
|
|
412
|
+
netLabelText,
|
|
400
413
|
mspPairId: trace.mspPairId,
|
|
401
414
|
pinIds: [...connection.pinIds],
|
|
402
415
|
axis: segment.axis,
|
|
@@ -417,6 +430,7 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
417
430
|
const spanPlacement = this.computeSpanPlacement({
|
|
418
431
|
trace,
|
|
419
432
|
connection,
|
|
433
|
+
netLabelText,
|
|
420
434
|
width,
|
|
421
435
|
height,
|
|
422
436
|
offset,
|
|
@@ -437,12 +451,14 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
437
451
|
private computeSpanPlacement({
|
|
438
452
|
trace,
|
|
439
453
|
connection,
|
|
454
|
+
netLabelText,
|
|
440
455
|
width,
|
|
441
456
|
height,
|
|
442
457
|
offset,
|
|
443
458
|
}: {
|
|
444
459
|
trace: SolvedTracePath
|
|
445
460
|
connection: InlineEligibleConnection
|
|
461
|
+
netLabelText?: string
|
|
446
462
|
width: number
|
|
447
463
|
height: number
|
|
448
464
|
offset: number
|
|
@@ -533,6 +549,7 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
533
549
|
return {
|
|
534
550
|
globalConnNetId: trace.globalConnNetId,
|
|
535
551
|
netId: connection.netId,
|
|
552
|
+
netLabelText,
|
|
536
553
|
mspPairId: trace.mspPairId,
|
|
537
554
|
pinIds: [...connection.pinIds],
|
|
538
555
|
axis,
|
|
@@ -636,95 +653,117 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
636
653
|
// Mirrors the previous pipeline stage's visualization so that a problem
|
|
637
654
|
// with no inline labels renders identically, then layers the inline labels
|
|
638
655
|
// on top.
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
656
|
+
return visualizeInlineNetLabelOutput({
|
|
657
|
+
inputProblem: this.inputProblem,
|
|
658
|
+
...this.getOutput(),
|
|
659
|
+
})
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
export const visualizeInlineNetLabelOutput = ({
|
|
664
|
+
inputProblem,
|
|
665
|
+
traces,
|
|
666
|
+
netLabelPlacements,
|
|
667
|
+
inlineNetLabelPlacements,
|
|
668
|
+
}: InlineNetLabelOutput): GraphicsObject => {
|
|
669
|
+
const graphics = visualizeInputProblem(inputProblem)
|
|
670
|
+
graphics.lines ??= []
|
|
671
|
+
graphics.rects ??= []
|
|
672
|
+
graphics.points ??= []
|
|
673
|
+
graphics.texts ??= []
|
|
674
|
+
|
|
675
|
+
for (const trace of traces) {
|
|
676
|
+
graphics.lines.push({
|
|
677
|
+
points: trace.tracePath,
|
|
678
|
+
strokeColor: "purple",
|
|
679
|
+
})
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
for (const label of netLabelPlacements) {
|
|
683
|
+
graphics.rects.push({
|
|
684
|
+
center: label.center,
|
|
685
|
+
width: label.width,
|
|
686
|
+
height: label.height,
|
|
687
|
+
fill: getColorFromString(label.globalConnNetId, 0.35),
|
|
688
|
+
strokeColor: getColorFromString(label.globalConnNetId, 0.9),
|
|
689
|
+
label: `netId: ${label.netId}\nglobalConnNetId: ${label.globalConnNetId}`,
|
|
690
|
+
} as Rect & { strokeColor: string })
|
|
691
|
+
graphics.points.push({
|
|
692
|
+
x: label.anchorPoint.x,
|
|
693
|
+
y: label.anchorPoint.y,
|
|
694
|
+
color: getColorFromString(label.globalConnNetId, 0.9),
|
|
695
|
+
label: `anchorPoint\norientation: ${label.orientation}`,
|
|
696
|
+
})
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
for (const inlineLabel of inlineNetLabelPlacements) {
|
|
700
|
+
if (inlineLabel.stubTracePath) {
|
|
647
701
|
graphics.lines.push({
|
|
648
|
-
points:
|
|
702
|
+
points: inlineLabel.stubTracePath,
|
|
649
703
|
strokeColor: "purple",
|
|
650
704
|
})
|
|
651
705
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
height: label.height,
|
|
659
|
-
fill: getColorFromString(label.globalConnNetId, 0.35),
|
|
660
|
-
strokeColor: getColorFromString(label.globalConnNetId, 0.9),
|
|
661
|
-
label: `netId: ${label.netId}\nglobalConnNetId: ${label.globalConnNetId}`,
|
|
662
|
-
} as Rect & { strokeColor: string })
|
|
663
|
-
graphics.points.push({
|
|
664
|
-
x: label.anchorPoint.x,
|
|
665
|
-
y: label.anchorPoint.y,
|
|
666
|
-
color: getColorFromString(label.globalConnNetId, 0.9),
|
|
667
|
-
label: `anchorPoint\norientation: ${label.orientation}`,
|
|
668
|
-
})
|
|
706
|
+
const isHorizontal = inlineLabel.axis === "x"
|
|
707
|
+
let renderedWidth = inlineLabel.width
|
|
708
|
+
let renderedHeight = inlineLabel.height
|
|
709
|
+
if (!isHorizontal) {
|
|
710
|
+
renderedWidth = inlineLabel.height
|
|
711
|
+
renderedHeight = inlineLabel.width
|
|
669
712
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
713
|
+
graphics.rects.push({
|
|
714
|
+
center: inlineLabel.center,
|
|
715
|
+
width: renderedWidth,
|
|
716
|
+
height: renderedHeight,
|
|
717
|
+
fill: getColorFromString(inlineLabel.globalConnNetId, 0.35),
|
|
718
|
+
strokeColor: "green",
|
|
719
|
+
label: [
|
|
720
|
+
`INLINE netId: ${inlineLabel.netId}`,
|
|
721
|
+
`axis: ${inlineLabel.axis}`,
|
|
722
|
+
`side: ${inlineLabel.side}`,
|
|
723
|
+
].join("\n"),
|
|
724
|
+
} as Rect & { strokeColor: string })
|
|
725
|
+
|
|
726
|
+
let textX = inlineLabel.center.x
|
|
727
|
+
let textY = inlineLabel.center.y
|
|
728
|
+
let anchorSide: Text["anchorSide"] = "center"
|
|
729
|
+
let rotation: Text["rotation"]
|
|
730
|
+
if (inlineLabel.stubTracePath) {
|
|
731
|
+
const stubStart = inlineLabel.stubTracePath[0]
|
|
732
|
+
const stubEnd = inlineLabel.stubTracePath[1]
|
|
733
|
+
let labelOffset = inlineLabel.width / 2
|
|
734
|
+
if (stubEnd[inlineLabel.axis] > stubStart[inlineLabel.axis]) {
|
|
735
|
+
labelOffset = -inlineLabel.width / 2
|
|
736
|
+
anchorSide = "center_left"
|
|
737
|
+
} else {
|
|
738
|
+
anchorSide = "center_right"
|
|
739
|
+
}
|
|
740
|
+
if (inlineLabel.axis === "x") {
|
|
741
|
+
textX += labelOffset
|
|
742
|
+
} else {
|
|
743
|
+
textY += labelOffset
|
|
677
744
|
}
|
|
678
|
-
const isHorizontal = inlineLabel.axis === "x"
|
|
679
|
-
graphics.rects.push({
|
|
680
|
-
center: inlineLabel.center,
|
|
681
|
-
width: isHorizontal ? inlineLabel.width : inlineLabel.height,
|
|
682
|
-
height: isHorizontal ? inlineLabel.height : inlineLabel.width,
|
|
683
|
-
fill: getColorFromString(inlineLabel.globalConnNetId, 0.35),
|
|
684
|
-
strokeColor: "green",
|
|
685
|
-
label: [
|
|
686
|
-
`INLINE netId: ${inlineLabel.netId}`,
|
|
687
|
-
`axis: ${inlineLabel.axis}`,
|
|
688
|
-
`side: ${inlineLabel.side}`,
|
|
689
|
-
].join("\n"),
|
|
690
|
-
} as Rect & { strokeColor: string })
|
|
691
|
-
graphics.texts.push({
|
|
692
|
-
x:
|
|
693
|
-
inlineLabel.stubTracePath && inlineLabel.axis === "x"
|
|
694
|
-
? inlineLabel.center.x +
|
|
695
|
-
(inlineLabel.stubTracePath[1].x > inlineLabel.stubTracePath[0].x
|
|
696
|
-
? -inlineLabel.width / 2
|
|
697
|
-
: inlineLabel.width / 2)
|
|
698
|
-
: inlineLabel.center.x,
|
|
699
|
-
y:
|
|
700
|
-
inlineLabel.stubTracePath && inlineLabel.axis === "y"
|
|
701
|
-
? inlineLabel.center.y +
|
|
702
|
-
(inlineLabel.stubTracePath[1].y > inlineLabel.stubTracePath[0].y
|
|
703
|
-
? -inlineLabel.width / 2
|
|
704
|
-
: inlineLabel.width / 2)
|
|
705
|
-
: inlineLabel.center.y,
|
|
706
|
-
text: inlineLabel.netId ?? "",
|
|
707
|
-
color: "green",
|
|
708
|
-
fontSize: inlineLabel.height,
|
|
709
|
-
anchorSide: inlineLabel.stubTracePath
|
|
710
|
-
? inlineLabel.stubTracePath[1][inlineLabel.axis] >
|
|
711
|
-
inlineLabel.stubTracePath[0][inlineLabel.axis]
|
|
712
|
-
? "center_left"
|
|
713
|
-
: "center_right"
|
|
714
|
-
: "center",
|
|
715
|
-
// Vertical labels read bottom-to-top, alongside the wire they name.
|
|
716
|
-
rotation: inlineLabel.axis === "y" ? 90 : undefined,
|
|
717
|
-
})
|
|
718
|
-
graphics.points.push({
|
|
719
|
-
x: inlineLabel.anchorPoint.x,
|
|
720
|
-
y: inlineLabel.anchorPoint.y,
|
|
721
|
-
color: "green",
|
|
722
|
-
label: `inline anchor\n${inlineLabel.netId}`,
|
|
723
|
-
})
|
|
724
745
|
}
|
|
725
|
-
|
|
726
|
-
|
|
746
|
+
if (inlineLabel.axis === "y") rotation = 90
|
|
747
|
+
|
|
748
|
+
graphics.texts.push({
|
|
749
|
+
x: textX,
|
|
750
|
+
y: textY,
|
|
751
|
+
text: inlineLabel.netLabelText ?? inlineLabel.netId ?? "",
|
|
752
|
+
color: "green",
|
|
753
|
+
fontSize: inlineLabel.height,
|
|
754
|
+
anchorSide,
|
|
755
|
+
// Vertical labels read bottom-to-top, alongside the wire they name.
|
|
756
|
+
rotation,
|
|
757
|
+
})
|
|
758
|
+
graphics.points.push({
|
|
759
|
+
x: inlineLabel.anchorPoint.x,
|
|
760
|
+
y: inlineLabel.anchorPoint.y,
|
|
761
|
+
color: "green",
|
|
762
|
+
label: `inline anchor\n${inlineLabel.netLabelText ?? inlineLabel.netId}`,
|
|
763
|
+
})
|
|
727
764
|
}
|
|
765
|
+
|
|
766
|
+
return graphics
|
|
728
767
|
}
|
|
729
768
|
|
|
730
769
|
/**
|
|
@@ -18,6 +18,7 @@ import { getNetLabelWidthForConnection } from "lib/utils/getNetLabelWidthForConn
|
|
|
18
18
|
export type OverlappingSameNetTraceGroup = {
|
|
19
19
|
globalConnNetId: string
|
|
20
20
|
netId?: string
|
|
21
|
+
netLabelText?: string
|
|
21
22
|
overlappingTraces?: SolvedTracePath
|
|
22
23
|
portOnlyPinId?: string
|
|
23
24
|
mspConnectionPairIds?: MspConnectionPairId[]
|
|
@@ -30,6 +31,8 @@ export interface NetLabelPlacement {
|
|
|
30
31
|
* Optional user-provided net identifier (if present in the input problem).
|
|
31
32
|
*/
|
|
32
33
|
netId?: string
|
|
34
|
+
/** User-facing label content, separate from the connectivity identifier. */
|
|
35
|
+
netLabelText?: string
|
|
33
36
|
/**
|
|
34
37
|
* MSP pair ids that the label is associated with. Port-only labels use [].
|
|
35
38
|
*/
|
|
@@ -116,18 +119,27 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
|
|
119
|
-
// Map pins to user-provided
|
|
122
|
+
// Map pins to user-provided connectivity ids and display text (if any).
|
|
120
123
|
const userNetIdByPinId: Record<string, string | undefined> = {}
|
|
124
|
+
const netLabelTextByPinId: Record<string, string | undefined> = {}
|
|
121
125
|
for (const dc of this.inputProblem.directConnections) {
|
|
122
126
|
if (dc.netId) {
|
|
123
127
|
const [a, b] = dc.pinIds
|
|
124
128
|
userNetIdByPinId[a] = dc.netId
|
|
125
129
|
userNetIdByPinId[b] = dc.netId
|
|
126
130
|
}
|
|
131
|
+
const netLabelText = dc.netLabelText?.trim()
|
|
132
|
+
if (netLabelText) {
|
|
133
|
+
const [a, b] = dc.pinIds
|
|
134
|
+
netLabelTextByPinId[a] = netLabelText
|
|
135
|
+
netLabelTextByPinId[b] = netLabelText
|
|
136
|
+
}
|
|
127
137
|
}
|
|
128
138
|
for (const nc of this.inputProblem.netConnections) {
|
|
129
139
|
for (const pid of nc.pinIds) {
|
|
130
140
|
userNetIdByPinId[pid] = nc.netId
|
|
141
|
+
const netLabelText = nc.netLabelText?.trim()
|
|
142
|
+
if (netLabelText) netLabelTextByPinId[pid] = netLabelText
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
145
|
|
|
@@ -237,6 +249,9 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
237
249
|
const group = {
|
|
238
250
|
globalConnNetId,
|
|
239
251
|
netId: userNetId,
|
|
252
|
+
netLabelText: [...component]
|
|
253
|
+
.map((pinId) => netLabelTextByPinId[pinId])
|
|
254
|
+
.find((text): text is string => Boolean(text)),
|
|
240
255
|
overlappingTraces: rep,
|
|
241
256
|
mspConnectionPairIds,
|
|
242
257
|
}
|
|
@@ -249,6 +264,7 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
249
264
|
groups.push({
|
|
250
265
|
globalConnNetId,
|
|
251
266
|
netId: userNetId,
|
|
267
|
+
netLabelText: netLabelTextByPinId[p],
|
|
252
268
|
portOnlyPinId: p,
|
|
253
269
|
})
|
|
254
270
|
}
|
|
@@ -354,6 +354,7 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
354
354
|
this.overlappingSameNetTraceGroup.globalConnNetId,
|
|
355
355
|
dcConnNetId: curr.dcConnNetId,
|
|
356
356
|
netId: this.overlappingSameNetTraceGroup.netId,
|
|
357
|
+
netLabelText: this.overlappingSameNetTraceGroup.netLabelText,
|
|
357
358
|
mspConnectionPairIds: [curr.mspPairId],
|
|
358
359
|
pinIds: [curr.pins[0].pinId, curr.pins[1].pinId],
|
|
359
360
|
orientation,
|
|
@@ -374,6 +375,7 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
374
375
|
globalConnNetId: this.overlappingSameNetTraceGroup.globalConnNetId,
|
|
375
376
|
dcConnNetId: bestCandidate.dcConnNetId,
|
|
376
377
|
netId: this.overlappingSameNetTraceGroup.netId,
|
|
378
|
+
netLabelText: this.overlappingSameNetTraceGroup.netLabelText,
|
|
377
379
|
mspConnectionPairIds: [bestCandidate.mspPairId],
|
|
378
380
|
pinIds: bestCandidate.pinIds,
|
|
379
381
|
orientation: bestCandidate.orientation,
|
package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/solvePortOnlyPin.ts
CHANGED
|
@@ -195,6 +195,7 @@ export function solveNetLabelPlacementForPortOnlyPin(params: {
|
|
|
195
195
|
globalConnNetId: overlappingSameNetTraceGroup.globalConnNetId,
|
|
196
196
|
dcConnNetId: undefined,
|
|
197
197
|
netId: overlappingSameNetTraceGroup.netId,
|
|
198
|
+
netLabelText: overlappingSameNetTraceGroup.netLabelText,
|
|
198
199
|
mspConnectionPairIds: [],
|
|
199
200
|
pinIds: [pinId],
|
|
200
201
|
orientation,
|
|
@@ -230,6 +231,7 @@ export function solveNetLabelPlacementForPortOnlyPin(params: {
|
|
|
230
231
|
globalConnNetId: overlappingSameNetTraceGroup.globalConnNetId,
|
|
231
232
|
dcConnNetId: undefined,
|
|
232
233
|
netId: overlappingSameNetTraceGroup.netId,
|
|
234
|
+
netLabelText: overlappingSameNetTraceGroup.netLabelText,
|
|
233
235
|
mspConnectionPairIds: [],
|
|
234
236
|
pinIds: [pinId],
|
|
235
237
|
orientation: fallbackOrientation,
|