@tscircuit/schematic-trace-solver 0.0.32 → 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/dist/index.d.ts +24 -53
- package/dist/index.js +492 -831
- 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 +3 -10
- 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/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 +1 -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,460 +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
|
-
maxVariants = 1e4
|
|
612
|
-
}) => {
|
|
613
|
-
const elbow = preprocessElbow(baseElbow);
|
|
614
|
-
assertOrthogonalPolyline(elbow);
|
|
615
|
-
const nPts = elbow.length;
|
|
616
|
-
if (nPts < 4) {
|
|
617
|
-
return {
|
|
618
|
-
elbowVariants: [elbow.map((p) => ({ ...p }))],
|
|
619
|
-
movableSegments: []
|
|
620
|
-
};
|
|
621
|
-
} else if (nPts === 4) {
|
|
622
|
-
const needsUTurn = checkIfUTurnNeeded(elbow);
|
|
623
|
-
if (needsUTurn) {
|
|
624
|
-
const expandedElbow = expandToUTurn(elbow);
|
|
625
|
-
return generateElbowVariants({ baseElbow: expandedElbow, guidelines });
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
const firstMovableIndex = 1;
|
|
629
|
-
const lastMovableIndex = nPts - 3;
|
|
630
|
-
const movableSegments = [];
|
|
631
|
-
const movableIdx = [];
|
|
632
|
-
const axes = [];
|
|
633
|
-
const optionsPerSegment = [];
|
|
634
|
-
for (let i = firstMovableIndex; i <= lastMovableIndex; i++) {
|
|
635
|
-
const prev = elbow[i - 1];
|
|
636
|
-
const start = elbow[i];
|
|
637
|
-
const end = elbow[i + 1];
|
|
638
|
-
const next2 = elbow[i + 2];
|
|
639
|
-
const { axis, facing } = computeFreedom(prev, start, end);
|
|
640
|
-
movableSegments.push({
|
|
641
|
-
start: { ...start },
|
|
642
|
-
end: { ...end },
|
|
643
|
-
freedom: facing,
|
|
644
|
-
dir: dir(facing)
|
|
645
|
-
});
|
|
646
|
-
movableIdx.push(i);
|
|
647
|
-
axes.push(axis);
|
|
648
|
-
const currentCoord = axis === "x" ? start.x : start.y;
|
|
649
|
-
const rawCandidates = collectAxisCandidates(axis, guidelines, currentCoord);
|
|
650
|
-
const filtered = rawCandidates.filter((pos) => {
|
|
651
|
-
if (axis === "y") {
|
|
652
|
-
const lenPrev = Math.abs(prev.y - pos);
|
|
653
|
-
const lenNext = Math.abs(next2.y - pos);
|
|
654
|
-
return lenPrev > MIN_LEN && lenNext > MIN_LEN;
|
|
655
|
-
} else {
|
|
656
|
-
const lenPrev = Math.abs(prev.x - pos);
|
|
657
|
-
const lenNext = Math.abs(next2.x - pos);
|
|
658
|
-
return lenPrev > MIN_LEN && lenNext > MIN_LEN;
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
optionsPerSegment.push(filtered);
|
|
662
|
-
}
|
|
663
|
-
const combos = cartesian(optionsPerSegment);
|
|
664
|
-
const seen = /* @__PURE__ */ new Set();
|
|
665
|
-
const elbowVariants = [];
|
|
666
|
-
{
|
|
667
|
-
const key = keyForPolyline(elbow);
|
|
668
|
-
seen.add(key);
|
|
669
|
-
elbowVariants.push(elbow.map((p) => ({ ...p })));
|
|
670
|
-
}
|
|
671
|
-
for (const combo of combos) {
|
|
672
|
-
if (combo.length === 0) continue;
|
|
673
|
-
const variant = elbow.map((p) => ({ ...p }));
|
|
674
|
-
for (let k = 0; k < movableIdx.length; k++) {
|
|
675
|
-
const segIndex = movableIdx[k];
|
|
676
|
-
const axis = axes[k];
|
|
677
|
-
const newPos = combo[k];
|
|
678
|
-
if (typeof newPos !== "number" || Number.isNaN(newPos)) continue;
|
|
679
|
-
if (axis === "y") {
|
|
680
|
-
variant[segIndex] = { ...variant[segIndex], y: newPos };
|
|
681
|
-
variant[segIndex + 1] = { ...variant[segIndex + 1], y: newPos };
|
|
682
|
-
} else {
|
|
683
|
-
variant[segIndex] = { ...variant[segIndex], x: newPos };
|
|
684
|
-
variant[segIndex + 1] = { ...variant[segIndex + 1], x: newPos };
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
try {
|
|
688
|
-
assertOrthogonalPolyline(variant);
|
|
689
|
-
} catch {
|
|
690
|
-
continue;
|
|
610
|
+
if (p.y < r.minY - eps) {
|
|
611
|
+
return [(p.y + r.minY) / 2];
|
|
691
612
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
seen.add(key);
|
|
695
|
-
elbowVariants.push(variant);
|
|
696
|
-
if (elbowVariants.length >= maxVariants) {
|
|
697
|
-
break;
|
|
698
|
-
}
|
|
613
|
+
if (p.y > r.maxY + eps) {
|
|
614
|
+
return [(p.y + r.maxY) / 2];
|
|
699
615
|
}
|
|
616
|
+
return [r.minY - 0.2, r.maxY + 0.2];
|
|
700
617
|
}
|
|
701
|
-
return { elbowVariants, movableSegments };
|
|
702
618
|
};
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
for (const guideline of guidelines) {
|
|
718
|
-
if (guideline.orientation === "horizontal") {
|
|
719
|
-
graphics.lines.push({
|
|
720
|
-
points: [
|
|
721
|
-
{ x: globalBounds.minX, y: guideline.y },
|
|
722
|
-
{ x: globalBounds.maxX, y: guideline.y }
|
|
723
|
-
],
|
|
724
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
725
|
-
strokeDash: "2 2"
|
|
726
|
-
});
|
|
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);
|
|
727
633
|
}
|
|
728
|
-
if (
|
|
729
|
-
|
|
730
|
-
points: [
|
|
731
|
-
{ x: guideline.x, y: globalBounds.minY },
|
|
732
|
-
{ x: guideline.x, y: globalBounds.maxY }
|
|
733
|
-
],
|
|
734
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
735
|
-
strokeDash: "2 2"
|
|
736
|
-
});
|
|
634
|
+
if (rightNeighbor !== void 0) {
|
|
635
|
+
out.push((colliding.maxX + rightNeighbor) / 2);
|
|
737
636
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
const
|
|
747
|
-
const
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
const cur = queue.shift();
|
|
752
|
-
for (const dc of directConns) {
|
|
753
|
-
if (dc.pinIds.includes(cur)) {
|
|
754
|
-
for (const p of dc.pinIds) {
|
|
755
|
-
if (!visited.has(p)) {
|
|
756
|
-
visited.add(p);
|
|
757
|
-
queue.push(p);
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
}
|
|
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);
|
|
762
650
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
const p0 = pins[0].pinId;
|
|
766
|
-
const p1 = pins[1].pinId;
|
|
767
|
-
const relatedPinIds = /* @__PURE__ */ new Set([
|
|
768
|
-
...findAllDirectlyConnectedPins(p0),
|
|
769
|
-
...findAllDirectlyConnectedPins(p1)
|
|
770
|
-
]);
|
|
771
|
-
const restrictedCenterLines = /* @__PURE__ */ new Map();
|
|
772
|
-
const chipFacingMap = /* @__PURE__ */ new Map();
|
|
773
|
-
const chipsOfFacingPins = new Set(pins.map((p) => p.chipId));
|
|
774
|
-
for (const pinId of relatedPinIds) {
|
|
775
|
-
const pin = pinIdMap.get(pinId);
|
|
776
|
-
if (!pin) continue;
|
|
777
|
-
const chip = chipMap[pin.chipId];
|
|
778
|
-
if (!chip) continue;
|
|
779
|
-
const facing = pin._facingDirection ?? getPinDirection(pin, chip);
|
|
780
|
-
let entry = chipFacingMap.get(chip.chipId);
|
|
781
|
-
if (!entry) {
|
|
782
|
-
entry = { center: chip.center };
|
|
783
|
-
const counts = { xPos: 0, xNeg: 0, yPos: 0, yNeg: 0 };
|
|
784
|
-
for (const cp of chip.pins) {
|
|
785
|
-
const cpFacing = cp._facingDirection ?? getPinDirection(cp, chip);
|
|
786
|
-
if (cpFacing === "x+") counts.xPos++;
|
|
787
|
-
if (cpFacing === "x-") counts.xNeg++;
|
|
788
|
-
if (cpFacing === "y+") counts.yPos++;
|
|
789
|
-
if (cpFacing === "y-") counts.yNeg++;
|
|
790
|
-
}
|
|
791
|
-
entry.counts = counts;
|
|
792
|
-
chipFacingMap.set(chip.chipId, entry);
|
|
651
|
+
if (topNeighbor !== void 0) {
|
|
652
|
+
out.push((colliding.maxY + topNeighbor) / 2);
|
|
793
653
|
}
|
|
794
|
-
|
|
795
|
-
if (facing === "x-") entry.hasXNeg = true;
|
|
796
|
-
if (facing === "y+") entry.hasYPos = true;
|
|
797
|
-
if (facing === "y-") entry.hasYNeg = true;
|
|
654
|
+
return out;
|
|
798
655
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
}
|
|
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;
|
|
818
697
|
}
|
|
819
|
-
return
|
|
698
|
+
return out;
|
|
820
699
|
};
|
|
700
|
+
var pathKey = (pts, decimals = 6) => pts.map((p) => `${p.x.toFixed(decimals)},${p.y.toFixed(decimals)}`).join("|");
|
|
821
701
|
|
|
822
|
-
// lib/solvers/SchematicTraceLinesSolver/
|
|
823
|
-
var
|
|
702
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts
|
|
703
|
+
var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
824
704
|
pins;
|
|
825
705
|
inputProblem;
|
|
826
|
-
guidelines;
|
|
827
706
|
chipMap;
|
|
828
|
-
|
|
707
|
+
obstacles;
|
|
708
|
+
rectById;
|
|
709
|
+
aabb;
|
|
829
710
|
baseElbow;
|
|
830
|
-
allCandidatePaths;
|
|
831
|
-
queuedCandidatePaths;
|
|
832
|
-
chipObstacleSpatialIndex;
|
|
833
711
|
solvedTracePath = null;
|
|
834
|
-
|
|
835
|
-
|
|
712
|
+
queue = [];
|
|
713
|
+
visited = /* @__PURE__ */ new Set();
|
|
836
714
|
constructor(params) {
|
|
837
715
|
super();
|
|
838
716
|
this.pins = params.pins;
|
|
839
717
|
this.inputProblem = params.inputProblem;
|
|
840
|
-
this.guidelines = params.guidelines;
|
|
841
718
|
this.chipMap = params.chipMap;
|
|
842
|
-
this.chipObstacleSpatialIndex = this.inputProblem._chipObstacleSpatialIndex || new ChipObstacleSpatialIndex(this.inputProblem.chips);
|
|
843
|
-
if (!this.inputProblem._chipObstacleSpatialIndex) {
|
|
844
|
-
this.inputProblem._chipObstacleSpatialIndex = this.chipObstacleSpatialIndex;
|
|
845
|
-
}
|
|
846
|
-
for (const chip of this.inputProblem.chips) {
|
|
847
|
-
for (const pin of chip.pins) {
|
|
848
|
-
this.pinIdMap.set(pin.pinId, { ...pin, chipId: chip.chipId });
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
719
|
for (const pin of this.pins) {
|
|
852
720
|
if (!pin._facingDirection) {
|
|
853
721
|
const chip = this.chipMap[pin.chipId];
|
|
854
722
|
pin._facingDirection = getPinDirection(pin, chip);
|
|
855
723
|
}
|
|
856
724
|
}
|
|
725
|
+
this.obstacles = getObstacleRects(this.inputProblem);
|
|
726
|
+
this.rectById = new Map(this.obstacles.map((r) => [r.chipId, r]));
|
|
857
727
|
const [pin1, pin2] = this.pins;
|
|
858
728
|
this.baseElbow = calculateElbow(
|
|
859
729
|
{
|
|
@@ -866,204 +736,130 @@ var SchematicTraceSingleLineSolver = class extends BaseSolver {
|
|
|
866
736
|
y: pin2.y,
|
|
867
737
|
facingDirection: pin2._facingDirection
|
|
868
738
|
},
|
|
869
|
-
{
|
|
870
|
-
overshoot: 0.2
|
|
871
|
-
}
|
|
739
|
+
{ overshoot: 0.2 }
|
|
872
740
|
);
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
maxVariants: 1e3
|
|
877
|
-
});
|
|
878
|
-
this.movableSegments = movableSegments;
|
|
879
|
-
const getPathLength = (pts) => {
|
|
880
|
-
let len = 0;
|
|
881
|
-
for (let i = 0; i < pts.length - 1; i++) {
|
|
882
|
-
const dx = pts[i + 1].x - pts[i].x;
|
|
883
|
-
const dy = pts[i + 1].y - pts[i].y;
|
|
884
|
-
len += Math.sqrt(dx * dx + dy * dy);
|
|
885
|
-
}
|
|
886
|
-
return len;
|
|
887
|
-
};
|
|
888
|
-
this.allCandidatePaths = [this.baseElbow, ...elbowVariants];
|
|
889
|
-
this.queuedCandidatePaths = [...this.allCandidatePaths].sort(
|
|
890
|
-
(a, b) => getPathLength(a) - getPathLength(b)
|
|
741
|
+
this.aabb = aabbFromPoints(
|
|
742
|
+
{ x: pin1.x, y: pin1.y },
|
|
743
|
+
{ x: pin2.x, y: pin2.y }
|
|
891
744
|
);
|
|
745
|
+
this.queue.push({ path: this.baseElbow, collisionChipIds: /* @__PURE__ */ new Set() });
|
|
746
|
+
this.visited.add(pathKey(this.baseElbow));
|
|
892
747
|
}
|
|
893
748
|
getConstructorParams() {
|
|
894
749
|
return {
|
|
895
750
|
chipMap: this.chipMap,
|
|
896
751
|
pins: this.pins,
|
|
897
|
-
guidelines: this.guidelines,
|
|
898
752
|
inputProblem: this.inputProblem
|
|
899
753
|
};
|
|
900
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
|
+
}
|
|
901
767
|
_step() {
|
|
902
|
-
if (this.
|
|
768
|
+
if (this.solvedTracePath) {
|
|
769
|
+
this.solved = true;
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const state = this.queue.shift();
|
|
773
|
+
if (!state) {
|
|
903
774
|
this.failed = true;
|
|
904
|
-
this.error = "No
|
|
775
|
+
this.error = "No collision-free path found";
|
|
905
776
|
return;
|
|
906
777
|
}
|
|
907
|
-
const
|
|
908
|
-
const
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
}
|
|
914
|
-
let
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
for (const [, rcl] of restrictedCenterLines) {
|
|
921
|
-
if (rcl.axes.has("x") && typeof rcl.x === "number") {
|
|
922
|
-
if ((start.x - rcl.x) * (end.x - rcl.x) < -EPS2) {
|
|
923
|
-
pathIsValid = false;
|
|
924
|
-
break;
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
if (rcl.axes.has("y") && typeof rcl.y === "number") {
|
|
928
|
-
if ((start.y - rcl.y) * (end.y - rcl.y) < -EPS2) {
|
|
929
|
-
pathIsValid = false;
|
|
930
|
-
break;
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
if (!pathIsValid) break;
|
|
935
|
-
const isStartPin = this.pins.some(
|
|
936
|
-
(pin) => Math.abs(pin.x - start.x) < 1e-10 && Math.abs(pin.y - start.y) < 1e-10
|
|
937
|
-
);
|
|
938
|
-
const isEndPin = this.pins.some(
|
|
939
|
-
(pin) => Math.abs(pin.x - end.x) < 1e-10 && Math.abs(pin.y - end.y) < 1e-10
|
|
940
|
-
);
|
|
941
|
-
if (isStartPin) {
|
|
942
|
-
const startPin = this.pins.find(
|
|
943
|
-
(pin) => Math.abs(pin.x - start.x) < 1e-10 && Math.abs(pin.y - start.y) < 1e-10
|
|
944
|
-
);
|
|
945
|
-
if (startPin) {
|
|
946
|
-
const bounds = getInputChipBounds(this.chipMap[startPin.chipId]);
|
|
947
|
-
const dx = end.x - start.x;
|
|
948
|
-
const dy = end.y - start.y;
|
|
949
|
-
const EPS3 = 1e-9;
|
|
950
|
-
const onLeft = Math.abs(start.x - bounds.minX) < 1e-9;
|
|
951
|
-
const onRight = Math.abs(start.x - bounds.maxX) < 1e-9;
|
|
952
|
-
const onBottom = Math.abs(start.y - bounds.minY) < 1e-9;
|
|
953
|
-
const onTop = Math.abs(start.y - bounds.maxY) < 1e-9;
|
|
954
|
-
const entersInterior = onLeft && dx > EPS3 || onRight && dx < -EPS3 || onBottom && dy > EPS3 || onTop && dy < -EPS3;
|
|
955
|
-
if (entersInterior) {
|
|
956
|
-
pathIsValid = false;
|
|
957
|
-
break;
|
|
958
|
-
}
|
|
959
|
-
if (!excludeChipIds.includes(startPin.chipId)) {
|
|
960
|
-
excludeChipIds.push(startPin.chipId);
|
|
961
|
-
}
|
|
962
|
-
}
|
|
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;
|
|
963
791
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
);
|
|
969
|
-
if (endPin) {
|
|
970
|
-
const bounds = getInputChipBounds(this.chipMap[endPin.chipId]);
|
|
971
|
-
const dx = start.x - end.x;
|
|
972
|
-
const dy = start.y - end.y;
|
|
973
|
-
const EPS3 = 1e-9;
|
|
974
|
-
const onLeft = Math.abs(end.x - bounds.minX) < 1e-9;
|
|
975
|
-
const onRight = Math.abs(end.x - bounds.maxX) < 1e-9;
|
|
976
|
-
const onBottom = Math.abs(end.y - bounds.minY) < 1e-9;
|
|
977
|
-
const onTop = Math.abs(end.y - bounds.maxY) < 1e-9;
|
|
978
|
-
const entersInterior = onLeft && dx > EPS3 || onRight && dx < -EPS3 || onBottom && dy > EPS3 || onTop && dy < -EPS3;
|
|
979
|
-
if (entersInterior) {
|
|
980
|
-
pathIsValid = false;
|
|
981
|
-
break;
|
|
982
|
-
}
|
|
983
|
-
if (!excludeChipIds.includes(endPin.chipId)) {
|
|
984
|
-
excludeChipIds.push(endPin.chipId);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
792
|
+
segIndex = 1;
|
|
793
|
+
} else if (isLastSegment) {
|
|
794
|
+
if (path.length < 3) {
|
|
795
|
+
return;
|
|
987
796
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
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
|
|
993
820
|
);
|
|
994
|
-
|
|
995
|
-
pathIsValid = false;
|
|
996
|
-
break;
|
|
997
|
-
}
|
|
821
|
+
candidates.push(...mids);
|
|
998
822
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
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 });
|
|
1002
838
|
}
|
|
1003
839
|
}
|
|
1004
840
|
visualize() {
|
|
1005
|
-
const
|
|
841
|
+
const g = visualizeInputProblem(this.inputProblem, {
|
|
1006
842
|
chipAlpha: 0.1,
|
|
1007
843
|
connectionAlpha: 0.1
|
|
1008
844
|
});
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
const boundsHeight = bounds.maxY - bounds.minY;
|
|
1012
|
-
visualizeGuidelines({ guidelines: this.guidelines, graphics });
|
|
1013
|
-
for (const { start, end, dir: dir2 } of this.movableSegments) {
|
|
1014
|
-
const mid = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 };
|
|
1015
|
-
const dist = Math.sqrt((start.x - end.x) ** 2 + (start.y - end.y) ** 2);
|
|
1016
|
-
graphics.lines.push({
|
|
1017
|
-
points: [start, mid, end],
|
|
1018
|
-
strokeColor: "rgba(0,0,255,0.5)",
|
|
1019
|
-
strokeDash: "2 2"
|
|
1020
|
-
});
|
|
1021
|
-
graphics.lines.push({
|
|
1022
|
-
points: [
|
|
1023
|
-
mid,
|
|
1024
|
-
{ x: mid.x + dir2.x * dist * 0.1, y: mid.y + dir2.y * dist * 0.1 }
|
|
1025
|
-
],
|
|
1026
|
-
strokeColor: "rgba(0,0,255,0.5)",
|
|
1027
|
-
strokeDash: "2 2"
|
|
1028
|
-
});
|
|
1029
|
-
}
|
|
1030
|
-
if (!this.solvedTracePath) {
|
|
1031
|
-
if (this.queuedCandidatePaths.length > 0) {
|
|
1032
|
-
graphics.lines.push({
|
|
1033
|
-
points: this.queuedCandidatePaths[0],
|
|
1034
|
-
strokeColor: "orange"
|
|
1035
|
-
});
|
|
1036
|
-
}
|
|
1037
|
-
for (let i = 1; i < this.queuedCandidatePaths.length; i++) {
|
|
1038
|
-
const candidatePath = this.queuedCandidatePaths[i];
|
|
1039
|
-
const pi = i / this.queuedCandidatePaths.length;
|
|
1040
|
-
graphics.lines.push({
|
|
1041
|
-
points: candidatePath.map((p) => ({
|
|
1042
|
-
x: p.x + pi * boundsWidth * 5e-3,
|
|
1043
|
-
y: p.y + pi * boundsHeight * 5e-3
|
|
1044
|
-
})),
|
|
1045
|
-
strokeColor: getColorFromString(
|
|
1046
|
-
`${candidatePath.reduce((acc, p) => `${acc},${p.x},${p.y}`, "")}`,
|
|
1047
|
-
0.5
|
|
1048
|
-
),
|
|
1049
|
-
strokeDash: "8 8"
|
|
1050
|
-
});
|
|
1051
|
-
}
|
|
845
|
+
for (const { path, collisionChipIds: collisionRectIds } of this.queue) {
|
|
846
|
+
g.lines.push({ points: path, strokeColor: "teal", strokeDash: "2 2" });
|
|
1052
847
|
}
|
|
1053
848
|
if (this.solvedTracePath) {
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
});
|
|
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" });
|
|
1058
852
|
}
|
|
1059
|
-
return
|
|
853
|
+
return g;
|
|
1060
854
|
}
|
|
1061
855
|
};
|
|
1062
856
|
|
|
857
|
+
// lib/solvers/GuidelinesSolver/visualizeGuidelines.ts
|
|
858
|
+
import { getBounds } from "graphics-debug";
|
|
859
|
+
|
|
1063
860
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts
|
|
1064
861
|
var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
1065
862
|
inputProblem;
|
|
1066
|
-
guidelines;
|
|
1067
863
|
mspConnectionPairs;
|
|
1068
864
|
dcConnMap;
|
|
1069
865
|
globalConnMap;
|
|
@@ -1078,7 +874,6 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1078
874
|
this.mspConnectionPairs = params.mspConnectionPairs;
|
|
1079
875
|
this.dcConnMap = params.dcConnMap;
|
|
1080
876
|
this.globalConnMap = params.globalConnMap;
|
|
1081
|
-
this.guidelines = params.guidelines;
|
|
1082
877
|
this.chipMap = params.chipMap;
|
|
1083
878
|
this.queuedConnectionPairs = [...this.mspConnectionPairs];
|
|
1084
879
|
}
|
|
@@ -1088,8 +883,7 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1088
883
|
chipMap: this.chipMap,
|
|
1089
884
|
mspConnectionPairs: this.mspConnectionPairs,
|
|
1090
885
|
dcConnMap: this.dcConnMap,
|
|
1091
|
-
globalConnMap: this.globalConnMap
|
|
1092
|
-
guidelines: this.guidelines
|
|
886
|
+
globalConnMap: this.globalConnMap
|
|
1093
887
|
};
|
|
1094
888
|
}
|
|
1095
889
|
_step() {
|
|
@@ -1127,11 +921,10 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1127
921
|
}
|
|
1128
922
|
this.currentConnectionPair = connectionPair;
|
|
1129
923
|
const { pins } = connectionPair;
|
|
1130
|
-
this.activeSubSolver = new
|
|
924
|
+
this.activeSubSolver = new SchematicTraceSingleLineSolver2({
|
|
1131
925
|
inputProblem: this.inputProblem,
|
|
1132
926
|
pins,
|
|
1133
|
-
chipMap: this.chipMap
|
|
1134
|
-
guidelines: this.guidelines
|
|
927
|
+
chipMap: this.chipMap
|
|
1135
928
|
});
|
|
1136
929
|
}
|
|
1137
930
|
visualize() {
|
|
@@ -1142,7 +935,6 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1142
935
|
chipAlpha: 0.1,
|
|
1143
936
|
connectionAlpha: 0.1
|
|
1144
937
|
});
|
|
1145
|
-
visualizeGuidelines({ guidelines: this.guidelines, graphics });
|
|
1146
938
|
for (const { mspPairId, tracePath } of this.solvedTracePaths) {
|
|
1147
939
|
graphics.lines.push({
|
|
1148
940
|
points: tracePath,
|
|
@@ -1169,17 +961,17 @@ var applyJogToTerminalSegment = ({
|
|
|
1169
961
|
segmentIndex: si,
|
|
1170
962
|
offset,
|
|
1171
963
|
JOG_SIZE,
|
|
1172
|
-
EPS:
|
|
964
|
+
EPS: EPS4 = 1e-6
|
|
1173
965
|
}) => {
|
|
1174
966
|
if (si !== 0 && si !== pts.length - 2) return;
|
|
1175
967
|
const start = pts[si];
|
|
1176
968
|
const end = pts[si + 1];
|
|
1177
|
-
const
|
|
1178
|
-
const
|
|
1179
|
-
if (!
|
|
1180
|
-
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;
|
|
1181
973
|
if (si === 0) {
|
|
1182
|
-
if (
|
|
974
|
+
if (isVertical2) {
|
|
1183
975
|
const jogY = start.y + segDir * JOG_SIZE;
|
|
1184
976
|
pts.splice(
|
|
1185
977
|
1,
|
|
@@ -1199,7 +991,7 @@ var applyJogToTerminalSegment = ({
|
|
|
1199
991
|
);
|
|
1200
992
|
}
|
|
1201
993
|
} else {
|
|
1202
|
-
if (
|
|
994
|
+
if (isVertical2) {
|
|
1203
995
|
const jogY = end.y - segDir * JOG_SIZE;
|
|
1204
996
|
pts.splice(
|
|
1205
997
|
si,
|
|
@@ -1242,13 +1034,13 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1242
1034
|
}
|
|
1243
1035
|
}
|
|
1244
1036
|
_step() {
|
|
1245
|
-
const
|
|
1037
|
+
const EPS4 = 1e-6;
|
|
1246
1038
|
const offsets = this.overlappingTraceSegments.map((_, idx) => {
|
|
1247
1039
|
const n = Math.floor(idx / 2) + 1;
|
|
1248
1040
|
const signed = idx % 2 === 0 ? -n : n;
|
|
1249
1041
|
return signed * this.SHIFT_DISTANCE;
|
|
1250
1042
|
});
|
|
1251
|
-
const eq = (a, b) => Math.abs(a - b) <
|
|
1043
|
+
const eq = (a, b) => Math.abs(a - b) < EPS4;
|
|
1252
1044
|
const samePoint = (p, q) => !!p && !!q && eq(p.x, q.x) && eq(p.y, q.y);
|
|
1253
1045
|
this.overlappingTraceSegments.forEach((group, gidx) => {
|
|
1254
1046
|
const offset = offsets[gidx];
|
|
@@ -1274,15 +1066,15 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1274
1066
|
segmentIndex: si,
|
|
1275
1067
|
offset,
|
|
1276
1068
|
JOG_SIZE,
|
|
1277
|
-
EPS:
|
|
1069
|
+
EPS: EPS4
|
|
1278
1070
|
});
|
|
1279
1071
|
} else {
|
|
1280
1072
|
const start = pts[si];
|
|
1281
1073
|
const end = pts[si + 1];
|
|
1282
|
-
const
|
|
1283
|
-
const
|
|
1284
|
-
if (!
|
|
1285
|
-
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) {
|
|
1286
1078
|
start.x += offset;
|
|
1287
1079
|
end.x += offset;
|
|
1288
1080
|
} else {
|
|
@@ -1376,7 +1168,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1376
1168
|
return islands;
|
|
1377
1169
|
}
|
|
1378
1170
|
findNextOverlapIssue() {
|
|
1379
|
-
const
|
|
1171
|
+
const EPS4 = 2e-3;
|
|
1380
1172
|
const netIds = Object.keys(this.traceNetIslands);
|
|
1381
1173
|
for (let i = 0; i < netIds.length; i++) {
|
|
1382
1174
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -1394,7 +1186,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1394
1186
|
const minB = Math.min(b1, b2);
|
|
1395
1187
|
const maxB = Math.max(b1, b2);
|
|
1396
1188
|
const overlap = Math.min(maxA, maxB) - Math.max(minA, minB);
|
|
1397
|
-
return overlap >
|
|
1189
|
+
return overlap > EPS4;
|
|
1398
1190
|
};
|
|
1399
1191
|
for (let pa = 0; pa < pathsA.length; pa++) {
|
|
1400
1192
|
const pathA = pathsA[pa];
|
|
@@ -1402,8 +1194,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1402
1194
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
1403
1195
|
const a1 = ptsA[sa];
|
|
1404
1196
|
const a2 = ptsA[sa + 1];
|
|
1405
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
1406
|
-
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;
|
|
1407
1199
|
if (!aVert && !aHorz) continue;
|
|
1408
1200
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
1409
1201
|
const pathB = pathsB[pb];
|
|
@@ -1411,11 +1203,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1411
1203
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
1412
1204
|
const b1 = ptsB[sb];
|
|
1413
1205
|
const b2 = ptsB[sb + 1];
|
|
1414
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
1415
|
-
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;
|
|
1416
1208
|
if (!bVert && !bHorz) continue;
|
|
1417
1209
|
if (aVert && bVert) {
|
|
1418
|
-
if (Math.abs(a1.x - b1.x) <
|
|
1210
|
+
if (Math.abs(a1.x - b1.x) < EPS4) {
|
|
1419
1211
|
if (overlaps1D(a1.y, a2.y, b1.y, b2.y)) {
|
|
1420
1212
|
const keyA = `${pa}:${sa}`;
|
|
1421
1213
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1436,7 +1228,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1436
1228
|
}
|
|
1437
1229
|
}
|
|
1438
1230
|
} else if (aHorz && bHorz) {
|
|
1439
|
-
if (Math.abs(a1.y - b1.y) <
|
|
1231
|
+
if (Math.abs(a1.y - b1.y) < EPS4) {
|
|
1440
1232
|
if (overlaps1D(a1.x, a2.x, b1.x, b2.x)) {
|
|
1441
1233
|
const keyA = `${pa}:${sa}`;
|
|
1442
1234
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1513,6 +1305,55 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1513
1305
|
}
|
|
1514
1306
|
};
|
|
1515
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
|
+
|
|
1516
1357
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry.ts
|
|
1517
1358
|
var NET_LABEL_HORIZONTAL_WIDTH = 0.45;
|
|
1518
1359
|
var NET_LABEL_HORIZONTAL_HEIGHT = 0.2;
|
|
@@ -1550,24 +1391,24 @@ function getRectBounds(center, w, h) {
|
|
|
1550
1391
|
}
|
|
1551
1392
|
|
|
1552
1393
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
|
|
1553
|
-
function
|
|
1554
|
-
const isVert = Math.abs(p1.x - p2.x) <
|
|
1555
|
-
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;
|
|
1556
1397
|
if (!isVert && !isHorz) return false;
|
|
1557
1398
|
if (isVert) {
|
|
1558
1399
|
const x = p1.x;
|
|
1559
|
-
if (x < rect.minX -
|
|
1400
|
+
if (x < rect.minX - EPS4 || x > rect.maxX + EPS4) return false;
|
|
1560
1401
|
const segMinY = Math.min(p1.y, p2.y);
|
|
1561
1402
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
1562
1403
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
1563
|
-
return overlap >
|
|
1404
|
+
return overlap > EPS4;
|
|
1564
1405
|
} else {
|
|
1565
1406
|
const y = p1.y;
|
|
1566
|
-
if (y < rect.minY -
|
|
1407
|
+
if (y < rect.minY - EPS4 || y > rect.maxY + EPS4) return false;
|
|
1567
1408
|
const segMinX = Math.min(p1.x, p2.x);
|
|
1568
1409
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
1569
1410
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
1570
|
-
return overlap >
|
|
1411
|
+
return overlap > EPS4;
|
|
1571
1412
|
}
|
|
1572
1413
|
}
|
|
1573
1414
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -1575,7 +1416,7 @@ function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex)
|
|
|
1575
1416
|
const pts = solved.tracePath;
|
|
1576
1417
|
for (let i = 0; i < pts.length - 1; i++) {
|
|
1577
1418
|
if (pairId === hostPathId && i === hostSegIndex) continue;
|
|
1578
|
-
if (
|
|
1419
|
+
if (segmentIntersectsRect2(pts[i], pts[i + 1], bounds))
|
|
1579
1420
|
return { hasIntersection: true, mspPairId: pairId, segIndex: i };
|
|
1580
1421
|
}
|
|
1581
1422
|
}
|
|
@@ -1924,14 +1765,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1924
1765
|
};
|
|
1925
1766
|
let bestCandidate = null;
|
|
1926
1767
|
let bestScore = -Infinity;
|
|
1927
|
-
const
|
|
1768
|
+
const EPS4 = 1e-6;
|
|
1928
1769
|
for (const curr of tracesToScan) {
|
|
1929
1770
|
const pts = curr.tracePath.slice();
|
|
1930
1771
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
1931
1772
|
const a = pts[si];
|
|
1932
1773
|
const b = pts[si + 1];
|
|
1933
|
-
const isH = Math.abs(a.y - b.y) <
|
|
1934
|
-
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;
|
|
1935
1776
|
if (!isH && !isV) continue;
|
|
1936
1777
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
1937
1778
|
const candidateOrients = orientations.filter(
|
|
@@ -2263,187 +2104,7 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2263
2104
|
};
|
|
2264
2105
|
|
|
2265
2106
|
// lib/solvers/GuidelinesSolver/GuidelinesSolver.ts
|
|
2266
|
-
import { getBounds as
|
|
2267
|
-
|
|
2268
|
-
// lib/solvers/GuidelinesSolver/getGeneratorForAllChipPairs.ts
|
|
2269
|
-
var getGeneratorForAllChipPairs = (chips) => {
|
|
2270
|
-
return (function* () {
|
|
2271
|
-
for (let i = 0; i < chips.length; i++) {
|
|
2272
|
-
for (let j = 0; j < chips.length; j++) {
|
|
2273
|
-
if (i !== j) {
|
|
2274
|
-
yield [chips[i], chips[j]];
|
|
2275
|
-
}
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
})();
|
|
2279
|
-
};
|
|
2280
|
-
|
|
2281
|
-
// lib/solvers/GuidelinesSolver/getHorizontalGuidelineY.ts
|
|
2282
|
-
function getHorizontalGuidelineY(chip1Bounds, chip2Bounds) {
|
|
2283
|
-
if (chip1Bounds.maxY <= chip2Bounds.minY) {
|
|
2284
|
-
return (chip1Bounds.maxY + chip2Bounds.minY) / 2;
|
|
2285
|
-
}
|
|
2286
|
-
if (chip2Bounds.maxY <= chip1Bounds.minY) {
|
|
2287
|
-
return (chip2Bounds.maxY + chip1Bounds.minY) / 2;
|
|
2288
|
-
}
|
|
2289
|
-
const overlapMinY = Math.max(chip1Bounds.minY, chip2Bounds.minY);
|
|
2290
|
-
const overlapMaxY = Math.min(chip1Bounds.maxY, chip2Bounds.maxY);
|
|
2291
|
-
return (overlapMinY + overlapMaxY) / 2;
|
|
2292
|
-
}
|
|
2293
|
-
|
|
2294
|
-
// lib/solvers/GuidelinesSolver/getVerticalGuidelineX.ts
|
|
2295
|
-
function getVerticalGuidelineX(chip1Bounds, chip2Bounds) {
|
|
2296
|
-
if (chip1Bounds.maxX <= chip2Bounds.minX) {
|
|
2297
|
-
return (chip1Bounds.maxX + chip2Bounds.minX) / 2;
|
|
2298
|
-
}
|
|
2299
|
-
if (chip2Bounds.maxX <= chip1Bounds.minX) {
|
|
2300
|
-
return (chip2Bounds.maxX + chip1Bounds.minX) / 2;
|
|
2301
|
-
}
|
|
2302
|
-
const overlapMinX = Math.max(chip1Bounds.minX, chip2Bounds.minX);
|
|
2303
|
-
const overlapMaxX = Math.min(chip1Bounds.maxX, chip2Bounds.maxX);
|
|
2304
|
-
return (overlapMinX + overlapMaxX) / 2;
|
|
2305
|
-
}
|
|
2306
|
-
|
|
2307
|
-
// lib/solvers/GuidelinesSolver/getInputProblemBounds.ts
|
|
2308
|
-
var getInputProblemBounds = (inputProblem) => {
|
|
2309
|
-
const bounds = {
|
|
2310
|
-
minX: Infinity,
|
|
2311
|
-
maxX: -Infinity,
|
|
2312
|
-
minY: Infinity,
|
|
2313
|
-
maxY: -Infinity
|
|
2314
|
-
};
|
|
2315
|
-
for (const chip of inputProblem.chips) {
|
|
2316
|
-
const chipBounds = getInputChipBounds(chip);
|
|
2317
|
-
bounds.minX = Math.min(bounds.minX, chipBounds.minX);
|
|
2318
|
-
bounds.maxX = Math.max(bounds.maxX, chipBounds.maxX);
|
|
2319
|
-
bounds.minY = Math.min(bounds.minY, chipBounds.minY);
|
|
2320
|
-
bounds.maxY = Math.max(bounds.maxY, chipBounds.maxY);
|
|
2321
|
-
}
|
|
2322
|
-
return bounds;
|
|
2323
|
-
};
|
|
2324
|
-
|
|
2325
|
-
// lib/solvers/GuidelinesSolver/GuidelinesSolver.ts
|
|
2326
|
-
var GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS = 0.1;
|
|
2327
|
-
var GuidelinesSolver = class extends BaseSolver {
|
|
2328
|
-
inputProblem;
|
|
2329
|
-
guidelines;
|
|
2330
|
-
chipPairsGenerator;
|
|
2331
|
-
usedXGuidelines;
|
|
2332
|
-
usedYGuidelines;
|
|
2333
|
-
constructor(params) {
|
|
2334
|
-
super();
|
|
2335
|
-
this.inputProblem = params.inputProblem;
|
|
2336
|
-
const inputProblemBounds = getInputProblemBounds(this.inputProblem);
|
|
2337
|
-
this.guidelines = [
|
|
2338
|
-
{
|
|
2339
|
-
orientation: "horizontal",
|
|
2340
|
-
y: inputProblemBounds.minY - GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS,
|
|
2341
|
-
x: void 0
|
|
2342
|
-
},
|
|
2343
|
-
{
|
|
2344
|
-
orientation: "horizontal",
|
|
2345
|
-
y: inputProblemBounds.maxY + GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS,
|
|
2346
|
-
x: void 0
|
|
2347
|
-
},
|
|
2348
|
-
{
|
|
2349
|
-
orientation: "vertical",
|
|
2350
|
-
y: void 0,
|
|
2351
|
-
x: inputProblemBounds.minX - GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS
|
|
2352
|
-
},
|
|
2353
|
-
{
|
|
2354
|
-
orientation: "vertical",
|
|
2355
|
-
y: void 0,
|
|
2356
|
-
x: inputProblemBounds.maxX + GUIDELINE_PADDING_FROM_PROBLEM_BOUNDS
|
|
2357
|
-
}
|
|
2358
|
-
];
|
|
2359
|
-
this.chipPairsGenerator = getGeneratorForAllChipPairs(
|
|
2360
|
-
this.inputProblem.chips
|
|
2361
|
-
);
|
|
2362
|
-
this.usedXGuidelines = /* @__PURE__ */ new Set();
|
|
2363
|
-
this.usedYGuidelines = /* @__PURE__ */ new Set();
|
|
2364
|
-
}
|
|
2365
|
-
getConstructorParams() {
|
|
2366
|
-
return {
|
|
2367
|
-
inputProblem: this.inputProblem
|
|
2368
|
-
};
|
|
2369
|
-
}
|
|
2370
|
-
_step() {
|
|
2371
|
-
const { done, value: chipPair } = this.chipPairsGenerator.next();
|
|
2372
|
-
if (done) {
|
|
2373
|
-
this.solved = true;
|
|
2374
|
-
return;
|
|
2375
|
-
}
|
|
2376
|
-
const [chip1, chip2] = chipPair;
|
|
2377
|
-
const chip1Bounds = getInputChipBounds(chip1);
|
|
2378
|
-
const chip2Bounds = getInputChipBounds(chip2);
|
|
2379
|
-
const horizontalGuidelineY = getHorizontalGuidelineY(
|
|
2380
|
-
chip1Bounds,
|
|
2381
|
-
chip2Bounds
|
|
2382
|
-
);
|
|
2383
|
-
const verticalGuidelineX = getVerticalGuidelineX(chip1Bounds, chip2Bounds);
|
|
2384
|
-
if (!this.usedYGuidelines.has(horizontalGuidelineY)) {
|
|
2385
|
-
this.usedYGuidelines.add(horizontalGuidelineY);
|
|
2386
|
-
this.guidelines.push({
|
|
2387
|
-
orientation: "horizontal",
|
|
2388
|
-
y: horizontalGuidelineY,
|
|
2389
|
-
x: void 0
|
|
2390
|
-
});
|
|
2391
|
-
}
|
|
2392
|
-
if (!this.usedXGuidelines.has(verticalGuidelineX)) {
|
|
2393
|
-
this.usedXGuidelines.add(verticalGuidelineX);
|
|
2394
|
-
this.guidelines.push({
|
|
2395
|
-
orientation: "vertical",
|
|
2396
|
-
y: void 0,
|
|
2397
|
-
x: verticalGuidelineX
|
|
2398
|
-
});
|
|
2399
|
-
}
|
|
2400
|
-
}
|
|
2401
|
-
visualize() {
|
|
2402
|
-
const graphics = visualizeInputProblem(this.inputProblem);
|
|
2403
|
-
const bounds = getBounds4(graphics);
|
|
2404
|
-
const boundsWidth = bounds.maxX - bounds.minX;
|
|
2405
|
-
const boundsHeight = bounds.maxY - bounds.minY;
|
|
2406
|
-
bounds.minX -= boundsWidth * 0.3;
|
|
2407
|
-
bounds.maxX += boundsWidth * 0.3;
|
|
2408
|
-
bounds.minY -= boundsHeight * 0.3;
|
|
2409
|
-
bounds.maxY += boundsHeight * 0.3;
|
|
2410
|
-
for (const guideline of this.guidelines) {
|
|
2411
|
-
if (guideline.orientation === "horizontal") {
|
|
2412
|
-
graphics.lines.push({
|
|
2413
|
-
points: [
|
|
2414
|
-
{
|
|
2415
|
-
x: bounds.minX,
|
|
2416
|
-
y: guideline.y
|
|
2417
|
-
},
|
|
2418
|
-
{
|
|
2419
|
-
x: bounds.maxX,
|
|
2420
|
-
y: guideline.y
|
|
2421
|
-
}
|
|
2422
|
-
],
|
|
2423
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
2424
|
-
strokeDash: "2 2"
|
|
2425
|
-
});
|
|
2426
|
-
}
|
|
2427
|
-
if (guideline.orientation === "vertical") {
|
|
2428
|
-
graphics.lines.push({
|
|
2429
|
-
points: [
|
|
2430
|
-
{
|
|
2431
|
-
x: guideline.x,
|
|
2432
|
-
y: bounds.minY
|
|
2433
|
-
},
|
|
2434
|
-
{
|
|
2435
|
-
x: guideline.x,
|
|
2436
|
-
y: bounds.maxY
|
|
2437
|
-
}
|
|
2438
|
-
],
|
|
2439
|
-
strokeColor: "rgba(0, 0, 0, 0.5)",
|
|
2440
|
-
strokeDash: "2 2"
|
|
2441
|
-
});
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
return graphics;
|
|
2445
|
-
}
|
|
2446
|
-
};
|
|
2107
|
+
import { getBounds as getBounds3 } from "graphics-debug";
|
|
2447
2108
|
|
|
2448
2109
|
// lib/solvers/SchematicTracePipelineSolver/correctPinsInsideChip.ts
|
|
2449
2110
|
var correctPinsInsideChips = (problem) => {
|
|
@@ -2507,7 +2168,7 @@ function definePipelineStep(solverName, solverClass, getConstructorParams, opts
|
|
|
2507
2168
|
}
|
|
2508
2169
|
var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
2509
2170
|
mspConnectionPairSolver;
|
|
2510
|
-
guidelinesSolver
|
|
2171
|
+
// guidelinesSolver?: GuidelinesSolver
|
|
2511
2172
|
schematicTraceLinesSolver;
|
|
2512
2173
|
traceOverlapShiftSolver;
|
|
2513
2174
|
netLabelPlacementSolver;
|
|
@@ -2526,19 +2187,18 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
2526
2187
|
}
|
|
2527
2188
|
}
|
|
2528
2189
|
),
|
|
2529
|
-
definePipelineStep(
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
),
|
|
2190
|
+
// definePipelineStep(
|
|
2191
|
+
// "guidelinesSolver",
|
|
2192
|
+
// GuidelinesSolver,
|
|
2193
|
+
// () => [
|
|
2194
|
+
// {
|
|
2195
|
+
// inputProblem: this.inputProblem,
|
|
2196
|
+
// },
|
|
2197
|
+
// ],
|
|
2198
|
+
// {
|
|
2199
|
+
// onSolved: (guidelinesSolver) => {},
|
|
2200
|
+
// },
|
|
2201
|
+
// ),
|
|
2542
2202
|
definePipelineStep(
|
|
2543
2203
|
"schematicTraceLinesSolver",
|
|
2544
2204
|
SchematicTraceLinesSolver,
|
|
@@ -2548,7 +2208,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
2548
2208
|
dcConnMap: this.mspConnectionPairSolver.dcConnMap,
|
|
2549
2209
|
globalConnMap: this.mspConnectionPairSolver.globalConnMap,
|
|
2550
2210
|
inputProblem: this.inputProblem,
|
|
2551
|
-
guidelines: this.guidelinesSolver
|
|
2211
|
+
// guidelines: this.guidelinesSolver!.guidelines,
|
|
2552
2212
|
chipMap: this.mspConnectionPairSolver.chipMap
|
|
2553
2213
|
}
|
|
2554
2214
|
],
|
|
@@ -2695,5 +2355,6 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
2695
2355
|
}
|
|
2696
2356
|
};
|
|
2697
2357
|
export {
|
|
2698
|
-
SchematicTracePipelineSolver
|
|
2358
|
+
SchematicTracePipelineSolver,
|
|
2359
|
+
SchematicTraceSingleLineSolver2
|
|
2699
2360
|
};
|