@tscircuit/schematic-trace-solver 0.0.60 → 0.0.61
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 +12 -1
- package/dist/index.js +101 -8
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +131 -11
- package/lib/solvers/AvailableNetOrientationSolver/geometry.ts +1 -1
- package/lib/solvers/AvailableNetOrientationSolver/types.ts +1 -1
- package/package.json +1 -1
- package/site/examples/example37.page.tsx +4 -0
- package/site/examples/example38.page.tsx +4 -0
- package/tests/assets/example37.json +173 -0
- package/tests/assets/example38.json +32 -0
- package/tests/examples/__snapshots__/example04.snap.svg +16 -17
- package/tests/examples/__snapshots__/example37.snap.svg +320 -0
- package/tests/examples/__snapshots__/example38.snap.svg +77 -0
- package/tests/examples/example37.test.ts +12 -0
- package/tests/examples/example38.test.ts +12 -0
package/dist/index.d.ts
CHANGED
|
@@ -648,7 +648,7 @@ type CandidateLabel = {
|
|
|
648
648
|
height: number;
|
|
649
649
|
};
|
|
650
650
|
type CandidateStatus$1 = "valid" | "chip-collision" | "trace-collision" | "netlabel-collision";
|
|
651
|
-
type CandidatePhase = "rotate" | "shift";
|
|
651
|
+
type CandidatePhase = "rotate" | "shift" | "lateral-shift";
|
|
652
652
|
type EvaluatedCandidate = CandidateLabel & {
|
|
653
653
|
status: CandidateStatus$1;
|
|
654
654
|
selected: boolean;
|
|
@@ -688,12 +688,23 @@ declare class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
688
688
|
private findValidRotatedCandidate;
|
|
689
689
|
private getAvailableOrientations;
|
|
690
690
|
private findValidShiftedCandidate;
|
|
691
|
+
/**
|
|
692
|
+
* When all candidates fail for the current (unshifted) position, try
|
|
693
|
+
* shifting the label anchor laterally — x for y-orientations, y for
|
|
694
|
+
* x-orientations — and re-attempting the required orientation.
|
|
695
|
+
*
|
|
696
|
+
* Offsets are tried in alternating sign order:
|
|
697
|
+
* -1·step, +1·step, -2·step, +2·step, …
|
|
698
|
+
* so the nearest escape routes are tested first.
|
|
699
|
+
*/
|
|
700
|
+
private findValidLateralShiftedCandidate;
|
|
691
701
|
private findValidCandidateInShiftColumn;
|
|
692
702
|
private evaluateCandidate;
|
|
693
703
|
private getSearchStartAnchor;
|
|
694
704
|
private getWickOffsetAnchor;
|
|
695
705
|
private getSideOffsetAnchor;
|
|
696
706
|
private getSearchDistanceLimit;
|
|
707
|
+
private getLateralColumnMaxDistance;
|
|
697
708
|
private createCandidate;
|
|
698
709
|
private getNetLabelWidth;
|
|
699
710
|
private getCandidateStatus;
|
package/dist/index.js
CHANGED
|
@@ -5873,11 +5873,28 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5873
5873
|
this.addConnectorTrace(label, candidate, labelIndex);
|
|
5874
5874
|
}
|
|
5875
5875
|
addConnectorTrace(label, candidate, labelIndex) {
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
candidate.
|
|
5879
|
-
|
|
5880
|
-
|
|
5876
|
+
let tracePath;
|
|
5877
|
+
if (candidate.phase === "lateral-shift") {
|
|
5878
|
+
const orientDir = dir(candidate.orientation);
|
|
5879
|
+
const kickedSource = {
|
|
5880
|
+
x: label.anchorPoint.x - orientDir.x * LABEL_SEARCH_STEP,
|
|
5881
|
+
y: label.anchorPoint.y - orientDir.y * LABEL_SEARCH_STEP
|
|
5882
|
+
};
|
|
5883
|
+
tracePath = simplifyOrthogonalPath([
|
|
5884
|
+
label.anchorPoint,
|
|
5885
|
+
...getConnectorTracePath(
|
|
5886
|
+
kickedSource,
|
|
5887
|
+
candidate.anchorPoint,
|
|
5888
|
+
candidate.orientation
|
|
5889
|
+
)
|
|
5890
|
+
]);
|
|
5891
|
+
} else {
|
|
5892
|
+
tracePath = getConnectorTracePath(
|
|
5893
|
+
label.anchorPoint,
|
|
5894
|
+
candidate.anchorPoint,
|
|
5895
|
+
candidate.orientation
|
|
5896
|
+
);
|
|
5897
|
+
}
|
|
5881
5898
|
if (tracePath.length < 2) return;
|
|
5882
5899
|
const mspPairId = `available-net-orientation-${labelIndex}-${label.netId ?? label.globalConnNetId}`;
|
|
5883
5900
|
const connectorTrace = {
|
|
@@ -5910,7 +5927,18 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5910
5927
|
labelIndex,
|
|
5911
5928
|
orientations
|
|
5912
5929
|
);
|
|
5913
|
-
|
|
5930
|
+
if (rotatedCandidate) return rotatedCandidate;
|
|
5931
|
+
const shiftedCandidate = this.findValidShiftedCandidate(
|
|
5932
|
+
label,
|
|
5933
|
+
orientations[0],
|
|
5934
|
+
labelIndex
|
|
5935
|
+
);
|
|
5936
|
+
if (shiftedCandidate) return shiftedCandidate;
|
|
5937
|
+
return this.findValidLateralShiftedCandidate(
|
|
5938
|
+
label,
|
|
5939
|
+
orientations[0],
|
|
5940
|
+
labelIndex
|
|
5941
|
+
);
|
|
5914
5942
|
}
|
|
5915
5943
|
findValidRotatedCandidate(label, labelIndex, orientations) {
|
|
5916
5944
|
for (const orientation of orientations) {
|
|
@@ -5964,6 +5992,50 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5964
5992
|
}
|
|
5965
5993
|
return null;
|
|
5966
5994
|
}
|
|
5995
|
+
/**
|
|
5996
|
+
* When all candidates fail for the current (unshifted) position, try
|
|
5997
|
+
* shifting the label anchor laterally — x for y-orientations, y for
|
|
5998
|
+
* x-orientations — and re-attempting the required orientation.
|
|
5999
|
+
*
|
|
6000
|
+
* Offsets are tried in alternating sign order:
|
|
6001
|
+
* -1·step, +1·step, -2·step, +2·step, …
|
|
6002
|
+
* so the nearest escape routes are tested first.
|
|
6003
|
+
*/
|
|
6004
|
+
findValidLateralShiftedCandidate(label, orientation, labelIndex) {
|
|
6005
|
+
const direction = dir(orientation);
|
|
6006
|
+
const initialBaseAnchor = this.getSearchStartAnchor(label, orientation);
|
|
6007
|
+
const lateralDir = {
|
|
6008
|
+
x: isYOrientation(orientation) ? 1 : 0,
|
|
6009
|
+
y: isXOrientation(orientation) ? 1 : 0
|
|
6010
|
+
};
|
|
6011
|
+
const maxSteps = Math.ceil(this.maxSearchDistance / LABEL_SEARCH_STEP);
|
|
6012
|
+
for (let step = 1; step <= maxSteps; step++) {
|
|
6013
|
+
for (const sign of [-1, 1]) {
|
|
6014
|
+
const lateralOffset = sign * step * LABEL_SEARCH_STEP;
|
|
6015
|
+
const baseAnchor = {
|
|
6016
|
+
x: initialBaseAnchor.x + lateralDir.x * lateralOffset,
|
|
6017
|
+
y: initialBaseAnchor.y + lateralDir.y * lateralOffset
|
|
6018
|
+
};
|
|
6019
|
+
const maxSearchDistance = this.getLateralColumnMaxDistance(
|
|
6020
|
+
label,
|
|
6021
|
+
orientation,
|
|
6022
|
+
baseAnchor
|
|
6023
|
+
);
|
|
6024
|
+
const candidate = this.findValidCandidateInShiftColumn({
|
|
6025
|
+
label,
|
|
6026
|
+
labelIndex,
|
|
6027
|
+
orientation,
|
|
6028
|
+
direction,
|
|
6029
|
+
baseAnchor,
|
|
6030
|
+
maxSearchDistance,
|
|
6031
|
+
outwardDistance: lateralOffset,
|
|
6032
|
+
phase: "lateral-shift"
|
|
6033
|
+
});
|
|
6034
|
+
if (candidate) return candidate;
|
|
6035
|
+
}
|
|
6036
|
+
}
|
|
6037
|
+
return null;
|
|
6038
|
+
}
|
|
5967
6039
|
findValidCandidateInShiftColumn(params) {
|
|
5968
6040
|
const {
|
|
5969
6041
|
label,
|
|
@@ -5972,7 +6044,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5972
6044
|
direction,
|
|
5973
6045
|
baseAnchor,
|
|
5974
6046
|
maxSearchDistance,
|
|
5975
|
-
outwardDistance
|
|
6047
|
+
outwardDistance,
|
|
6048
|
+
phase = "shift"
|
|
5976
6049
|
} = params;
|
|
5977
6050
|
for (let distance3 = LABEL_SEARCH_STEP; distance3 <= maxSearchDistance + EPS7; distance3 += LABEL_SEARCH_STEP) {
|
|
5978
6051
|
const anchorPoint = {
|
|
@@ -5984,7 +6057,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5984
6057
|
candidate,
|
|
5985
6058
|
label,
|
|
5986
6059
|
labelIndex,
|
|
5987
|
-
|
|
6060
|
+
phase,
|
|
5988
6061
|
distance3,
|
|
5989
6062
|
outwardDistance
|
|
5990
6063
|
);
|
|
@@ -6065,6 +6138,21 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6065
6138
|
const labelLength = orientation === "y+" || orientation === "y-" ? height : width;
|
|
6066
6139
|
return Math.min(this.maxSearchDistance, labelLength * 2);
|
|
6067
6140
|
}
|
|
6141
|
+
getLateralColumnMaxDistance(label, orientation, baseAnchor) {
|
|
6142
|
+
const chipId = label.pinIds.map((pid) => this.pinMap[pid]?.chipId).find(Boolean);
|
|
6143
|
+
const chip = chipId ? this.chipObstacleSpatialIndex.chips.find((c) => c.chipId === chipId) : null;
|
|
6144
|
+
if (chip) {
|
|
6145
|
+
if (orientation === "y-")
|
|
6146
|
+
return Math.max(0, baseAnchor.y - chip.bounds.minY);
|
|
6147
|
+
if (orientation === "y+")
|
|
6148
|
+
return Math.max(0, chip.bounds.maxY - baseAnchor.y);
|
|
6149
|
+
if (orientation === "x-")
|
|
6150
|
+
return Math.max(0, baseAnchor.x - chip.bounds.minX);
|
|
6151
|
+
if (orientation === "x+")
|
|
6152
|
+
return Math.max(0, chip.bounds.maxX - baseAnchor.x);
|
|
6153
|
+
}
|
|
6154
|
+
return this.getSearchDistanceLimit(label, orientation);
|
|
6155
|
+
}
|
|
6068
6156
|
createCandidate(label, anchorPoint, orientation) {
|
|
6069
6157
|
const { width, height } = getDimsForOrientation({
|
|
6070
6158
|
orientation,
|
|
@@ -6111,6 +6199,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6111
6199
|
if (tracePathCrossesAnyTrace(connectorTrace, this.traceMap)) {
|
|
6112
6200
|
return "trace-collision";
|
|
6113
6201
|
}
|
|
6202
|
+
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6203
|
+
if (tracePathCrossesAnyBounds(connectorTrace, chip.bounds)) {
|
|
6204
|
+
return "chip-collision";
|
|
6205
|
+
}
|
|
6206
|
+
}
|
|
6114
6207
|
for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
|
|
6115
6208
|
if (i === labelIndex) continue;
|
|
6116
6209
|
const otherLabel = this.outputNetLabelPlacements[i];
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
isYOrientation,
|
|
21
21
|
rangesOverlap,
|
|
22
22
|
rectsOverlap,
|
|
23
|
+
simplifyOrthogonalPath,
|
|
23
24
|
traceCrossesBoundsInterior,
|
|
24
25
|
tracePathCrossesAnyBounds,
|
|
25
26
|
tracePathCrossesAnyTrace,
|
|
@@ -127,7 +128,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
127
128
|
|
|
128
129
|
private applyCandidate(
|
|
129
130
|
label: NetLabelPlacement,
|
|
130
|
-
candidate:
|
|
131
|
+
candidate: EvaluatedCandidate,
|
|
131
132
|
labelIndex: number,
|
|
132
133
|
) {
|
|
133
134
|
this.outputNetLabelPlacements[labelIndex] = {
|
|
@@ -139,14 +140,33 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
139
140
|
|
|
140
141
|
private addConnectorTrace(
|
|
141
142
|
label: NetLabelPlacement,
|
|
142
|
-
candidate:
|
|
143
|
+
candidate: EvaluatedCandidate,
|
|
143
144
|
labelIndex: number,
|
|
144
145
|
) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
candidate.orientation
|
|
149
|
-
|
|
146
|
+
let tracePath: Point[]
|
|
147
|
+
|
|
148
|
+
if (candidate.phase === "lateral-shift") {
|
|
149
|
+
const orientDir = dir(candidate.orientation)
|
|
150
|
+
const kickedSource = {
|
|
151
|
+
x: label.anchorPoint.x - orientDir.x * LABEL_SEARCH_STEP,
|
|
152
|
+
y: label.anchorPoint.y - orientDir.y * LABEL_SEARCH_STEP,
|
|
153
|
+
}
|
|
154
|
+
tracePath = simplifyOrthogonalPath([
|
|
155
|
+
label.anchorPoint,
|
|
156
|
+
...getConnectorTracePath(
|
|
157
|
+
kickedSource,
|
|
158
|
+
candidate.anchorPoint,
|
|
159
|
+
candidate.orientation,
|
|
160
|
+
),
|
|
161
|
+
])
|
|
162
|
+
} else {
|
|
163
|
+
tracePath = getConnectorTracePath(
|
|
164
|
+
label.anchorPoint,
|
|
165
|
+
candidate.anchorPoint,
|
|
166
|
+
candidate.orientation,
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
150
170
|
if (tracePath.length < 2) return
|
|
151
171
|
|
|
152
172
|
const mspPairId = `available-net-orientation-${labelIndex}-${label.netId ?? label.globalConnNetId}`
|
|
@@ -185,10 +205,19 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
185
205
|
labelIndex,
|
|
186
206
|
orientations,
|
|
187
207
|
)
|
|
208
|
+
if (rotatedCandidate) return rotatedCandidate
|
|
209
|
+
|
|
210
|
+
const shiftedCandidate = this.findValidShiftedCandidate(
|
|
211
|
+
label,
|
|
212
|
+
orientations[0]!,
|
|
213
|
+
labelIndex,
|
|
214
|
+
)
|
|
215
|
+
if (shiftedCandidate) return shiftedCandidate
|
|
188
216
|
|
|
189
|
-
return (
|
|
190
|
-
|
|
191
|
-
|
|
217
|
+
return this.findValidLateralShiftedCandidate(
|
|
218
|
+
label,
|
|
219
|
+
orientations[0]!,
|
|
220
|
+
labelIndex,
|
|
192
221
|
)
|
|
193
222
|
}
|
|
194
223
|
|
|
@@ -266,6 +295,63 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
266
295
|
return null
|
|
267
296
|
}
|
|
268
297
|
|
|
298
|
+
/**
|
|
299
|
+
* When all candidates fail for the current (unshifted) position, try
|
|
300
|
+
* shifting the label anchor laterally — x for y-orientations, y for
|
|
301
|
+
* x-orientations — and re-attempting the required orientation.
|
|
302
|
+
*
|
|
303
|
+
* Offsets are tried in alternating sign order:
|
|
304
|
+
* -1·step, +1·step, -2·step, +2·step, …
|
|
305
|
+
* so the nearest escape routes are tested first.
|
|
306
|
+
*/
|
|
307
|
+
private findValidLateralShiftedCandidate(
|
|
308
|
+
label: NetLabelPlacement,
|
|
309
|
+
orientation: FacingDirection,
|
|
310
|
+
labelIndex: number,
|
|
311
|
+
): EvaluatedCandidate | null {
|
|
312
|
+
const direction = dir(orientation)
|
|
313
|
+
const initialBaseAnchor = this.getSearchStartAnchor(label, orientation)
|
|
314
|
+
|
|
315
|
+
// Lateral axis: perpendicular to the orientation direction
|
|
316
|
+
const lateralDir: Point = {
|
|
317
|
+
x: isYOrientation(orientation) ? 1 : 0,
|
|
318
|
+
y: isXOrientation(orientation) ? 1 : 0,
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const maxSteps = Math.ceil(this.maxSearchDistance / LABEL_SEARCH_STEP)
|
|
322
|
+
|
|
323
|
+
for (let step = 1; step <= maxSteps; step++) {
|
|
324
|
+
for (const sign of [-1, 1]) {
|
|
325
|
+
const lateralOffset = sign * step * LABEL_SEARCH_STEP
|
|
326
|
+
const baseAnchor = {
|
|
327
|
+
x: initialBaseAnchor.x + lateralDir.x * lateralOffset,
|
|
328
|
+
y: initialBaseAnchor.y + lateralDir.y * lateralOffset,
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const maxSearchDistance = this.getLateralColumnMaxDistance(
|
|
332
|
+
label,
|
|
333
|
+
orientation,
|
|
334
|
+
baseAnchor,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
const candidate = this.findValidCandidateInShiftColumn({
|
|
338
|
+
label,
|
|
339
|
+
labelIndex,
|
|
340
|
+
orientation,
|
|
341
|
+
direction,
|
|
342
|
+
baseAnchor,
|
|
343
|
+
maxSearchDistance,
|
|
344
|
+
outwardDistance: lateralOffset,
|
|
345
|
+
phase: "lateral-shift",
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
if (candidate) return candidate
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return null
|
|
353
|
+
}
|
|
354
|
+
|
|
269
355
|
private findValidCandidateInShiftColumn(params: {
|
|
270
356
|
label: NetLabelPlacement
|
|
271
357
|
labelIndex: number
|
|
@@ -274,6 +360,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
274
360
|
baseAnchor: Point
|
|
275
361
|
maxSearchDistance: number
|
|
276
362
|
outwardDistance: number
|
|
363
|
+
phase?: CandidatePhase
|
|
277
364
|
}) {
|
|
278
365
|
const {
|
|
279
366
|
label,
|
|
@@ -283,6 +370,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
283
370
|
baseAnchor,
|
|
284
371
|
maxSearchDistance,
|
|
285
372
|
outwardDistance,
|
|
373
|
+
phase = "shift",
|
|
286
374
|
} = params
|
|
287
375
|
|
|
288
376
|
for (
|
|
@@ -299,7 +387,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
299
387
|
candidate,
|
|
300
388
|
label,
|
|
301
389
|
labelIndex,
|
|
302
|
-
|
|
390
|
+
phase,
|
|
303
391
|
distance,
|
|
304
392
|
outwardDistance,
|
|
305
393
|
)
|
|
@@ -412,6 +500,32 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
412
500
|
return Math.min(this.maxSearchDistance, labelLength * 2)
|
|
413
501
|
}
|
|
414
502
|
|
|
503
|
+
private getLateralColumnMaxDistance(
|
|
504
|
+
label: NetLabelPlacement,
|
|
505
|
+
orientation: FacingDirection,
|
|
506
|
+
baseAnchor: Point,
|
|
507
|
+
) {
|
|
508
|
+
const chipId = label.pinIds
|
|
509
|
+
.map((pid) => this.pinMap[pid]?.chipId)
|
|
510
|
+
.find(Boolean)
|
|
511
|
+
const chip = chipId
|
|
512
|
+
? this.chipObstacleSpatialIndex.chips.find((c) => c.chipId === chipId)
|
|
513
|
+
: null
|
|
514
|
+
|
|
515
|
+
if (chip) {
|
|
516
|
+
if (orientation === "y-")
|
|
517
|
+
return Math.max(0, baseAnchor.y - chip.bounds.minY)
|
|
518
|
+
if (orientation === "y+")
|
|
519
|
+
return Math.max(0, chip.bounds.maxY - baseAnchor.y)
|
|
520
|
+
if (orientation === "x-")
|
|
521
|
+
return Math.max(0, baseAnchor.x - chip.bounds.minX)
|
|
522
|
+
if (orientation === "x+")
|
|
523
|
+
return Math.max(0, chip.bounds.maxX - baseAnchor.x)
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return this.getSearchDistanceLimit(label, orientation)
|
|
527
|
+
}
|
|
528
|
+
|
|
415
529
|
private createCandidate(
|
|
416
530
|
label: NetLabelPlacement,
|
|
417
531
|
anchorPoint: Point,
|
|
@@ -474,6 +588,12 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
474
588
|
return "trace-collision"
|
|
475
589
|
}
|
|
476
590
|
|
|
591
|
+
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
592
|
+
if (tracePathCrossesAnyBounds(connectorTrace, chip.bounds)) {
|
|
593
|
+
return "chip-collision"
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
477
597
|
for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
|
|
478
598
|
if (i === labelIndex) continue
|
|
479
599
|
const otherLabel = this.outputNetLabelPlacements[i]!
|
|
@@ -168,7 +168,7 @@ export const getConnectorTracePath = (
|
|
|
168
168
|
: [source, { x: source.x, y: target.y }, target],
|
|
169
169
|
)
|
|
170
170
|
|
|
171
|
-
const simplifyOrthogonalPath = (path: Point[]) => {
|
|
171
|
+
export const simplifyOrthogonalPath = (path: Point[]) => {
|
|
172
172
|
const deduped = path.filter(
|
|
173
173
|
(point, index) => index === 0 || !pointsEqual(point, path[index - 1]!),
|
|
174
174
|
)
|
|
@@ -33,7 +33,7 @@ export type CandidateStatus =
|
|
|
33
33
|
| "trace-collision"
|
|
34
34
|
| "netlabel-collision"
|
|
35
35
|
|
|
36
|
-
export type CandidatePhase = "rotate" | "shift"
|
|
36
|
+
export type CandidatePhase = "rotate" | "shift" | "lateral-shift"
|
|
37
37
|
|
|
38
38
|
export type EvaluatedCandidate = CandidateLabel & {
|
|
39
39
|
status: CandidateStatus
|
package/package.json
CHANGED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
{
|
|
2
|
+
"chips": [
|
|
3
|
+
{
|
|
4
|
+
"chipId": "schematic_component_0",
|
|
5
|
+
"center": {
|
|
6
|
+
"x": -3.69,
|
|
7
|
+
"y": 1.7
|
|
8
|
+
},
|
|
9
|
+
"width": 1.1,
|
|
10
|
+
"height": 0.388910699999999,
|
|
11
|
+
"pins": [
|
|
12
|
+
{
|
|
13
|
+
"pinId": "R1.1",
|
|
14
|
+
"x": -4.24,
|
|
15
|
+
"y": 1.7
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"pinId": "R1.2",
|
|
19
|
+
"x": -3.14,
|
|
20
|
+
"y": 1.7
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"chipId": "schematic_component_1",
|
|
26
|
+
"center": {
|
|
27
|
+
"x": -6.19,
|
|
28
|
+
"y": 0.3
|
|
29
|
+
},
|
|
30
|
+
"width": 1.1,
|
|
31
|
+
"height": 0.84,
|
|
32
|
+
"pins": [
|
|
33
|
+
{
|
|
34
|
+
"pinId": "C1.1",
|
|
35
|
+
"x": -6.74,
|
|
36
|
+
"y": 0.3
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"pinId": "C1.2",
|
|
40
|
+
"x": -5.640000000000001,
|
|
41
|
+
"y": 0.3
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"chipId": "schematic_component_2",
|
|
47
|
+
"center": {
|
|
48
|
+
"x": 0,
|
|
49
|
+
"y": 0
|
|
50
|
+
},
|
|
51
|
+
"width": 0.4,
|
|
52
|
+
"height": 1,
|
|
53
|
+
"pins": [
|
|
54
|
+
{
|
|
55
|
+
"pinId": "U1.1",
|
|
56
|
+
"x": -0.6000000000000001,
|
|
57
|
+
"y": 0.30000000000000004
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"pinId": "U1.2",
|
|
61
|
+
"x": -0.6000000000000001,
|
|
62
|
+
"y": 0.10000000000000003
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"pinId": "U1.3",
|
|
66
|
+
"x": -0.6000000000000001,
|
|
67
|
+
"y": -0.09999999999999998
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"pinId": "U1.4",
|
|
71
|
+
"x": -0.6000000000000001,
|
|
72
|
+
"y": -0.30000000000000004
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"pinId": "U1.5",
|
|
76
|
+
"x": 0.6000000000000001,
|
|
77
|
+
"y": -0.30000000000000004
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"pinId": "U1.6",
|
|
81
|
+
"x": 0.6000000000000001,
|
|
82
|
+
"y": -0.10000000000000003
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"pinId": "U1.7",
|
|
86
|
+
"x": 0.6000000000000001,
|
|
87
|
+
"y": 0.09999999999999998
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"pinId": "U1.8",
|
|
91
|
+
"x": 0.6000000000000001,
|
|
92
|
+
"y": 0.30000000000000004
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"chipId": "schematic_component_3",
|
|
98
|
+
"center": {
|
|
99
|
+
"x": -2.92,
|
|
100
|
+
"y": -0.4
|
|
101
|
+
},
|
|
102
|
+
"width": 0.4,
|
|
103
|
+
"height": 1,
|
|
104
|
+
"pins": [
|
|
105
|
+
{
|
|
106
|
+
"pinId": "U2.1",
|
|
107
|
+
"x": -3.52,
|
|
108
|
+
"y": -0.09999999999999998
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"pinId": "U2.2",
|
|
112
|
+
"x": -3.52,
|
|
113
|
+
"y": -0.3
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"pinId": "U2.3",
|
|
117
|
+
"x": -3.52,
|
|
118
|
+
"y": -0.5
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"pinId": "U2.4",
|
|
122
|
+
"x": -3.52,
|
|
123
|
+
"y": -0.7000000000000001
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"pinId": "U2.5",
|
|
127
|
+
"x": -2.32,
|
|
128
|
+
"y": -0.7000000000000001
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"pinId": "U2.6",
|
|
132
|
+
"x": -2.32,
|
|
133
|
+
"y": -0.5
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"pinId": "U2.7",
|
|
137
|
+
"x": -2.32,
|
|
138
|
+
"y": -0.30000000000000004
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"pinId": "U2.8",
|
|
142
|
+
"x": -2.32,
|
|
143
|
+
"y": -0.09999999999999998
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"directConnections": [
|
|
149
|
+
{
|
|
150
|
+
"pinIds": ["C1.1", "R1.1"],
|
|
151
|
+
"netId": ".C1 > .pin1 to R1.pin1"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"pinIds": ["U1.1", "C1.2"],
|
|
155
|
+
"netId": ".U1 > .pin1 to C1.pin2"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"pinIds": ["U1.2", "R1.2"],
|
|
159
|
+
"netId": ".U1 > .pin2 to R1.pin2"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"pinIds": ["U2.1", "U1.3"],
|
|
163
|
+
"netId": ".U2 > .pin1 to U1.pin3"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"pinIds": ["U2.2", "U1.4"],
|
|
167
|
+
"netId": ".U2 > .pin2 to U1.pin4"
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
"netConnections": [],
|
|
171
|
+
"availableNetLabelOrientations": {},
|
|
172
|
+
"maxMspPairDistance": 2.4
|
|
173
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"chips": [
|
|
3
|
+
{
|
|
4
|
+
"chipId": "schematic_component_0",
|
|
5
|
+
"center": {
|
|
6
|
+
"x": 0,
|
|
7
|
+
"y": 0
|
|
8
|
+
},
|
|
9
|
+
"width": 0.2,
|
|
10
|
+
"height": 0.325,
|
|
11
|
+
"pins": [
|
|
12
|
+
{
|
|
13
|
+
"pinId": "TP1.1",
|
|
14
|
+
"x": -1.2246467991473533e-17,
|
|
15
|
+
"y": 0.2
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"directConnections": [],
|
|
21
|
+
"netConnections": [
|
|
22
|
+
{
|
|
23
|
+
"netId": "GND",
|
|
24
|
+
"pinIds": ["TP1.1"],
|
|
25
|
+
"netLabelWidth": 0.48
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"availableNetLabelOrientations": {
|
|
29
|
+
"GND": ["y-"]
|
|
30
|
+
},
|
|
31
|
+
"maxMspPairDistance": 2.4
|
|
32
|
+
}
|
|
@@ -2,39 +2,38 @@
|
|
|
2
2
|
<rect width="100%" height="100%" fill="white" />
|
|
3
3
|
<g>
|
|
4
4
|
<circle data-type="point" data-label="Q1.1
|
|
5
|
-
y+" data-x="0.30397715550000004" data-y="0.5800832909999993" cx="
|
|
5
|
+
y+" data-x="0.30397715550000004" data-y="0.5800832909999993" cx="386.41696544795997" cy="192.03773223990865" r="3" fill="hsl(315, 100%, 50%, 0.8)" />
|
|
6
6
|
</g>
|
|
7
7
|
<g>
|
|
8
8
|
<circle data-type="point" data-label="Q1.2
|
|
9
|
-
y-" data-x="0.31067575550000137" data-y="-0.5800832909999993" cx="
|
|
9
|
+
y-" data-x="0.31067575550000137" data-y="-0.5800832909999993" cx="388.6751471623335" cy="583.1443755831586" r="3" fill="hsl(316, 100%, 50%, 0.8)" />
|
|
10
10
|
</g>
|
|
11
11
|
<g>
|
|
12
12
|
<circle data-type="point" data-label="Q1.3
|
|
13
|
-
x-" data-x="-0.4467558855000001" data-y="-0.10250625000000019" cx="
|
|
13
|
+
x-" data-x="-0.4467558855000001" data-y="-0.10250625000000019" cx="133.33548191977735" cy="422.1471909191105" r="3" fill="hsl(317, 100%, 50%, 0.8)" />
|
|
14
14
|
</g>
|
|
15
15
|
<g>
|
|
16
|
-
<circle data-type="point" data-label="
|
|
17
|
-
orientation: y+" data-x="0.30397715550000004" data-y="0.5800832909999993" cx="402.5477478715151" cy="162.47313199841204" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
16
|
+
<circle data-type="point" data-label="" data-x="0.30397715550000004" data-y="0.5800832909999993" cx="386.41696544795997" cy="192.03773223990865" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
18
17
|
</g>
|
|
19
18
|
<g>
|
|
20
|
-
<circle data-type="point" data-label="
|
|
21
|
-
orientation: y-" data-x="0.31067575550000137" data-y="-0.5800832909999993" cx="404.36681333050564" cy="477.52686800158796" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
19
|
+
<circle data-type="point" data-label="" data-x="0.5606757555000014" data-y="-0.5290832909999993" cx="472.95326924654" cy="565.9516386779806" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
22
20
|
</g>
|
|
23
21
|
<g>
|
|
24
|
-
<polyline data-points="0.30397715550000004,0.5800832909999993 0.31067575550000137,-0.5800832909999993" data-type="line" data-label="" points="
|
|
22
|
+
<polyline data-points="0.30397715550000004,0.5800832909999993 0.31067575550000137,-0.5800832909999993" data-type="line" data-label="" points="386.41696544795997,192.03773223990865 388.6751471623335,583.1443755831586" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
25
23
|
</g>
|
|
26
24
|
<g>
|
|
27
|
-
<
|
|
25
|
+
<polyline data-points="0.31067575550000137,-0.5800832909999993 0.31067575550000137,-0.6300832909999994 0.5606757555000014,-0.6300832909999994 0.5606757555000014,-0.5290832909999993" data-type="line" data-label="" points="388.6751471623335,583.1443755831586 388.6751471623335,600 472.95326924654,600 472.95326924654,565.9516386779806" fill="none" stroke="purple" stroke-width="1" />
|
|
26
|
+
</g>
|
|
27
|
+
<g>
|
|
28
|
+
<rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0" x="133.33548191977735" y="192.03773223990865" width="301.2139764800545" height="391.10664334324997" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.0029663688964285694" />
|
|
28
29
|
</g>
|
|
29
30
|
<g>
|
|
30
31
|
<rect data-type="rect" data-label="netId: V3_3
|
|
31
|
-
globalConnNetId: connectivity_net0
|
|
32
|
-
available orientations: y+" data-x="0.30397715550000004" data-y="0.8060832909999993" x="375.3918427720889" y="40" width="54.311810198852356" height="122.20157294741779" fill="#ef444466" stroke="#ef4444" stroke-width="0.003682440324999998" />
|
|
32
|
+
globalConnNetId: connectivity_net0" data-x="0.30397715550000004" data-y="0.8060832909999993" x="352.7057166142773" y="40" width="67.42249766736523" height="151.70061975157182" fill="#ef444466" stroke="#ef4444" stroke-width="0.0029663688964285694" />
|
|
33
33
|
</g>
|
|
34
34
|
<g>
|
|
35
35
|
<rect data-type="rect" data-label="netId: V3_3
|
|
36
|
-
globalConnNetId: connectivity_net0
|
|
37
|
-
available orientations: y+" data-x="0.31067575550000137" data-y="-0.8060832909999993" x="377.2109082310795" y="477.7984270525822" width="54.3118101988523" height="122.20157294741779" fill="#ef444466" stroke="#ef4444" stroke-width="0.003682440324999998" />
|
|
36
|
+
globalConnNetId: connectivity_net0" data-x="0.5606757555000014" data-y="-0.3040832909999993" x="439.2420204128574" y="414.25101892640873" width="67.42249766736518" height="151.70061975157182" fill="#ef444466" stroke="#ef4444" stroke-width="0.0029663688964285694" />
|
|
38
37
|
</g>
|
|
39
38
|
<g id="crosshair" style="display: none">
|
|
40
39
|
<line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
|
|
@@ -64,12 +63,12 @@ available orientations: y+" data-x="0.31067575550000137" data-y="-0.806083290999
|
|
|
64
63
|
|
|
65
64
|
// Calculate real coordinates using inverse transformation
|
|
66
65
|
const matrix = {
|
|
67
|
-
"a":
|
|
66
|
+
"a": 337.1124883368262,
|
|
68
67
|
"c": 0,
|
|
69
|
-
"e":
|
|
68
|
+
"e": 283.9424701598046,
|
|
70
69
|
"b": 0,
|
|
71
|
-
"d": -
|
|
72
|
-
"f":
|
|
70
|
+
"d": -337.1124883368262,
|
|
71
|
+
"f": 387.59105391153366
|
|
73
72
|
};
|
|
74
73
|
// Manually invert and apply the affine transform
|
|
75
74
|
// Since we only use translate and scale, we can directly compute:
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="100%" height="100%" fill="white" />
|
|
3
|
+
<g>
|
|
4
|
+
<circle data-type="point" data-label="R1.1
|
|
5
|
+
x-" data-x="-4.24" data-y="1.7" cx="240.53050397877985" cy="230.66942944297082" r="3" fill="hsl(226, 100%, 50%, 0.8)" />
|
|
6
|
+
</g>
|
|
7
|
+
<g>
|
|
8
|
+
<circle data-type="point" data-label="R1.2
|
|
9
|
+
x+" data-x="-3.1399999999999997" data-y="1.7" cx="322.2281167108754" cy="230.66942944297082" r="3" fill="hsl(227, 100%, 50%, 0.8)" />
|
|
10
|
+
</g>
|
|
11
|
+
<g>
|
|
12
|
+
<circle data-type="point" data-label="C1.1
|
|
13
|
+
x-" data-x="-6.74" data-y="0.3" cx="54.85411140583557" cy="334.6482092838196" r="3" fill="hsl(121, 100%, 50%, 0.8)" />
|
|
14
|
+
</g>
|
|
15
|
+
<g>
|
|
16
|
+
<circle data-type="point" data-label="C1.2
|
|
17
|
+
x+" data-x="-5.640000000000001" data-y="0.3" cx="136.55172413793105" cy="334.6482092838196" r="3" fill="hsl(122, 100%, 50%, 0.8)" />
|
|
18
|
+
</g>
|
|
19
|
+
<g>
|
|
20
|
+
<circle data-type="point" data-label="U1.1
|
|
21
|
+
x-" data-x="-0.6000000000000001" data-y="0.30000000000000004" cx="510.8753315649867" cy="334.6482092838196" r="3" fill="hsl(319, 100%, 50%, 0.8)" />
|
|
22
|
+
</g>
|
|
23
|
+
<g>
|
|
24
|
+
<circle data-type="point" data-label="U1.2
|
|
25
|
+
x-" data-x="-0.6000000000000001" data-y="0.10000000000000003" cx="510.8753315649867" cy="349.50232068965516" r="3" fill="hsl(320, 100%, 50%, 0.8)" />
|
|
26
|
+
</g>
|
|
27
|
+
<g>
|
|
28
|
+
<circle data-type="point" data-label="U1.3
|
|
29
|
+
x-" data-x="-0.6000000000000001" data-y="-0.09999999999999998" cx="510.8753315649867" cy="364.3564320954907" r="3" fill="hsl(321, 100%, 50%, 0.8)" />
|
|
30
|
+
</g>
|
|
31
|
+
<g>
|
|
32
|
+
<circle data-type="point" data-label="U1.4
|
|
33
|
+
x-" data-x="-0.6000000000000001" data-y="-0.30000000000000004" cx="510.8753315649867" cy="379.21054350132624" r="3" fill="hsl(322, 100%, 50%, 0.8)" />
|
|
34
|
+
</g>
|
|
35
|
+
<g>
|
|
36
|
+
<circle data-type="point" data-label="U1.5
|
|
37
|
+
x+" data-x="0.6000000000000001" data-y="-0.30000000000000004" cx="600" cy="379.21054350132624" r="3" fill="hsl(323, 100%, 50%, 0.8)" />
|
|
38
|
+
</g>
|
|
39
|
+
<g>
|
|
40
|
+
<circle data-type="point" data-label="U1.6
|
|
41
|
+
x+" data-x="0.6000000000000001" data-y="-0.10000000000000003" cx="600" cy="364.3564320954907" r="3" fill="hsl(324, 100%, 50%, 0.8)" />
|
|
42
|
+
</g>
|
|
43
|
+
<g>
|
|
44
|
+
<circle data-type="point" data-label="U1.7
|
|
45
|
+
x+" data-x="0.6000000000000001" data-y="0.09999999999999998" cx="600" cy="349.50232068965516" r="3" fill="hsl(325, 100%, 50%, 0.8)" />
|
|
46
|
+
</g>
|
|
47
|
+
<g>
|
|
48
|
+
<circle data-type="point" data-label="U1.8
|
|
49
|
+
x+" data-x="0.6000000000000001" data-y="0.30000000000000004" cx="600" cy="334.6482092838196" r="3" fill="hsl(326, 100%, 50%, 0.8)" />
|
|
50
|
+
</g>
|
|
51
|
+
<g>
|
|
52
|
+
<circle data-type="point" data-label="U2.1
|
|
53
|
+
x-" data-x="-3.52" data-y="-0.09999999999999998" cx="294.0053050397878" cy="364.3564320954907" r="3" fill="hsl(200, 100%, 50%, 0.8)" />
|
|
54
|
+
</g>
|
|
55
|
+
<g>
|
|
56
|
+
<circle data-type="point" data-label="U2.2
|
|
57
|
+
x-" data-x="-3.52" data-y="-0.3" cx="294.0053050397878" cy="379.21054350132624" r="3" fill="hsl(201, 100%, 50%, 0.8)" />
|
|
58
|
+
</g>
|
|
59
|
+
<g>
|
|
60
|
+
<circle data-type="point" data-label="U2.3
|
|
61
|
+
x-" data-x="-3.52" data-y="-0.5" cx="294.0053050397878" cy="394.06465490716175" r="3" fill="hsl(202, 100%, 50%, 0.8)" />
|
|
62
|
+
</g>
|
|
63
|
+
<g>
|
|
64
|
+
<circle data-type="point" data-label="U2.4
|
|
65
|
+
x-" data-x="-3.52" data-y="-0.7000000000000001" cx="294.0053050397878" cy="408.9187663129973" r="3" fill="hsl(203, 100%, 50%, 0.8)" />
|
|
66
|
+
</g>
|
|
67
|
+
<g>
|
|
68
|
+
<circle data-type="point" data-label="U2.5
|
|
69
|
+
x+" data-x="-2.32" data-y="-0.7000000000000001" cx="383.1299734748011" cy="408.9187663129973" r="3" fill="hsl(204, 100%, 50%, 0.8)" />
|
|
70
|
+
</g>
|
|
71
|
+
<g>
|
|
72
|
+
<circle data-type="point" data-label="U2.6
|
|
73
|
+
x+" data-x="-2.32" data-y="-0.5" cx="383.1299734748011" cy="394.06465490716175" r="3" fill="hsl(205, 100%, 50%, 0.8)" />
|
|
74
|
+
</g>
|
|
75
|
+
<g>
|
|
76
|
+
<circle data-type="point" data-label="U2.7
|
|
77
|
+
x+" data-x="-2.32" data-y="-0.30000000000000004" cx="383.1299734748011" cy="379.21054350132624" r="3" fill="hsl(206, 100%, 50%, 0.8)" />
|
|
78
|
+
</g>
|
|
79
|
+
<g>
|
|
80
|
+
<circle data-type="point" data-label="U2.8
|
|
81
|
+
x+" data-x="-2.32" data-y="-0.09999999999999998" cx="383.1299734748011" cy="364.3564320954907" r="3" fill="hsl(207, 100%, 50%, 0.8)" />
|
|
82
|
+
</g>
|
|
83
|
+
<g>
|
|
84
|
+
<circle data-type="point" data-label="anchor
|
|
85
|
+
orientation: y+" data-x="-0.6000000000000001" data-y="0.30000000000000004" cx="510.8753315649867" cy="334.6482092838196" r="3" fill="red" />
|
|
86
|
+
</g>
|
|
87
|
+
<g>
|
|
88
|
+
<circle data-type="point" data-label="anchor
|
|
89
|
+
orientation: y-" data-x="-0.6000000000000001" data-y="0.30000000000000004" cx="510.8753315649867" cy="334.6482092838196" r="3" fill="red" />
|
|
90
|
+
</g>
|
|
91
|
+
<g>
|
|
92
|
+
<circle data-type="point" data-label="anchor
|
|
93
|
+
orientation: y+" data-x="-0.6500000000000001" data-y="0.30000000000000004" cx="507.16180371352783" cy="334.6482092838196" r="3" fill="red" />
|
|
94
|
+
</g>
|
|
95
|
+
<g>
|
|
96
|
+
<circle data-type="point" data-label="anchor
|
|
97
|
+
orientation: y-" data-x="-0.6500000000000001" data-y="0.30000000000000004" cx="507.16180371352783" cy="334.6482092838196" r="3" fill="red" />
|
|
98
|
+
</g>
|
|
99
|
+
<g>
|
|
100
|
+
<circle data-type="point" data-label="anchor
|
|
101
|
+
orientation: y+" data-x="-0.7000000000000001" data-y="0.30000000000000004" cx="503.44827586206895" cy="334.6482092838196" r="3" fill="red" />
|
|
102
|
+
</g>
|
|
103
|
+
<g>
|
|
104
|
+
<circle data-type="point" data-label="anchor
|
|
105
|
+
orientation: y-" data-x="-0.7000000000000001" data-y="0.30000000000000004" cx="503.44827586206895" cy="334.6482092838196" r="3" fill="red" />
|
|
106
|
+
</g>
|
|
107
|
+
<g>
|
|
108
|
+
<circle data-type="point" data-label="anchor
|
|
109
|
+
orientation: x+" data-x="-0.7000000000000001" data-y="0.30000000000000004" cx="503.44827586206895" cy="334.6482092838196" r="3" fill="red" />
|
|
110
|
+
</g>
|
|
111
|
+
<g>
|
|
112
|
+
<circle data-type="point" data-label="anchor
|
|
113
|
+
orientation: x-" data-x="-0.7000000000000001" data-y="0.30000000000000004" cx="503.44827586206895" cy="334.6482092838196" r="3" fill="orange" />
|
|
114
|
+
</g>
|
|
115
|
+
<g>
|
|
116
|
+
<circle data-type="point" data-label="anchor
|
|
117
|
+
orientation: x+" data-x="-0.7000000000000001" data-y="0.25000000000000006" cx="503.44827586206895" cy="338.3617371352785" r="3" fill="red" />
|
|
118
|
+
</g>
|
|
119
|
+
<g>
|
|
120
|
+
<circle data-type="point" data-label="anchor
|
|
121
|
+
orientation: x-" data-x="-0.7000000000000001" data-y="0.25000000000000006" cx="503.44827586206895" cy="338.3617371352785" r="3" fill="orange" />
|
|
122
|
+
</g>
|
|
123
|
+
<g>
|
|
124
|
+
<circle data-type="point" data-label="anchor
|
|
125
|
+
orientation: x+" data-x="-0.7000000000000001" data-y="0.20000000000000004" cx="503.44827586206895" cy="342.07526498673735" r="3" fill="red" />
|
|
126
|
+
</g>
|
|
127
|
+
<g>
|
|
128
|
+
<circle data-type="point" data-label="anchor
|
|
129
|
+
orientation: x-" data-x="-0.7000000000000001" data-y="0.20000000000000004" cx="503.44827586206895" cy="342.07526498673735" r="3" fill="orange" />
|
|
130
|
+
</g>
|
|
131
|
+
<g>
|
|
132
|
+
<circle data-type="point" data-label="anchor
|
|
133
|
+
orientation: y+" data-x="-0.7000000000000001" data-y="0.20000000000000004" cx="503.44827586206895" cy="342.07526498673735" r="3" fill="red" />
|
|
134
|
+
</g>
|
|
135
|
+
<g>
|
|
136
|
+
<circle data-type="point" data-label="anchor
|
|
137
|
+
orientation: y-" data-x="-0.7000000000000001" data-y="0.20000000000000004" cx="503.44827586206895" cy="342.07526498673735" r="3" fill="red" />
|
|
138
|
+
</g>
|
|
139
|
+
<g>
|
|
140
|
+
<circle data-type="point" data-label="anchor
|
|
141
|
+
orientation: y+" data-x="-3.1700000000000004" data-y="0.2" cx="320" cy="342.07526498673735" r="3" fill="orange" />
|
|
142
|
+
</g>
|
|
143
|
+
<g>
|
|
144
|
+
<circle data-type="point" data-label="anchor
|
|
145
|
+
orientation: y-" data-x="-3.1700000000000004" data-y="0.2" cx="320" cy="342.07526498673735" r="3" fill="red" />
|
|
146
|
+
</g>
|
|
147
|
+
<g>
|
|
148
|
+
<circle data-type="point" data-label="anchor
|
|
149
|
+
orientation: y+" data-x="-5.640000000000001" data-y="0.19999999999999998" cx="136.55172413793105" cy="342.07526498673735" r="3" fill="red" />
|
|
150
|
+
</g>
|
|
151
|
+
<g>
|
|
152
|
+
<circle data-type="point" data-label="anchor
|
|
153
|
+
orientation: y-" data-x="-5.640000000000001" data-y="0.19999999999999998" cx="136.55172413793105" cy="342.07526498673735" r="3" fill="red" />
|
|
154
|
+
</g>
|
|
155
|
+
<g>
|
|
156
|
+
<polyline data-points="-6.74,0.3 -4.24,1.7" data-type="line" data-label="" points="54.85411140583557,334.6482092838196 240.53050397877985,230.66942944297082" fill="none" stroke="hsl(24, 100%, 50%, 0.8)" stroke-width="1" />
|
|
157
|
+
</g>
|
|
158
|
+
<g>
|
|
159
|
+
<polyline data-points="-0.6000000000000001,0.30000000000000004 -5.640000000000001,0.3" data-type="line" data-label="" points="510.8753315649867,334.6482092838196 136.55172413793105,334.6482092838196" fill="none" stroke="hsl(8, 100%, 50%, 0.8)" stroke-width="1" />
|
|
160
|
+
</g>
|
|
161
|
+
<g>
|
|
162
|
+
<polyline data-points="-0.6000000000000001,0.10000000000000003 -3.1399999999999997,1.7" data-type="line" data-label="" points="510.8753315649867,349.50232068965516 322.2281167108754,230.66942944297082" fill="none" stroke="hsl(8, 100%, 50%, 0.8)" stroke-width="1" />
|
|
163
|
+
</g>
|
|
164
|
+
<g>
|
|
165
|
+
<polyline data-points="-3.52,-0.09999999999999998 -0.6000000000000001,-0.09999999999999998" data-type="line" data-label="" points="294.0053050397878,364.3564320954907 510.8753315649867,364.3564320954907" fill="none" stroke="hsl(152, 100%, 50%, 0.8)" stroke-width="1" />
|
|
166
|
+
</g>
|
|
167
|
+
<g>
|
|
168
|
+
<polyline data-points="-3.52,-0.3 -0.6000000000000001,-0.30000000000000004" data-type="line" data-label="" points="294.0053050397878,379.21054350132624 510.8753315649867,379.21054350132624" fill="none" stroke="hsl(152, 100%, 50%, 0.8)" stroke-width="1" />
|
|
169
|
+
</g>
|
|
170
|
+
<g>
|
|
171
|
+
<polyline data-points="-6.74,0.3 -6.94,0.3 -6.94,1.7 -4.24,1.7" data-type="line" data-label="" points="54.85411140583557,334.6482092838196 40,334.6482092838196 40,230.66942944297082 240.53050397877985,230.66942944297082" fill="none" stroke="black" stroke-width="1" />
|
|
172
|
+
</g>
|
|
173
|
+
<g>
|
|
174
|
+
<polyline data-points="-0.6000000000000001,0.30000000000000004 -0.7000000000000001,0.30000000000000004 -0.7000000000000001,0.20000000000000004 -5.640000000000001,0.19999999999999998" data-type="line" data-label="" points="510.8753315649867,334.6482092838196 503.44827586206895,334.6482092838196 503.44827586206895,342.07526498673735 136.55172413793105,342.07526498673735" fill="none" stroke="black" stroke-width="1" />
|
|
175
|
+
</g>
|
|
176
|
+
<g>
|
|
177
|
+
<polyline data-points="-3.52,-0.09999999999999998 -3.72,-0.09999999999999998 -3.72,0.4 -0.8000000000000007,0.4 -0.8000000000000007,-0.09999999999999998 -0.6000000000000005,-0.09999999999999998" data-type="line" data-label="" points="294.0053050397878,364.3564320954907 279.1511936339523,364.3564320954907 279.1511936339523,327.22115358090184 496.02122015915114,327.22115358090184 496.02122015915114,364.3564320954907 510.8753315649867,364.3564320954907" fill="none" stroke="black" stroke-width="1" />
|
|
178
|
+
</g>
|
|
179
|
+
<g>
|
|
180
|
+
<rect data-type="rect" data-label="schematic_component_0" data-x="-3.69" data-y="1.7" x="240.53050397877985" y="216.22712228116714" width="81.69761273209554" height="28.884614323607337" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013464285714285717" />
|
|
181
|
+
</g>
|
|
182
|
+
<g>
|
|
183
|
+
<rect data-type="rect" data-label="schematic_component_1" data-x="-6.19" data-y="0.3" x="54.85411140583557" y="303.45457533156497" width="81.69761273209548" height="62.38726790450926" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013464285714285717" />
|
|
184
|
+
</g>
|
|
185
|
+
<g>
|
|
186
|
+
<rect data-type="rect" data-label="schematic_component_2" data-x="0" data-y="0" x="510.8753315649867" y="319.7940978779841" width="89.12466843501329" height="74.27055702917767" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013464285714285717" />
|
|
187
|
+
</g>
|
|
188
|
+
<g>
|
|
189
|
+
<rect data-type="rect" data-label="schematic_component_3" data-x="-2.92" data-y="-0.4" x="294.0053050397878" y="349.50232068965516" width="89.12466843501329" height="74.27055702917772" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013464285714285717" />
|
|
190
|
+
</g>
|
|
191
|
+
<g>
|
|
192
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
193
|
+
orientation: y+" data-x="-0.6000000000000001" data-y="0.5251" x="503.44827586206895" y="301.2190315649867" width="14.85411140583551" height="33.421750663129956" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
194
|
+
</g>
|
|
195
|
+
<g>
|
|
196
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
197
|
+
orientation: y-" data-x="-0.6000000000000001" data-y="0.07490000000000005" x="503.44827586206895" y="334.6556363395225" width="14.85411140583551" height="33.421750663129956" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
198
|
+
</g>
|
|
199
|
+
<g>
|
|
200
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
201
|
+
orientation: y+" data-x="-0.6500000000000001" data-y="0.5251" x="499.7347480106101" y="301.2190315649867" width="14.854111405835567" height="33.421750663129956" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
202
|
+
</g>
|
|
203
|
+
<g>
|
|
204
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
205
|
+
orientation: y-" data-x="-0.6500000000000001" data-y="0.07490000000000005" x="499.7347480106101" y="334.6556363395225" width="14.854111405835567" height="33.421750663129956" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
206
|
+
</g>
|
|
207
|
+
<g>
|
|
208
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
209
|
+
orientation: y+" data-x="-0.7000000000000001" data-y="0.5251" x="496.0212201591512" y="301.2190315649867" width="14.85411140583551" height="33.421750663129956" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
210
|
+
</g>
|
|
211
|
+
<g>
|
|
212
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
213
|
+
orientation: y-" data-x="-0.7000000000000001" data-y="0.07490000000000005" x="496.0212201591512" y="334.6556363395225" width="14.85411140583551" height="33.421750663129956" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
214
|
+
</g>
|
|
215
|
+
<g>
|
|
216
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
217
|
+
orientation: x+" data-x="-0.4749000000000001" data-y="0.30000000000000004" x="503.4557029177719" y="327.22115358090184" width="33.421750663129956" height="14.85411140583551" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
218
|
+
</g>
|
|
219
|
+
<g>
|
|
220
|
+
<rect data-type="rect" data-label="status: trace-collision
|
|
221
|
+
orientation: x-" data-x="-0.9251" data-y="0.30000000000000004" x="470.0190981432361" y="327.22115358090184" width="33.421750663129956" height="14.85411140583551" fill="rgba(220, 140, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
222
|
+
</g>
|
|
223
|
+
<g>
|
|
224
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
225
|
+
orientation: x+" data-x="-0.4749000000000001" data-y="0.25000000000000006" x="503.4557029177719" y="330.9346814323607" width="33.421750663129956" height="14.854111405835567" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
226
|
+
</g>
|
|
227
|
+
<g>
|
|
228
|
+
<rect data-type="rect" data-label="status: trace-collision
|
|
229
|
+
orientation: x-" data-x="-0.9251" data-y="0.25000000000000006" x="470.0190981432361" y="330.9346814323607" width="33.421750663129956" height="14.854111405835567" fill="rgba(220, 140, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
230
|
+
</g>
|
|
231
|
+
<g>
|
|
232
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
233
|
+
orientation: x+" data-x="-0.4749000000000001" data-y="0.20000000000000004" x="503.4557029177719" y="334.6482092838196" width="33.421750663129956" height="14.854111405835567" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
234
|
+
</g>
|
|
235
|
+
<g>
|
|
236
|
+
<rect data-type="rect" data-label="status: trace-collision
|
|
237
|
+
orientation: x-" data-x="-0.9251" data-y="0.20000000000000004" x="470.0190981432361" y="334.6482092838196" width="33.421750663129956" height="14.854111405835567" fill="rgba(220, 140, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
238
|
+
</g>
|
|
239
|
+
<g>
|
|
240
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
241
|
+
orientation: y+" data-x="-0.7000000000000001" data-y="0.42510000000000003" x="496.0212201591512" y="308.6460872679045" width="14.85411140583551" height="33.421750663129956" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
242
|
+
</g>
|
|
243
|
+
<g>
|
|
244
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
245
|
+
orientation: y-" data-x="-0.7000000000000001" data-y="-0.02509999999999997" x="496.0212201591512" y="342.08269204244027" width="14.85411140583551" height="33.42175066313001" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
246
|
+
</g>
|
|
247
|
+
<g>
|
|
248
|
+
<rect data-type="rect" data-label="status: trace-collision
|
|
249
|
+
orientation: y+" data-x="-3.1700000000000004" data-y="0.42510000000000003" x="312.57294429708224" y="308.6460872679045" width="14.85411140583551" height="33.421750663129956" fill="rgba(220, 140, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
250
|
+
</g>
|
|
251
|
+
<g>
|
|
252
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
253
|
+
orientation: y-" data-x="-3.1700000000000004" data-y="-0.025099999999999983" x="312.57294429708224" y="342.08269204244027" width="14.85411140583551" height="33.42175066313001" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
254
|
+
</g>
|
|
255
|
+
<g>
|
|
256
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
257
|
+
orientation: y+" data-x="-5.640000000000001" data-y="0.4251" x="129.1246684350133" y="308.6460872679045" width="14.85411140583551" height="33.42175066313001" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
258
|
+
</g>
|
|
259
|
+
<g>
|
|
260
|
+
<rect data-type="rect" data-label="status: chip-collision
|
|
261
|
+
orientation: y-" data-x="-5.640000000000001" data-y="-0.025100000000000025" x="129.1246684350133" y="342.08269204244027" width="14.85411140583551" height="33.42175066313001" fill="rgba(220, 0, 0, 0.25)" stroke="black" stroke-width="0.013464285714285717" />
|
|
262
|
+
</g>
|
|
263
|
+
<g id="crosshair" style="display: none">
|
|
264
|
+
<line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
|
|
265
|
+
<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>
|
|
266
|
+
</g>
|
|
267
|
+
<script>
|
|
268
|
+
<![CDATA[
|
|
269
|
+
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
270
|
+
const svg = e.currentTarget;
|
|
271
|
+
const rect = svg.getBoundingClientRect();
|
|
272
|
+
const x = e.clientX - rect.left;
|
|
273
|
+
const y = e.clientY - rect.top;
|
|
274
|
+
const crosshair = svg.getElementById('crosshair');
|
|
275
|
+
const h = svg.getElementById('crosshair-h');
|
|
276
|
+
const v = svg.getElementById('crosshair-v');
|
|
277
|
+
const coords = svg.getElementById('coordinates');
|
|
278
|
+
|
|
279
|
+
crosshair.style.display = 'block';
|
|
280
|
+
h.setAttribute('x1', '0');
|
|
281
|
+
h.setAttribute('x2', '640');
|
|
282
|
+
h.setAttribute('y1', y);
|
|
283
|
+
h.setAttribute('y2', y);
|
|
284
|
+
v.setAttribute('x1', x);
|
|
285
|
+
v.setAttribute('x2', x);
|
|
286
|
+
v.setAttribute('y1', '0');
|
|
287
|
+
v.setAttribute('y2', '640');
|
|
288
|
+
|
|
289
|
+
// Calculate real coordinates using inverse transformation
|
|
290
|
+
const matrix = {
|
|
291
|
+
"a": 74.27055702917771,
|
|
292
|
+
"c": 0,
|
|
293
|
+
"e": 555.4376657824934,
|
|
294
|
+
"b": 0,
|
|
295
|
+
"d": -74.27055702917771,
|
|
296
|
+
"f": 356.9293763925729
|
|
297
|
+
};
|
|
298
|
+
// Manually invert and apply the affine transform
|
|
299
|
+
// Since we only use translate and scale, we can directly compute:
|
|
300
|
+
// x' = (x - tx) / sx
|
|
301
|
+
// y' = (y - ty) / sy
|
|
302
|
+
const sx = matrix.a;
|
|
303
|
+
const sy = matrix.d;
|
|
304
|
+
const tx = matrix.e;
|
|
305
|
+
const ty = matrix.f;
|
|
306
|
+
const realPoint = {
|
|
307
|
+
x: (x - tx) / sx,
|
|
308
|
+
y: (y - ty) / sy // Flip y back since we used negative scale
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
|
|
312
|
+
coords.setAttribute('x', (x + 5).toString());
|
|
313
|
+
coords.setAttribute('y', (y - 5).toString());
|
|
314
|
+
});
|
|
315
|
+
document.currentScript.parentElement.addEventListener('mouseleave', () => {
|
|
316
|
+
document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
|
|
317
|
+
});
|
|
318
|
+
]]>
|
|
319
|
+
</script>
|
|
320
|
+
</svg>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="100%" height="100%" fill="white" />
|
|
3
|
+
<g>
|
|
4
|
+
<circle data-type="point" data-label="TP1.1
|
|
5
|
+
y+" data-x="-1.2246467991473533e-17" data-y="0.2" cx="440.48192771084337" cy="88.19277108433738" r="3" fill="hsl(128, 100%, 50%, 0.8)" />
|
|
6
|
+
</g>
|
|
7
|
+
<g>
|
|
8
|
+
<circle data-type="point" data-label="" data-x="-0.25" data-y="0.14900000000000002" cx="199.5180722891566" cy="137.34939759036146" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
9
|
+
</g>
|
|
10
|
+
<g>
|
|
11
|
+
<polyline data-points="-1.2246467991473533e-17,0.2 -1.2246467991473533e-17,0.25 -0.25,0.25 -0.25,0.14900000000000002" data-type="line" data-label="" points="440.48192771084337,88.19277108433738 440.48192771084337,40.00000000000003 199.5180722891566,40.00000000000003 199.5180722891566,137.34939759036146" fill="none" stroke="purple" stroke-width="1" />
|
|
12
|
+
</g>
|
|
13
|
+
<g>
|
|
14
|
+
<rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0" x="344.09638554216866" y="88.19277108433738" width="192.77108433734935" height="385.5421686746988" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.0010375" />
|
|
15
|
+
</g>
|
|
16
|
+
<g>
|
|
17
|
+
<rect data-type="rect" data-label="netId: GND
|
|
18
|
+
globalConnNetId: connectivity_net0" data-x="-0.25" data-y="-0.09099999999999997" x="103.13253012048193" y="137.34939759036146" width="192.77108433734935" height="462.6506024096385" fill="#00000066" stroke="#000000" stroke-width="0.0010375" />
|
|
19
|
+
</g>
|
|
20
|
+
<g id="crosshair" style="display: none">
|
|
21
|
+
<line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
|
|
22
|
+
<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>
|
|
23
|
+
</g>
|
|
24
|
+
<script>
|
|
25
|
+
<![CDATA[
|
|
26
|
+
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
27
|
+
const svg = e.currentTarget;
|
|
28
|
+
const rect = svg.getBoundingClientRect();
|
|
29
|
+
const x = e.clientX - rect.left;
|
|
30
|
+
const y = e.clientY - rect.top;
|
|
31
|
+
const crosshair = svg.getElementById('crosshair');
|
|
32
|
+
const h = svg.getElementById('crosshair-h');
|
|
33
|
+
const v = svg.getElementById('crosshair-v');
|
|
34
|
+
const coords = svg.getElementById('coordinates');
|
|
35
|
+
|
|
36
|
+
crosshair.style.display = 'block';
|
|
37
|
+
h.setAttribute('x1', '0');
|
|
38
|
+
h.setAttribute('x2', '640');
|
|
39
|
+
h.setAttribute('y1', y);
|
|
40
|
+
h.setAttribute('y2', y);
|
|
41
|
+
v.setAttribute('x1', x);
|
|
42
|
+
v.setAttribute('x2', x);
|
|
43
|
+
v.setAttribute('y1', '0');
|
|
44
|
+
v.setAttribute('y2', '640');
|
|
45
|
+
|
|
46
|
+
// Calculate real coordinates using inverse transformation
|
|
47
|
+
const matrix = {
|
|
48
|
+
"a": 963.855421686747,
|
|
49
|
+
"c": 0,
|
|
50
|
+
"e": 440.48192771084337,
|
|
51
|
+
"b": 0,
|
|
52
|
+
"d": -963.855421686747,
|
|
53
|
+
"f": 280.9638554216868
|
|
54
|
+
};
|
|
55
|
+
// Manually invert and apply the affine transform
|
|
56
|
+
// Since we only use translate and scale, we can directly compute:
|
|
57
|
+
// x' = (x - tx) / sx
|
|
58
|
+
// y' = (y - ty) / sy
|
|
59
|
+
const sx = matrix.a;
|
|
60
|
+
const sy = matrix.d;
|
|
61
|
+
const tx = matrix.e;
|
|
62
|
+
const ty = matrix.f;
|
|
63
|
+
const realPoint = {
|
|
64
|
+
x: (x - tx) / sx,
|
|
65
|
+
y: (y - ty) / sy // Flip y back since we used negative scale
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
|
|
69
|
+
coords.setAttribute('x', (x + 5).toString());
|
|
70
|
+
coords.setAttribute('y', (y - 5).toString());
|
|
71
|
+
});
|
|
72
|
+
document.currentScript.parentElement.addEventListener('mouseleave', () => {
|
|
73
|
+
document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
|
|
74
|
+
});
|
|
75
|
+
]]>
|
|
76
|
+
</script>
|
|
77
|
+
</svg>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { test, expect } from "bun:test"
|
|
2
|
+
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
|
+
import inputProblem from "../assets/example37.json"
|
|
4
|
+
import "tests/fixtures/matcher"
|
|
5
|
+
|
|
6
|
+
test("example37", () => {
|
|
7
|
+
const solver = new SchematicTracePipelineSolver(inputProblem as any)
|
|
8
|
+
|
|
9
|
+
solver.solve()
|
|
10
|
+
|
|
11
|
+
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
12
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { test, expect } from "bun:test"
|
|
2
|
+
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
|
+
import inputProblem from "../assets/example38.json"
|
|
4
|
+
import "tests/fixtures/matcher"
|
|
5
|
+
|
|
6
|
+
test("example38", () => {
|
|
7
|
+
const solver = new SchematicTracePipelineSolver(inputProblem as any)
|
|
8
|
+
|
|
9
|
+
solver.solve()
|
|
10
|
+
|
|
11
|
+
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
12
|
+
})
|