@tscircuit/schematic-trace-solver 0.0.125 → 0.0.127
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/README.md +28 -0
- package/dist/index.d.ts +159 -2
- package/dist/index.js +739 -36
- package/lib/index.ts +2 -0
- package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +424 -0
- package/lib/solvers/InlineNetLabelSolver/getAxisAlignedSegments.ts +73 -0
- package/lib/solvers/NetLabelTraceCollisionSolver/NetLabelTraceCollisionSolver.ts +15 -0
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +86 -11
- package/lib/solvers/TraceElbowTransitionSimplificationSolver/TraceElbowTransitionSimplificationSolver.ts +216 -0
- package/lib/solvers/TraceElbowTransitionSimplificationSolver/generateElbowTransitionSimplificationCandidates.ts +186 -0
- package/lib/solvers/TraceElbowTransitionSimplificationSolver/types.ts +10 -0
- package/lib/solvers/TraceLabelOverlapAvoidanceSolver/TraceLabelOverlapAvoidanceSolver.ts +3 -0
- package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/OverlapAvoidanceStepSolver/OverlapAvoidanceStepSolver.ts +16 -0
- package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/SingleOverlapSolver/SingleOverlapSolver.ts +56 -13
- package/lib/types/InputProblem.ts +24 -0
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260806T093501Z.page.tsx +4 -0
- package/site/examples/inline-net-label01.page.tsx +6 -0
- package/tests/assets/inline-net-label01.json +47 -0
- package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +3 -3
- package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +6 -6
- package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +135 -0
- package/tests/bug-reports/bug-report-20260806T093501Z/bug-report-20260806T093501Z.json +505 -0
- package/tests/bug-reports/bug-report-20260806T093501Z/bug-report-20260806T093501Z.test.ts +66 -0
- package/tests/examples/__snapshots__/example33.snap.svg +1 -1
- package/tests/functions/getAxisAlignedSegments.test.ts +56 -0
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label01.snap.svg +54 -0
- package/tests/solvers/InlineNetLabelSolver/inline-net-label01.test.ts +44 -0
package/README.md
CHANGED
|
@@ -35,6 +35,34 @@ Finally, the `NetLabelPlacementSolver` places net labels for each net connection
|
|
|
35
35
|
this requires drawing small traces to adapt to the `availableFacingDirections` of the net connection.
|
|
36
36
|
If there is crowding at the pin, we look for an available spot along the trace connected to the pin.
|
|
37
37
|
|
|
38
|
+
### Inline net labels
|
|
39
|
+
|
|
40
|
+
A point-to-point signal trace can be labeled *inline*: the net name is drawn
|
|
41
|
+
parallel to the wire (above a horizontal trace, to the left of a vertical one)
|
|
42
|
+
instead of as an anchored label hanging off the end of it. This keeps the visual
|
|
43
|
+
line between the two pins intact.
|
|
44
|
+
|
|
45
|
+
Inline labels are opt-in per direct connection - set `allowInlineNetLabel: true`
|
|
46
|
+
on the `directConnection`. The caller (usually [@tscircuit/core](https://github.com/tscircuit/core))
|
|
47
|
+
decides which connections deserve one; the solver only honors the request when
|
|
48
|
+
the connection actually got routed, since there is nothing to run parallel to
|
|
49
|
+
otherwise.
|
|
50
|
+
|
|
51
|
+
The `InlineNetLabelSolver` runs last in the pipeline and exposes
|
|
52
|
+
`inlineNetLabelPlacements`. A net that receives an inline label has its anchored
|
|
53
|
+
`NetLabelPlacement` removed from `getOutput().netLabelPlacements`, so a net is
|
|
54
|
+
never labeled twice.
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
directConnections: [
|
|
58
|
+
{
|
|
59
|
+
pinIds: ["U1.1", "D1.1"],
|
|
60
|
+
netId: "USER_LED_ANODE",
|
|
61
|
+
allowInlineNetLabel: true,
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
```
|
|
65
|
+
|
|
38
66
|
## Usage
|
|
39
67
|
|
|
40
68
|
```tsx
|
package/dist/index.d.ts
CHANGED
|
@@ -88,6 +88,27 @@ interface InputDirectConnection {
|
|
|
88
88
|
pinIds: [PinId, PinId];
|
|
89
89
|
netId?: string;
|
|
90
90
|
netLabelWidth?: number;
|
|
91
|
+
/**
|
|
92
|
+
* When true, this point-to-point connection may be labeled with an "inline
|
|
93
|
+
* net label": the net name is drawn parallel to (and offset from) the routed
|
|
94
|
+
* trace instead of being placed as a separate anchored net label at the end
|
|
95
|
+
* of the trace.
|
|
96
|
+
*
|
|
97
|
+
* Only set this for connections whose net name is worth showing on the wire -
|
|
98
|
+
* the solver trusts the caller (e.g. @tscircuit/core) to make that decision.
|
|
99
|
+
* An inline label is only emitted when the connection actually got routed.
|
|
100
|
+
*/
|
|
101
|
+
allowInlineNetLabel?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Extent of the inline net label along the trace. Falls back to
|
|
104
|
+
* `netLabelWidth`, then to an estimate from the netId text.
|
|
105
|
+
*/
|
|
106
|
+
inlineNetLabelWidth?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Height of the inline net label text. Defaults to
|
|
109
|
+
* DEFAULT_INLINE_NET_LABEL_HEIGHT.
|
|
110
|
+
*/
|
|
111
|
+
inlineNetLabelHeight?: number;
|
|
91
112
|
}
|
|
92
113
|
interface InputNetConnection {
|
|
93
114
|
netId: string;
|
|
@@ -441,6 +462,13 @@ declare class NetLabelPlacementSolver extends BaseSolver {
|
|
|
441
462
|
visualize(): GraphicsObject;
|
|
442
463
|
}
|
|
443
464
|
|
|
465
|
+
interface CompletedTraceReroute {
|
|
466
|
+
initialTrace: SolvedTracePath;
|
|
467
|
+
reroutedTracePath: Point[];
|
|
468
|
+
label: NetLabelPlacement;
|
|
469
|
+
detourCount: number;
|
|
470
|
+
}
|
|
471
|
+
|
|
444
472
|
interface LabelMergingSolverInput {
|
|
445
473
|
netLabelPlacements: NetLabelPlacement[];
|
|
446
474
|
inputProblem: InputProblem;
|
|
@@ -479,6 +507,7 @@ interface SingleOverlapSolverInput {
|
|
|
479
507
|
paddingBuffer: number;
|
|
480
508
|
detourCount: number;
|
|
481
509
|
tracesToAvoidOverlapping?: SolvedTracePath[];
|
|
510
|
+
netLabelPlacements?: NetLabelPlacement[];
|
|
482
511
|
}
|
|
483
512
|
/**
|
|
484
513
|
* This solver attempts to find a valid rerouting for a single trace that is
|
|
@@ -493,6 +522,8 @@ declare class SingleOverlapSolver extends BaseSolver {
|
|
|
493
522
|
obstacles: ReturnType<typeof getObstacleRects>;
|
|
494
523
|
label: NetLabelPlacement;
|
|
495
524
|
tracesToAvoidOverlapping: SolvedTracePath[];
|
|
525
|
+
netLabelPlacements: NetLabelPlacement[];
|
|
526
|
+
detourCount: number;
|
|
496
527
|
_tried: number;
|
|
497
528
|
constructor(solverInput: SingleOverlapSolverInput);
|
|
498
529
|
_step(): void;
|
|
@@ -520,6 +551,7 @@ declare class OverlapAvoidanceStepSolver extends BaseSolver {
|
|
|
520
551
|
allTraces: SolvedTracePath[];
|
|
521
552
|
tracesToAvoidOverlapping: SolvedTracePath[];
|
|
522
553
|
modifiedTraces: SolvedTracePath[];
|
|
554
|
+
completedReroutes: CompletedTraceReroute[];
|
|
523
555
|
private readonly PADDING_BUFFER;
|
|
524
556
|
private detourCounts;
|
|
525
557
|
activeSubSolver: SingleOverlapSolver | null;
|
|
@@ -570,6 +602,7 @@ declare class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
|
|
|
570
602
|
_step(): void;
|
|
571
603
|
getOutput(): {
|
|
572
604
|
traces: SolvedTracePath[];
|
|
605
|
+
completedReroutes: CompletedTraceReroute[];
|
|
573
606
|
netLabelPlacements: NetLabelPlacement[];
|
|
574
607
|
};
|
|
575
608
|
visualize(): GraphicsObject;
|
|
@@ -958,6 +991,7 @@ declare class NetLabelTraceCollisionSolver extends BaseSolver {
|
|
|
958
991
|
netLabelPlacements: NetLabelPlacement[];
|
|
959
992
|
outputTraces: SolvedTracePath[];
|
|
960
993
|
outputNetLabelPlacements: NetLabelPlacement[];
|
|
994
|
+
completedReroutes: CompletedTraceReroute[];
|
|
961
995
|
activeSubSolver: SingleOverlapSolver | null;
|
|
962
996
|
private recentlyFailed;
|
|
963
997
|
private detourCounts;
|
|
@@ -972,6 +1006,7 @@ declare class NetLabelTraceCollisionSolver extends BaseSolver {
|
|
|
972
1006
|
private reanchorLabelsOnMovedTrace;
|
|
973
1007
|
getOutput(): {
|
|
974
1008
|
traces: SolvedTracePath[];
|
|
1009
|
+
completedReroutes: CompletedTraceReroute[];
|
|
975
1010
|
netLabelPlacements: NetLabelPlacement[];
|
|
976
1011
|
};
|
|
977
1012
|
private getOverlapKey;
|
|
@@ -1083,6 +1118,124 @@ declare class SameNetJunctionAlignmentSolver extends BaseSolver {
|
|
|
1083
1118
|
visualize(): GraphicsObject;
|
|
1084
1119
|
}
|
|
1085
1120
|
|
|
1121
|
+
interface TraceElbowTransitionSimplificationSolverInput {
|
|
1122
|
+
inputProblem: InputProblem;
|
|
1123
|
+
traces: SolvedTracePath[];
|
|
1124
|
+
completedReroutes: CompletedTraceReroute[];
|
|
1125
|
+
netLabelPlacements: NetLabelPlacement[];
|
|
1126
|
+
paddingBuffer: number;
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Post-processes traces after trace/label overlap avoidance. It removes
|
|
1130
|
+
* redundant elbow transitions and, when needed, shifts a simplified elbow
|
|
1131
|
+
* around a rendered label. Every replacement is revalidated against labels,
|
|
1132
|
+
* components, other-net traces, and label anchors.
|
|
1133
|
+
*/
|
|
1134
|
+
declare class TraceElbowTransitionSimplificationSolver extends BaseSolver {
|
|
1135
|
+
private input;
|
|
1136
|
+
private outputTraces;
|
|
1137
|
+
private traceIdQueue;
|
|
1138
|
+
private obstacles;
|
|
1139
|
+
constructor(input: TraceElbowTransitionSimplificationSolverInput);
|
|
1140
|
+
_step(): void;
|
|
1141
|
+
getOutput(): {
|
|
1142
|
+
traces: SolvedTracePath[];
|
|
1143
|
+
netLabelPlacements: NetLabelPlacement[];
|
|
1144
|
+
};
|
|
1145
|
+
visualize(): GraphicsObject;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
declare const DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18;
|
|
1149
|
+
/**
|
|
1150
|
+
* Gap between the trace and the near edge of the inline label text.
|
|
1151
|
+
*/
|
|
1152
|
+
declare const INLINE_NET_LABEL_TRACE_MARGIN = 0.05;
|
|
1153
|
+
/**
|
|
1154
|
+
* How much of the label is allowed to hang off the end of the wire it names,
|
|
1155
|
+
* as a fraction of the label's length. A short elbow stub is technically clear
|
|
1156
|
+
* of every obstacle but reads as a label floating in space, so runs shorter
|
|
1157
|
+
* than this are not considered.
|
|
1158
|
+
*/
|
|
1159
|
+
declare const MIN_INLINE_NET_LABEL_SEGMENT_RATIO = 0.5;
|
|
1160
|
+
/**
|
|
1161
|
+
* A net label drawn parallel to the trace it names, rather than anchored to the
|
|
1162
|
+
* end of it. Used for point-to-point signal traces, where an anchored label
|
|
1163
|
+
* would break the visual line between the two pins.
|
|
1164
|
+
*
|
|
1165
|
+
* `center` is the center of the text box in the schematic's own (unrotated)
|
|
1166
|
+
* coordinate space. `width` is the extent of the text along the trace and
|
|
1167
|
+
* `height` is its extent perpendicular to the trace, so a vertical label has
|
|
1168
|
+
* its `width` running along y.
|
|
1169
|
+
*/
|
|
1170
|
+
interface InlineNetLabelPlacement {
|
|
1171
|
+
globalConnNetId: string;
|
|
1172
|
+
netId?: string;
|
|
1173
|
+
mspPairId: string;
|
|
1174
|
+
pinIds: PinId[];
|
|
1175
|
+
/** Axis the text runs along: "x" reads left-to-right, "y" reads bottom-to-top */
|
|
1176
|
+
axis: "x" | "y";
|
|
1177
|
+
/** Midpoint of the trace segment the label is attached to */
|
|
1178
|
+
anchorPoint: Point;
|
|
1179
|
+
/** Center of the label text, offset perpendicular to the trace */
|
|
1180
|
+
center: Point;
|
|
1181
|
+
/** Extent along the trace */
|
|
1182
|
+
width: number;
|
|
1183
|
+
/** Extent perpendicular to the trace */
|
|
1184
|
+
height: number;
|
|
1185
|
+
/**
|
|
1186
|
+
* Which side of the trace the label sits on. For a horizontal trace, "y+" is
|
|
1187
|
+
* above; for a vertical trace, "x-" is the left side (which is "above" once
|
|
1188
|
+
* the text is rotated).
|
|
1189
|
+
*/
|
|
1190
|
+
side: "x+" | "x-" | "y+" | "y-";
|
|
1191
|
+
}
|
|
1192
|
+
interface InlineNetLabelSolverInput {
|
|
1193
|
+
inputProblem: InputProblem;
|
|
1194
|
+
traces: SolvedTracePath[];
|
|
1195
|
+
netLabelPlacements: NetLabelPlacement[];
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Places "inline net labels" - net names drawn alongside the trace they belong
|
|
1199
|
+
* to - for direct connections that opted in via `allowInlineNetLabel`.
|
|
1200
|
+
*
|
|
1201
|
+
* Any regular (anchored) net label placement for the same net is dropped, so a
|
|
1202
|
+
* net is never labeled twice.
|
|
1203
|
+
*/
|
|
1204
|
+
declare class InlineNetLabelSolver extends BaseSolver {
|
|
1205
|
+
inputProblem: InputProblem;
|
|
1206
|
+
traces: SolvedTracePath[];
|
|
1207
|
+
inputNetLabelPlacements: NetLabelPlacement[];
|
|
1208
|
+
inlineNetLabelPlacements: InlineNetLabelPlacement[];
|
|
1209
|
+
/** Direct connections that opted in, still waiting to be processed */
|
|
1210
|
+
queuedDirectConnections: InputDirectConnection[];
|
|
1211
|
+
private tracesByPinPairKey;
|
|
1212
|
+
constructor(input: InlineNetLabelSolverInput);
|
|
1213
|
+
getConstructorParams(): [InlineNetLabelSolverInput];
|
|
1214
|
+
_step(): void;
|
|
1215
|
+
private computeInlinePlacement;
|
|
1216
|
+
/**
|
|
1217
|
+
* An inline label may not sit on top of a chip, a component's text, or a
|
|
1218
|
+
* trace belonging to another net.
|
|
1219
|
+
*/
|
|
1220
|
+
private isObstructed;
|
|
1221
|
+
/**
|
|
1222
|
+
* Net label placements superseded by an inline label. A net gets one label or
|
|
1223
|
+
* the other, never both.
|
|
1224
|
+
*/
|
|
1225
|
+
private getSupersededNetLabelKeys;
|
|
1226
|
+
getOutput(): {
|
|
1227
|
+
traces: SolvedTracePath[];
|
|
1228
|
+
netLabelPlacements: NetLabelPlacement[];
|
|
1229
|
+
inlineNetLabelPlacements: InlineNetLabelPlacement[];
|
|
1230
|
+
};
|
|
1231
|
+
visualize(): GraphicsObject;
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Mirrors the net label text width used by @tscircuit/core so a label that core
|
|
1235
|
+
* did not measure for us still reserves a sane amount of space.
|
|
1236
|
+
*/
|
|
1237
|
+
declare const estimateInlineNetLabelWidth: (text: string, fontSize?: number) => number;
|
|
1238
|
+
|
|
1086
1239
|
/**
|
|
1087
1240
|
* Pipeline solver that runs a series of solvers to find the best schematic layout.
|
|
1088
1241
|
* Coordinates the entire layout process from chip partitioning through final packing.
|
|
@@ -1117,14 +1270,18 @@ declare class SchematicTracePipelineSolver extends BaseSolver {
|
|
|
1117
1270
|
netLabelTraceCollisionSolver?: NetLabelTraceCollisionSolver;
|
|
1118
1271
|
traceCleanupSolver2?: TraceCleanupSolver;
|
|
1119
1272
|
netLabelNetLabelCollisionSolver?: NetLabelNetLabelCollisionSolver;
|
|
1273
|
+
traceElbowTransitionSimplificationSolver?: TraceElbowTransitionSimplificationSolver;
|
|
1274
|
+
preAlignmentTraceElbowTransitionSimplificationSolver?: TraceElbowTransitionSimplificationSolver;
|
|
1275
|
+
finalTraceElbowTransitionSimplificationSolver?: TraceElbowTransitionSimplificationSolver;
|
|
1120
1276
|
sameNetJunctionAlignmentSolver?: SameNetJunctionAlignmentSolver;
|
|
1277
|
+
inlineNetLabelSolver?: InlineNetLabelSolver;
|
|
1121
1278
|
startTimeOfPhase: Record<string, number>;
|
|
1122
1279
|
endTimeOfPhase: Record<string, number>;
|
|
1123
1280
|
timeSpentOnPhase: Record<string, number>;
|
|
1124
1281
|
firstIterationOfPhase: Record<string, number>;
|
|
1125
1282
|
inputProblem: InputProblem;
|
|
1126
1283
|
hideRatsNet: boolean;
|
|
1127
|
-
pipelineDef: (PipelineStep<typeof MspConnectionPairSolver> | PipelineStep<typeof SchematicTraceLinesSolver> | PipelineStep<typeof LongDistancePairSolver> | PipelineStep<typeof UnroutedTraceRecoverySolver> | PipelineStep<typeof TraceOverlapShiftSolver> | PipelineStep<typeof NetLabelPlacementSolver> | PipelineStep<typeof TraceLabelOverlapAvoidanceSolver> | PipelineStep<typeof TraceCleanupSolver> | PipelineStep<typeof Example28Solver> | PipelineStep<typeof AvailableNetOrientationSolver> | PipelineStep<typeof RailNetLabelCornerPlacementSolver> | PipelineStep<typeof TraceAnchoredNetLabelOverlapSolver> | PipelineStep<typeof NetLabelTraceCollisionSolver> | PipelineStep<typeof NetLabelNetLabelCollisionSolver> | PipelineStep<typeof SameNetJunctionAlignmentSolver>)[];
|
|
1284
|
+
pipelineDef: (PipelineStep<typeof MspConnectionPairSolver> | PipelineStep<typeof SchematicTraceLinesSolver> | PipelineStep<typeof LongDistancePairSolver> | PipelineStep<typeof UnroutedTraceRecoverySolver> | PipelineStep<typeof TraceOverlapShiftSolver> | PipelineStep<typeof NetLabelPlacementSolver> | PipelineStep<typeof TraceLabelOverlapAvoidanceSolver> | PipelineStep<typeof TraceElbowTransitionSimplificationSolver> | PipelineStep<typeof TraceCleanupSolver> | PipelineStep<typeof Example28Solver> | PipelineStep<typeof AvailableNetOrientationSolver> | PipelineStep<typeof RailNetLabelCornerPlacementSolver> | PipelineStep<typeof TraceAnchoredNetLabelOverlapSolver> | PipelineStep<typeof NetLabelTraceCollisionSolver> | PipelineStep<typeof NetLabelNetLabelCollisionSolver> | PipelineStep<typeof SameNetJunctionAlignmentSolver> | PipelineStep<typeof InlineNetLabelSolver>)[];
|
|
1128
1285
|
constructor(inputProblem: InputProblem, opts?: Options);
|
|
1129
1286
|
getConstructorParams(): ConstructorParameters<typeof SchematicTracePipelineSolver>;
|
|
1130
1287
|
currentPipelineStepIndex: number;
|
|
@@ -1140,4 +1297,4 @@ declare class SchematicTracePipelineSolver extends BaseSolver {
|
|
|
1140
1297
|
preview(): GraphicsObject;
|
|
1141
1298
|
}
|
|
1142
1299
|
|
|
1143
|
-
export { type ChipId, type InputChip, type InputDirectConnection, type InputNetConnection, type InputPin, type InputProblem, type NetId, type PinId, SchematicTracePipelineSolver, SchematicTraceSingleLineSolver2, type SectionId, type TextBoxes };
|
|
1300
|
+
export { type ChipId, DEFAULT_INLINE_NET_LABEL_HEIGHT, INLINE_NET_LABEL_TRACE_MARGIN, type InlineNetLabelPlacement, InlineNetLabelSolver, type InputChip, type InputDirectConnection, type InputNetConnection, type InputPin, type InputProblem, MIN_INLINE_NET_LABEL_SEGMENT_RATIO, type NetId, type NetLabelPlacement, type PinId, SchematicTracePipelineSolver, SchematicTraceSingleLineSolver2, type SectionId, type TextBoxes, estimateInlineNetLabelWidth };
|