@tscircuit/schematic-trace-solver 0.0.100 → 0.0.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +6 -3
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +13 -2
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateEndpointCollisionDetours.ts +5 -2
- package/package.json +1 -1
- package/tests/examples/__snapshots__/example11.snap.svg +19 -23
- package/tests/repros/__snapshots__/repro47-endpoint-obstacle-detour.snap.svg +19 -23
- package/tests/repros/repro47-endpoint-obstacle-detour.test.ts +2 -2
- package/tests/solvers/SchematicTraceSingleLineSolver2/generate-endpoint-collision-detours.test.ts +37 -0
package/dist/index.js
CHANGED
|
@@ -894,7 +894,7 @@ var generateEndpointCollisionDetours = ({
|
|
|
894
894
|
collidingSegmentIndex,
|
|
895
895
|
obstacle
|
|
896
896
|
}) => {
|
|
897
|
-
if (path.length
|
|
897
|
+
if (path.length < 3 || path.length > 4) return [];
|
|
898
898
|
const lastSegmentIndex = path.length - 2;
|
|
899
899
|
if (collidingSegmentIndex !== 0 && collidingSegmentIndex !== lastSegmentIndex) {
|
|
900
900
|
return [];
|
|
@@ -917,7 +917,7 @@ var generateEndpointCollisionDetours = ({
|
|
|
917
917
|
const detours = [];
|
|
918
918
|
for (const escapeCoordinate of [...new Set(escapeCoordinates)]) {
|
|
919
919
|
for (const detourCoordinate of [...new Set(detourCoordinates)]) {
|
|
920
|
-
const
|
|
920
|
+
const orderedDetourPrefix = firstSegmentAxis === "y" ? [
|
|
921
921
|
start,
|
|
922
922
|
{ x: escapeCoordinate, y: start.y },
|
|
923
923
|
{ x: escapeCoordinate, y: detourCoordinate },
|
|
@@ -930,6 +930,7 @@ var generateEndpointCollisionDetours = ({
|
|
|
930
930
|
{ x: detourCoordinate, y: end.y },
|
|
931
931
|
end
|
|
932
932
|
];
|
|
933
|
+
const orderedDetour = [...orderedDetourPrefix, ...orderedPath.slice(3)];
|
|
933
934
|
const detour = shouldReverse ? orderedDetour.reverse() : orderedDetour;
|
|
934
935
|
if (hasOnlyNonzeroOrthogonalSegments(detour)) detours.push(detour);
|
|
935
936
|
}
|
|
@@ -1287,7 +1288,9 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1287
1288
|
let { segIndex, rect } = collision;
|
|
1288
1289
|
const isFirstSegment = segIndex === 0;
|
|
1289
1290
|
const isLastSegment = segIndex === path.length - 2;
|
|
1290
|
-
|
|
1291
|
+
const isEndpointChipObstacle = rect.kind === "chip" && this.pins.some((pin) => pin.chipId === rect.chipId);
|
|
1292
|
+
const canGenerateEndpointDetour = path.length === 3 || path.length === 4 && this.connectionPair !== void 0 && !isEndpointChipObstacle;
|
|
1293
|
+
if (canGenerateEndpointDetour && (isFirstSegment || isLastSegment)) {
|
|
1291
1294
|
const detours = generateEndpointCollisionDetours({
|
|
1292
1295
|
path,
|
|
1293
1296
|
collidingSegmentIndex: segIndex,
|
|
@@ -357,8 +357,19 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
357
357
|
// Never move the first or last segments - move adjacent segment instead
|
|
358
358
|
const isFirstSegment = segIndex === 0
|
|
359
359
|
const isLastSegment = segIndex === path.length - 2
|
|
360
|
-
|
|
361
|
-
|
|
360
|
+
const isEndpointChipObstacle =
|
|
361
|
+
rect.kind === "chip" &&
|
|
362
|
+
this.pins.some((pin) => pin.chipId === rect.chipId)
|
|
363
|
+
// U-shaped detours are local repairs for fixed MSP pairs obstructed by an
|
|
364
|
+
// intermediate obstacle. Endpoint-chip and optional long-distance routing
|
|
365
|
+
// require multi-trace or net-level selection instead.
|
|
366
|
+
const canGenerateEndpointDetour =
|
|
367
|
+
path.length === 3 ||
|
|
368
|
+
(path.length === 4 &&
|
|
369
|
+
this.connectionPair !== undefined &&
|
|
370
|
+
!isEndpointChipObstacle)
|
|
371
|
+
|
|
372
|
+
if (canGenerateEndpointDetour && (isFirstSegment || isLastSegment)) {
|
|
362
373
|
const detours = generateEndpointCollisionDetours({
|
|
363
374
|
path,
|
|
364
375
|
collidingSegmentIndex: segIndex,
|
|
@@ -28,7 +28,9 @@ export const generateEndpointCollisionDetours = ({
|
|
|
28
28
|
collidingSegmentIndex: number
|
|
29
29
|
obstacle: ObstacleRect
|
|
30
30
|
}): Point[][] => {
|
|
31
|
-
|
|
31
|
+
// Endpoint detours expand the initial L- and U-shaped elbow candidates.
|
|
32
|
+
// Longer paths have already been expanded and are handled by segment shifts.
|
|
33
|
+
if (path.length < 3 || path.length > 4) return []
|
|
32
34
|
|
|
33
35
|
const lastSegmentIndex = path.length - 2
|
|
34
36
|
if (
|
|
@@ -58,7 +60,7 @@ export const generateEndpointCollisionDetours = ({
|
|
|
58
60
|
const detours: Point[][] = []
|
|
59
61
|
for (const escapeCoordinate of [...new Set(escapeCoordinates)]) {
|
|
60
62
|
for (const detourCoordinate of [...new Set(detourCoordinates)]) {
|
|
61
|
-
const
|
|
63
|
+
const orderedDetourPrefix =
|
|
62
64
|
firstSegmentAxis === "y"
|
|
63
65
|
? [
|
|
64
66
|
start!,
|
|
@@ -75,6 +77,7 @@ export const generateEndpointCollisionDetours = ({
|
|
|
75
77
|
end!,
|
|
76
78
|
]
|
|
77
79
|
|
|
80
|
+
const orderedDetour = [...orderedDetourPrefix, ...orderedPath.slice(3)]
|
|
78
81
|
const detour = shouldReverse ? orderedDetour.reverse() : orderedDetour
|
|
79
82
|
if (hasOnlyNonzeroOrthogonalSegments(detour)) detours.push(detour)
|
|
80
83
|
}
|
package/package.json
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="0.48,0.765 -0.48,-0.765" data-type="line" data-label="" points="
|
|
2
|
-
globalConnNetId: connectivity_net2" data-x="0.
|
|
3
|
-
globalConnNetId:
|
|
4
|
-
globalConnNetId:
|
|
5
|
-
globalConnNetId:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
x-" data-x="
|
|
9
|
-
x+" data-x="
|
|
10
|
-
x-" data-x="
|
|
11
|
-
x+" data-x="
|
|
12
|
-
x-" data-x="
|
|
13
|
-
|
|
14
|
-
x
|
|
15
|
-
y
|
|
16
|
-
|
|
17
|
-
orientation:
|
|
18
|
-
orientation:
|
|
19
|
-
orientation: x+" data-x="1.48" data-y="-0.665" cx="536.2544169611307" cy="427.0671378091873" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
20
|
-
orientation: x+" data-x="-0.48" data-y="0.765" cx="259.2226148409894" cy="224.94699646643113" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
21
|
-
orientation: y+" data-x="0.24" data-y="0.765" cx="360.9893992932862" cy="224.94699646643113" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
22
|
-
orientation: y+" data-x="1.7800000000000002" data-y="0.765" cx="578.6572438162544" cy="224.94699646643113" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5"/><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text></g><script><![CDATA[
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="0.48,0.765 -0.48,-0.765" data-type="line" data-label="" points="391.4893617021276,213.51063829787233 248.51063829787228,441.3829787234042" fill="none" stroke="hsl(224, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.58,0.765 -1.58,-0.765" data-type="line" data-label="" points="555.3191489361701,213.51063829787233 84.68085106382975,441.3829787234042" fill="none" stroke="hsl(224, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="0.5800000000000001,-0.665 -1.58,0.765" data-type="line" data-label="" points="406.3829787234042,426.48936170212767 84.68085106382975,213.51063829787233" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.48,-0.665 -0.48,0.765" data-type="line" data-label="" points="540.4255319148936,426.48936170212767 248.51063829787228,213.51063829787233" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="0.48,0.765 0.27999999999999997,0.765 0.27999999999999997,0.665 -0.1,0.665 -0.1,-0.765 -0.48,-0.765" data-type="line" data-label="" points="391.4893617021276,213.51063829787233 361.7021276595744,213.51063829787233 361.7021276595744,228.40425531914892 305.10638297872333,228.40425531914892 305.10638297872333,441.3829787234042 248.51063829787228,441.3829787234042" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.58,0.765 1.7800000000000002,0.765 1.7800000000000002,0 -1.8800000000000001,0 -1.8800000000000001,-0.765 -1.58,-0.765" data-type="line" data-label="" points="555.3191489361701,213.51063829787233 585.1063829787233,213.51063829787233 585.1063829787233,327.4468085106383 39.99999999999994,327.4468085106383 39.99999999999994,441.3829787234042 84.68085106382975,441.3829787234042" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0.5800000000000001,-0.665 0.050000000000000044,-0.665 0.050000000000000044,-0.37054465000000053 -1.68,-0.37054465000000053 -1.68,0.765 -1.58,0.765" data-type="line" data-label="" points="406.3829787234042,426.48936170212767 327.4468085106382,426.48936170212767 327.4468085106382,382.63430957446815 69.78723404255317,382.63430957446815 69.78723404255317,213.51063829787233 84.68085106382975,213.51063829787233" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.48,-0.665 1.68,-0.665 1.68,0.37054465000000053 0.1,0.37054465000000053 0.1,0.865 -0.38,0.865 -0.38,0.765 -0.48,0.765" data-type="line" data-label="" points="540.4255319148936,426.48936170212767 570.2127659574467,426.48936170212767 570.2127659574467,272.2593074468084 334.89361702127655,272.2593074468084 334.89361702127655,198.61702127659575 263.4042553191489,198.61702127659575 263.4042553191489,213.51063829787233 248.51063829787228,213.51063829787233" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="-1.03" data-y="0.765" x="84.68085106382976" y="184.54920319148943" width="163.82978723404253" height="57.922870212765815" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.006714285714285715"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="1.03" data-y="0.765" x="391.48936170212767" y="184.54920319148943" width="163.8297872340425" height="57.922870212765815" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.006714285714285715"/></g><g><rect data-type="rect" data-label="schematic_component_2" data-x="-1.03" data-y="-0.765" x="84.68085106382976" y="412.4215436170213" width="163.82978723404253" height="57.922870212765815" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.006714285714285715"/></g><g><rect data-type="rect" data-label="schematic_component_3" data-x="1.03" data-y="-0.765" x="406.3829787234042" y="401.9148936170212" width="134.04255319148933" height="78.936170212766" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.006714285714285715"/></g><g><rect data-type="rect" data-label="netId: .J1 > .pin1 to .R1 > .pin1
|
|
2
|
+
globalConnNetId: connectivity_net2" data-x="0.31500000000000006" data-y="-0.44000000000000006" x="352.0212765957446" y="359.468085106383" width="29.787234042553223" height="67.02127659574472" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.006714285714285715"/></g><g><rect data-type="rect" data-label="netId: .J1 > .pin3 to .R1 > .pin2
|
|
3
|
+
globalConnNetId: connectivity_net3" data-x="1.68" data-y="-0.89" x="555.31914893617" y="426.48936170212767" width="29.787234042553223" height="67.02127659574467" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.006714285714285715"/></g><g><rect data-type="rect" data-label="netId: .R2 > .pin1 to .R3 > .pin2
|
|
4
|
+
globalConnNetId: connectivity_net0" data-x="0.27999999999999997" data-y="0.99" x="346.8085106382978" y="146.48936170212767" width="29.787234042553166" height="67.0212765957447" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.006714285714285715"/></g><g><rect data-type="rect" data-label="netId: .R2 > .pin2 to .R3 > .pin1
|
|
5
|
+
globalConnNetId: connectivity_net1" data-x="1.7800000000000002" data-y="0.99" x="570.2127659574467" y="146.48936170212767" width="29.787234042553223" height="67.0212765957447" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.006714285714285715"/></g><g><circle data-type="point" data-label="R1.1
|
|
6
|
+
x-" data-x="-1.58" data-y="0.765" cx="84.68085106382975" cy="213.51063829787233" r="3" fill="hsl(226, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R1.2
|
|
7
|
+
x+" data-x="-0.48" data-y="0.765" cx="248.51063829787228" cy="213.51063829787233" r="3" fill="hsl(227, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.1
|
|
8
|
+
x-" data-x="0.48" data-y="0.765" cx="391.4893617021276" cy="213.51063829787233" r="3" fill="hsl(107, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.2
|
|
9
|
+
x+" data-x="1.58" data-y="0.765" cx="555.3191489361701" cy="213.51063829787233" r="3" fill="hsl(108, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.1
|
|
10
|
+
x-" data-x="-1.58" data-y="-0.765" cx="84.68085106382975" cy="441.3829787234042" r="3" fill="hsl(348, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.2
|
|
11
|
+
x+" data-x="-0.48" data-y="-0.765" cx="248.51063829787228" cy="441.3829787234042" r="3" fill="hsl(349, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.1
|
|
12
|
+
x-" data-x="0.5800000000000001" data-y="-0.665" cx="406.3829787234042" cy="426.48936170212767" r="3" fill="hsl(218, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.2
|
|
13
|
+
y-" data-x="1.03" data-y="-1.03" cx="473.4042553191489" cy="480.8510638297872" r="3" fill="hsl(219, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.3
|
|
14
|
+
x+" data-x="1.48" data-y="-0.665" cx="540.4255319148936" cy="426.48936170212767" r="3" fill="hsl(220, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
15
|
+
orientation: y+" data-x="0.31500000000000006" data-y="-0.665" cx="366.9148936170212" cy="426.48936170212767" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
16
|
+
orientation: y-" data-x="1.68" data-y="-0.665" cx="570.2127659574467" cy="426.48936170212767" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
17
|
+
orientation: y+" data-x="0.27999999999999997" data-y="0.765" cx="361.7021276595744" cy="213.51063829787233" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
18
|
+
orientation: y+" data-x="1.7800000000000002" data-y="0.765" cx="585.1063829787233" cy="213.51063829787233" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5"/><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text></g><script><![CDATA[
|
|
23
19
|
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
24
20
|
const svg = e.currentTarget;
|
|
25
21
|
const rect = svg.getBoundingClientRect();
|
|
@@ -41,7 +37,7 @@ orientation: y+" data-x="1.7800000000000002" data-y="0.765" cx="578.657243816254
|
|
|
41
37
|
v.setAttribute('y2', '640');
|
|
42
38
|
|
|
43
39
|
// Calculate real coordinates using inverse transformation
|
|
44
|
-
const matrix = {"a":
|
|
40
|
+
const matrix = {"a":148.93617021276594,"c":0,"e":319.99999999999994,"b":0,"d":-148.93617021276594,"f":327.4468085106383};
|
|
45
41
|
// Manually invert and apply the affine transform
|
|
46
42
|
// Since we only use translate and scale, we can directly compute:
|
|
47
43
|
// x' = (x - tx) / sx
|
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="0.6499999999999999,0.825 -0.6499999999999999,-0.825" data-type="line" data-label="" points="
|
|
2
|
-
globalConnNetId: connectivity_net2" data-x="0.
|
|
3
|
-
globalConnNetId:
|
|
4
|
-
globalConnNetId:
|
|
5
|
-
globalConnNetId:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
x-" data-x="
|
|
9
|
-
x+" data-x="
|
|
10
|
-
x-" data-x="
|
|
11
|
-
x+" data-x="
|
|
12
|
-
x-" data-x="
|
|
13
|
-
|
|
14
|
-
x
|
|
15
|
-
y
|
|
16
|
-
|
|
17
|
-
orientation:
|
|
18
|
-
orientation:
|
|
19
|
-
orientation: x+" data-x="1.4" data-y="-0.725" cx="528.8963963963964" cy="442.97297297297297" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
20
|
-
orientation: x+" data-x="-0.6499999999999999" data-y="0.825" cx="205.6981981981982" cy="198.6036036036036" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
21
|
-
orientation: y+" data-x="0.32499999999999996" data-y="0.825" cx="359.4144144144144" cy="198.6036036036036" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
22
|
-
orientation: y+" data-x="1.4500000000000002" data-y="0.825" cx="536.7792792792793" cy="198.6036036036036" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5"/><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text></g><script><![CDATA[
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="0.6499999999999999,0.825 -0.6499999999999999,-0.825" data-type="line" data-label="" points="413.3333333333333,182.22222222222226 182.22222222222223,475.55555555555554" fill="none" stroke="hsl(224, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.25,0.825 -1.25,-0.825" data-type="line" data-label="" points="520,182.22222222222226 75.55555555555554,475.55555555555554" fill="none" stroke="hsl(224, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="0.49999999999999994,-0.725 -1.25,0.825" data-type="line" data-label="" points="386.66666666666663,457.7777777777778 75.55555555555554,182.22222222222226" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.4,-0.725 -0.6499999999999999,0.825" data-type="line" data-label="" points="546.6666666666666,457.7777777777778 182.22222222222223,182.22222222222226" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="0.6499999999999999,0.825 0.4499999999999999,0.825 0.4499999999999999,0.725 -0.1,0.725 -0.1,-0.825 -0.6499999999999999,-0.825" data-type="line" data-label="" points="413.3333333333333,182.22222222222226 377.77777777777777,182.22222222222226 377.77777777777777,200.00000000000003 280,200.00000000000003 280,475.55555555555554 182.22222222222223,475.55555555555554" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.25,0.825 1.4500000000000002,0.825 1.4500000000000002,0 -1.45,0 -1.45,-0.825 -1.25,-0.825" data-type="line" data-label="" points="520,182.22222222222226 555.5555555555557,182.22222222222226 555.5555555555557,328.8888888888889 40,328.8888888888889 40,475.55555555555554 75.55555555555554,475.55555555555554" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0.5,-0.725 -0.07499999999999996,-0.725 -0.07499999999999996,0.17000000000000004 -1.45,0.17000000000000004 -1.45,0.825 -1.25,0.825" data-type="line" data-label="" points="386.66666666666663,457.7777777777778 284.44444444444446,457.7777777777778 284.44444444444446,298.6666666666667 40,298.6666666666667 40,182.22222222222226 75.55555555555554,182.22222222222226" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.4,-0.725 1.5999999999999999,-0.725 1.5999999999999999,0.28499999999999986 0.1,0.28499999999999986 0.1,0.825 -0.6499999999999999,0.825" data-type="line" data-label="" points="546.6666666666666,457.7777777777778 582.2222222222222,457.7777777777778 582.2222222222222,278.2222222222223 315.55555555555554,278.2222222222223 315.55555555555554,182.22222222222226 182.22222222222223,182.22222222222226" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="-0.95" data-y="0.825" x="75.55555555555554" y="121.7777777777778" width="106.66666666666669" height="120.88888888888891" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005625"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="0.95" data-y="0.825" x="413.33333333333326" y="121.7777777777778" width="106.66666666666669" height="120.88888888888891" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005625"/></g><g><rect data-type="rect" data-label="schematic_component_2" data-x="-0.95" data-y="-0.825" x="75.55555555555554" y="415.1111111111111" width="106.66666666666669" height="120.88888888888891" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005625"/></g><g><rect data-type="rect" data-label="schematic_component_3" data-x="0.95" data-y="-0.825" x="386.66666666666663" y="426.15489151111115" width="160" height="98.8013280888888" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005625"/></g><g><rect data-type="rect" data-label="netId: .J1 > .pin1 to .R1 > .pin1
|
|
2
|
+
globalConnNetId: connectivity_net2" data-x="0.21250000000000002" data-y="-0.5" x="317.77777777777777" y="377.7777777777778" width="35.55555555555554" height="80" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005625"/></g><g><rect data-type="rect" data-label="netId: .J1 > .pin3 to .R1 > .pin2
|
|
3
|
+
globalConnNetId: connectivity_net3" data-x="1.5999999999999999" data-y="-0.95" x="564.4444444444443" y="457.7777777777778" width="35.55555555555566" height="80" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005625"/></g><g><rect data-type="rect" data-label="netId: .R2 > .pin1 to .R3 > .pin2
|
|
4
|
+
globalConnNetId: connectivity_net0" data-x="0.4499999999999999" data-y="1.05" x="360" y="102.22222222222226" width="35.5555555555556" height="80" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005625"/></g><g><rect data-type="rect" data-label="netId: .R2 > .pin2 to .R3 > .pin1
|
|
5
|
+
globalConnNetId: connectivity_net1" data-x="1.4500000000000002" data-y="1.05" x="537.7777777777778" y="102.22222222222226" width="35.55555555555554" height="80" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005625"/></g><g><circle data-type="point" data-label="R1.1
|
|
6
|
+
x-" data-x="-1.25" data-y="0.825" cx="75.55555555555554" cy="182.22222222222226" r="3" fill="hsl(226, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R1.2
|
|
7
|
+
x+" data-x="-0.6499999999999999" data-y="0.825" cx="182.22222222222223" cy="182.22222222222226" r="3" fill="hsl(227, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.1
|
|
8
|
+
x-" data-x="0.6499999999999999" data-y="0.825" cx="413.3333333333333" cy="182.22222222222226" r="3" fill="hsl(107, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.2
|
|
9
|
+
x+" data-x="1.25" data-y="0.825" cx="520" cy="182.22222222222226" r="3" fill="hsl(108, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.1
|
|
10
|
+
x-" data-x="-1.25" data-y="-0.825" cx="75.55555555555554" cy="475.55555555555554" r="3" fill="hsl(348, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.2
|
|
11
|
+
x+" data-x="-0.6499999999999999" data-y="-0.825" cx="182.22222222222223" cy="475.55555555555554" r="3" fill="hsl(349, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.1
|
|
12
|
+
x-" data-x="0.49999999999999994" data-y="-0.725" cx="386.66666666666663" cy="457.7777777777778" r="3" fill="hsl(218, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.2
|
|
13
|
+
y-" data-x="0.95" data-y="-1.1028787352499998" cx="466.66666666666663" cy="524.9562195999999" r="3" fill="hsl(219, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.3
|
|
14
|
+
x+" data-x="1.4" data-y="-0.725" cx="546.6666666666666" cy="457.7777777777778" r="3" fill="hsl(220, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
15
|
+
orientation: y+" data-x="0.21250000000000002" data-y="-0.725" cx="335.55555555555554" cy="457.7777777777778" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
16
|
+
orientation: y-" data-x="1.5999999999999999" data-y="-0.725" cx="582.2222222222222" cy="457.7777777777778" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
17
|
+
orientation: y+" data-x="0.4499999999999999" data-y="0.825" cx="377.77777777777777" cy="182.22222222222226" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
18
|
+
orientation: y+" data-x="1.4500000000000002" data-y="0.825" cx="555.5555555555557" cy="182.22222222222226" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5"/><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text></g><script><![CDATA[
|
|
23
19
|
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
24
20
|
const svg = e.currentTarget;
|
|
25
21
|
const rect = svg.getBoundingClientRect();
|
|
@@ -41,7 +37,7 @@ orientation: y+" data-x="1.4500000000000002" data-y="0.825" cx="536.779279279279
|
|
|
41
37
|
v.setAttribute('y2', '640');
|
|
42
38
|
|
|
43
39
|
// Calculate real coordinates using inverse transformation
|
|
44
|
-
const matrix = {"a":
|
|
40
|
+
const matrix = {"a":177.77777777777777,"c":0,"e":297.77777777777777,"b":0,"d":-177.77777777777777,"f":328.8888888888889};
|
|
45
41
|
// Manually invert and apply the affine transform
|
|
46
42
|
// Since we only use translate and scale, we can directly compute:
|
|
47
43
|
// x' = (x - tx) / sx
|
|
@@ -3,7 +3,7 @@ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipeline
|
|
|
3
3
|
import "tests/fixtures/matcher"
|
|
4
4
|
import inputProblem from "./assets/repro47-endpoint-obstacle-detour.input.json"
|
|
5
5
|
|
|
6
|
-
test("repro47: endpoint obstacle detours
|
|
6
|
+
test("repro47: endpoint obstacle detours route around nearby components", () => {
|
|
7
7
|
const solver = new SchematicTracePipelineSolver(inputProblem as any)
|
|
8
8
|
|
|
9
9
|
solver.solve()
|
|
@@ -14,6 +14,6 @@ test("repro47: endpoint obstacle detours fall back to net labels", () => {
|
|
|
14
14
|
(pair) => pair.mspPairId,
|
|
15
15
|
)
|
|
16
16
|
.sort(),
|
|
17
|
-
).toEqual([
|
|
17
|
+
).toEqual([])
|
|
18
18
|
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
19
19
|
})
|
package/tests/solvers/SchematicTraceSingleLineSolver2/generate-endpoint-collision-detours.test.ts
CHANGED
|
@@ -36,3 +36,40 @@ test("endpoint collision detours preserve both endpoint anchors", () => {
|
|
|
36
36
|
),
|
|
37
37
|
).toBe(true)
|
|
38
38
|
})
|
|
39
|
+
|
|
40
|
+
test("endpoint collision detours preserve the remainder of a U-shaped path", () => {
|
|
41
|
+
const path = [
|
|
42
|
+
{ x: 0, y: 1 },
|
|
43
|
+
{ x: 2, y: 1 },
|
|
44
|
+
{ x: 2, y: -1 },
|
|
45
|
+
{ x: 4, y: -1 },
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
const obstacle = {
|
|
49
|
+
minX: 1,
|
|
50
|
+
maxX: 3,
|
|
51
|
+
minY: 0,
|
|
52
|
+
maxY: 2,
|
|
53
|
+
kind: "chip" as const,
|
|
54
|
+
chipId: "U1",
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const collidingSegmentIndex of [0, 2]) {
|
|
58
|
+
const detours = generateEndpointCollisionDetours({
|
|
59
|
+
path,
|
|
60
|
+
collidingSegmentIndex,
|
|
61
|
+
obstacle,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
expect(detours.length).toBeGreaterThan(0)
|
|
65
|
+
const preservedSegment =
|
|
66
|
+
collidingSegmentIndex === 0 ? path.slice(-2) : path.slice(0, 2)
|
|
67
|
+
for (const detour of detours) {
|
|
68
|
+
expect(detour[0]).toEqual(path[0])
|
|
69
|
+
expect(detour.at(-1)).toEqual(path.at(-1))
|
|
70
|
+
expect(
|
|
71
|
+
collidingSegmentIndex === 0 ? detour.slice(-2) : detour.slice(0, 2),
|
|
72
|
+
).toEqual(preservedSegment)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
})
|