@tscircuit/schematic-trace-solver 0.0.169 → 0.0.170
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 +213 -106
- package/lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts +17 -4
- package/lib/solvers/NetLabelToTraceSolver/reduceTraceCrossings.ts +180 -0
- package/package.json +1 -1
- package/tests/examples/__snapshots__/example37.snap.svg +2 -2
- package/tests/examples/example37.test.ts +13 -1
package/dist/index.js
CHANGED
|
@@ -325,19 +325,19 @@ var doesPairCrossRestrictedCenterLines = (params) => {
|
|
|
325
325
|
chipMap
|
|
326
326
|
});
|
|
327
327
|
if (restrictedCenterLines.size === 0) return false;
|
|
328
|
-
const
|
|
328
|
+
const EPS15 = 1e-9;
|
|
329
329
|
const crossesSegment = (a, b) => {
|
|
330
330
|
for (const [, rcl] of restrictedCenterLines) {
|
|
331
331
|
if (rcl.axes.has("x") && typeof rcl.x === "number") {
|
|
332
|
-
if ((a.x - rcl.x) * (b.x - rcl.x) < -
|
|
332
|
+
if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS15) return true;
|
|
333
333
|
}
|
|
334
334
|
if (rcl.axes.has("y") && typeof rcl.y === "number") {
|
|
335
|
-
if ((a.y - rcl.y) * (b.y - rcl.y) < -
|
|
335
|
+
if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS15) return true;
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
338
|
return false;
|
|
339
339
|
};
|
|
340
|
-
if (Math.abs(p1.x - p2.x) <
|
|
340
|
+
if (Math.abs(p1.x - p2.x) < EPS15 || Math.abs(p1.y - p2.y) < EPS15) {
|
|
341
341
|
return crossesSegment({ x: p1.x, y: p1.y }, { x: p2.x, y: p2.y });
|
|
342
342
|
}
|
|
343
343
|
const elbowHV = { x: p2.x, y: p1.y };
|
|
@@ -1575,8 +1575,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1575
1575
|
if (!collision) {
|
|
1576
1576
|
const first = path[0];
|
|
1577
1577
|
const last = path[path.length - 1];
|
|
1578
|
-
const
|
|
1579
|
-
const samePoint = (p, q) => Math.abs(p.x - q.x) <
|
|
1578
|
+
const EPS15 = 1e-9;
|
|
1579
|
+
const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS15 && Math.abs(p.y - q.y) < EPS15;
|
|
1580
1580
|
if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
|
|
1581
1581
|
this.solvedTracePath = path;
|
|
1582
1582
|
this.solved = true;
|
|
@@ -1887,17 +1887,17 @@ var applyJogToTerminalSegment = ({
|
|
|
1887
1887
|
segmentIndex: si,
|
|
1888
1888
|
offset,
|
|
1889
1889
|
JOG_SIZE,
|
|
1890
|
-
EPS:
|
|
1890
|
+
EPS: EPS15 = 1e-6
|
|
1891
1891
|
}) => {
|
|
1892
1892
|
if (si !== 0 && si !== pts.length - 2) return;
|
|
1893
1893
|
const start = pts[si];
|
|
1894
1894
|
const end = pts[si + 1];
|
|
1895
|
-
const
|
|
1896
|
-
const
|
|
1897
|
-
if (!
|
|
1898
|
-
const segDir =
|
|
1895
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS15;
|
|
1896
|
+
const isHorizontal5 = Math.abs(start.y - end.y) < EPS15;
|
|
1897
|
+
if (!isVertical6 && !isHorizontal5) return;
|
|
1898
|
+
const segDir = isVertical6 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
|
|
1899
1899
|
if (pts.length === 2) {
|
|
1900
|
-
if (
|
|
1900
|
+
if (isVertical6) {
|
|
1901
1901
|
const jogYNearStart = start.y + segDir * JOG_SIZE;
|
|
1902
1902
|
const jogYNearEnd = end.y - segDir * JOG_SIZE;
|
|
1903
1903
|
pts.splice(
|
|
@@ -1923,7 +1923,7 @@ var applyJogToTerminalSegment = ({
|
|
|
1923
1923
|
return;
|
|
1924
1924
|
}
|
|
1925
1925
|
if (si === 0) {
|
|
1926
|
-
if (
|
|
1926
|
+
if (isVertical6) {
|
|
1927
1927
|
const jogY = start.y + segDir * JOG_SIZE;
|
|
1928
1928
|
pts.splice(
|
|
1929
1929
|
1,
|
|
@@ -1943,7 +1943,7 @@ var applyJogToTerminalSegment = ({
|
|
|
1943
1943
|
);
|
|
1944
1944
|
}
|
|
1945
1945
|
} else {
|
|
1946
|
-
if (
|
|
1946
|
+
if (isVertical6) {
|
|
1947
1947
|
const jogY = end.y - segDir * JOG_SIZE;
|
|
1948
1948
|
pts.splice(
|
|
1949
1949
|
si,
|
|
@@ -2175,11 +2175,11 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2175
2175
|
}) {
|
|
2176
2176
|
const blockingCollisions = this.getBlockingCollisions({ group, offset });
|
|
2177
2177
|
if (blockingCollisions.length === 0) return offset;
|
|
2178
|
-
const crossesThroughObstacle = (candidateOffset) => blockingCollisions.some(({ start, isVertical:
|
|
2178
|
+
const crossesThroughObstacle = (candidateOffset) => blockingCollisions.some(({ start, isVertical: isVertical6, obstacle }) => {
|
|
2179
2179
|
let orig;
|
|
2180
2180
|
let min;
|
|
2181
2181
|
let max;
|
|
2182
|
-
if (
|
|
2182
|
+
if (isVertical6) {
|
|
2183
2183
|
orig = start.x;
|
|
2184
2184
|
min = obstacle.minX;
|
|
2185
2185
|
max = obstacle.maxX;
|
|
@@ -2191,8 +2191,8 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2191
2191
|
const next = orig + candidateOffset;
|
|
2192
2192
|
return orig <= min + EPS5 && next >= max - EPS5 || orig >= max - EPS5 && next <= min + EPS5;
|
|
2193
2193
|
});
|
|
2194
|
-
const edges = blockingCollisions.map(({ start, isVertical:
|
|
2195
|
-
if (
|
|
2194
|
+
const edges = blockingCollisions.map(({ start, isVertical: isVertical6, obstacle }) => {
|
|
2195
|
+
if (isVertical6) {
|
|
2196
2196
|
return {
|
|
2197
2197
|
coord: start.x,
|
|
2198
2198
|
lowEdge: obstacle.minX,
|
|
@@ -2226,10 +2226,10 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2226
2226
|
const start = trace.tracePath[traceSegmentIndex];
|
|
2227
2227
|
const end = trace.tracePath[traceSegmentIndex + 1];
|
|
2228
2228
|
if (!start || !end) continue;
|
|
2229
|
-
const
|
|
2230
|
-
const
|
|
2231
|
-
if (!
|
|
2232
|
-
const shiftedSegment =
|
|
2229
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS5;
|
|
2230
|
+
const isHorizontal5 = Math.abs(start.y - end.y) < EPS5;
|
|
2231
|
+
if (!isVertical6 && !isHorizontal5) continue;
|
|
2232
|
+
const shiftedSegment = isVertical6 ? [
|
|
2233
2233
|
{ ...start, x: start.x + offset },
|
|
2234
2234
|
{ ...end, x: end.x + offset }
|
|
2235
2235
|
] : [
|
|
@@ -2240,7 +2240,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2240
2240
|
if (collision) {
|
|
2241
2241
|
blockingCollisions.push({
|
|
2242
2242
|
start,
|
|
2243
|
-
isVertical:
|
|
2243
|
+
isVertical: isVertical6,
|
|
2244
2244
|
obstacle: collision.rect
|
|
2245
2245
|
});
|
|
2246
2246
|
}
|
|
@@ -2327,7 +2327,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2327
2327
|
return islands;
|
|
2328
2328
|
}
|
|
2329
2329
|
findNextOverlapIssue() {
|
|
2330
|
-
const
|
|
2330
|
+
const EPS15 = 2e-3;
|
|
2331
2331
|
const netIds = Object.keys(this.traceNetIslands);
|
|
2332
2332
|
for (let i = 0; i < netIds.length; i++) {
|
|
2333
2333
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -2354,7 +2354,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2354
2354
|
segmentBIndex,
|
|
2355
2355
|
rangeOverlap
|
|
2356
2356
|
}) => {
|
|
2357
|
-
if (rangeOverlap >
|
|
2357
|
+
if (rangeOverlap > EPS15) {
|
|
2358
2358
|
const keyA = `${pathAIndex}:${segmentAIndex}`;
|
|
2359
2359
|
const keyB = `${pathBIndex}:${segmentBIndex}`;
|
|
2360
2360
|
if (!seenA.has(keyA)) {
|
|
@@ -2373,7 +2373,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2373
2373
|
}
|
|
2374
2374
|
return;
|
|
2375
2375
|
}
|
|
2376
|
-
if (rangeOverlap < -
|
|
2376
|
+
if (rangeOverlap < -EPS15) return;
|
|
2377
2377
|
const pathA = pathsA[pathAIndex].tracePath;
|
|
2378
2378
|
const pathB = pathsB[pathBIndex].tracePath;
|
|
2379
2379
|
const segmentAStart = pathA[segmentAIndex];
|
|
@@ -2396,8 +2396,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2396
2396
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
2397
2397
|
const a1 = ptsA[sa];
|
|
2398
2398
|
const a2 = ptsA[sa + 1];
|
|
2399
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
2400
|
-
const aHorz = Math.abs(a1.y - a2.y) <
|
|
2399
|
+
const aVert = Math.abs(a1.x - a2.x) < EPS15;
|
|
2400
|
+
const aHorz = Math.abs(a1.y - a2.y) < EPS15;
|
|
2401
2401
|
if (!aVert && !aHorz) continue;
|
|
2402
2402
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
2403
2403
|
const pathB = pathsB[pb];
|
|
@@ -2408,11 +2408,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2408
2408
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
2409
2409
|
const b1 = ptsB[sb];
|
|
2410
2410
|
const b2 = ptsB[sb + 1];
|
|
2411
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
2412
|
-
const bHorz = Math.abs(b1.y - b2.y) <
|
|
2411
|
+
const bVert = Math.abs(b1.x - b2.x) < EPS15;
|
|
2412
|
+
const bHorz = Math.abs(b1.y - b2.y) < EPS15;
|
|
2413
2413
|
if (!bVert && !bHorz) continue;
|
|
2414
2414
|
if (aVert && bVert) {
|
|
2415
|
-
if (Math.abs(a1.x - b1.x) <
|
|
2415
|
+
if (Math.abs(a1.x - b1.x) < EPS15) {
|
|
2416
2416
|
recordCollinearInteraction({
|
|
2417
2417
|
pathAIndex: pa,
|
|
2418
2418
|
segmentAIndex: sa,
|
|
@@ -2422,7 +2422,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2422
2422
|
});
|
|
2423
2423
|
}
|
|
2424
2424
|
} else if (aHorz && bHorz) {
|
|
2425
|
-
if (Math.abs(a1.y - b1.y) <
|
|
2425
|
+
if (Math.abs(a1.y - b1.y) < EPS15) {
|
|
2426
2426
|
recordCollinearInteraction({
|
|
2427
2427
|
pathAIndex: pa,
|
|
2428
2428
|
segmentAIndex: sa,
|
|
@@ -2478,15 +2478,15 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2478
2478
|
return null;
|
|
2479
2479
|
}
|
|
2480
2480
|
findNextDiagonalSegment() {
|
|
2481
|
-
const
|
|
2481
|
+
const EPS15 = 2e-3;
|
|
2482
2482
|
for (const mspPairId in this.correctedTraceMap) {
|
|
2483
2483
|
const tracePath = this.correctedTraceMap[mspPairId].tracePath;
|
|
2484
2484
|
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
2485
2485
|
const p1 = tracePath[i];
|
|
2486
2486
|
const p2 = tracePath[i + 1];
|
|
2487
|
-
const
|
|
2488
|
-
const
|
|
2489
|
-
if (!
|
|
2487
|
+
const isHorizontal5 = Math.abs(p1.y - p2.y) < EPS15;
|
|
2488
|
+
const isVertical6 = Math.abs(p1.x - p2.x) < EPS15;
|
|
2489
|
+
if (!isHorizontal5 && !isVertical6) {
|
|
2490
2490
|
return { mspPairId, tracePath, i, p1, p2 };
|
|
2491
2491
|
}
|
|
2492
2492
|
}
|
|
@@ -2499,13 +2499,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2499
2499
|
return false;
|
|
2500
2500
|
}
|
|
2501
2501
|
const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
|
|
2502
|
-
const
|
|
2502
|
+
const EPS15 = 2e-3;
|
|
2503
2503
|
const p0 = i > 0 ? tracePath[i - 1] : null;
|
|
2504
2504
|
const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
|
|
2505
|
-
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) <
|
|
2506
|
-
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) <
|
|
2507
|
-
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) <
|
|
2508
|
-
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) <
|
|
2505
|
+
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS15 : false;
|
|
2506
|
+
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS15 : false;
|
|
2507
|
+
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS15 : false;
|
|
2508
|
+
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS15 : false;
|
|
2509
2509
|
const elbow1 = { x: p1.x, y: p2.y };
|
|
2510
2510
|
const elbow2 = { x: p2.x, y: p1.y };
|
|
2511
2511
|
let score1 = 0;
|
|
@@ -2667,24 +2667,24 @@ var ChipObstacleSpatialIndex = class {
|
|
|
2667
2667
|
};
|
|
2668
2668
|
|
|
2669
2669
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
|
|
2670
|
-
function segmentIntersectsRect2(p1, p2, rect,
|
|
2671
|
-
const isVert = Math.abs(p1.x - p2.x) <
|
|
2672
|
-
const isHorz = Math.abs(p1.y - p2.y) <
|
|
2670
|
+
function segmentIntersectsRect2(p1, p2, rect, EPS15 = 1e-9) {
|
|
2671
|
+
const isVert = Math.abs(p1.x - p2.x) < EPS15;
|
|
2672
|
+
const isHorz = Math.abs(p1.y - p2.y) < EPS15;
|
|
2673
2673
|
if (!isVert && !isHorz) return false;
|
|
2674
2674
|
if (isVert) {
|
|
2675
2675
|
const x = p1.x;
|
|
2676
|
-
if (x < rect.minX -
|
|
2676
|
+
if (x < rect.minX - EPS15 || x > rect.maxX + EPS15) return false;
|
|
2677
2677
|
const segMinY = Math.min(p1.y, p2.y);
|
|
2678
2678
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
2679
2679
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
2680
|
-
return overlap >
|
|
2680
|
+
return overlap > EPS15;
|
|
2681
2681
|
} else {
|
|
2682
2682
|
const y = p1.y;
|
|
2683
|
-
if (y < rect.minY -
|
|
2683
|
+
if (y < rect.minY - EPS15 || y > rect.maxY + EPS15) return false;
|
|
2684
2684
|
const segMinX = Math.min(p1.x, p2.x);
|
|
2685
2685
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
2686
2686
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
2687
|
-
return overlap >
|
|
2687
|
+
return overlap > EPS15;
|
|
2688
2688
|
}
|
|
2689
2689
|
}
|
|
2690
2690
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -3083,14 +3083,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
3083
3083
|
};
|
|
3084
3084
|
let bestCandidate = null;
|
|
3085
3085
|
let bestScore = -Infinity;
|
|
3086
|
-
const
|
|
3086
|
+
const EPS15 = 1e-6;
|
|
3087
3087
|
for (const curr of tracesToScan) {
|
|
3088
3088
|
const pts = curr.tracePath.slice();
|
|
3089
3089
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
3090
3090
|
const a = pts[si];
|
|
3091
3091
|
const b = pts[si + 1];
|
|
3092
|
-
const isH = Math.abs(a.y - b.y) <
|
|
3093
|
-
const isV = Math.abs(a.x - b.x) <
|
|
3092
|
+
const isH = Math.abs(a.y - b.y) < EPS15;
|
|
3093
|
+
const isV = Math.abs(a.x - b.x) < EPS15;
|
|
3094
3094
|
if (!isH && !isV) continue;
|
|
3095
3095
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
3096
3096
|
const candidateOrients = orientations.filter(
|
|
@@ -4176,11 +4176,11 @@ var doesPathCoincideWithTraces = (path, traces) => {
|
|
|
4176
4176
|
for (let i = 0; i < path.length - 1; i++) {
|
|
4177
4177
|
const pathSegStart = path[i];
|
|
4178
4178
|
const pathSegEnd = path[i + 1];
|
|
4179
|
-
const
|
|
4180
|
-
const
|
|
4181
|
-
if (!
|
|
4182
|
-
const crossAxis =
|
|
4183
|
-
const alongAxis =
|
|
4179
|
+
const isVertical6 = Math.abs(pathSegStart.x - pathSegEnd.x) < COINCIDENT_EPS;
|
|
4180
|
+
const isHorizontal5 = Math.abs(pathSegStart.y - pathSegEnd.y) < COINCIDENT_EPS;
|
|
4181
|
+
if (!isVertical6 && !isHorizontal5) continue;
|
|
4182
|
+
const crossAxis = isVertical6 ? "x" : "y";
|
|
4183
|
+
const alongAxis = isVertical6 ? "y" : "x";
|
|
4184
4184
|
for (const trace of traces) {
|
|
4185
4185
|
for (let j = 0; j < trace.tracePath.length - 1; j++) {
|
|
4186
4186
|
const traceSegStart = trace.tracePath[j];
|
|
@@ -4204,7 +4204,7 @@ var doesPathCoincideWithTraces = (path, traces) => {
|
|
|
4204
4204
|
};
|
|
4205
4205
|
var doesPathOverlapTraceStrokes = (path, traces) => {
|
|
4206
4206
|
const traceStrokeRadius = SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE / 2;
|
|
4207
|
-
const getStrokeBounds = (start, end,
|
|
4207
|
+
const getStrokeBounds = (start, end, isVertical6) => isVertical6 ? {
|
|
4208
4208
|
minX: start.x - traceStrokeRadius,
|
|
4209
4209
|
maxX: start.x + traceStrokeRadius,
|
|
4210
4210
|
minY: Math.min(start.y, end.y),
|
|
@@ -4218,22 +4218,22 @@ var doesPathOverlapTraceStrokes = (path, traces) => {
|
|
|
4218
4218
|
for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
|
|
4219
4219
|
const pathStart = path[pathIndex];
|
|
4220
4220
|
const pathEnd = path[pathIndex + 1];
|
|
4221
|
-
const
|
|
4222
|
-
const
|
|
4223
|
-
if (!
|
|
4224
|
-
const pathBounds = getStrokeBounds(pathStart, pathEnd,
|
|
4221
|
+
const isVertical6 = Math.abs(pathStart.x - pathEnd.x) < COINCIDENT_EPS;
|
|
4222
|
+
const isHorizontal5 = Math.abs(pathStart.y - pathEnd.y) < COINCIDENT_EPS;
|
|
4223
|
+
if (!isVertical6 && !isHorizontal5) continue;
|
|
4224
|
+
const pathBounds = getStrokeBounds(pathStart, pathEnd, isVertical6);
|
|
4225
4225
|
for (const trace of traces) {
|
|
4226
4226
|
for (let traceIndex = 0; traceIndex < trace.tracePath.length - 1; traceIndex++) {
|
|
4227
4227
|
const traceStart = trace.tracePath[traceIndex];
|
|
4228
4228
|
const traceEnd = trace.tracePath[traceIndex + 1];
|
|
4229
|
-
const isParallel =
|
|
4229
|
+
const isParallel = isVertical6 ? Math.abs(traceStart.x - traceEnd.x) < COINCIDENT_EPS : Math.abs(traceStart.y - traceEnd.y) < COINCIDENT_EPS;
|
|
4230
4230
|
if (!isParallel) continue;
|
|
4231
4231
|
const overlap = boundsIntersection(
|
|
4232
4232
|
pathBounds,
|
|
4233
|
-
getStrokeBounds(traceStart, traceEnd,
|
|
4233
|
+
getStrokeBounds(traceStart, traceEnd, isVertical6)
|
|
4234
4234
|
);
|
|
4235
4235
|
if (!overlap) continue;
|
|
4236
|
-
const overlapLength =
|
|
4236
|
+
const overlapLength = isVertical6 ? overlap.maxY - overlap.minY : overlap.maxX - overlap.minX;
|
|
4237
4237
|
if (overlapLength > COINCIDENT_EPS) return true;
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
@@ -6015,12 +6015,12 @@ var EPS8 = 1e-9;
|
|
|
6015
6015
|
|
|
6016
6016
|
// lib/solvers/Example28Solver/segmentRunsAlongRectBoundary.ts
|
|
6017
6017
|
var segmentRunsAlongRectBoundary = (start, end, rect) => {
|
|
6018
|
-
const
|
|
6019
|
-
const
|
|
6020
|
-
if (
|
|
6018
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS8;
|
|
6019
|
+
const isHorizontal5 = Math.abs(start.y - end.y) < EPS8;
|
|
6020
|
+
if (isVertical6) {
|
|
6021
6021
|
return Math.abs(start.x - rect.minX) < EPS8 || Math.abs(start.x - rect.maxX) < EPS8;
|
|
6022
6022
|
}
|
|
6023
|
-
if (
|
|
6023
|
+
if (isHorizontal5) {
|
|
6024
6024
|
return Math.abs(start.y - rect.minY) < EPS8 || Math.abs(start.y - rect.maxY) < EPS8;
|
|
6025
6025
|
}
|
|
6026
6026
|
return false;
|
|
@@ -6614,12 +6614,12 @@ var findPerpendicularPathCrossings = (path, otherPath) => {
|
|
|
6614
6614
|
for (let pathSegmentIndex = 1; pathSegmentIndex < path.length - 2; pathSegmentIndex++) {
|
|
6615
6615
|
const start = path[pathSegmentIndex];
|
|
6616
6616
|
const end = path[pathSegmentIndex + 1];
|
|
6617
|
-
const
|
|
6617
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS9;
|
|
6618
6618
|
for (let otherPathSegmentIndex = 1; otherPathSegmentIndex < otherPath.length - 2; otherPathSegmentIndex++) {
|
|
6619
6619
|
const otherStart = otherPath[otherPathSegmentIndex];
|
|
6620
6620
|
const otherEnd = otherPath[otherPathSegmentIndex + 1];
|
|
6621
6621
|
const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS9;
|
|
6622
|
-
if (
|
|
6622
|
+
if (isVertical6 === otherIsVertical) continue;
|
|
6623
6623
|
const intersection = getSegmentIntersection(
|
|
6624
6624
|
start,
|
|
6625
6625
|
end,
|
|
@@ -7727,8 +7727,8 @@ var getChipBoundaryOverlap = (path, chipObstacles) => {
|
|
|
7727
7727
|
return total;
|
|
7728
7728
|
};
|
|
7729
7729
|
var getSegmentOverlapWithRectSpan = (start, end, rect) => {
|
|
7730
|
-
const
|
|
7731
|
-
if (
|
|
7730
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS8;
|
|
7731
|
+
if (isVertical6) {
|
|
7732
7732
|
return Math.min(Math.max(start.y, end.y), rect.maxY) - Math.max(Math.min(start.y, end.y), rect.minY);
|
|
7733
7733
|
}
|
|
7734
7734
|
return Math.min(Math.max(start.x, end.x), rect.maxX) - Math.max(Math.min(start.x, end.x), rect.minX);
|
|
@@ -11978,11 +11978,11 @@ var NetLabelNetLabelCollisionSolver = class extends BaseSolver {
|
|
|
11978
11978
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
11979
11979
|
const segStart = pts[si];
|
|
11980
11980
|
const segEnd = pts[si + 1];
|
|
11981
|
-
const
|
|
11982
|
-
const
|
|
11983
|
-
if (!
|
|
11981
|
+
const isHorizontal5 = Math.abs(segStart.y - segEnd.y) < SEGMENT_PARALLEL_EPS;
|
|
11982
|
+
const isVertical6 = Math.abs(segStart.x - segEnd.x) < SEGMENT_PARALLEL_EPS;
|
|
11983
|
+
if (!isHorizontal5 && !isVertical6) continue;
|
|
11984
11984
|
let perpendicularOrientations;
|
|
11985
|
-
if (
|
|
11985
|
+
if (isHorizontal5) {
|
|
11986
11986
|
perpendicularOrientations = ["y+", "y-"];
|
|
11987
11987
|
} else {
|
|
11988
11988
|
perpendicularOrientations = ["x+", "x-"];
|
|
@@ -13660,9 +13660,9 @@ var getStubLength = (path) => {
|
|
|
13660
13660
|
return Math.abs(end.x - start.x) + Math.abs(end.y - start.y);
|
|
13661
13661
|
};
|
|
13662
13662
|
var getLabelBounds2 = (placement) => {
|
|
13663
|
-
const
|
|
13664
|
-
const width =
|
|
13665
|
-
const height =
|
|
13663
|
+
const isVertical6 = placement.axis === "y";
|
|
13664
|
+
const width = isVertical6 ? placement.height : placement.width;
|
|
13665
|
+
const height = isVertical6 ? placement.width : placement.height;
|
|
13666
13666
|
return {
|
|
13667
13667
|
minX: placement.center.x - width / 2,
|
|
13668
13668
|
maxX: placement.center.x + width / 2,
|
|
@@ -13890,9 +13890,9 @@ var isPointOnPath2 = (point, path) => {
|
|
|
13890
13890
|
const maxX = Math.max(start.x, end.x) + POINT_EPSILON;
|
|
13891
13891
|
const minY = Math.min(start.y, end.y) - POINT_EPSILON;
|
|
13892
13892
|
const maxY = Math.max(start.y, end.y) + POINT_EPSILON;
|
|
13893
|
-
const
|
|
13894
|
-
const
|
|
13895
|
-
if ((
|
|
13893
|
+
const isHorizontal5 = Math.abs(start.y - end.y) <= POINT_EPSILON;
|
|
13894
|
+
const isVertical6 = Math.abs(start.x - end.x) <= POINT_EPSILON;
|
|
13895
|
+
if ((isHorizontal5 && Math.abs(point.y - start.y) <= POINT_EPSILON || isVertical6 && Math.abs(point.x - start.x) <= POINT_EPSILON) && point.x >= minX && point.x <= maxX && point.y >= minY && point.y <= maxY) {
|
|
13896
13896
|
return true;
|
|
13897
13897
|
}
|
|
13898
13898
|
}
|
|
@@ -15127,10 +15127,10 @@ orientation: ${label.orientation}`
|
|
|
15127
15127
|
strokeColor: "purple"
|
|
15128
15128
|
});
|
|
15129
15129
|
}
|
|
15130
|
-
const
|
|
15130
|
+
const isHorizontal5 = inlineLabel.axis === "x";
|
|
15131
15131
|
let renderedWidth = inlineLabel.width;
|
|
15132
15132
|
let renderedHeight = inlineLabel.height;
|
|
15133
|
-
if (!
|
|
15133
|
+
if (!isHorizontal5) {
|
|
15134
15134
|
renderedWidth = inlineLabel.height;
|
|
15135
15135
|
renderedHeight = inlineLabel.width;
|
|
15136
15136
|
}
|
|
@@ -15230,9 +15230,9 @@ var getCollisionLimitedTerminalStubEnd = ({
|
|
|
15230
15230
|
ownGlobalConnNetId,
|
|
15231
15231
|
ignoredTraceIds
|
|
15232
15232
|
}) => {
|
|
15233
|
-
const
|
|
15234
|
-
const alongAxis =
|
|
15235
|
-
const acrossAxis =
|
|
15233
|
+
const isHorizontal5 = Math.abs(intendedEnd.x - start.x) >= Math.abs(intendedEnd.y - start.y);
|
|
15234
|
+
const alongAxis = isHorizontal5 ? "x" : "y";
|
|
15235
|
+
const acrossAxis = isHorizontal5 ? "y" : "x";
|
|
15236
15236
|
const direction = Math.sign(intendedEnd[alongAxis] - start[alongAxis]) || 1;
|
|
15237
15237
|
const intendedLength = Math.abs(intendedEnd[alongAxis] - start[alongAxis]);
|
|
15238
15238
|
let availableLength = intendedLength;
|
|
@@ -15270,7 +15270,7 @@ var getCollisionLimitedTerminalStubEnd = ({
|
|
|
15270
15270
|
}
|
|
15271
15271
|
}
|
|
15272
15272
|
if (availableLength + GEOMETRY_EPSILON < minimumLength) return null;
|
|
15273
|
-
return
|
|
15273
|
+
return isHorizontal5 ? { x: start.x + direction * availableLength, y: start.y } : { x: start.x, y: start.y + direction * availableLength };
|
|
15274
15274
|
};
|
|
15275
15275
|
|
|
15276
15276
|
// lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts
|
|
@@ -15279,23 +15279,6 @@ import {
|
|
|
15279
15279
|
getBoundFromCenteredRect
|
|
15280
15280
|
} from "@tscircuit/math-utils";
|
|
15281
15281
|
|
|
15282
|
-
// lib/solvers/NetLabelTraceRecovery/getTraceRecoveryConnectivityMaps.ts
|
|
15283
|
-
var getTraceRecoveryConnectivityMaps = (inputProblem) => {
|
|
15284
|
-
const chipMap = {};
|
|
15285
|
-
const pinMap = /* @__PURE__ */ new Map();
|
|
15286
|
-
for (const chip of inputProblem.chips) {
|
|
15287
|
-
chipMap[chip.chipId] = chip;
|
|
15288
|
-
for (const pin of chip.pins) {
|
|
15289
|
-
pinMap.set(pin.pinId, {
|
|
15290
|
-
...pin,
|
|
15291
|
-
chipId: chip.chipId,
|
|
15292
|
-
_facingDirection: pin._facingDirection ?? getPinDirection(pin, chip)
|
|
15293
|
-
});
|
|
15294
|
-
}
|
|
15295
|
-
}
|
|
15296
|
-
return { chipMap, pinMap };
|
|
15297
|
-
};
|
|
15298
|
-
|
|
15299
15282
|
// lib/solvers/NetLabelTraceRecovery/doesTraceRecoveryPathConflict.ts
|
|
15300
15283
|
import { doSegmentsIntersect as doSegmentsIntersect4 } from "@tscircuit/math-utils";
|
|
15301
15284
|
var EPSILON = 1e-6;
|
|
@@ -15372,6 +15355,124 @@ var doesTraceRecoveryPathConflict = (tracePath, collisionTraces) => {
|
|
|
15372
15355
|
return false;
|
|
15373
15356
|
};
|
|
15374
15357
|
|
|
15358
|
+
// lib/solvers/NetLabelTraceRecovery/getTraceRecoveryConnectivityMaps.ts
|
|
15359
|
+
var getTraceRecoveryConnectivityMaps = (inputProblem) => {
|
|
15360
|
+
const chipMap = {};
|
|
15361
|
+
const pinMap = /* @__PURE__ */ new Map();
|
|
15362
|
+
for (const chip of inputProblem.chips) {
|
|
15363
|
+
chipMap[chip.chipId] = chip;
|
|
15364
|
+
for (const pin of chip.pins) {
|
|
15365
|
+
pinMap.set(pin.pinId, {
|
|
15366
|
+
...pin,
|
|
15367
|
+
chipId: chip.chipId,
|
|
15368
|
+
_facingDirection: pin._facingDirection ?? getPinDirection(pin, chip)
|
|
15369
|
+
});
|
|
15370
|
+
}
|
|
15371
|
+
}
|
|
15372
|
+
return { chipMap, pinMap };
|
|
15373
|
+
};
|
|
15374
|
+
|
|
15375
|
+
// lib/solvers/NetLabelToTraceSolver/reduceTraceCrossings.ts
|
|
15376
|
+
var EPS14 = 1e-9;
|
|
15377
|
+
var isHorizontal4 = (start, end) => Math.abs(start.y - end.y) < EPS14;
|
|
15378
|
+
var isVertical5 = (start, end) => Math.abs(start.x - end.x) < EPS14;
|
|
15379
|
+
var compactConsecutivePoints = (path) => path.filter((point, index) => {
|
|
15380
|
+
const previousPoint = path[index - 1];
|
|
15381
|
+
return !previousPoint || Math.abs(point.x - previousPoint.x) >= EPS14 || Math.abs(point.y - previousPoint.y) >= EPS14;
|
|
15382
|
+
});
|
|
15383
|
+
var isValidOrthogonalPath = (path) => {
|
|
15384
|
+
if (path.length < 2 || !path.every((point, index) => {
|
|
15385
|
+
const nextPoint = path[index + 1];
|
|
15386
|
+
if (!nextPoint) return true;
|
|
15387
|
+
return isHorizontal4(point, nextPoint) || isVertical5(point, nextPoint);
|
|
15388
|
+
})) {
|
|
15389
|
+
return false;
|
|
15390
|
+
}
|
|
15391
|
+
for (let firstSegmentIndex = 0; firstSegmentIndex < path.length - 1; firstSegmentIndex++) {
|
|
15392
|
+
for (let secondSegmentIndex = firstSegmentIndex + 2; secondSegmentIndex < path.length - 1; secondSegmentIndex++) {
|
|
15393
|
+
if (segmentsIntersect(
|
|
15394
|
+
path[firstSegmentIndex],
|
|
15395
|
+
path[firstSegmentIndex + 1],
|
|
15396
|
+
path[secondSegmentIndex],
|
|
15397
|
+
path[secondSegmentIndex + 1]
|
|
15398
|
+
)) {
|
|
15399
|
+
return false;
|
|
15400
|
+
}
|
|
15401
|
+
}
|
|
15402
|
+
}
|
|
15403
|
+
return true;
|
|
15404
|
+
};
|
|
15405
|
+
var getEndpointAlignedSegmentCandidates = (tracePath) => {
|
|
15406
|
+
const candidates = [];
|
|
15407
|
+
for (let segmentIndex = 2; segmentIndex <= tracePath.length - 4; segmentIndex++) {
|
|
15408
|
+
const previousPoint = tracePath[segmentIndex - 1];
|
|
15409
|
+
const start = tracePath[segmentIndex];
|
|
15410
|
+
const end = tracePath[segmentIndex + 1];
|
|
15411
|
+
const nextPoint = tracePath[segmentIndex + 2];
|
|
15412
|
+
const segmentIsVertical = isVertical5(start, end);
|
|
15413
|
+
const segmentIsHorizontal = isHorizontal4(start, end);
|
|
15414
|
+
if (!segmentIsVertical && !segmentIsHorizontal || segmentIsVertical && (!isHorizontal4(previousPoint, start) || !isHorizontal4(end, nextPoint)) || segmentIsHorizontal && (!isVertical5(previousPoint, start) || !isVertical5(end, nextPoint))) {
|
|
15415
|
+
continue;
|
|
15416
|
+
}
|
|
15417
|
+
const alignedCoordinates = segmentIsVertical ? [previousPoint.x, nextPoint.x] : [previousPoint.y, nextPoint.y];
|
|
15418
|
+
for (const alignedCoordinate of alignedCoordinates) {
|
|
15419
|
+
if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS14) {
|
|
15420
|
+
continue;
|
|
15421
|
+
}
|
|
15422
|
+
const candidate = tracePath.map((point) => ({ ...point }));
|
|
15423
|
+
if (segmentIsVertical) {
|
|
15424
|
+
candidate[segmentIndex].x = alignedCoordinate;
|
|
15425
|
+
candidate[segmentIndex + 1].x = alignedCoordinate;
|
|
15426
|
+
} else {
|
|
15427
|
+
candidate[segmentIndex].y = alignedCoordinate;
|
|
15428
|
+
candidate[segmentIndex + 1].y = alignedCoordinate;
|
|
15429
|
+
}
|
|
15430
|
+
const compactedCandidate = compactConsecutivePoints(candidate);
|
|
15431
|
+
if (isValidOrthogonalPath(compactedCandidate)) {
|
|
15432
|
+
candidates.push(compactedCandidate);
|
|
15433
|
+
}
|
|
15434
|
+
}
|
|
15435
|
+
}
|
|
15436
|
+
return candidates;
|
|
15437
|
+
};
|
|
15438
|
+
var countOtherNetCrossings2 = ({
|
|
15439
|
+
tracePath,
|
|
15440
|
+
globalConnNetId,
|
|
15441
|
+
otherTraces
|
|
15442
|
+
}) => otherTraces.reduce(
|
|
15443
|
+
(crossingCount, otherTrace) => crossingCount + (otherTrace.globalConnNetId === globalConnNetId ? 0 : countPathIntersections(tracePath, otherTrace.tracePath)),
|
|
15444
|
+
0
|
|
15445
|
+
);
|
|
15446
|
+
var reduceTraceCrossings = ({
|
|
15447
|
+
tracePath,
|
|
15448
|
+
globalConnNetId,
|
|
15449
|
+
otherTraces,
|
|
15450
|
+
isCandidateValid
|
|
15451
|
+
}) => {
|
|
15452
|
+
let bestPath = tracePath;
|
|
15453
|
+
let bestCrossingCount = countOtherNetCrossings2({
|
|
15454
|
+
tracePath,
|
|
15455
|
+
globalConnNetId,
|
|
15456
|
+
otherTraces
|
|
15457
|
+
});
|
|
15458
|
+
let bestPathLength = getPathLength2(tracePath);
|
|
15459
|
+
for (const candidate of getEndpointAlignedSegmentCandidates(tracePath)) {
|
|
15460
|
+
if (!isCandidateValid(candidate)) continue;
|
|
15461
|
+
const crossingCount = countOtherNetCrossings2({
|
|
15462
|
+
tracePath: candidate,
|
|
15463
|
+
globalConnNetId,
|
|
15464
|
+
otherTraces
|
|
15465
|
+
});
|
|
15466
|
+
const pathLength = getPathLength2(candidate);
|
|
15467
|
+
if (crossingCount < bestCrossingCount || crossingCount === bestCrossingCount && pathLength < bestPathLength) {
|
|
15468
|
+
bestPath = candidate;
|
|
15469
|
+
bestCrossingCount = crossingCount;
|
|
15470
|
+
bestPathLength = pathLength;
|
|
15471
|
+
}
|
|
15472
|
+
}
|
|
15473
|
+
return bestPath;
|
|
15474
|
+
};
|
|
15475
|
+
|
|
15375
15476
|
// lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts
|
|
15376
15477
|
var AVAILABLE_NET_ORIENTATION_PREFIX = "available-net-orientation-";
|
|
15377
15478
|
var RECOVERED_TRACE_PREFIX = "net-label-to-trace-";
|
|
@@ -15631,7 +15732,7 @@ var NetLabelToTraceSolver = class extends BaseSolver {
|
|
|
15631
15732
|
}
|
|
15632
15733
|
tryAcceptCurrentRoute() {
|
|
15633
15734
|
const candidate = this.currentCandidate;
|
|
15634
|
-
|
|
15735
|
+
let tracePath = this.activeSubSolver?.solvedTracePath;
|
|
15635
15736
|
if (!candidate || !tracePath) return;
|
|
15636
15737
|
const retainedTraces = this.outputTraces.filter(
|
|
15637
15738
|
(trace) => !this.isSupersededConnectorTrace(trace, candidate)
|
|
@@ -15645,6 +15746,12 @@ var NetLabelToTraceSolver = class extends BaseSolver {
|
|
|
15645
15746
|
if (doesTraceRecoveryPathConflict(tracePath, collisionTraces) || this.routeIntersectsRemainingLabels(tracePath, candidate)) {
|
|
15646
15747
|
return;
|
|
15647
15748
|
}
|
|
15749
|
+
tracePath = reduceTraceCrossings({
|
|
15750
|
+
tracePath,
|
|
15751
|
+
globalConnNetId: candidate.firstLabel.globalConnNetId,
|
|
15752
|
+
otherTraces: collisionTraces,
|
|
15753
|
+
isCandidateValid: (candidatePath) => findFirstCollision(candidatePath, this.activeSubSolver.obstacles) === null && !doesTraceRecoveryPathConflict(candidatePath, collisionTraces) && !this.routeIntersectsRemainingLabels(candidatePath, candidate)
|
|
15754
|
+
});
|
|
15648
15755
|
const [firstPin, secondPin] = candidate.pins;
|
|
15649
15756
|
const mspPairId = `${RECOVERED_TRACE_PREFIX}${candidate.key}`;
|
|
15650
15757
|
const recoveredTrace = {
|
|
@@ -5,16 +5,17 @@ import {
|
|
|
5
5
|
} from "@tscircuit/math-utils"
|
|
6
6
|
import type { GraphicsObject } from "graphics-debug"
|
|
7
7
|
import { BaseSolver } from "lib/solvers/BaseSolver/BaseSolver"
|
|
8
|
-
import { getConnectivityMapsFromInputProblem } from "lib/solvers/MspConnectionPairSolver/getConnectivityMapFromInputProblem"
|
|
9
8
|
import { doesPairCrossRestrictedCenterLines } from "lib/solvers/MspConnectionPairSolver/doesPairCrossRestrictedCenterLines"
|
|
9
|
+
import { getConnectivityMapsFromInputProblem } from "lib/solvers/MspConnectionPairSolver/getConnectivityMapFromInputProblem"
|
|
10
10
|
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
11
|
+
import { doesTraceRecoveryPathConflict } from "lib/solvers/NetLabelTraceRecovery/doesTraceRecoveryPathConflict"
|
|
11
12
|
import {
|
|
12
13
|
getTraceRecoveryConnectivityMaps,
|
|
13
14
|
type TraceRecoveryPin,
|
|
14
15
|
} from "lib/solvers/NetLabelTraceRecovery/getTraceRecoveryConnectivityMaps"
|
|
15
|
-
import { doesTraceRecoveryPathConflict } from "lib/solvers/NetLabelTraceRecovery/doesTraceRecoveryPathConflict"
|
|
16
16
|
import { getTraceConnectedPinComponents } from "lib/solvers/SchematicTraceLinesSolver/getTraceConnectedPinComponents"
|
|
17
17
|
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
18
|
+
import { findFirstCollision } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
|
|
18
19
|
import { SchematicTraceSingleLineSolver2 } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2"
|
|
19
20
|
import type {
|
|
20
21
|
ChipId,
|
|
@@ -24,10 +25,11 @@ import type {
|
|
|
24
25
|
} from "lib/types/InputProblem"
|
|
25
26
|
import { arePinsInDifferentSchematicSections } from "lib/utils/arePinsInDifferentSchematicSections"
|
|
26
27
|
import {
|
|
27
|
-
type InlineNetLabelPlacement,
|
|
28
28
|
type InlineNetLabelOutput,
|
|
29
|
+
type InlineNetLabelPlacement,
|
|
29
30
|
visualizeInlineNetLabelOutput,
|
|
30
31
|
} from "../InlineNetLabelSolver/InlineNetLabelSolver"
|
|
32
|
+
import { reduceTraceCrossings } from "./reduceTraceCrossings"
|
|
31
33
|
|
|
32
34
|
type GlobalConnNetId = NetLabelPlacement["globalConnNetId"]
|
|
33
35
|
|
|
@@ -420,7 +422,7 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
420
422
|
|
|
421
423
|
private tryAcceptCurrentRoute() {
|
|
422
424
|
const candidate = this.currentCandidate
|
|
423
|
-
|
|
425
|
+
let tracePath = this.activeSubSolver?.solvedTracePath
|
|
424
426
|
if (!candidate || !tracePath) return
|
|
425
427
|
|
|
426
428
|
const retainedTraces = this.outputTraces.filter(
|
|
@@ -440,6 +442,17 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
440
442
|
return
|
|
441
443
|
}
|
|
442
444
|
|
|
445
|
+
tracePath = reduceTraceCrossings({
|
|
446
|
+
tracePath,
|
|
447
|
+
globalConnNetId: candidate.firstLabel.globalConnNetId,
|
|
448
|
+
otherTraces: collisionTraces,
|
|
449
|
+
isCandidateValid: (candidatePath) =>
|
|
450
|
+
findFirstCollision(candidatePath, this.activeSubSolver!.obstacles) ===
|
|
451
|
+
null &&
|
|
452
|
+
!doesTraceRecoveryPathConflict(candidatePath, collisionTraces) &&
|
|
453
|
+
!this.routeIntersectsRemainingLabels(candidatePath, candidate),
|
|
454
|
+
})
|
|
455
|
+
|
|
443
456
|
const [firstPin, secondPin] = candidate.pins
|
|
444
457
|
const mspPairId = `${RECOVERED_TRACE_PREFIX}${candidate.key}`
|
|
445
458
|
const recoveredTrace: SolvedTracePath = {
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type { Point } from "@tscircuit/math-utils"
|
|
2
|
+
import {
|
|
3
|
+
countPathIntersections,
|
|
4
|
+
getPathLength,
|
|
5
|
+
segmentsIntersect,
|
|
6
|
+
} from "lib/solvers/Example28Solver/geometry"
|
|
7
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
8
|
+
|
|
9
|
+
const EPS = 1e-9
|
|
10
|
+
|
|
11
|
+
const isHorizontal = (start: Point, end: Point) =>
|
|
12
|
+
Math.abs(start.y - end.y) < EPS
|
|
13
|
+
|
|
14
|
+
const isVertical = (start: Point, end: Point) => Math.abs(start.x - end.x) < EPS
|
|
15
|
+
|
|
16
|
+
const compactConsecutivePoints = (path: Point[]) =>
|
|
17
|
+
path.filter((point, index) => {
|
|
18
|
+
const previousPoint = path[index - 1]
|
|
19
|
+
return (
|
|
20
|
+
!previousPoint ||
|
|
21
|
+
Math.abs(point.x - previousPoint.x) >= EPS ||
|
|
22
|
+
Math.abs(point.y - previousPoint.y) >= EPS
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const isValidOrthogonalPath = (path: Point[]) => {
|
|
27
|
+
if (
|
|
28
|
+
path.length < 2 ||
|
|
29
|
+
!path.every((point, index) => {
|
|
30
|
+
const nextPoint = path[index + 1]
|
|
31
|
+
if (!nextPoint) return true
|
|
32
|
+
return isHorizontal(point, nextPoint) || isVertical(point, nextPoint)
|
|
33
|
+
})
|
|
34
|
+
) {
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
for (
|
|
39
|
+
let firstSegmentIndex = 0;
|
|
40
|
+
firstSegmentIndex < path.length - 1;
|
|
41
|
+
firstSegmentIndex++
|
|
42
|
+
) {
|
|
43
|
+
for (
|
|
44
|
+
let secondSegmentIndex = firstSegmentIndex + 2;
|
|
45
|
+
secondSegmentIndex < path.length - 1;
|
|
46
|
+
secondSegmentIndex++
|
|
47
|
+
) {
|
|
48
|
+
if (
|
|
49
|
+
segmentsIntersect(
|
|
50
|
+
path[firstSegmentIndex]!,
|
|
51
|
+
path[firstSegmentIndex + 1]!,
|
|
52
|
+
path[secondSegmentIndex]!,
|
|
53
|
+
path[secondSegmentIndex + 1]!,
|
|
54
|
+
)
|
|
55
|
+
) {
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const getEndpointAlignedSegmentCandidates = (tracePath: Point[]) => {
|
|
65
|
+
const candidates: Point[][] = []
|
|
66
|
+
|
|
67
|
+
// Preserve the terminal segment at each pin. For an interior segment whose
|
|
68
|
+
// neighboring segments are perpendicular, align it with either neighboring
|
|
69
|
+
// endpoint corridor. This keeps the same orthogonal topology while allowing
|
|
70
|
+
// a midpoint elbow to move away from avoidable trace crossings.
|
|
71
|
+
for (
|
|
72
|
+
let segmentIndex = 2;
|
|
73
|
+
segmentIndex <= tracePath.length - 4;
|
|
74
|
+
segmentIndex++
|
|
75
|
+
) {
|
|
76
|
+
const previousPoint = tracePath[segmentIndex - 1]!
|
|
77
|
+
const start = tracePath[segmentIndex]!
|
|
78
|
+
const end = tracePath[segmentIndex + 1]!
|
|
79
|
+
const nextPoint = tracePath[segmentIndex + 2]!
|
|
80
|
+
const segmentIsVertical = isVertical(start, end)
|
|
81
|
+
const segmentIsHorizontal = isHorizontal(start, end)
|
|
82
|
+
|
|
83
|
+
if (
|
|
84
|
+
(!segmentIsVertical && !segmentIsHorizontal) ||
|
|
85
|
+
(segmentIsVertical &&
|
|
86
|
+
(!isHorizontal(previousPoint, start) ||
|
|
87
|
+
!isHorizontal(end, nextPoint))) ||
|
|
88
|
+
(segmentIsHorizontal &&
|
|
89
|
+
(!isVertical(previousPoint, start) || !isVertical(end, nextPoint)))
|
|
90
|
+
) {
|
|
91
|
+
continue
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const alignedCoordinates = segmentIsVertical
|
|
95
|
+
? [previousPoint.x, nextPoint.x]
|
|
96
|
+
: [previousPoint.y, nextPoint.y]
|
|
97
|
+
for (const alignedCoordinate of alignedCoordinates) {
|
|
98
|
+
if (
|
|
99
|
+
Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) <
|
|
100
|
+
EPS
|
|
101
|
+
) {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const candidate = tracePath.map((point) => ({ ...point }))
|
|
106
|
+
if (segmentIsVertical) {
|
|
107
|
+
candidate[segmentIndex]!.x = alignedCoordinate
|
|
108
|
+
candidate[segmentIndex + 1]!.x = alignedCoordinate
|
|
109
|
+
} else {
|
|
110
|
+
candidate[segmentIndex]!.y = alignedCoordinate
|
|
111
|
+
candidate[segmentIndex + 1]!.y = alignedCoordinate
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const compactedCandidate = compactConsecutivePoints(candidate)
|
|
115
|
+
if (isValidOrthogonalPath(compactedCandidate)) {
|
|
116
|
+
candidates.push(compactedCandidate)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return candidates
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const countOtherNetCrossings = ({
|
|
125
|
+
tracePath,
|
|
126
|
+
globalConnNetId,
|
|
127
|
+
otherTraces,
|
|
128
|
+
}: {
|
|
129
|
+
tracePath: Point[]
|
|
130
|
+
globalConnNetId: string
|
|
131
|
+
otherTraces: SolvedTracePath[]
|
|
132
|
+
}) =>
|
|
133
|
+
otherTraces.reduce(
|
|
134
|
+
(crossingCount, otherTrace) =>
|
|
135
|
+
crossingCount +
|
|
136
|
+
(otherTrace.globalConnNetId === globalConnNetId
|
|
137
|
+
? 0
|
|
138
|
+
: countPathIntersections(tracePath, otherTrace.tracePath)),
|
|
139
|
+
0,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
export const reduceTraceCrossings = ({
|
|
143
|
+
tracePath,
|
|
144
|
+
globalConnNetId,
|
|
145
|
+
otherTraces,
|
|
146
|
+
isCandidateValid,
|
|
147
|
+
}: {
|
|
148
|
+
tracePath: Point[]
|
|
149
|
+
globalConnNetId: string
|
|
150
|
+
otherTraces: SolvedTracePath[]
|
|
151
|
+
isCandidateValid: (candidate: Point[]) => boolean
|
|
152
|
+
}) => {
|
|
153
|
+
let bestPath = tracePath
|
|
154
|
+
let bestCrossingCount = countOtherNetCrossings({
|
|
155
|
+
tracePath,
|
|
156
|
+
globalConnNetId,
|
|
157
|
+
otherTraces,
|
|
158
|
+
})
|
|
159
|
+
let bestPathLength = getPathLength(tracePath)
|
|
160
|
+
|
|
161
|
+
for (const candidate of getEndpointAlignedSegmentCandidates(tracePath)) {
|
|
162
|
+
if (!isCandidateValid(candidate)) continue
|
|
163
|
+
const crossingCount = countOtherNetCrossings({
|
|
164
|
+
tracePath: candidate,
|
|
165
|
+
globalConnNetId,
|
|
166
|
+
otherTraces,
|
|
167
|
+
})
|
|
168
|
+
const pathLength = getPathLength(candidate)
|
|
169
|
+
if (
|
|
170
|
+
crossingCount < bestCrossingCount ||
|
|
171
|
+
(crossingCount === bestCrossingCount && pathLength < bestPathLength)
|
|
172
|
+
) {
|
|
173
|
+
bestPath = candidate
|
|
174
|
+
bestCrossingCount = crossingCount
|
|
175
|
+
bestPathLength = pathLength
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return bestPath
|
|
180
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<svg width="1200" height="2016" viewBox="0 0 1200 2016" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Solver debug visualization on top and Circuit JSON schematic on the bottom">
|
|
2
2
|
<g transform="translate(0, 0) scale(1.875, 1.875) translate(0, 0)">
|
|
3
|
-
<rect width="100%" height="100%" fill="white"/><g><polyline data-points="-6.74,0.3 -4.24,1.7" data-type="line" data-label="" points="61.98952879581145,334.4564787958115 245.23560209424073,231.8386777486911" fill="none" stroke="hsl(24, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.30000000000000004 -5.640000000000001,0.3" data-type="line" data-label="" points="512.0418848167538,334.4564787958115 142.61780104712034,334.4564787958115" fill="none" stroke="hsl(8, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.10000000000000003 -3.1399999999999997,1.7" data-type="line" data-label="" points="512.0418848167538,349.11616465968586 325.8638743455497,231.8386777486911" fill="none" stroke="hsl(8, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-3.52,-0.09999999999999998 -0.6000000000000001,-0.09999999999999998" data-type="line" data-label="" points="298.01047120418843,363.77585052356017 512.0418848167538,363.77585052356017" fill="none" stroke="hsl(152, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-3.52,-0.3 -0.6000000000000001,-0.30000000000000004" data-type="line" data-label="" points="298.01047120418843,378.4355363874345 512.0418848167538,378.4355363874345" fill="none" stroke="hsl(152, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-6.74,0.3 -6.94,0.3 -6.94,1.7 -4.24,1.7" data-type="line" data-label="" points="61.98952879581145,334.4564787958115 47.329842931937094,334.4564787958115 47.329842931937094,231.8386777486911 245.23560209424073,231.8386777486911" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.30000000000000004 -5.640000000000001,0.3" data-type="line" data-label="" points="512.0418848167538,334.4564787958115 142.61780104712034,334.4564787958115" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-3.52,-0.09999999999999998 -3.72,-0.09999999999999998 -3.72,0.19999999999999998 -1.1510000000000002,0.19999999999999998 -1.1510000000000002,-0.09999999999999998 -0.6000000000000005,-0.09999999999999998" data-type="line" data-label="" points="298.01047120418843,363.77585052356017 283.3507853403141,363.77585052356017 283.3507853403141,341.78632172774866 471.65445026177997,341.78632172774866 471.65445026177997,363.77585052356017 512.0418848167538,363.77585052356017" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.10000000000000003 -0.8,0.10000000000000003 -
|
|
3
|
+
<rect width="100%" height="100%" fill="white"/><g><polyline data-points="-6.74,0.3 -4.24,1.7" data-type="line" data-label="" points="61.98952879581145,334.4564787958115 245.23560209424073,231.8386777486911" fill="none" stroke="hsl(24, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.30000000000000004 -5.640000000000001,0.3" data-type="line" data-label="" points="512.0418848167538,334.4564787958115 142.61780104712034,334.4564787958115" fill="none" stroke="hsl(8, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.10000000000000003 -3.1399999999999997,1.7" data-type="line" data-label="" points="512.0418848167538,349.11616465968586 325.8638743455497,231.8386777486911" fill="none" stroke="hsl(8, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-3.52,-0.09999999999999998 -0.6000000000000001,-0.09999999999999998" data-type="line" data-label="" points="298.01047120418843,363.77585052356017 512.0418848167538,363.77585052356017" fill="none" stroke="hsl(152, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-3.52,-0.3 -0.6000000000000001,-0.30000000000000004" data-type="line" data-label="" points="298.01047120418843,378.4355363874345 512.0418848167538,378.4355363874345" fill="none" stroke="hsl(152, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-6.74,0.3 -6.94,0.3 -6.94,1.7 -4.24,1.7" data-type="line" data-label="" points="61.98952879581145,334.4564787958115 47.329842931937094,334.4564787958115 47.329842931937094,231.8386777486911 245.23560209424073,231.8386777486911" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.30000000000000004 -5.640000000000001,0.3" data-type="line" data-label="" points="512.0418848167538,334.4564787958115 142.61780104712034,334.4564787958115" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-3.52,-0.09999999999999998 -3.72,-0.09999999999999998 -3.72,0.19999999999999998 -1.1510000000000002,0.19999999999999998 -1.1510000000000002,-0.09999999999999998 -0.6000000000000005,-0.09999999999999998" data-type="line" data-label="" points="298.01047120418843,363.77585052356017 283.3507853403141,363.77585052356017 283.3507853403141,341.78632172774866 471.65445026177997,341.78632172774866 471.65445026177997,363.77585052356017 512.0418848167538,363.77585052356017" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.10000000000000003 -0.8,0.10000000000000003 -0.8,1.7 -2.9399999999999995,1.7 -3.1399999999999997,1.7" data-type="line" data-label="" points="512.0418848167538,349.11616465968586 497.3821989528795,349.11616465968586 497.3821989528795,231.8386777486911 340.52356020942403,231.8386777486911 325.8638743455497,231.8386777486911" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-0.6000000000000001,0.10000000000000003 -0.8,0.10000000000000003 -0.8,1.7 -2.9399999999999995,1.7 -3.1399999999999997,1.7" data-type="line" data-label="recovered from net labels: U1.2 -> R1.2" points="512.0418848167538,349.11616465968586 497.3821989528795,349.11616465968586 497.3821989528795,231.8386777486911 340.52356020942403,231.8386777486911 325.8638743455497,231.8386777486911" fill="none" stroke="green" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="-3.69" data-y="1.7" x="245.23560209424076" y="217.58540602094246" width="80.62827225130894" height="28.506543455497336" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013642857142857144"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="-6.19" data-y="0.3" x="61.98952879581145" y="303.67113848167537" width="80.62827225130889" height="61.57068062827227" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013642857142857144"/></g><g><rect data-type="rect" data-label="schematic_component_2" data-x="0" data-y="0" x="512.0418848167538" y="319.79679293193715" width="87.95811518324604" height="73.29842931937173" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013642857142857144"/></g><g><rect data-type="rect" data-label="schematic_component_3" data-x="-2.92" data-y="-0.4" x="298.01047120418843" y="349.11616465968586" width="87.95811518324604" height="73.29842931937173" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013642857142857144"/></g><g><rect data-type="rect" data-label="netId: .C1 > .pin1 to R1.pin1
|
|
4
4
|
globalConnNetId: connectivity_net0" data-x="-6.94" data-y="0.07499999999999998" x="39.99999999999997" y="334.45647879581145" width="14.659685863874245" height="32.98429319371729" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.013642857142857144"/></g><g><rect data-type="rect" data-label="netId: .U1 > .pin1 to C1.pin2
|
|
5
5
|
globalConnNetId: connectivity_net1" data-x="-3.12" data-y="0.525" x="319.9999999999999" y="301.4721856020942" width="14.659685863874415" height="32.98429319371729" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.013642857142857144"/></g><g><rect data-type="rect" data-label="netId: .U2 > .pin1 to U1.pin3
|
|
6
6
|
globalConnNetId: connectivity_net3" data-x="-3.9450000000000003" data-y="-0.09999999999999998" x="250.36649214659676" y="356.446007591623" width="32.98429319371729" height="14.659685863874358" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.013642857142857144"/></g><g><rect data-type="rect" data-label="netId: .U2 > .pin2 to U1.pin4
|
|
@@ -87,7 +87,7 @@ orientation: x-" data-x="-0.6000000000000001" data-y="-0.30000000000000004" cx="
|
|
|
87
87
|
.port-label { fill: rgb(0, 100, 100); }
|
|
88
88
|
.component-name { fill: rgb(0, 100, 100); }
|
|
89
89
|
|
|
90
|
-
</style><rect class="boundary" x="0" y="0" width="1200" height="800"/><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"><path d="M 109.83981693392002 454.6338672769 L 82.3798627005201 454.6338672769 L 82.3798627005201 262.41418764310004 L 453.08924485142006 262.41418764310004" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 109.83981693392002 454.6338672769 L 82.3798627005201 454.6338672769 L 82.3798627005201 262.41418764310004 L 453.08924485142006 262.41418764310004" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"><path d="M 952.8604118993001 454.6338672769 L 260.86956521762 454.6338672769" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 952.8604118993001 454.6338672769 L 260.86956521762 454.6338672769" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"><path d="M 551.9450800916601 509.5537757437 L 524.4851258582601 509.5537757437 L 524.4851258582601 468.3638443936 L 877.2082379862829 468.3638443936 L 877.2082379862829 509.5537757437 L 952.8604118993 509.5537757437" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 551.9450800916601 509.5537757437 L 524.4851258582601 509.5537757437 L 524.4851258582601 468.3638443936 L 877.2082379862829 468.3638443936 L 877.2082379862829 509.5537757437 L 952.8604118993 509.5537757437" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"><path d="M 952.8604118993001 482.09382151029996 L 925.4004576659 482.09382151029996 L 778.48970251721 482.09382151029996 L 778.48970251721 262.41418764310004 L 631.5789473685202 262.41418764310004 L 604.11899313512 262.41418764310004" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 952.8604118993001 482.09382151029996 L 925.4004576659 482.09382151029996 L 778.48970251721 482.09382151029996 L 778.48970251721 262.41418764310004 L 631.5789473685202 262.41418764310004 L 604.11899313512 262.41418764310004" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"/><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_0__stack1"><rect class="component-overlay sch-component-overlay" x="453.08924485142" y="242.28192219688282" width="151.02974828370003" height="40.264530892434436" fill="transparent"/><path class="sch-component-symbol-path" d="M 453.08924485142 262.41418764310004 L 478.2659038903128 262.41418764310004" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 578.9423340962273 262.41418764310004 L 604.11899313512 262.41418764310004" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 478.2659038903128 242.28192219688282 L 578.9423340962273 242.28192219688282 L 578.9423340962273 282.54645308931725 L 478.2659038903128 282.54645308931725 L 478.2659038903128 242.28192219688282" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="528.60411899327" y="222.13958810078003" stroke="rgb(245, 241, 237)" stroke-width="2.7459954233399997px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="ideographic" font-size="24.713958810059996px">R1</text><text class="sch-component-text" x="528.60411899327" y="302.68878718542004" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="hanging" font-size="24.713958810059996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_1__stack1"><rect class="component-overlay sch-component-overlay" x="109.83981693392003" y="414.35423340963723" width="151.02974828369997" height="80.55926773452552" fill="transparent"/><path class="sch-component-symbol-path" d="M 260.86956521762 454.6338672769 L 200.45766590414 454.6338672769" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 170.25171624740003 454.6338672769 L 109.83981693392003 454.6338672769" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 200.45766590414 414.35423340963723 L 200.45766590414 494.91350114416275" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 170.25171624740003 414.35423340963723 L 170.25171624740003 494.91350114416275" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="185.35469107577" y="394.22196796342" stroke="rgb(245, 241, 237)" stroke-width="2.7459954233399997px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="ideographic" font-size="24.713958810059996px">C1</text><text class="sch-component-text" x="185.35469107577" y="515.0457665903799" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="hanging" font-size="24.713958810059996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_2__stack1"><rect class="component chip sch-component-body" x="1007.7803203661" y="427.17391304349997" width="54.91990846679994" height="137.29977116700002" stroke-width="2.7459954233399997px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="1007.7803203661" y="427.17391304349997" width="54.91990846679994" height="137.29977116700002" fill="transparent"/><text class="sch-text" x="1035.2402745995" y="495.823798627" fill="#0f172a" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="24.713958810059996px" transform="rotate(0, 1035.2402745995, 495.823798627)">U1</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="454.6338672769" x2="952.8604118993001" y2="454.6338672769" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_0__stack1"><rect x="950.1144164759601" y="451.88787185356" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="451.88787185356" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="482.09382151029996" x2="952.8604118993001" y2="482.09382151029996" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_1__stack1"><rect x="950.1144164759601" y="479.34782608695997" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="479.34782608695997" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="509.5537757437" x2="952.8604118993001" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_2__stack1"><rect x="950.1144164759601" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">3</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="537.0137299771" x2="955.60640732264" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_3__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="952.8604118993001" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="950.1144164759601" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">4</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="537.0137299771" x2="1114.87414187636" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_4__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">5</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="509.5537757437" x2="1114.87414187636" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_5__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="509.5537757437" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">6</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="482.09382151029996" x2="1114.87414187636" y2="482.09382151029996" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_6__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="482.09382151029996" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="479.34782608695997" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="479.34782608695997" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">7</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="454.6338672769" x2="1114.87414187636" y2="454.6338672769" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_7__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="454.6338672769" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="451.88787185356" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="451.88787185356" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">8</text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_3__stack1"><rect class="component chip sch-component-body" x="606.86498855846" y="482.09382151029996" width="54.91990846680005" height="137.29977116699996" stroke-width="2.7459954233399997px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="606.86498855846" y="482.09382151029996" width="54.91990846680005" height="137.29977116699996" fill="transparent"/><text class="sch-text" x="634.32494279186" y="550.7437070937999" fill="#0f172a" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="24.713958810059996px" transform="rotate(0, 634.32494279186, 550.7437070937999)">U2</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="509.5537757437" x2="551.9450800916601" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_0__stack1"><rect x="549.1990846683201" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="537.0137299771" x2="554.6910755150001" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_1__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="551.9450800916601" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="549.1990846683201" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="564.4736842105" x2="554.6910755150001" y2="564.4736842105" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_2__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="551.9450800916601" cy="564.4736842105" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="549.1990846683201" y="561.72768878716" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="561.72768878716" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">3</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="591.9336384439" x2="554.6910755150001" y2="591.9336384439" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_3__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="551.9450800916601" cy="591.9336384439" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="549.1990846683201" y="589.18764302056" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="589.18764302056" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">4</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="591.9336384439" x2="713.9588100687201" y2="591.9336384439" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_4__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="591.9336384439" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="589.18764302056" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="589.18764302056" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">5</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="564.4736842105" x2="713.9588100687201" y2="564.4736842105" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_5__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="564.4736842105" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="561.72768878716" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="561.72768878716" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">6</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="537.0137299771" x2="713.9588100687201" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_6__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">7</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="509.5537757437" x2="713.9588100687201" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_7__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="509.5537757437" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">8</text></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_0__stack1"><circle cx="487.41418764317007" cy="262.41418764310004" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_1__stack1"><circle cx="638.4439359268702" cy="262.41418764310004" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_0__stack1"><circle cx="144.16475972567002" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_1__stack1"><circle cx="295.19450800937" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_0__stack1"><circle cx="952.8604118993001" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_1__stack1"><circle cx="952.8604118993001" cy="482.09382151029996" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_2__stack1"><circle cx="952.8604118993001" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_3__stack1"><circle cx="952.8604118993001" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_4__stack1"><circle cx="1117.6201372997" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_5__stack1"><circle cx="1117.6201372997" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_6__stack1"><circle cx="1117.6201372997" cy="482.09382151029996" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_7__stack1"><circle cx="1117.6201372997" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_0__stack1"><circle cx="551.9450800916601" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_1__stack1"><circle cx="551.9450800916601" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_2__stack1"><circle cx="551.9450800916601" cy="564.4736842105" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_3__stack1"><circle cx="551.9450800916601" cy="591.9336384439" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_4__stack1"><circle cx="716.7048054920601" cy="591.9336384439" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_5__stack1"><circle cx="716.7048054920601" cy="564.4736842105" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_6__stack1"><circle cx="716.7048054920601" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_7__stack1"><circle cx="716.7048054920601" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="
|
|
90
|
+
</style><rect class="boundary" x="0" y="0" width="1200" height="800"/><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"><path d="M 109.83981693392002 454.6338672769 L 82.3798627005201 454.6338672769 L 82.3798627005201 262.41418764310004 L 453.08924485142006 262.41418764310004" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 109.83981693392002 454.6338672769 L 82.3798627005201 454.6338672769 L 82.3798627005201 262.41418764310004 L 453.08924485142006 262.41418764310004" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"><path d="M 952.8604118993001 454.6338672769 L 260.86956521762 454.6338672769" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 952.8604118993001 454.6338672769 L 260.86956521762 454.6338672769" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"><path d="M 551.9450800916601 509.5537757437 L 524.4851258582601 509.5537757437 L 524.4851258582601 468.3638443936 L 877.2082379862829 468.3638443936 L 877.2082379862829 509.5537757437 L 952.8604118993 509.5537757437" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 551.9450800916601 509.5537757437 L 524.4851258582601 509.5537757437 L 524.4851258582601 468.3638443936 L 877.2082379862829 468.3638443936 L 877.2082379862829 509.5537757437 L 952.8604118993 509.5537757437" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"><path d="M 952.8604118993001 482.09382151029996 L 925.4004576659 482.09382151029996 L 925.4004576659 262.41418764310004 L 631.5789473685202 262.41418764310004 L 604.11899313512 262.41418764310004" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.967963386719997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 952.8604118993001 482.09382151029996 L 925.4004576659 482.09382151029996 L 925.4004576659 262.41418764310004 L 631.5789473685202 262.41418764310004 L 604.11899313512 262.41418764310004" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"/><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_0__stack1"><rect class="component-overlay sch-component-overlay" x="453.08924485142" y="242.28192219688282" width="151.02974828370003" height="40.264530892434436" fill="transparent"/><path class="sch-component-symbol-path" d="M 453.08924485142 262.41418764310004 L 478.2659038903128 262.41418764310004" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 578.9423340962273 262.41418764310004 L 604.11899313512 262.41418764310004" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 478.2659038903128 242.28192219688282 L 578.9423340962273 242.28192219688282 L 578.9423340962273 282.54645308931725 L 478.2659038903128 282.54645308931725 L 478.2659038903128 242.28192219688282" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="528.60411899327" y="222.13958810078003" stroke="rgb(245, 241, 237)" stroke-width="2.7459954233399997px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="ideographic" font-size="24.713958810059996px">R1</text><text class="sch-component-text" x="528.60411899327" y="302.68878718542004" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="hanging" font-size="24.713958810059996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_1__stack1"><rect class="component-overlay sch-component-overlay" x="109.83981693392003" y="414.35423340963723" width="151.02974828369997" height="80.55926773452552" fill="transparent"/><path class="sch-component-symbol-path" d="M 260.86956521762 454.6338672769 L 200.45766590414 454.6338672769" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 170.25171624740003 454.6338672769 L 109.83981693392003 454.6338672769" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 200.45766590414 414.35423340963723 L 200.45766590414 494.91350114416275" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 170.25171624740003 414.35423340963723 L 170.25171624740003 494.91350114416275" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7459954233399997px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="185.35469107577" y="394.22196796342" stroke="rgb(245, 241, 237)" stroke-width="2.7459954233399997px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="ideographic" font-size="24.713958810059996px">C1</text><text class="sch-component-text" x="185.35469107577" y="515.0457665903799" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="hanging" font-size="24.713958810059996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_2__stack1"><rect class="component chip sch-component-body" x="1007.7803203661" y="427.17391304349997" width="54.91990846679994" height="137.29977116700002" stroke-width="2.7459954233399997px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="1007.7803203661" y="427.17391304349997" width="54.91990846679994" height="137.29977116700002" fill="transparent"/><text class="sch-text" x="1035.2402745995" y="495.823798627" fill="#0f172a" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="24.713958810059996px" transform="rotate(0, 1035.2402745995, 495.823798627)">U1</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="454.6338672769" x2="952.8604118993001" y2="454.6338672769" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_0__stack1"><rect x="950.1144164759601" y="451.88787185356" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="451.88787185356" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="482.09382151029996" x2="952.8604118993001" y2="482.09382151029996" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_1__stack1"><rect x="950.1144164759601" y="479.34782608695997" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="479.34782608695997" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="509.5537757437" x2="952.8604118993001" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_2__stack1"><rect x="950.1144164759601" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">3</text><line class="component-pin sch-component-pin sch-port-line" x1="1007.7803203661" y1="537.0137299771" x2="955.60640732264" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_3__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="952.8604118993001" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="950.1144164759601" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="980.3203661327" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">4</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="537.0137299771" x2="1114.87414187636" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_4__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">5</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="509.5537757437" x2="1114.87414187636" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_5__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="509.5537757437" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">6</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="482.09382151029996" x2="1114.87414187636" y2="482.09382151029996" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_6__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="482.09382151029996" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="479.34782608695997" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="479.34782608695997" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">7</text><line class="component-pin sch-component-pin sch-port-line" x1="1062.7002288329" y1="454.6338672769" x2="1114.87414187636" y2="454.6338672769" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_2_7__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1117.6201372997" cy="454.6338672769" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="1114.87414187636" y="451.88787185356" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1090.1601830663" y="451.88787185356" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">8</text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_3__stack1"><rect class="component chip sch-component-body" x="606.86498855846" y="482.09382151029996" width="54.91990846680005" height="137.29977116699996" stroke-width="2.7459954233399997px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="606.86498855846" y="482.09382151029996" width="54.91990846680005" height="137.29977116699996" fill="transparent"/><text class="sch-text" x="634.32494279186" y="550.7437070937999" fill="#0f172a" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="24.713958810059996px" transform="rotate(0, 634.32494279186, 550.7437070937999)">U2</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="509.5537757437" x2="551.9450800916601" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_0__stack1"><rect x="549.1990846683201" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="537.0137299771" x2="554.6910755150001" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_1__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="551.9450800916601" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="549.1990846683201" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="564.4736842105" x2="554.6910755150001" y2="564.4736842105" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_2__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="551.9450800916601" cy="564.4736842105" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="549.1990846683201" y="561.72768878716" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="561.72768878716" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">3</text><line class="component-pin sch-component-pin sch-port-line" x1="606.86498855846" y1="591.9336384439" x2="554.6910755150001" y2="591.9336384439" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_3__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="551.9450800916601" cy="591.9336384439" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="549.1990846683201" y="589.18764302056" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="579.4050343250601" y="589.18764302056" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">4</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="591.9336384439" x2="713.9588100687201" y2="591.9336384439" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_4__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="591.9336384439" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="589.18764302056" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="589.18764302056" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">5</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="564.4736842105" x2="713.9588100687201" y2="564.4736842105" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_5__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="564.4736842105" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="561.72768878716" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="561.72768878716" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">6</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="537.0137299771" x2="713.9588100687201" y2="537.0137299771" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_6__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="537.0137299771" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="534.26773455376" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="534.26773455376" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">7</text><line class="component-pin sch-component-pin sch-port-line" x1="661.7848970252601" y1="509.5537757437" x2="713.9588100687201" y2="509.5537757437" stroke-width="2.7459954233399997px"/><g class="sch-port" data-schematic-port-id="source_port_3_7__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.7048054920601" cy="509.5537757437" r="2.7459954233399997" stroke-width="2.7459954233399997px"/><rect x="713.9588100687201" y="506.80778032036" width="5.491990846679999" height="5.491990846679999" opacity="0"/></g><text class="pin-number sch-pin-number" x="689.24485125866" y="506.80778032036" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.59496567505px" transform="">8</text></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_0__stack1"><circle cx="487.41418764317007" cy="262.41418764310004" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_1__stack1"><circle cx="638.4439359268702" cy="262.41418764310004" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_0__stack1"><circle cx="144.16475972567002" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_1__stack1"><circle cx="295.19450800937" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_0__stack1"><circle cx="952.8604118993001" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_1__stack1"><circle cx="952.8604118993001" cy="482.09382151029996" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_2__stack1"><circle cx="952.8604118993001" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_3__stack1"><circle cx="952.8604118993001" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_4__stack1"><circle cx="1117.6201372997" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_5__stack1"><circle cx="1117.6201372997" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_6__stack1"><circle cx="1117.6201372997" cy="482.09382151029996" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_7__stack1"><circle cx="1117.6201372997" cy="454.6338672769" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_0__stack1"><circle cx="551.9450800916601" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_1__stack1"><circle cx="551.9450800916601" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_2__stack1"><circle cx="551.9450800916601" cy="564.4736842105" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_3__stack1"><circle cx="551.9450800916601" cy="591.9336384439" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_4__stack1"><circle cx="716.7048054920601" cy="591.9336384439" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_5__stack1"><circle cx="716.7048054920601" cy="564.4736842105" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_6__stack1"><circle cx="716.7048054920601" cy="537.0137299771" r="5.491990846679999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_3_7__stack1"><circle cx="716.7048054920601" cy="509.5537757437" r="5.491990846679999" fill="red" opacity="0"/></g><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="
|
|
91
91
|
M 82.3798627005201,454.6338672769
|
|
92
92
|
L 96.1098398172201,462.048054919918
|
|
93
93
|
L 96.1098398172201,509.1327231121212
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { countCrossingsWithOtherTraces } from "lib/solvers/Example28Solver/countCrossingsWithOtherTraces"
|
|
2
3
|
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
4
|
import inputProblem from "../assets/example37.json"
|
|
4
5
|
import "tests/fixtures/matcher"
|
|
@@ -8,5 +9,16 @@ test("example37", () => {
|
|
|
8
9
|
|
|
9
10
|
solver.solve()
|
|
10
11
|
|
|
12
|
+
const traces = solver.netLabelToTraceSolver!.getOutput().traces
|
|
13
|
+
const recoveredTrace = traces.find(
|
|
14
|
+
(trace) => trace.mspPairId === "net-label-to-trace-R1.2--U1.2",
|
|
15
|
+
)!
|
|
16
|
+
|
|
17
|
+
expect(
|
|
18
|
+
countCrossingsWithOtherTraces({
|
|
19
|
+
trace: recoveredTrace,
|
|
20
|
+
outputTraces: traces,
|
|
21
|
+
}),
|
|
22
|
+
).toBe(1)
|
|
11
23
|
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
12
24
|
})
|