@tscircuit/schematic-trace-solver 0.0.31 → 0.0.33
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/CLAUDE.md +8 -0
- package/dist/index.d.ts +24 -53
- package/dist/index.js +494 -807
- package/lib/index.ts +1 -0
- package/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +54 -3
- package/lib/solvers/MspConnectionPairSolver/doesPairCrossRestrictedCenterLines.ts +62 -0
- package/lib/solvers/MspConnectionPairSolver/getMspConnectionPairsFromPins.ts +7 -2
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts +5 -11
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver/SchematicTraceSingleLineSolver.ts +37 -7
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver/generateElbowVariants.ts +7 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +239 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions.ts +57 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/mid.ts +97 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts +65 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect.ts +19 -0
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +14 -14
- package/package.json +1 -1
- package/site/SchematicTracePipelineSolver/SchematicTracePipelineSolver03.page.tsx +486 -0
- package/site/examples/example09.page.tsx +1 -1
- package/tests/examples/__snapshots__/example01.snap.svg +29 -29
- package/tests/examples/__snapshots__/example02.snap.svg +13 -10
- package/tests/examples/__snapshots__/example04.snap.svg +12 -12
- package/tests/examples/__snapshots__/example05.snap.svg +38 -38
- package/tests/examples/__snapshots__/example06.snap.svg +14 -14
- package/tests/examples/__snapshots__/example08.snap.svg +29 -23
- package/tests/examples/__snapshots__/example09.snap.svg +119 -149
- package/tests/examples/__snapshots__/example11.snap.svg +39 -33
- package/tests/examples/__snapshots__/example12.snap.svg +32 -29
- package/tests/examples/__snapshots__/example13.snap.svg +87 -84
- package/tests/examples/__snapshots__/example15.snap.svg +57 -57
- package/tests/examples/__snapshots__/example16.snap.svg +3 -3
- package/tests/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver_repro03.test.ts +491 -0
package/dist/index.js
CHANGED
|
@@ -139,7 +139,8 @@ function getOrthogonalMinimumSpanningTree(pins, opts = {}) {
|
|
|
139
139
|
for (let v = 0; v < n; v++) {
|
|
140
140
|
if (!inTree[v]) {
|
|
141
141
|
const d0 = manhattan(pins[u], pins[v]);
|
|
142
|
-
const
|
|
142
|
+
const isForbidden = opts?.forbidEdge?.(pins[u], pins[v]) ?? false;
|
|
143
|
+
const d = d0 > maxDistance || isForbidden ? Number.POSITIVE_INFINITY : d0;
|
|
143
144
|
if (d < bestDist[v] || d === bestDist[v] && pins[u].pinId < pins[parent[v]]?.pinId) {
|
|
144
145
|
bestDist[v] = d;
|
|
145
146
|
parent[v] = u;
|
|
@@ -150,14 +151,6 @@ function getOrthogonalMinimumSpanningTree(pins, opts = {}) {
|
|
|
150
151
|
return edges;
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
// lib/utils/getColorFromString.ts
|
|
154
|
-
var getColorFromString = (string, alpha = 1) => {
|
|
155
|
-
const hash = string.split("").reduce((acc, char) => {
|
|
156
|
-
return acc * 31 + char.charCodeAt(0);
|
|
157
|
-
}, 0);
|
|
158
|
-
return `hsl(${hash % 360}, 100%, 50%, ${alpha})`;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
154
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver/getPinDirection.ts
|
|
162
155
|
var getPinDirection = (pin, chip) => {
|
|
163
156
|
const { x, y } = pin;
|
|
@@ -188,6 +181,126 @@ var getPinDirection = (pin, chip) => {
|
|
|
188
181
|
return "x-";
|
|
189
182
|
};
|
|
190
183
|
|
|
184
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver/getRestrictedCenterLines.ts
|
|
185
|
+
var getRestrictedCenterLines = (params) => {
|
|
186
|
+
const { pins, inputProblem, pinIdMap, chipMap } = params;
|
|
187
|
+
const findAllDirectlyConnectedPins = (startPinId) => {
|
|
188
|
+
const visited = /* @__PURE__ */ new Set();
|
|
189
|
+
const queue = [startPinId];
|
|
190
|
+
visited.add(startPinId);
|
|
191
|
+
const directConns = inputProblem.directConnections || [];
|
|
192
|
+
while (queue.length) {
|
|
193
|
+
const cur = queue.shift();
|
|
194
|
+
for (const dc of directConns) {
|
|
195
|
+
if (dc.pinIds.includes(cur)) {
|
|
196
|
+
for (const p of dc.pinIds) {
|
|
197
|
+
if (!visited.has(p)) {
|
|
198
|
+
visited.add(p);
|
|
199
|
+
queue.push(p);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return visited;
|
|
206
|
+
};
|
|
207
|
+
const p0 = pins[0].pinId;
|
|
208
|
+
const p1 = pins[1].pinId;
|
|
209
|
+
const relatedPinIds = /* @__PURE__ */ new Set([
|
|
210
|
+
...findAllDirectlyConnectedPins(p0),
|
|
211
|
+
...findAllDirectlyConnectedPins(p1)
|
|
212
|
+
]);
|
|
213
|
+
const restrictedCenterLines = /* @__PURE__ */ new Map();
|
|
214
|
+
const chipFacingMap = /* @__PURE__ */ new Map();
|
|
215
|
+
const chipsOfFacingPins = new Set(pins.map((p) => p.chipId));
|
|
216
|
+
for (const pinId of relatedPinIds) {
|
|
217
|
+
const pin = pinIdMap.get(pinId);
|
|
218
|
+
if (!pin) continue;
|
|
219
|
+
const chip = chipMap[pin.chipId];
|
|
220
|
+
if (!chip) continue;
|
|
221
|
+
const facing = pin._facingDirection ?? getPinDirection(pin, chip);
|
|
222
|
+
let entry = chipFacingMap.get(chip.chipId);
|
|
223
|
+
if (!entry) {
|
|
224
|
+
entry = { center: chip.center };
|
|
225
|
+
const counts = { xPos: 0, xNeg: 0, yPos: 0, yNeg: 0 };
|
|
226
|
+
for (const cp of chip.pins) {
|
|
227
|
+
const cpFacing = cp._facingDirection ?? getPinDirection(cp, chip);
|
|
228
|
+
if (cpFacing === "x+") counts.xPos++;
|
|
229
|
+
if (cpFacing === "x-") counts.xNeg++;
|
|
230
|
+
if (cpFacing === "y+") counts.yPos++;
|
|
231
|
+
if (cpFacing === "y-") counts.yNeg++;
|
|
232
|
+
}
|
|
233
|
+
entry.counts = counts;
|
|
234
|
+
chipFacingMap.set(chip.chipId, entry);
|
|
235
|
+
}
|
|
236
|
+
if (facing === "x+") entry.hasXPos = true;
|
|
237
|
+
if (facing === "x-") entry.hasXNeg = true;
|
|
238
|
+
if (facing === "y+") entry.hasYPos = true;
|
|
239
|
+
if (facing === "y-") entry.hasYNeg = true;
|
|
240
|
+
}
|
|
241
|
+
for (const [chipId, faces] of chipFacingMap) {
|
|
242
|
+
const axes = /* @__PURE__ */ new Set();
|
|
243
|
+
const rcl = { axes };
|
|
244
|
+
const counts = faces.counts;
|
|
245
|
+
const anySideHasMultiplePins = !!(counts && (counts.xPos > 1 || counts.xNeg > 1 || counts.yPos > 1 || counts.yNeg > 1));
|
|
246
|
+
const skipCenterRestriction = !anySideHasMultiplePins && chipsOfFacingPins.has(chipId);
|
|
247
|
+
if (!skipCenterRestriction) {
|
|
248
|
+
if (faces.hasXPos && faces.hasXNeg) {
|
|
249
|
+
rcl.x = faces.center.x;
|
|
250
|
+
axes.add("x");
|
|
251
|
+
}
|
|
252
|
+
if (faces.hasYPos && faces.hasYNeg) {
|
|
253
|
+
rcl.y = faces.center.y;
|
|
254
|
+
axes.add("y");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (axes.size > 0) {
|
|
258
|
+
restrictedCenterLines.set(chipId, rcl);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return restrictedCenterLines;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// lib/solvers/MspConnectionPairSolver/doesPairCrossRestrictedCenterLines.ts
|
|
265
|
+
var doesPairCrossRestrictedCenterLines = (params) => {
|
|
266
|
+
const { inputProblem, chipMap, pinIdMap, p1, p2 } = params;
|
|
267
|
+
const restrictedCenterLines = getRestrictedCenterLines({
|
|
268
|
+
pins: [p1, p2],
|
|
269
|
+
inputProblem,
|
|
270
|
+
pinIdMap,
|
|
271
|
+
chipMap
|
|
272
|
+
});
|
|
273
|
+
if (restrictedCenterLines.size === 0) return false;
|
|
274
|
+
const EPS4 = 1e-9;
|
|
275
|
+
const crossesSegment = (a, b) => {
|
|
276
|
+
for (const [, rcl] of restrictedCenterLines) {
|
|
277
|
+
if (rcl.axes.has("x") && typeof rcl.x === "number") {
|
|
278
|
+
if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS4) return true;
|
|
279
|
+
}
|
|
280
|
+
if (rcl.axes.has("y") && typeof rcl.y === "number") {
|
|
281
|
+
if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS4) return true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return false;
|
|
285
|
+
};
|
|
286
|
+
if (Math.abs(p1.x - p2.x) < EPS4 || Math.abs(p1.y - p2.y) < EPS4) {
|
|
287
|
+
return crossesSegment({ x: p1.x, y: p1.y }, { x: p2.x, y: p2.y });
|
|
288
|
+
}
|
|
289
|
+
const elbowHV = { x: p2.x, y: p1.y };
|
|
290
|
+
const elbowVH = { x: p1.x, y: p2.y };
|
|
291
|
+
const hvCrosses = crossesSegment({ x: p1.x, y: p1.y }, elbowHV) || crossesSegment(elbowHV, { x: p2.x, y: p2.y });
|
|
292
|
+
const vhCrosses = crossesSegment({ x: p1.x, y: p1.y }, elbowVH) || crossesSegment(elbowVH, { x: p2.x, y: p2.y });
|
|
293
|
+
return hvCrosses && vhCrosses;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
// lib/utils/getColorFromString.ts
|
|
297
|
+
var getColorFromString = (string, alpha = 1) => {
|
|
298
|
+
const hash = string.split("").reduce((acc, char) => {
|
|
299
|
+
return acc * 31 + char.charCodeAt(0);
|
|
300
|
+
}, 0);
|
|
301
|
+
return `hsl(${hash % 360}, 100%, 50%, ${alpha})`;
|
|
302
|
+
};
|
|
303
|
+
|
|
191
304
|
// lib/solvers/SchematicTracePipelineSolver/visualizeInputProblem.ts
|
|
192
305
|
var visualizeInputProblem = (inputProblem, opts = {}) => {
|
|
193
306
|
const { connectionAlpha = 0.8, chipAlpha = 0.8 } = opts;
|
|
@@ -328,6 +441,16 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
328
441
|
if (manhattanDist > this.maxMspPairDistance) {
|
|
329
442
|
return;
|
|
330
443
|
}
|
|
444
|
+
const pinIdMap2 = new Map(Object.entries(this.pinMap));
|
|
445
|
+
if (doesPairCrossRestrictedCenterLines({
|
|
446
|
+
inputProblem: this.inputProblem,
|
|
447
|
+
chipMap: this.chipMap,
|
|
448
|
+
pinIdMap: pinIdMap2,
|
|
449
|
+
p1,
|
|
450
|
+
p2
|
|
451
|
+
})) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
331
454
|
const globalConnNetId = this.globalConnMap.getNetConnectedToId(pin1);
|
|
332
455
|
const userNetId = this.userNetIdByPinId[pin1] ?? this.userNetIdByPinId[pin2];
|
|
333
456
|
this.mspConnectionPairs.push({
|
|
@@ -339,11 +462,32 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
339
462
|
});
|
|
340
463
|
return;
|
|
341
464
|
}
|
|
465
|
+
const pinIdMap = new Map(Object.entries(this.pinMap));
|
|
342
466
|
const msp = getOrthogonalMinimumSpanningTree(
|
|
343
467
|
directlyConnectedPins.map((p) => this.pinMap[p]).filter(Boolean),
|
|
344
|
-
{
|
|
468
|
+
{
|
|
469
|
+
maxDistance: this.maxMspPairDistance,
|
|
470
|
+
forbidEdge: (a, b) => doesPairCrossRestrictedCenterLines({
|
|
471
|
+
inputProblem: this.inputProblem,
|
|
472
|
+
chipMap: this.chipMap,
|
|
473
|
+
pinIdMap,
|
|
474
|
+
p1: a,
|
|
475
|
+
p2: b
|
|
476
|
+
})
|
|
477
|
+
}
|
|
345
478
|
);
|
|
346
479
|
for (const [pin1, pin2] of msp) {
|
|
480
|
+
const p1Obj = this.pinMap[pin1];
|
|
481
|
+
const p2Obj = this.pinMap[pin2];
|
|
482
|
+
if (doesPairCrossRestrictedCenterLines({
|
|
483
|
+
inputProblem: this.inputProblem,
|
|
484
|
+
chipMap: this.chipMap,
|
|
485
|
+
pinIdMap,
|
|
486
|
+
p1: p1Obj,
|
|
487
|
+
p2: p2Obj
|
|
488
|
+
})) {
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
347
491
|
const globalConnNetId = this.globalConnMap.getNetConnectedToId(pin1);
|
|
348
492
|
const userNetId = this.userNetIdByPinId[pin1] ?? this.userNetIdByPinId[pin2];
|
|
349
493
|
this.mspConnectionPairs.push({
|
|
@@ -351,7 +495,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
351
495
|
dcConnNetId: dcNetId,
|
|
352
496
|
globalConnNetId,
|
|
353
497
|
userNetId,
|
|
354
|
-
pins: [
|
|
498
|
+
pins: [p1Obj, p2Obj]
|
|
355
499
|
});
|
|
356
500
|
}
|
|
357
501
|
}
|
|
@@ -382,11 +526,8 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
382
526
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts
|
|
383
527
|
import "graphics-debug";
|
|
384
528
|
|
|
385
|
-
// lib/solvers/SchematicTraceLinesSolver/
|
|
386
|
-
import {
|
|
387
|
-
|
|
388
|
-
// lib/data-structures/ChipObstacleSpatialIndex.ts
|
|
389
|
-
import Flatbush from "flatbush";
|
|
529
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts
|
|
530
|
+
import { calculateElbow } from "calculate-elbow";
|
|
390
531
|
|
|
391
532
|
// lib/solvers/GuidelinesSolver/getInputChipBounds.ts
|
|
392
533
|
function getInputChipBounds(chip) {
|
|
@@ -400,456 +541,189 @@ function getInputChipBounds(chip) {
|
|
|
400
541
|
};
|
|
401
542
|
}
|
|
402
543
|
|
|
403
|
-
// lib/
|
|
404
|
-
var
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
spatialIndexIdToChip;
|
|
408
|
-
constructor(chips) {
|
|
409
|
-
this.chips = chips.map((chip) => ({
|
|
410
|
-
...chip,
|
|
411
|
-
bounds: getInputChipBounds(chip),
|
|
412
|
-
spatialIndexId: null
|
|
413
|
-
}));
|
|
414
|
-
this.spatialIndexIdToChip = /* @__PURE__ */ new Map();
|
|
415
|
-
this.spatialIndex = new Flatbush(chips.length);
|
|
416
|
-
for (const chip of this.chips) {
|
|
417
|
-
chip.spatialIndexId = this.spatialIndex.add(
|
|
418
|
-
chip.bounds.minX,
|
|
419
|
-
chip.bounds.minY,
|
|
420
|
-
chip.bounds.maxX,
|
|
421
|
-
chip.bounds.maxY
|
|
422
|
-
);
|
|
423
|
-
this.spatialIndexIdToChip.set(chip.spatialIndexId, chip);
|
|
424
|
-
}
|
|
425
|
-
this.spatialIndex.finish();
|
|
426
|
-
}
|
|
427
|
-
getChipsInBounds(bounds) {
|
|
428
|
-
const chipSpatialIndexIds = this.spatialIndex.search(
|
|
429
|
-
bounds.minX,
|
|
430
|
-
bounds.minY,
|
|
431
|
-
bounds.maxX,
|
|
432
|
-
bounds.maxY
|
|
433
|
-
);
|
|
434
|
-
return chipSpatialIndexIds.map((id) => this.spatialIndexIdToChip.get(id));
|
|
435
|
-
}
|
|
436
|
-
doesOrthogonalLineIntersectChip(line, opts = {}) {
|
|
437
|
-
const excludeChipIds = opts.excludeChipIds ?? [];
|
|
438
|
-
const [p1, p2] = line;
|
|
439
|
-
const { x: x1, y: y1 } = p1;
|
|
440
|
-
const { x: x2, y: y2 } = p2;
|
|
441
|
-
const chips = this.getChipsInBounds({
|
|
442
|
-
minX: Math.min(x1, x2),
|
|
443
|
-
minY: Math.min(y1, y2),
|
|
444
|
-
maxX: Math.max(x1, x2),
|
|
445
|
-
maxY: Math.max(y1, y2)
|
|
446
|
-
}).filter((chip) => !excludeChipIds.includes(chip.chipId));
|
|
447
|
-
return chips.length > 0;
|
|
448
|
-
}
|
|
544
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect.ts
|
|
545
|
+
var chipToRect = (chip) => {
|
|
546
|
+
const b = getInputChipBounds(chip);
|
|
547
|
+
return { chipId: chip.chipId, ...b };
|
|
449
548
|
};
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
import { calculateElbow } from "calculate-elbow";
|
|
453
|
-
|
|
454
|
-
// lib/utils/dir.ts
|
|
455
|
-
var dir = (facingDirection) => {
|
|
456
|
-
switch (facingDirection) {
|
|
457
|
-
case "x+":
|
|
458
|
-
return { x: 1, y: 0 };
|
|
459
|
-
case "x-":
|
|
460
|
-
return { x: -1, y: 0 };
|
|
461
|
-
case "y+":
|
|
462
|
-
return { x: 0, y: 1 };
|
|
463
|
-
case "y-":
|
|
464
|
-
return { x: 0, y: -1 };
|
|
465
|
-
}
|
|
466
|
-
throw new Error(`Invalid facing direction: ${facingDirection}`);
|
|
549
|
+
var getObstacleRects = (problem) => {
|
|
550
|
+
return problem.chips.map(chipToRect);
|
|
467
551
|
};
|
|
468
552
|
|
|
469
|
-
// lib/solvers/SchematicTraceLinesSolver/
|
|
470
|
-
var EPS = 1e-
|
|
471
|
-
var
|
|
472
|
-
var
|
|
473
|
-
|
|
474
|
-
const
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return true;
|
|
485
|
-
if (endFacing === "x+" && p2.x < end.x - EPS && startFacing === "x-")
|
|
486
|
-
return true;
|
|
487
|
-
if (endFacing === "y-" && p2.y > end.y + EPS && startFacing === "y+")
|
|
488
|
-
return true;
|
|
489
|
-
if (endFacing === "y+" && p2.y < end.y - EPS && startFacing === "y-")
|
|
490
|
-
return true;
|
|
491
|
-
return false;
|
|
492
|
-
};
|
|
493
|
-
var expandToUTurn = (elbow) => {
|
|
494
|
-
if (elbow.length !== 4) return elbow;
|
|
495
|
-
const [start, p1, p2, end] = elbow;
|
|
496
|
-
const overshoot = Math.max(
|
|
497
|
-
Math.abs(start.x - p1.x),
|
|
498
|
-
Math.abs(start.y - p1.y),
|
|
499
|
-
0.2
|
|
500
|
-
// minimum overshoot
|
|
501
|
-
);
|
|
502
|
-
const startOrient = orientationOf(start, p1);
|
|
503
|
-
const expanded = [{ ...start }];
|
|
504
|
-
if (startOrient === "horizontal") {
|
|
505
|
-
const startDir = p1.x > start.x ? 1 : -1;
|
|
506
|
-
expanded.push({ x: start.x + startDir * overshoot, y: start.y });
|
|
507
|
-
const verticalSpace = Math.max(
|
|
508
|
-
overshoot * 2,
|
|
509
|
-
Math.abs(end.y - start.y) + overshoot
|
|
510
|
-
);
|
|
511
|
-
const midY = end.y > start.y ? start.y - verticalSpace : start.y + verticalSpace;
|
|
512
|
-
expanded.push({ x: start.x + startDir * overshoot, y: midY });
|
|
513
|
-
const endOrient = orientationOf(p2, end);
|
|
514
|
-
const endApproachX = endOrient === "horizontal" ? end.x > p2.x ? end.x - overshoot : end.x + overshoot : end.x;
|
|
515
|
-
expanded.push({ x: endApproachX, y: midY });
|
|
516
|
-
expanded.push({ x: endApproachX, y: end.y });
|
|
553
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions.ts
|
|
554
|
+
var EPS = 1e-9;
|
|
555
|
+
var isVertical = (a, b, eps = EPS) => Math.abs(a.x - b.x) < eps;
|
|
556
|
+
var isHorizontal = (a, b, eps = EPS) => Math.abs(a.y - b.y) < eps;
|
|
557
|
+
var segmentIntersectsRect = (a, b, r, eps = EPS) => {
|
|
558
|
+
const vert = isVertical(a, b, eps);
|
|
559
|
+
const horz = isHorizontal(a, b, eps);
|
|
560
|
+
if (!vert && !horz) return false;
|
|
561
|
+
if (vert) {
|
|
562
|
+
const x = a.x;
|
|
563
|
+
if (x < r.minX - eps || x > r.maxX + eps) return false;
|
|
564
|
+
const segMinY = Math.min(a.y, b.y);
|
|
565
|
+
const segMaxY = Math.max(a.y, b.y);
|
|
566
|
+
const overlap = Math.min(segMaxY, r.maxY) - Math.max(segMinY, r.minY);
|
|
567
|
+
return overlap > eps;
|
|
517
568
|
} else {
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const midX = end.x > start.x ? start.x - horizontalSpace : start.x + horizontalSpace;
|
|
525
|
-
expanded.push({ x: midX, y: start.y + startDir * overshoot });
|
|
526
|
-
const endOrient = orientationOf(p2, end);
|
|
527
|
-
const endApproachY = endOrient === "vertical" ? end.y > p2.y ? end.y - overshoot : end.y + overshoot : end.y;
|
|
528
|
-
expanded.push({ x: midX, y: endApproachY });
|
|
529
|
-
expanded.push({ x: end.x, y: endApproachY });
|
|
530
|
-
}
|
|
531
|
-
expanded.push({ ...end });
|
|
532
|
-
return expanded;
|
|
533
|
-
};
|
|
534
|
-
var isAxisAligned = (a, b) => Math.abs(a.x - b.x) < EPS || Math.abs(a.y - b.y) < EPS;
|
|
535
|
-
var orientationOf = (a, b) => {
|
|
536
|
-
const dx = Math.abs(a.x - b.x);
|
|
537
|
-
const dy = Math.abs(a.y - b.y);
|
|
538
|
-
if (dx < EPS && dy >= EPS) return "vertical";
|
|
539
|
-
if (dy < EPS && dx >= EPS) return "horizontal";
|
|
540
|
-
throw new Error("Non-orthogonal or degenerate segment detected.");
|
|
541
|
-
};
|
|
542
|
-
var assertOrthogonalPolyline = (pts) => {
|
|
543
|
-
if (pts.length < 2) {
|
|
544
|
-
throw new Error("Polyline must have at least two points.");
|
|
569
|
+
const y = a.y;
|
|
570
|
+
if (y < r.minY - eps || y > r.maxY + eps) return false;
|
|
571
|
+
const segMinX = Math.min(a.x, b.x);
|
|
572
|
+
const segMaxX = Math.max(a.x, b.x);
|
|
573
|
+
const overlap = Math.min(segMaxX, r.maxX) - Math.max(segMinX, r.minX);
|
|
574
|
+
return overlap > eps;
|
|
545
575
|
}
|
|
576
|
+
};
|
|
577
|
+
var findFirstCollision = (pts, rects, opts = {}) => {
|
|
546
578
|
for (let i = 0; i < pts.length - 1; i++) {
|
|
547
579
|
const a = pts[i];
|
|
548
580
|
const b = pts[i + 1];
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
throw new Error("Polyline contains a near-zero length segment.");
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
};
|
|
558
|
-
var uniqSortedWithTol = (vals, tol = EPS) => {
|
|
559
|
-
const sorted = vals.slice().sort((a, b) => a - b);
|
|
560
|
-
const out = [];
|
|
561
|
-
for (const v of sorted) {
|
|
562
|
-
if (out.length === 0 || Math.abs(v - out[out.length - 1]) > tol) out.push(v);
|
|
563
|
-
}
|
|
564
|
-
return out;
|
|
565
|
-
};
|
|
566
|
-
var keyForPolyline = (pts, decimals = 9) => pts.map((p) => `${p.x.toFixed(decimals)},${p.y.toFixed(decimals)}`).join("|");
|
|
567
|
-
var preprocessElbow = (pts, tol = MIN_LEN) => {
|
|
568
|
-
if (pts.length === 0) return [];
|
|
569
|
-
const out = [{ ...pts[0] }];
|
|
570
|
-
for (let i = 1; i < pts.length; i++) {
|
|
571
|
-
const p = pts[i];
|
|
572
|
-
const last = out[out.length - 1];
|
|
573
|
-
const manhattan = Math.abs(p.x - last.x) + Math.abs(p.y - last.y);
|
|
574
|
-
if (manhattan > tol) out.push({ ...p });
|
|
575
|
-
}
|
|
576
|
-
return out;
|
|
577
|
-
};
|
|
578
|
-
var collectAxisCandidates = (axis, guidelines, currentCoord) => {
|
|
579
|
-
const positions = [];
|
|
580
|
-
for (const g of guidelines) {
|
|
581
|
-
if (axis === "x") {
|
|
582
|
-
if (g.orientation === "vertical" && typeof g.x === "number") {
|
|
583
|
-
positions.push(g.x);
|
|
584
|
-
}
|
|
585
|
-
} else {
|
|
586
|
-
if (g.orientation === "horizontal" && typeof g.y === "number") {
|
|
587
|
-
positions.push(g.y);
|
|
581
|
+
const excluded = opts.excludeRectIdsForSegment?.(i) ?? /* @__PURE__ */ new Set();
|
|
582
|
+
for (const r of rects) {
|
|
583
|
+
if (excluded.has(r.chipId)) continue;
|
|
584
|
+
if (segmentIntersectsRect(a, b, r)) {
|
|
585
|
+
return { segIndex: i, rect: r };
|
|
588
586
|
}
|
|
589
587
|
}
|
|
590
588
|
}
|
|
591
|
-
|
|
592
|
-
return uniqSortedWithTol(positions);
|
|
589
|
+
return null;
|
|
593
590
|
};
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
591
|
+
|
|
592
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/mid.ts
|
|
593
|
+
var EPS2 = 1e-9;
|
|
594
|
+
var aabbFromPoints = (a, b) => ({
|
|
595
|
+
minX: Math.min(a.x, b.x),
|
|
596
|
+
maxX: Math.max(a.x, b.x),
|
|
597
|
+
minY: Math.min(a.y, b.y),
|
|
598
|
+
maxY: Math.max(a.y, b.y)
|
|
599
|
+
});
|
|
600
|
+
var midBetweenPointAndRect = (axis, p, r, eps = EPS2) => {
|
|
601
|
+
if (axis === "x") {
|
|
602
|
+
if (p.x < r.minX - eps) {
|
|
603
|
+
return [(p.x + r.minX) / 2];
|
|
604
|
+
}
|
|
605
|
+
if (p.x > r.maxX + eps) {
|
|
606
|
+
return [(p.x + r.maxX) / 2];
|
|
607
|
+
}
|
|
608
|
+
return [r.minX - 0.2, r.maxX + 0.2];
|
|
599
609
|
} else {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
};
|
|
604
|
-
var cartesian = (arrays) => arrays.length === 0 ? [[]] : arrays.reduce(
|
|
605
|
-
(acc, curr) => acc.flatMap((a) => curr.map((c) => [...a, c])),
|
|
606
|
-
[[]]
|
|
607
|
-
);
|
|
608
|
-
var generateElbowVariants = ({
|
|
609
|
-
baseElbow,
|
|
610
|
-
guidelines
|
|
611
|
-
}) => {
|
|
612
|
-
const elbow = preprocessElbow(baseElbow);
|
|
613
|
-
assertOrthogonalPolyline(elbow);
|
|
614
|
-
const nPts = elbow.length;
|
|
615
|
-
if (nPts < 4) {
|
|
616
|
-
return {
|
|
617
|
-
elbowVariants: [elbow.map((p) => ({ ...p }))],
|
|
618
|
-
movableSegments: []
|
|
619
|
-
};
|
|
620
|
-
} else if (nPts === 4) {
|
|
621
|
-
const needsUTurn = checkIfUTurnNeeded(elbow);
|
|
622
|
-
if (needsUTurn) {
|
|
623
|
-
const expandedElbow = expandToUTurn(elbow);
|
|
624
|
-
return generateElbowVariants({ baseElbow: expandedElbow, guidelines });
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
const firstMovableIndex = 1;
|
|
628
|
-
const lastMovableIndex = nPts - 3;
|
|
629
|
-
const movableSegments = [];
|
|
630
|
-
const movableIdx = [];
|
|
631
|
-
const axes = [];
|
|
632
|
-
const optionsPerSegment = [];
|
|
633
|
-
for (let i = firstMovableIndex; i <= lastMovableIndex; i++) {
|
|
634
|
-
const prev = elbow[i - 1];
|
|
635
|
-
const start = elbow[i];
|
|
636
|
-
const end = elbow[i + 1];
|
|
637
|
-
const next2 = elbow[i + 2];
|
|
638
|
-
const { axis, facing } = computeFreedom(prev, start, end);
|
|
639
|
-
movableSegments.push({
|
|
640
|
-
start: { ...start },
|
|
641
|
-
end: { ...end },
|
|
642
|
-
freedom: facing,
|
|
643
|
-
dir: dir(facing)
|
|
644
|
-
});
|
|
645
|
-
movableIdx.push(i);
|
|
646
|
-
axes.push(axis);
|
|
647
|
-
const currentCoord = axis === "x" ? start.x : start.y;
|
|
648
|
-
const rawCandidates = collectAxisCandidates(axis, guidelines, currentCoord);
|
|
649
|
-
const filtered = rawCandidates.filter((pos) => {
|
|
650
|
-
if (axis === "y") {
|
|
651
|
-
const lenPrev = Math.abs(prev.y - pos);
|
|
652
|
-
const lenNext = Math.abs(next2.y - pos);
|
|
653
|
-
return lenPrev > MIN_LEN && lenNext > MIN_LEN;
|
|
654
|
-
} else {
|
|
655
|
-
const lenPrev = Math.abs(prev.x - pos);
|
|
656
|
-
const lenNext = Math.abs(next2.x - pos);
|
|
657
|
-
return lenPrev > MIN_LEN && lenNext > MIN_LEN;
|
|
658
|
-
}
|
|
659
|
-
});
|
|
660
|
-
optionsPerSegment.push(filtered);
|
|
661
|
-
}
|
|
662
|
-
const combos = cartesian(optionsPerSegment);
|
|
663
|
-
const seen = /* @__PURE__ */ new Set();
|
|
664
|
-
const elbowVariants = [];
|
|
665
|
-
{
|
|
666
|
-
const key = keyForPolyline(elbow);
|
|
667
|
-
seen.add(key);
|
|
668
|
-
elbowVariants.push(elbow.map((p) => ({ ...p })));
|
|
669
|
-
}
|
|
670
|
-
for (const combo of combos) {
|
|
671
|
-
if (combo.length === 0) continue;
|
|
672
|
-
const variant = elbow.map((p) => ({ ...p }));
|
|
673
|
-
for (let k = 0; k < movableIdx.length; k++) {
|
|
674
|
-
const segIndex = movableIdx[k];
|
|
675
|
-
const axis = axes[k];
|
|
676
|
-
const newPos = combo[k];
|
|
677
|
-
if (typeof newPos !== "number" || Number.isNaN(newPos)) continue;
|
|
678
|
-
if (axis === "y") {
|
|
679
|
-
variant[segIndex] = { ...variant[segIndex], y: newPos };
|
|
680
|
-
variant[segIndex + 1] = { ...variant[segIndex + 1], y: newPos };
|
|
681
|
-
} else {
|
|
682
|
-
variant[segIndex] = { ...variant[segIndex], x: newPos };
|
|
683
|
-
variant[segIndex + 1] = { ...variant[segIndex + 1], x: newPos };
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
try {
|
|
687
|
-
assertOrthogonalPolyline(variant);
|
|
688
|
-
} catch {
|
|
689
|
-
continue;
|
|
610
|
+
if (p.y < r.minY - eps) {
|
|
611
|
+
return [(p.y + r.minY) / 2];
|
|
690
612
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
seen.add(key);
|
|
694
|
-
elbowVariants.push(variant);
|
|
613
|
+
if (p.y > r.maxY + eps) {
|
|
614
|
+
return [(p.y + r.maxY) / 2];
|
|
695
615
|
}
|
|
616
|
+
return [r.minY - 0.2, r.maxY + 0.2];
|
|
696
617
|
}
|
|
697
|
-
return { elbowVariants, movableSegments };
|
|
698
618
|
};
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
for (const guideline of guidelines) {
|
|
714
|
-
if (guideline.orientation === "horizontal") {
|
|
715
|
-
graphics.lines.push({
|
|
716
|
-
points: [
|
|
717
|
-
{ x: globalBounds.minX, y: guideline.y },
|
|
718
|
-
{ x: globalBounds.maxX, y: guideline.y }
|
|
719
|
-
],
|
|
720
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
721
|
-
strokeDash: "2 2"
|
|
722
|
-
});
|
|
619
|
+
var candidateMidsFromSet = (axis, colliding, rectsById, collisionRectIds, aabb, eps = EPS2) => {
|
|
620
|
+
const setRects = [...collisionRectIds].map((id) => rectsById.get(id)).filter((r) => !!r);
|
|
621
|
+
if (axis === "x") {
|
|
622
|
+
const leftBoundaries = [aabb.minX, ...setRects.map((r) => r.maxX)].filter(
|
|
623
|
+
(v) => v < colliding.minX - eps
|
|
624
|
+
);
|
|
625
|
+
const rightBoundaries = [aabb.maxX, ...setRects.map((r) => r.minX)].filter(
|
|
626
|
+
(v) => v > colliding.maxX + eps
|
|
627
|
+
);
|
|
628
|
+
const leftNeighbor = leftBoundaries.length > 0 ? Math.max(...leftBoundaries) : void 0;
|
|
629
|
+
const rightNeighbor = rightBoundaries.length > 0 ? Math.min(...rightBoundaries) : void 0;
|
|
630
|
+
const out = [];
|
|
631
|
+
if (leftNeighbor !== void 0) {
|
|
632
|
+
out.push((leftNeighbor + colliding.minX) / 2);
|
|
723
633
|
}
|
|
724
|
-
if (
|
|
725
|
-
|
|
726
|
-
points: [
|
|
727
|
-
{ x: guideline.x, y: globalBounds.minY },
|
|
728
|
-
{ x: guideline.x, y: globalBounds.maxY }
|
|
729
|
-
],
|
|
730
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
731
|
-
strokeDash: "2 2"
|
|
732
|
-
});
|
|
634
|
+
if (rightNeighbor !== void 0) {
|
|
635
|
+
out.push((colliding.maxX + rightNeighbor) / 2);
|
|
733
636
|
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
const
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
const cur = queue.shift();
|
|
748
|
-
for (const dc of directConns) {
|
|
749
|
-
if (dc.pinIds.includes(cur)) {
|
|
750
|
-
for (const p of dc.pinIds) {
|
|
751
|
-
if (!visited.has(p)) {
|
|
752
|
-
visited.add(p);
|
|
753
|
-
queue.push(p);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
}
|
|
637
|
+
return out;
|
|
638
|
+
} else {
|
|
639
|
+
const bottomBoundaries = [aabb.minY, ...setRects.map((r) => r.maxY)].filter(
|
|
640
|
+
(v) => v < colliding.minY - eps
|
|
641
|
+
);
|
|
642
|
+
const topBoundaries = [aabb.maxY, ...setRects.map((r) => r.minY)].filter(
|
|
643
|
+
(v) => v > colliding.maxY + eps
|
|
644
|
+
);
|
|
645
|
+
const bottomNeighbor = bottomBoundaries.length > 0 ? Math.max(...bottomBoundaries) : void 0;
|
|
646
|
+
const topNeighbor = topBoundaries.length > 0 ? Math.min(...topBoundaries) : void 0;
|
|
647
|
+
const out = [];
|
|
648
|
+
if (bottomNeighbor !== void 0) {
|
|
649
|
+
out.push((bottomNeighbor + colliding.minY) / 2);
|
|
758
650
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
const p0 = pins[0].pinId;
|
|
762
|
-
const p1 = pins[1].pinId;
|
|
763
|
-
const relatedPinIds = /* @__PURE__ */ new Set([
|
|
764
|
-
...findAllDirectlyConnectedPins(p0),
|
|
765
|
-
...findAllDirectlyConnectedPins(p1)
|
|
766
|
-
]);
|
|
767
|
-
const restrictedCenterLines = /* @__PURE__ */ new Map();
|
|
768
|
-
const chipFacingMap = /* @__PURE__ */ new Map();
|
|
769
|
-
const chipsOfFacingPins = new Set(pins.map((p) => p.chipId));
|
|
770
|
-
for (const pinId of relatedPinIds) {
|
|
771
|
-
const pin = pinIdMap.get(pinId);
|
|
772
|
-
if (!pin) continue;
|
|
773
|
-
const chip = chipMap[pin.chipId];
|
|
774
|
-
if (!chip) continue;
|
|
775
|
-
const facing = pin._facingDirection ?? getPinDirection(pin, chip);
|
|
776
|
-
let entry = chipFacingMap.get(chip.chipId);
|
|
777
|
-
if (!entry) {
|
|
778
|
-
entry = { center: chip.center };
|
|
779
|
-
const counts = { xPos: 0, xNeg: 0, yPos: 0, yNeg: 0 };
|
|
780
|
-
for (const cp of chip.pins) {
|
|
781
|
-
const cpFacing = cp._facingDirection ?? getPinDirection(cp, chip);
|
|
782
|
-
if (cpFacing === "x+") counts.xPos++;
|
|
783
|
-
if (cpFacing === "x-") counts.xNeg++;
|
|
784
|
-
if (cpFacing === "y+") counts.yPos++;
|
|
785
|
-
if (cpFacing === "y-") counts.yNeg++;
|
|
786
|
-
}
|
|
787
|
-
entry.counts = counts;
|
|
788
|
-
chipFacingMap.set(chip.chipId, entry);
|
|
651
|
+
if (topNeighbor !== void 0) {
|
|
652
|
+
out.push((colliding.maxY + topNeighbor) / 2);
|
|
789
653
|
}
|
|
790
|
-
|
|
791
|
-
if (facing === "x-") entry.hasXNeg = true;
|
|
792
|
-
if (facing === "y+") entry.hasYPos = true;
|
|
793
|
-
if (facing === "y-") entry.hasYNeg = true;
|
|
654
|
+
return out;
|
|
794
655
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
}
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts
|
|
659
|
+
var EPS3 = 1e-9;
|
|
660
|
+
var shiftSegmentOrth = (pts, segIndex, axis, newCoord, eps = EPS3) => {
|
|
661
|
+
if (segIndex < 0 || segIndex >= pts.length - 1) return null;
|
|
662
|
+
const a = pts[segIndex];
|
|
663
|
+
const b = pts[segIndex + 1];
|
|
664
|
+
const vert = isVertical(a, b, eps);
|
|
665
|
+
const horz = isHorizontal(a, b, eps);
|
|
666
|
+
if (!vert && !horz) return null;
|
|
667
|
+
if (vert && axis !== "x") return null;
|
|
668
|
+
if (horz && axis !== "y") return null;
|
|
669
|
+
const out = pts.map((p) => ({ ...p }));
|
|
670
|
+
if (axis === "x") {
|
|
671
|
+
if (Math.abs(a.x - newCoord) < eps && Math.abs(b.x - newCoord) < eps)
|
|
672
|
+
return null;
|
|
673
|
+
out[segIndex] = { ...out[segIndex], x: newCoord };
|
|
674
|
+
out[segIndex + 1] = { ...out[segIndex + 1], x: newCoord };
|
|
675
|
+
} else {
|
|
676
|
+
if (Math.abs(a.y - newCoord) < eps && Math.abs(b.y - newCoord) < eps)
|
|
677
|
+
return null;
|
|
678
|
+
out[segIndex] = { ...out[segIndex], y: newCoord };
|
|
679
|
+
out[segIndex + 1] = { ...out[segIndex + 1], y: newCoord };
|
|
680
|
+
}
|
|
681
|
+
if (segIndex - 1 >= 0) {
|
|
682
|
+
const p = out[segIndex - 1];
|
|
683
|
+
const q = out[segIndex];
|
|
684
|
+
const manhattan = Math.abs(p.x - q.x) + Math.abs(p.y - q.y);
|
|
685
|
+
if (manhattan < eps) return null;
|
|
686
|
+
}
|
|
687
|
+
if (segIndex + 2 <= out.length - 1) {
|
|
688
|
+
const p = out[segIndex + 1];
|
|
689
|
+
const q = out[segIndex + 2];
|
|
690
|
+
const manhattan = Math.abs(p.x - q.x) + Math.abs(p.y - q.y);
|
|
691
|
+
if (manhattan < eps) return null;
|
|
692
|
+
}
|
|
693
|
+
for (let i = 0; i < out.length - 1; i++) {
|
|
694
|
+
const u = out[i];
|
|
695
|
+
const v = out[i + 1];
|
|
696
|
+
if (!isHorizontal(u, v, eps) && !isVertical(u, v, eps)) return null;
|
|
814
697
|
}
|
|
815
|
-
return
|
|
698
|
+
return out;
|
|
816
699
|
};
|
|
700
|
+
var pathKey = (pts, decimals = 6) => pts.map((p) => `${p.x.toFixed(decimals)},${p.y.toFixed(decimals)}`).join("|");
|
|
817
701
|
|
|
818
|
-
// lib/solvers/SchematicTraceLinesSolver/
|
|
819
|
-
var
|
|
702
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts
|
|
703
|
+
var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
820
704
|
pins;
|
|
821
705
|
inputProblem;
|
|
822
|
-
guidelines;
|
|
823
706
|
chipMap;
|
|
824
|
-
|
|
707
|
+
obstacles;
|
|
708
|
+
rectById;
|
|
709
|
+
aabb;
|
|
825
710
|
baseElbow;
|
|
826
|
-
allCandidatePaths;
|
|
827
|
-
queuedCandidatePaths;
|
|
828
|
-
chipObstacleSpatialIndex;
|
|
829
711
|
solvedTracePath = null;
|
|
830
|
-
|
|
831
|
-
|
|
712
|
+
queue = [];
|
|
713
|
+
visited = /* @__PURE__ */ new Set();
|
|
832
714
|
constructor(params) {
|
|
833
715
|
super();
|
|
834
716
|
this.pins = params.pins;
|
|
835
717
|
this.inputProblem = params.inputProblem;
|
|
836
|
-
this.guidelines = params.guidelines;
|
|
837
718
|
this.chipMap = params.chipMap;
|
|
838
|
-
this.chipObstacleSpatialIndex = this.inputProblem._chipObstacleSpatialIndex || new ChipObstacleSpatialIndex(this.inputProblem.chips);
|
|
839
|
-
if (!this.inputProblem._chipObstacleSpatialIndex) {
|
|
840
|
-
this.inputProblem._chipObstacleSpatialIndex = this.chipObstacleSpatialIndex;
|
|
841
|
-
}
|
|
842
|
-
for (const chip of this.inputProblem.chips) {
|
|
843
|
-
for (const pin of chip.pins) {
|
|
844
|
-
this.pinIdMap.set(pin.pinId, { ...pin, chipId: chip.chipId });
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
719
|
for (const pin of this.pins) {
|
|
848
720
|
if (!pin._facingDirection) {
|
|
849
721
|
const chip = this.chipMap[pin.chipId];
|
|
850
722
|
pin._facingDirection = getPinDirection(pin, chip);
|
|
851
723
|
}
|
|
852
724
|
}
|
|
725
|
+
this.obstacles = getObstacleRects(this.inputProblem);
|
|
726
|
+
this.rectById = new Map(this.obstacles.map((r) => [r.chipId, r]));
|
|
853
727
|
const [pin1, pin2] = this.pins;
|
|
854
728
|
this.baseElbow = calculateElbow(
|
|
855
729
|
{
|
|
@@ -862,182 +736,130 @@ var SchematicTraceSingleLineSolver = class extends BaseSolver {
|
|
|
862
736
|
y: pin2.y,
|
|
863
737
|
facingDirection: pin2._facingDirection
|
|
864
738
|
},
|
|
865
|
-
{
|
|
866
|
-
overshoot: 0.2
|
|
867
|
-
}
|
|
739
|
+
{ overshoot: 0.2 }
|
|
868
740
|
);
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
});
|
|
873
|
-
this.movableSegments = movableSegments;
|
|
874
|
-
const getPathLength = (pts) => {
|
|
875
|
-
let len = 0;
|
|
876
|
-
for (let i = 0; i < pts.length - 1; i++) {
|
|
877
|
-
const dx = pts[i + 1].x - pts[i].x;
|
|
878
|
-
const dy = pts[i + 1].y - pts[i].y;
|
|
879
|
-
len += Math.sqrt(dx * dx + dy * dy);
|
|
880
|
-
}
|
|
881
|
-
return len;
|
|
882
|
-
};
|
|
883
|
-
this.allCandidatePaths = [this.baseElbow, ...elbowVariants];
|
|
884
|
-
this.queuedCandidatePaths = [...this.allCandidatePaths].sort(
|
|
885
|
-
(a, b) => getPathLength(a) - getPathLength(b)
|
|
741
|
+
this.aabb = aabbFromPoints(
|
|
742
|
+
{ x: pin1.x, y: pin1.y },
|
|
743
|
+
{ x: pin2.x, y: pin2.y }
|
|
886
744
|
);
|
|
745
|
+
this.queue.push({ path: this.baseElbow, collisionChipIds: /* @__PURE__ */ new Set() });
|
|
746
|
+
this.visited.add(pathKey(this.baseElbow));
|
|
887
747
|
}
|
|
888
748
|
getConstructorParams() {
|
|
889
749
|
return {
|
|
890
750
|
chipMap: this.chipMap,
|
|
891
751
|
pins: this.pins,
|
|
892
|
-
guidelines: this.guidelines,
|
|
893
752
|
inputProblem: this.inputProblem
|
|
894
753
|
};
|
|
895
754
|
}
|
|
755
|
+
axisOfSegment(a, b) {
|
|
756
|
+
if (isVertical(a, b)) return "x";
|
|
757
|
+
if (isHorizontal(a, b)) return "y";
|
|
758
|
+
return null;
|
|
759
|
+
}
|
|
760
|
+
pathLength(pts) {
|
|
761
|
+
let sum = 0;
|
|
762
|
+
for (let i = 0; i < pts.length - 1; i++) {
|
|
763
|
+
sum += Math.abs(pts[i + 1].x - pts[i].x) + Math.abs(pts[i + 1].y - pts[i].y);
|
|
764
|
+
}
|
|
765
|
+
return sum;
|
|
766
|
+
}
|
|
896
767
|
_step() {
|
|
897
|
-
if (this.
|
|
768
|
+
if (this.solvedTracePath) {
|
|
769
|
+
this.solved = true;
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const state = this.queue.shift();
|
|
773
|
+
if (!state) {
|
|
898
774
|
this.failed = true;
|
|
899
|
-
this.error = "No
|
|
775
|
+
this.error = "No collision-free path found";
|
|
900
776
|
return;
|
|
901
777
|
}
|
|
902
|
-
const
|
|
903
|
-
const
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
if (rcl.axes.has("x") && typeof rcl.x === "number") {
|
|
916
|
-
if ((start.x - rcl.x) * (end.x - rcl.x) < -EPS2) return;
|
|
917
|
-
}
|
|
918
|
-
if (rcl.axes.has("y") && typeof rcl.y === "number") {
|
|
919
|
-
if ((start.y - rcl.y) * (end.y - rcl.y) < -EPS2) return;
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
const isStartPin = this.pins.some(
|
|
923
|
-
(pin) => Math.abs(pin.x - start.x) < 1e-10 && Math.abs(pin.y - start.y) < 1e-10
|
|
924
|
-
);
|
|
925
|
-
const isEndPin = this.pins.some(
|
|
926
|
-
(pin) => Math.abs(pin.x - end.x) < 1e-10 && Math.abs(pin.y - end.y) < 1e-10
|
|
927
|
-
);
|
|
928
|
-
if (isStartPin) {
|
|
929
|
-
const startPin = this.pins.find(
|
|
930
|
-
(pin) => Math.abs(pin.x - start.x) < 1e-10 && Math.abs(pin.y - start.y) < 1e-10
|
|
931
|
-
);
|
|
932
|
-
if (startPin) {
|
|
933
|
-
const bounds = getInputChipBounds(this.chipMap[startPin.chipId]);
|
|
934
|
-
const dx = end.x - start.x;
|
|
935
|
-
const dy = end.y - start.y;
|
|
936
|
-
const EPS3 = 1e-9;
|
|
937
|
-
const onLeft = Math.abs(start.x - bounds.minX) < 1e-9;
|
|
938
|
-
const onRight = Math.abs(start.x - bounds.maxX) < 1e-9;
|
|
939
|
-
const onBottom = Math.abs(start.y - bounds.minY) < 1e-9;
|
|
940
|
-
const onTop = Math.abs(start.y - bounds.maxY) < 1e-9;
|
|
941
|
-
const entersInterior = onLeft && dx > EPS3 || onRight && dx < -EPS3 || onBottom && dy > EPS3 || onTop && dy < -EPS3;
|
|
942
|
-
if (entersInterior) return;
|
|
943
|
-
if (!excludeChipIds.includes(startPin.chipId)) {
|
|
944
|
-
excludeChipIds.push(startPin.chipId);
|
|
945
|
-
}
|
|
946
|
-
}
|
|
778
|
+
const { path, collisionChipIds } = state;
|
|
779
|
+
const collision = findFirstCollision(path, this.obstacles);
|
|
780
|
+
if (!collision) {
|
|
781
|
+
this.solvedTracePath = path;
|
|
782
|
+
this.solved = true;
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
let { segIndex, rect } = collision;
|
|
786
|
+
const isFirstSegment = segIndex === 0;
|
|
787
|
+
const isLastSegment = segIndex === path.length - 2;
|
|
788
|
+
if (isFirstSegment) {
|
|
789
|
+
if (path.length < 3) {
|
|
790
|
+
return;
|
|
947
791
|
}
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
if (endPin) {
|
|
953
|
-
const bounds = getInputChipBounds(this.chipMap[endPin.chipId]);
|
|
954
|
-
const dx = start.x - end.x;
|
|
955
|
-
const dy = start.y - end.y;
|
|
956
|
-
const EPS3 = 1e-9;
|
|
957
|
-
const onLeft = Math.abs(end.x - bounds.minX) < 1e-9;
|
|
958
|
-
const onRight = Math.abs(end.x - bounds.maxX) < 1e-9;
|
|
959
|
-
const onBottom = Math.abs(end.y - bounds.minY) < 1e-9;
|
|
960
|
-
const onTop = Math.abs(end.y - bounds.maxY) < 1e-9;
|
|
961
|
-
const entersInterior = onLeft && dx > EPS3 || onRight && dx < -EPS3 || onBottom && dy > EPS3 || onTop && dy < -EPS3;
|
|
962
|
-
if (entersInterior) return;
|
|
963
|
-
if (!excludeChipIds.includes(endPin.chipId)) {
|
|
964
|
-
excludeChipIds.push(endPin.chipId);
|
|
965
|
-
}
|
|
966
|
-
}
|
|
792
|
+
segIndex = 1;
|
|
793
|
+
} else if (isLastSegment) {
|
|
794
|
+
if (path.length < 3) {
|
|
795
|
+
return;
|
|
967
796
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
797
|
+
segIndex = path.length - 3;
|
|
798
|
+
}
|
|
799
|
+
const a = path[segIndex];
|
|
800
|
+
const b = path[segIndex + 1];
|
|
801
|
+
const axis = this.axisOfSegment(a, b);
|
|
802
|
+
if (!axis) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
const [PA, PB] = this.pins;
|
|
806
|
+
const candidates = [];
|
|
807
|
+
if (collisionChipIds.size === 0) {
|
|
808
|
+
const m1 = midBetweenPointAndRect(axis, { x: PA.x, y: PA.y }, rect);
|
|
809
|
+
const m2 = midBetweenPointAndRect(axis, { x: PB.x, y: PB.y }, rect);
|
|
810
|
+
const allCandidates = [...m1, ...m2];
|
|
811
|
+
const uniqueCandidates = [...new Set(allCandidates)];
|
|
812
|
+
candidates.push(...uniqueCandidates);
|
|
813
|
+
} else {
|
|
814
|
+
const mids = candidateMidsFromSet(
|
|
815
|
+
axis,
|
|
816
|
+
rect,
|
|
817
|
+
this.rectById,
|
|
818
|
+
collisionChipIds,
|
|
819
|
+
this.aabb
|
|
972
820
|
);
|
|
973
|
-
|
|
821
|
+
candidates.push(...mids);
|
|
822
|
+
}
|
|
823
|
+
const newStates = [];
|
|
824
|
+
for (const coord of candidates) {
|
|
825
|
+
const newPath = shiftSegmentOrth(path, segIndex, axis, coord);
|
|
826
|
+
if (!newPath) continue;
|
|
827
|
+
const key = pathKey(newPath);
|
|
828
|
+
if (this.visited.has(key)) continue;
|
|
829
|
+
this.visited.add(key);
|
|
830
|
+
const nextSet = new Set(collisionChipIds);
|
|
831
|
+
nextSet.add(rect.chipId);
|
|
832
|
+
const len = this.pathLength(newPath);
|
|
833
|
+
newStates.push({ path: newPath, collisionRectIds: nextSet, len });
|
|
834
|
+
}
|
|
835
|
+
newStates.sort((a2, b2) => a2.len - b2.len);
|
|
836
|
+
for (const st of newStates) {
|
|
837
|
+
this.queue.push({ path: st.path, collisionChipIds: st.collisionRectIds });
|
|
974
838
|
}
|
|
975
|
-
this.solvedTracePath = nextCandidatePath;
|
|
976
|
-
this.solved = true;
|
|
977
839
|
}
|
|
978
840
|
visualize() {
|
|
979
|
-
const
|
|
841
|
+
const g = visualizeInputProblem(this.inputProblem, {
|
|
980
842
|
chipAlpha: 0.1,
|
|
981
843
|
connectionAlpha: 0.1
|
|
982
844
|
});
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
const boundsHeight = bounds.maxY - bounds.minY;
|
|
986
|
-
visualizeGuidelines({ guidelines: this.guidelines, graphics });
|
|
987
|
-
for (const { start, end, dir: dir2 } of this.movableSegments) {
|
|
988
|
-
const mid = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 };
|
|
989
|
-
const dist = Math.sqrt((start.x - end.x) ** 2 + (start.y - end.y) ** 2);
|
|
990
|
-
graphics.lines.push({
|
|
991
|
-
points: [start, mid, end],
|
|
992
|
-
strokeColor: "rgba(0,0,255,0.5)",
|
|
993
|
-
strokeDash: "2 2"
|
|
994
|
-
});
|
|
995
|
-
graphics.lines.push({
|
|
996
|
-
points: [
|
|
997
|
-
mid,
|
|
998
|
-
{ x: mid.x + dir2.x * dist * 0.1, y: mid.y + dir2.y * dist * 0.1 }
|
|
999
|
-
],
|
|
1000
|
-
strokeColor: "rgba(0,0,255,0.5)",
|
|
1001
|
-
strokeDash: "2 2"
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
if (!this.solvedTracePath) {
|
|
1005
|
-
if (this.queuedCandidatePaths.length > 0) {
|
|
1006
|
-
graphics.lines.push({
|
|
1007
|
-
points: this.queuedCandidatePaths[0],
|
|
1008
|
-
strokeColor: "orange"
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
for (let i = 1; i < this.queuedCandidatePaths.length; i++) {
|
|
1012
|
-
const candidatePath = this.queuedCandidatePaths[i];
|
|
1013
|
-
const pi = i / this.queuedCandidatePaths.length;
|
|
1014
|
-
graphics.lines.push({
|
|
1015
|
-
points: candidatePath.map((p) => ({
|
|
1016
|
-
x: p.x + pi * boundsWidth * 5e-3,
|
|
1017
|
-
y: p.y + pi * boundsHeight * 5e-3
|
|
1018
|
-
})),
|
|
1019
|
-
strokeColor: getColorFromString(
|
|
1020
|
-
`${candidatePath.reduce((acc, p) => `${acc},${p.x},${p.y}`, "")}`,
|
|
1021
|
-
0.5
|
|
1022
|
-
),
|
|
1023
|
-
strokeDash: "8 8"
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
845
|
+
for (const { path, collisionChipIds: collisionRectIds } of this.queue) {
|
|
846
|
+
g.lines.push({ points: path, strokeColor: "teal", strokeDash: "2 2" });
|
|
1026
847
|
}
|
|
1027
848
|
if (this.solvedTracePath) {
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
});
|
|
849
|
+
g.lines.push({ points: this.solvedTracePath, strokeColor: "green" });
|
|
850
|
+
} else if (this.queue.length > 0) {
|
|
851
|
+
g.lines.push({ points: this.queue[0].path, strokeColor: "orange" });
|
|
1032
852
|
}
|
|
1033
|
-
return
|
|
853
|
+
return g;
|
|
1034
854
|
}
|
|
1035
855
|
};
|
|
1036
856
|
|
|
857
|
+
// lib/solvers/GuidelinesSolver/visualizeGuidelines.ts
|
|
858
|
+
import { getBounds } from "graphics-debug";
|
|
859
|
+
|
|
1037
860
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts
|
|
1038
861
|
var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
1039
862
|
inputProblem;
|
|
1040
|
-
guidelines;
|
|
1041
863
|
mspConnectionPairs;
|
|
1042
864
|
dcConnMap;
|
|
1043
865
|
globalConnMap;
|
|
@@ -1052,7 +874,6 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1052
874
|
this.mspConnectionPairs = params.mspConnectionPairs;
|
|
1053
875
|
this.dcConnMap = params.dcConnMap;
|
|
1054
876
|
this.globalConnMap = params.globalConnMap;
|
|
1055
|
-
this.guidelines = params.guidelines;
|
|
1056
877
|
this.chipMap = params.chipMap;
|
|
1057
878
|
this.queuedConnectionPairs = [...this.mspConnectionPairs];
|
|
1058
879
|
}
|
|
@@ -1062,8 +883,7 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1062
883
|
chipMap: this.chipMap,
|
|
1063
884
|
mspConnectionPairs: this.mspConnectionPairs,
|
|
1064
885
|
dcConnMap: this.dcConnMap,
|
|
1065
|
-
globalConnMap: this.globalConnMap
|
|
1066
|
-
guidelines: this.guidelines
|
|
886
|
+
globalConnMap: this.globalConnMap
|
|
1067
887
|
};
|
|
1068
888
|
}
|
|
1069
889
|
_step() {
|
|
@@ -1095,17 +915,16 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1095
915
|
return;
|
|
1096
916
|
}
|
|
1097
917
|
const connectionPair = this.queuedConnectionPairs.shift();
|
|
1098
|
-
this.currentConnectionPair = connectionPair;
|
|
1099
918
|
if (!connectionPair) {
|
|
1100
919
|
this.solved = true;
|
|
1101
920
|
return;
|
|
1102
921
|
}
|
|
922
|
+
this.currentConnectionPair = connectionPair;
|
|
1103
923
|
const { pins } = connectionPair;
|
|
1104
|
-
this.activeSubSolver = new
|
|
924
|
+
this.activeSubSolver = new SchematicTraceSingleLineSolver2({
|
|
1105
925
|
inputProblem: this.inputProblem,
|
|
1106
926
|
pins,
|
|
1107
|
-
chipMap: this.chipMap
|
|
1108
|
-
guidelines: this.guidelines
|
|
927
|
+
chipMap: this.chipMap
|
|
1109
928
|
});
|
|
1110
929
|
}
|
|
1111
930
|
visualize() {
|
|
@@ -1116,7 +935,6 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1116
935
|
chipAlpha: 0.1,
|
|
1117
936
|
connectionAlpha: 0.1
|
|
1118
937
|
});
|
|
1119
|
-
visualizeGuidelines({ guidelines: this.guidelines, graphics });
|
|
1120
938
|
for (const { mspPairId, tracePath } of this.solvedTracePaths) {
|
|
1121
939
|
graphics.lines.push({
|
|
1122
940
|
points: tracePath,
|
|
@@ -1143,17 +961,17 @@ var applyJogToTerminalSegment = ({
|
|
|
1143
961
|
segmentIndex: si,
|
|
1144
962
|
offset,
|
|
1145
963
|
JOG_SIZE,
|
|
1146
|
-
EPS:
|
|
964
|
+
EPS: EPS4 = 1e-6
|
|
1147
965
|
}) => {
|
|
1148
966
|
if (si !== 0 && si !== pts.length - 2) return;
|
|
1149
967
|
const start = pts[si];
|
|
1150
968
|
const end = pts[si + 1];
|
|
1151
|
-
const
|
|
1152
|
-
const
|
|
1153
|
-
if (!
|
|
1154
|
-
const segDir =
|
|
969
|
+
const isVertical2 = Math.abs(start.x - end.x) < EPS4;
|
|
970
|
+
const isHorizontal2 = Math.abs(start.y - end.y) < EPS4;
|
|
971
|
+
if (!isVertical2 && !isHorizontal2) return;
|
|
972
|
+
const segDir = isVertical2 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
|
|
1155
973
|
if (si === 0) {
|
|
1156
|
-
if (
|
|
974
|
+
if (isVertical2) {
|
|
1157
975
|
const jogY = start.y + segDir * JOG_SIZE;
|
|
1158
976
|
pts.splice(
|
|
1159
977
|
1,
|
|
@@ -1173,7 +991,7 @@ var applyJogToTerminalSegment = ({
|
|
|
1173
991
|
);
|
|
1174
992
|
}
|
|
1175
993
|
} else {
|
|
1176
|
-
if (
|
|
994
|
+
if (isVertical2) {
|
|
1177
995
|
const jogY = end.y - segDir * JOG_SIZE;
|
|
1178
996
|
pts.splice(
|
|
1179
997
|
si,
|
|
@@ -1216,13 +1034,13 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1216
1034
|
}
|
|
1217
1035
|
}
|
|
1218
1036
|
_step() {
|
|
1219
|
-
const
|
|
1037
|
+
const EPS4 = 1e-6;
|
|
1220
1038
|
const offsets = this.overlappingTraceSegments.map((_, idx) => {
|
|
1221
1039
|
const n = Math.floor(idx / 2) + 1;
|
|
1222
1040
|
const signed = idx % 2 === 0 ? -n : n;
|
|
1223
1041
|
return signed * this.SHIFT_DISTANCE;
|
|
1224
1042
|
});
|
|
1225
|
-
const eq = (a, b) => Math.abs(a - b) <
|
|
1043
|
+
const eq = (a, b) => Math.abs(a - b) < EPS4;
|
|
1226
1044
|
const samePoint = (p, q) => !!p && !!q && eq(p.x, q.x) && eq(p.y, q.y);
|
|
1227
1045
|
this.overlappingTraceSegments.forEach((group, gidx) => {
|
|
1228
1046
|
const offset = offsets[gidx];
|
|
@@ -1248,15 +1066,15 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1248
1066
|
segmentIndex: si,
|
|
1249
1067
|
offset,
|
|
1250
1068
|
JOG_SIZE,
|
|
1251
|
-
EPS:
|
|
1069
|
+
EPS: EPS4
|
|
1252
1070
|
});
|
|
1253
1071
|
} else {
|
|
1254
1072
|
const start = pts[si];
|
|
1255
1073
|
const end = pts[si + 1];
|
|
1256
|
-
const
|
|
1257
|
-
const
|
|
1258
|
-
if (!
|
|
1259
|
-
if (
|
|
1074
|
+
const isVertical2 = Math.abs(start.x - end.x) < EPS4;
|
|
1075
|
+
const isHorizontal2 = Math.abs(start.y - end.y) < EPS4;
|
|
1076
|
+
if (!isVertical2 && !isHorizontal2) continue;
|
|
1077
|
+
if (isVertical2) {
|
|
1260
1078
|
start.x += offset;
|
|
1261
1079
|
end.x += offset;
|
|
1262
1080
|
} else {
|
|
@@ -1350,7 +1168,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1350
1168
|
return islands;
|
|
1351
1169
|
}
|
|
1352
1170
|
findNextOverlapIssue() {
|
|
1353
|
-
const
|
|
1171
|
+
const EPS4 = 2e-3;
|
|
1354
1172
|
const netIds = Object.keys(this.traceNetIslands);
|
|
1355
1173
|
for (let i = 0; i < netIds.length; i++) {
|
|
1356
1174
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -1368,7 +1186,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1368
1186
|
const minB = Math.min(b1, b2);
|
|
1369
1187
|
const maxB = Math.max(b1, b2);
|
|
1370
1188
|
const overlap = Math.min(maxA, maxB) - Math.max(minA, minB);
|
|
1371
|
-
return overlap >
|
|
1189
|
+
return overlap > EPS4;
|
|
1372
1190
|
};
|
|
1373
1191
|
for (let pa = 0; pa < pathsA.length; pa++) {
|
|
1374
1192
|
const pathA = pathsA[pa];
|
|
@@ -1376,8 +1194,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1376
1194
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
1377
1195
|
const a1 = ptsA[sa];
|
|
1378
1196
|
const a2 = ptsA[sa + 1];
|
|
1379
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
1380
|
-
const aHorz = Math.abs(a1.y - a2.y) <
|
|
1197
|
+
const aVert = Math.abs(a1.x - a2.x) < EPS4;
|
|
1198
|
+
const aHorz = Math.abs(a1.y - a2.y) < EPS4;
|
|
1381
1199
|
if (!aVert && !aHorz) continue;
|
|
1382
1200
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
1383
1201
|
const pathB = pathsB[pb];
|
|
@@ -1385,11 +1203,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1385
1203
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
1386
1204
|
const b1 = ptsB[sb];
|
|
1387
1205
|
const b2 = ptsB[sb + 1];
|
|
1388
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
1389
|
-
const bHorz = Math.abs(b1.y - b2.y) <
|
|
1206
|
+
const bVert = Math.abs(b1.x - b2.x) < EPS4;
|
|
1207
|
+
const bHorz = Math.abs(b1.y - b2.y) < EPS4;
|
|
1390
1208
|
if (!bVert && !bHorz) continue;
|
|
1391
1209
|
if (aVert && bVert) {
|
|
1392
|
-
if (Math.abs(a1.x - b1.x) <
|
|
1210
|
+
if (Math.abs(a1.x - b1.x) < EPS4) {
|
|
1393
1211
|
if (overlaps1D(a1.y, a2.y, b1.y, b2.y)) {
|
|
1394
1212
|
const keyA = `${pa}:${sa}`;
|
|
1395
1213
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1410,7 +1228,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1410
1228
|
}
|
|
1411
1229
|
}
|
|
1412
1230
|
} else if (aHorz && bHorz) {
|
|
1413
|
-
if (Math.abs(a1.y - b1.y) <
|
|
1231
|
+
if (Math.abs(a1.y - b1.y) < EPS4) {
|
|
1414
1232
|
if (overlaps1D(a1.x, a2.x, b1.x, b2.x)) {
|
|
1415
1233
|
const keyA = `${pa}:${sa}`;
|
|
1416
1234
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1487,6 +1305,55 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1487
1305
|
}
|
|
1488
1306
|
};
|
|
1489
1307
|
|
|
1308
|
+
// lib/data-structures/ChipObstacleSpatialIndex.ts
|
|
1309
|
+
import Flatbush from "flatbush";
|
|
1310
|
+
var ChipObstacleSpatialIndex = class {
|
|
1311
|
+
chips;
|
|
1312
|
+
spatialIndex;
|
|
1313
|
+
spatialIndexIdToChip;
|
|
1314
|
+
constructor(chips) {
|
|
1315
|
+
this.chips = chips.map((chip) => ({
|
|
1316
|
+
...chip,
|
|
1317
|
+
bounds: getInputChipBounds(chip),
|
|
1318
|
+
spatialIndexId: null
|
|
1319
|
+
}));
|
|
1320
|
+
this.spatialIndexIdToChip = /* @__PURE__ */ new Map();
|
|
1321
|
+
this.spatialIndex = new Flatbush(chips.length);
|
|
1322
|
+
for (const chip of this.chips) {
|
|
1323
|
+
chip.spatialIndexId = this.spatialIndex.add(
|
|
1324
|
+
chip.bounds.minX,
|
|
1325
|
+
chip.bounds.minY,
|
|
1326
|
+
chip.bounds.maxX,
|
|
1327
|
+
chip.bounds.maxY
|
|
1328
|
+
);
|
|
1329
|
+
this.spatialIndexIdToChip.set(chip.spatialIndexId, chip);
|
|
1330
|
+
}
|
|
1331
|
+
this.spatialIndex.finish();
|
|
1332
|
+
}
|
|
1333
|
+
getChipsInBounds(bounds) {
|
|
1334
|
+
const chipSpatialIndexIds = this.spatialIndex.search(
|
|
1335
|
+
bounds.minX,
|
|
1336
|
+
bounds.minY,
|
|
1337
|
+
bounds.maxX,
|
|
1338
|
+
bounds.maxY
|
|
1339
|
+
);
|
|
1340
|
+
return chipSpatialIndexIds.map((id) => this.spatialIndexIdToChip.get(id));
|
|
1341
|
+
}
|
|
1342
|
+
doesOrthogonalLineIntersectChip(line, opts = {}) {
|
|
1343
|
+
const excludeChipIds = opts.excludeChipIds ?? [];
|
|
1344
|
+
const [p1, p2] = line;
|
|
1345
|
+
const { x: x1, y: y1 } = p1;
|
|
1346
|
+
const { x: x2, y: y2 } = p2;
|
|
1347
|
+
const chips = this.getChipsInBounds({
|
|
1348
|
+
minX: Math.min(x1, x2),
|
|
1349
|
+
minY: Math.min(y1, y2),
|
|
1350
|
+
maxX: Math.max(x1, x2),
|
|
1351
|
+
maxY: Math.max(y1, y2)
|
|
1352
|
+
}).filter((chip) => !excludeChipIds.includes(chip.chipId));
|
|
1353
|
+
return chips.length > 0;
|
|
1354
|
+
}
|
|
1355
|
+
};
|
|
1356
|
+
|
|
1490
1357
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry.ts
|
|
1491
1358
|
var NET_LABEL_HORIZONTAL_WIDTH = 0.45;
|
|
1492
1359
|
var NET_LABEL_HORIZONTAL_HEIGHT = 0.2;
|
|
@@ -1524,24 +1391,24 @@ function getRectBounds(center, w, h) {
|
|
|
1524
1391
|
}
|
|
1525
1392
|
|
|
1526
1393
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
|
|
1527
|
-
function
|
|
1528
|
-
const isVert = Math.abs(p1.x - p2.x) <
|
|
1529
|
-
const isHorz = Math.abs(p1.y - p2.y) <
|
|
1394
|
+
function segmentIntersectsRect2(p1, p2, rect, EPS4 = 1e-9) {
|
|
1395
|
+
const isVert = Math.abs(p1.x - p2.x) < EPS4;
|
|
1396
|
+
const isHorz = Math.abs(p1.y - p2.y) < EPS4;
|
|
1530
1397
|
if (!isVert && !isHorz) return false;
|
|
1531
1398
|
if (isVert) {
|
|
1532
1399
|
const x = p1.x;
|
|
1533
|
-
if (x < rect.minX -
|
|
1400
|
+
if (x < rect.minX - EPS4 || x > rect.maxX + EPS4) return false;
|
|
1534
1401
|
const segMinY = Math.min(p1.y, p2.y);
|
|
1535
1402
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
1536
1403
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
1537
|
-
return overlap >
|
|
1404
|
+
return overlap > EPS4;
|
|
1538
1405
|
} else {
|
|
1539
1406
|
const y = p1.y;
|
|
1540
|
-
if (y < rect.minY -
|
|
1407
|
+
if (y < rect.minY - EPS4 || y > rect.maxY + EPS4) return false;
|
|
1541
1408
|
const segMinX = Math.min(p1.x, p2.x);
|
|
1542
1409
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
1543
1410
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
1544
|
-
return overlap >
|
|
1411
|
+
return overlap > EPS4;
|
|
1545
1412
|
}
|
|
1546
1413
|
}
|
|
1547
1414
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -1549,7 +1416,7 @@ function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex)
|
|
|
1549
1416
|
const pts = solved.tracePath;
|
|
1550
1417
|
for (let i = 0; i < pts.length - 1; i++) {
|
|
1551
1418
|
if (pairId === hostPathId && i === hostSegIndex) continue;
|
|
1552
|
-
if (
|
|
1419
|
+
if (segmentIntersectsRect2(pts[i], pts[i + 1], bounds))
|
|
1553
1420
|
return { hasIntersection: true, mspPairId: pairId, segIndex: i };
|
|
1554
1421
|
}
|
|
1555
1422
|
}
|
|
@@ -1898,14 +1765,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1898
1765
|
};
|
|
1899
1766
|
let bestCandidate = null;
|
|
1900
1767
|
let bestScore = -Infinity;
|
|
1901
|
-
const
|
|
1768
|
+
const EPS4 = 1e-6;
|
|
1902
1769
|
for (const curr of tracesToScan) {
|
|
1903
1770
|
const pts = curr.tracePath.slice();
|
|
1904
1771
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
1905
1772
|
const a = pts[si];
|
|
1906
1773
|
const b = pts[si + 1];
|
|
1907
|
-
const isH = Math.abs(a.y - b.y) <
|
|
1908
|
-
const isV = Math.abs(a.x - b.x) <
|
|
1774
|
+
const isH = Math.abs(a.y - b.y) < EPS4;
|
|
1775
|
+
const isV = Math.abs(a.x - b.x) < EPS4;
|
|
1909
1776
|
if (!isH && !isV) continue;
|
|
1910
1777
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
1911
1778
|
const candidateOrients = orientations.filter(
|
|
@@ -2237,187 +2104,7 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2237
2104
|
};
|
|
2238
2105
|
|
|
2239
2106
|
// lib/solvers/GuidelinesSolver/GuidelinesSolver.ts
|
|
2240
|
-
import { getBounds as
|
|
2241
|
-
|
|
2242
|
-
// lib/solvers/GuidelinesSolver/getGeneratorForAllChipPairs.ts
|
|
2243
|
-
var getGeneratorForAllChipPairs = (chips) => {
|
|
2244
|
-
return (function* () {
|
|
2245
|
-
for (let i = 0; i < chips.length; i++) {
|
|
2246
|
-
for (let j = 0; j < chips.length; j++) {
|
|
2247
|
-
if (i !== j) {
|
|
2248
|
-
yield [chips[i], chips[j]];
|
|
2249
|
-
}
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2252
|
-
})();
|
|
2253
|
-
};
|
|
2254
|
-
|
|
2255
|
-
// lib/solvers/GuidelinesSolver/getHorizontalGuidelineY.ts
|
|
2256
|
-
function getHorizontalGuidelineY(chip1Bounds, chip2Bounds) {
|
|
2257
|
-
if (chip1Bounds.maxY <= chip2Bounds.minY) {
|
|
2258
|
-
return (chip1Bounds.maxY + chip2Bounds.minY) / 2;
|
|
2259
|
-
}
|
|
2260
|
-
if (chip2Bounds.maxY <= chip1Bounds.minY) {
|
|
2261
|
-
return (chip2Bounds.maxY + chip1Bounds.minY) / 2;
|
|
2262
|
-
}
|
|
2263
|
-
const overlapMinY = Math.max(chip1Bounds.minY, chip2Bounds.minY);
|
|
2264
|
-
const overlapMaxY = Math.min(chip1Bounds.maxY, chip2Bounds.maxY);
|
|
2265
|
-
return (overlapMinY + overlapMaxY) / 2;
|
|
2266
|
-
}
|
|
2267
|
-
|
|
2268
|
-
// lib/solvers/GuidelinesSolver/getVerticalGuidelineX.ts
|
|
2269
|
-
function getVerticalGuidelineX(chip1Bounds, chip2Bounds) {
|
|
2270
|
-
if (chip1Bounds.maxX <= chip2Bounds.minX) {
|
|
2271
|
-
return (chip1Bounds.maxX + chip2Bounds.minX) / 2;
|
|
2272
|
-
}
|
|
2273
|
-
if (chip2Bounds.maxX <= chip1Bounds.minX) {
|
|
2274
|
-
return (chip2Bounds.maxX + chip1Bounds.minX) / 2;
|
|
2275
|
-
}
|
|
2276
|
-
const overlapMinX = Math.max(chip1Bounds.minX, chip2Bounds.minX);
|
|
2277
|
-
const overlapMaxX = Math.min(chip1Bounds.maxX, chip2Bounds.maxX);
|
|
2278
|
-
return (overlapMinX + overlapMaxX) / 2;
|
|
2279
|
-
}
|
|
2280
|
-
|
|
2281
|
-
// lib/solvers/GuidelinesSolver/getInputProblemBounds.ts
|
|
2282
|
-
var getInputProblemBounds = (inputProblem) => {
|
|
2283
|
-
const bounds = {
|
|
2284
|
-
minX: Infinity,
|
|
2285
|
-
maxX: -Infinity,
|
|
2286
|
-
minY: Infinity,
|
|
2287
|
-
maxY: -Infinity
|
|
2288
|
-
};
|
|
2289
|
-
for (const chip of inputProblem.chips) {
|
|
2290
|
-
const chipBounds = getInputChipBounds(chip);
|
|
2291
|
-
bounds.minX = Math.min(bounds.minX, chipBounds.minX);
|
|
2292
|
-
bounds.maxX = Math.max(bounds.maxX, chipBounds.maxX);
|
|
2293
|
-
bounds.minY = Math.min(bounds.minY, chipBounds.minY);
|
|
2294
|
-
bounds.maxY = Math.max(bounds.maxY, chipBounds.maxY);
|
|
2295
|
-
}
|
|
2296
|
-
return bounds;
|
|
2297
|
-
};
|
|
2298
|
-
|
|
2299
|
-
// lib/solvers/GuidelinesSolver/GuidelinesSolver.ts
|
|
2300
|
-
var GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS = 0.1;
|
|
2301
|
-
var GuidelinesSolver = class extends BaseSolver {
|
|
2302
|
-
inputProblem;
|
|
2303
|
-
guidelines;
|
|
2304
|
-
chipPairsGenerator;
|
|
2305
|
-
usedXGuidelines;
|
|
2306
|
-
usedYGuidelines;
|
|
2307
|
-
constructor(params) {
|
|
2308
|
-
super();
|
|
2309
|
-
this.inputProblem = params.inputProblem;
|
|
2310
|
-
const inputProblemBounds = getInputProblemBounds(this.inputProblem);
|
|
2311
|
-
this.guidelines = [
|
|
2312
|
-
{
|
|
2313
|
-
orientation: "horizontal",
|
|
2314
|
-
y: inputProblemBounds.minY - GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS,
|
|
2315
|
-
x: void 0
|
|
2316
|
-
},
|
|
2317
|
-
{
|
|
2318
|
-
orientation: "horizontal",
|
|
2319
|
-
y: inputProblemBounds.maxY + GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS,
|
|
2320
|
-
x: void 0
|
|
2321
|
-
},
|
|
2322
|
-
{
|
|
2323
|
-
orientation: "vertical",
|
|
2324
|
-
y: void 0,
|
|
2325
|
-
x: inputProblemBounds.minX - GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS
|
|
2326
|
-
},
|
|
2327
|
-
{
|
|
2328
|
-
orientation: "vertical",
|
|
2329
|
-
y: void 0,
|
|
2330
|
-
x: inputProblemBounds.maxX + GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS
|
|
2331
|
-
}
|
|
2332
|
-
];
|
|
2333
|
-
this.chipPairsGenerator = getGeneratorForAllChipPairs(
|
|
2334
|
-
this.inputProblem.chips
|
|
2335
|
-
);
|
|
2336
|
-
this.usedXGuidelines = /* @__PURE__ */ new Set();
|
|
2337
|
-
this.usedYGuidelines = /* @__PURE__ */ new Set();
|
|
2338
|
-
}
|
|
2339
|
-
getConstructorParams() {
|
|
2340
|
-
return {
|
|
2341
|
-
inputProblem: this.inputProblem
|
|
2342
|
-
};
|
|
2343
|
-
}
|
|
2344
|
-
_step() {
|
|
2345
|
-
const { done, value: chipPair } = this.chipPairsGenerator.next();
|
|
2346
|
-
if (done) {
|
|
2347
|
-
this.solved = true;
|
|
2348
|
-
return;
|
|
2349
|
-
}
|
|
2350
|
-
const [chip1, chip2] = chipPair;
|
|
2351
|
-
const chip1Bounds = getInputChipBounds(chip1);
|
|
2352
|
-
const chip2Bounds = getInputChipBounds(chip2);
|
|
2353
|
-
const horizontalGuidelineY = getHorizontalGuidelineY(
|
|
2354
|
-
chip1Bounds,
|
|
2355
|
-
chip2Bounds
|
|
2356
|
-
);
|
|
2357
|
-
const verticalGuidelineX = getVerticalGuidelineX(chip1Bounds, chip2Bounds);
|
|
2358
|
-
if (!this.usedYGuidelines.has(horizontalGuidelineY)) {
|
|
2359
|
-
this.usedYGuidelines.add(horizontalGuidelineY);
|
|
2360
|
-
this.guidelines.push({
|
|
2361
|
-
orientation: "horizontal",
|
|
2362
|
-
y: horizontalGuidelineY,
|
|
2363
|
-
x: void 0
|
|
2364
|
-
});
|
|
2365
|
-
}
|
|
2366
|
-
if (!this.usedXGuidelines.has(verticalGuidelineX)) {
|
|
2367
|
-
this.usedXGuidelines.add(verticalGuidelineX);
|
|
2368
|
-
this.guidelines.push({
|
|
2369
|
-
orientation: "vertical",
|
|
2370
|
-
y: void 0,
|
|
2371
|
-
x: verticalGuidelineX
|
|
2372
|
-
});
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
visualize() {
|
|
2376
|
-
const graphics = visualizeInputProblem(this.inputProblem);
|
|
2377
|
-
const bounds = getBounds4(graphics);
|
|
2378
|
-
const boundsWidth = bounds.maxX - bounds.minX;
|
|
2379
|
-
const boundsHeight = bounds.maxY - bounds.minY;
|
|
2380
|
-
bounds.minX -= boundsWidth * 0.3;
|
|
2381
|
-
bounds.maxX += boundsWidth * 0.3;
|
|
2382
|
-
bounds.minY -= boundsHeight * 0.3;
|
|
2383
|
-
bounds.maxY += boundsHeight * 0.3;
|
|
2384
|
-
for (const guideline of this.guidelines) {
|
|
2385
|
-
if (guideline.orientation === "horizontal") {
|
|
2386
|
-
graphics.lines.push({
|
|
2387
|
-
points: [
|
|
2388
|
-
{
|
|
2389
|
-
x: bounds.minX,
|
|
2390
|
-
y: guideline.y
|
|
2391
|
-
},
|
|
2392
|
-
{
|
|
2393
|
-
x: bounds.maxX,
|
|
2394
|
-
y: guideline.y
|
|
2395
|
-
}
|
|
2396
|
-
],
|
|
2397
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
2398
|
-
strokeDash: "2 2"
|
|
2399
|
-
});
|
|
2400
|
-
}
|
|
2401
|
-
if (guideline.orientation === "vertical") {
|
|
2402
|
-
graphics.lines.push({
|
|
2403
|
-
points: [
|
|
2404
|
-
{
|
|
2405
|
-
x: guideline.x,
|
|
2406
|
-
y: bounds.minY
|
|
2407
|
-
},
|
|
2408
|
-
{
|
|
2409
|
-
x: guideline.x,
|
|
2410
|
-
y: bounds.maxY
|
|
2411
|
-
}
|
|
2412
|
-
],
|
|
2413
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
2414
|
-
strokeDash: "2 2"
|
|
2415
|
-
});
|
|
2416
|
-
}
|
|
2417
|
-
}
|
|
2418
|
-
return graphics;
|
|
2419
|
-
}
|
|
2420
|
-
};
|
|
2107
|
+
import { getBounds as getBounds3 } from "graphics-debug";
|
|
2421
2108
|
|
|
2422
2109
|
// lib/solvers/SchematicTracePipelineSolver/correctPinsInsideChip.ts
|
|
2423
2110
|
var correctPinsInsideChips = (problem) => {
|
|
@@ -2481,7 +2168,7 @@ function definePipelineStep(solverName, solverClass, getConstructorParams, opts
|
|
|
2481
2168
|
}
|
|
2482
2169
|
var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
2483
2170
|
mspConnectionPairSolver;
|
|
2484
|
-
guidelinesSolver
|
|
2171
|
+
// guidelinesSolver?: GuidelinesSolver
|
|
2485
2172
|
schematicTraceLinesSolver;
|
|
2486
2173
|
traceOverlapShiftSolver;
|
|
2487
2174
|
netLabelPlacementSolver;
|
|
@@ -2500,19 +2187,18 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
2500
2187
|
}
|
|
2501
2188
|
}
|
|
2502
2189
|
),
|
|
2503
|
-
definePipelineStep(
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
),
|
|
2190
|
+
// definePipelineStep(
|
|
2191
|
+
// "guidelinesSolver",
|
|
2192
|
+
// GuidelinesSolver,
|
|
2193
|
+
// () => [
|
|
2194
|
+
// {
|
|
2195
|
+
// inputProblem: this.inputProblem,
|
|
2196
|
+
// },
|
|
2197
|
+
// ],
|
|
2198
|
+
// {
|
|
2199
|
+
// onSolved: (guidelinesSolver) => {},
|
|
2200
|
+
// },
|
|
2201
|
+
// ),
|
|
2516
2202
|
definePipelineStep(
|
|
2517
2203
|
"schematicTraceLinesSolver",
|
|
2518
2204
|
SchematicTraceLinesSolver,
|
|
@@ -2522,7 +2208,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
2522
2208
|
dcConnMap: this.mspConnectionPairSolver.dcConnMap,
|
|
2523
2209
|
globalConnMap: this.mspConnectionPairSolver.globalConnMap,
|
|
2524
2210
|
inputProblem: this.inputProblem,
|
|
2525
|
-
guidelines: this.guidelinesSolver
|
|
2211
|
+
// guidelines: this.guidelinesSolver!.guidelines,
|
|
2526
2212
|
chipMap: this.mspConnectionPairSolver.chipMap
|
|
2527
2213
|
}
|
|
2528
2214
|
],
|
|
@@ -2669,5 +2355,6 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
2669
2355
|
}
|
|
2670
2356
|
};
|
|
2671
2357
|
export {
|
|
2672
|
-
SchematicTracePipelineSolver
|
|
2358
|
+
SchematicTracePipelineSolver,
|
|
2359
|
+
SchematicTraceSingleLineSolver2
|
|
2673
2360
|
};
|