@tscircuit/checks 0.0.121 → 0.0.123
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 +207 -176
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -237,7 +237,16 @@ function checkEachPcbPortConnectedToPcbTraces(circuitJson) {
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
// lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
|
|
240
|
-
import { getReadableNameForElement as getReadableNameForElement2
|
|
240
|
+
import { cju, getReadableNameForElement as getReadableNameForElement2 } from "@tscircuit/circuit-json-util";
|
|
241
|
+
import { getPrimaryId } from "@tscircuit/circuit-json-util";
|
|
242
|
+
import {
|
|
243
|
+
segmentToBoundsMinDistance,
|
|
244
|
+
segmentToCircleMinDistance
|
|
245
|
+
} from "@tscircuit/math-utils";
|
|
246
|
+
import { segmentToSegmentMinDistance } from "@tscircuit/math-utils";
|
|
247
|
+
import {
|
|
248
|
+
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
|
|
249
|
+
} from "circuit-json-to-connectivity-map";
|
|
241
250
|
|
|
242
251
|
// lib/data-structures/SpatialIndex.ts
|
|
243
252
|
var SpatialObjectIndex = class {
|
|
@@ -338,37 +347,13 @@ var SpatialObjectIndex = class {
|
|
|
338
347
|
}
|
|
339
348
|
};
|
|
340
349
|
|
|
341
|
-
// lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
|
|
342
|
-
import {
|
|
343
|
-
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
|
|
344
|
-
} from "circuit-json-to-connectivity-map";
|
|
345
|
-
|
|
346
|
-
// lib/check-each-pcb-trace-non-overlapping/getCollidableBounds.ts
|
|
347
|
-
import { getBoundsOfPcbElements as getBoundsOfPcbElements2 } from "@tscircuit/circuit-json-util";
|
|
348
|
-
var getCollidableBounds = (collidable) => {
|
|
349
|
-
if (collidable.type === "pcb_trace_segment") {
|
|
350
|
-
return {
|
|
351
|
-
minX: Math.min(collidable.x1, collidable.x2),
|
|
352
|
-
minY: Math.min(collidable.y1, collidable.y2),
|
|
353
|
-
maxX: Math.max(collidable.x1, collidable.x2),
|
|
354
|
-
maxY: Math.max(collidable.y1, collidable.y2)
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
return getBoundsOfPcbElements2([collidable]);
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
// lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
|
|
361
|
-
import {
|
|
362
|
-
segmentToBoundsMinDistance,
|
|
363
|
-
segmentToCircleMinDistance
|
|
364
|
-
} from "@tscircuit/math-utils";
|
|
365
|
-
|
|
366
350
|
// node_modules/@tscircuit/jlcpcb-manufacturing-specs/lib/jlcpcb-manufacturing-specs.ts
|
|
367
351
|
var jlcMinTolerances = {
|
|
368
352
|
min_trace_width: 0.1,
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
353
|
+
min_via_hole_edge_to_via_hole_edge_clearance: 0.1,
|
|
354
|
+
min_plated_hole_drill_edge_to_drill_edge_clearance: 0.15,
|
|
355
|
+
min_trace_to_pad_edge_clearance: 0.1,
|
|
356
|
+
min_pad_edge_to_pad_edge_clearance: 0.1,
|
|
372
357
|
min_board_edge_clearance: 0.2,
|
|
373
358
|
min_via_hole_diameter: 0.2,
|
|
374
359
|
min_via_pad_diameter: 0.3
|
|
@@ -379,38 +364,128 @@ var DEFAULT_TRACE_MARGIN = 0.1;
|
|
|
379
364
|
var DEFAULT_TRACE_THICKNESS = jlcMinTolerances.min_trace_width;
|
|
380
365
|
var DEFAULT_VIA_DIAMETER = jlcMinTolerances.min_via_pad_diameter;
|
|
381
366
|
var DEFAULT_VIA_BOARD_MARGIN = 0.3;
|
|
382
|
-
var DEFAULT_SAME_NET_VIA_MARGIN = jlcMinTolerances.
|
|
383
|
-
var DEFAULT_DIFFERENT_NET_VIA_MARGIN = jlcMinTolerances.
|
|
384
|
-
var DEFAULT_PAD_PAD_CLEARANCE = jlcMinTolerances.
|
|
385
|
-
var DEFAULT_PAD_TRACE_CLEARANCE = jlcMinTolerances.
|
|
367
|
+
var DEFAULT_SAME_NET_VIA_MARGIN = jlcMinTolerances.min_via_hole_edge_to_via_hole_edge_clearance;
|
|
368
|
+
var DEFAULT_DIFFERENT_NET_VIA_MARGIN = jlcMinTolerances.min_via_hole_edge_to_via_hole_edge_clearance;
|
|
369
|
+
var DEFAULT_PAD_PAD_CLEARANCE = jlcMinTolerances.min_pad_edge_to_pad_edge_clearance;
|
|
370
|
+
var DEFAULT_PAD_TRACE_CLEARANCE = jlcMinTolerances.min_trace_to_pad_edge_clearance;
|
|
386
371
|
var EPSILON = 5e-3;
|
|
387
372
|
|
|
388
|
-
// lib/
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if (segment.start_pcb_port_id)
|
|
394
|
-
connectedPcbPorts.add(segment.start_pcb_port_id);
|
|
395
|
-
if (segment.end_pcb_port_id)
|
|
396
|
-
connectedPcbPorts.add(segment.end_pcb_port_id);
|
|
397
|
-
}
|
|
373
|
+
// lib/util/getLayersOfPcbElement.ts
|
|
374
|
+
import { all_layers } from "circuit-json";
|
|
375
|
+
function getLayersOfPcbElement(obj) {
|
|
376
|
+
if (obj.type === "pcb_trace_segment") {
|
|
377
|
+
return [obj.layer];
|
|
398
378
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
function getPcbPortIdsConnectedToTraces(traces) {
|
|
402
|
-
const connectedPorts = /* @__PURE__ */ new Set();
|
|
403
|
-
for (const trace of traces) {
|
|
404
|
-
for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
|
|
405
|
-
connectedPorts.add(portId);
|
|
406
|
-
}
|
|
379
|
+
if (obj.type === "pcb_smtpad") {
|
|
380
|
+
return [obj.layer];
|
|
407
381
|
}
|
|
408
|
-
|
|
382
|
+
if (obj.type === "pcb_plated_hole") {
|
|
383
|
+
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
384
|
+
}
|
|
385
|
+
if (obj.type === "pcb_hole") {
|
|
386
|
+
return [...all_layers];
|
|
387
|
+
}
|
|
388
|
+
if (obj.type === "pcb_via") {
|
|
389
|
+
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
390
|
+
}
|
|
391
|
+
if (obj.type === "pcb_keepout") {
|
|
392
|
+
return Array.isArray(obj.layers) ? obj.layers : [];
|
|
393
|
+
}
|
|
394
|
+
return [];
|
|
409
395
|
}
|
|
410
396
|
|
|
411
|
-
// lib/check-each-pcb-trace-non-overlapping/
|
|
412
|
-
|
|
413
|
-
|
|
397
|
+
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegmentAndBounds.ts
|
|
398
|
+
var getClosestPointBetweenSegmentAndBounds = (segment, bounds) => {
|
|
399
|
+
const p1 = { x: segment.x1, y: segment.y1 };
|
|
400
|
+
const p2 = { x: segment.x2, y: segment.y2 };
|
|
401
|
+
const minX = bounds.minX;
|
|
402
|
+
const minY = bounds.minY;
|
|
403
|
+
const maxX = bounds.maxX;
|
|
404
|
+
const maxY = bounds.maxY;
|
|
405
|
+
if (p1.x === p2.x && p1.y === p2.y) {
|
|
406
|
+
const closestX = Math.max(minX, Math.min(maxX, p1.x));
|
|
407
|
+
const closestY = Math.max(minY, Math.min(maxY, p1.y));
|
|
408
|
+
if (closestX === p1.x && closestY === p1.y) {
|
|
409
|
+
return { x: p1.x, y: p1.y };
|
|
410
|
+
}
|
|
411
|
+
return { x: closestX, y: closestY };
|
|
412
|
+
}
|
|
413
|
+
const dx = p2.x - p1.x;
|
|
414
|
+
const dy = p2.y - p1.y;
|
|
415
|
+
const tMinX = dx !== 0 ? (minX - p1.x) / dx : Number.NEGATIVE_INFINITY;
|
|
416
|
+
const tMaxX = dx !== 0 ? (maxX - p1.x) / dx : Number.POSITIVE_INFINITY;
|
|
417
|
+
const tMinY = dy !== 0 ? (minY - p1.y) / dy : Number.NEGATIVE_INFINITY;
|
|
418
|
+
const tMaxY = dy !== 0 ? (maxY - p1.y) / dy : Number.POSITIVE_INFINITY;
|
|
419
|
+
const tEnter = Math.max(Math.min(tMinX, tMaxX), Math.min(tMinY, tMaxY));
|
|
420
|
+
const tExit = Math.min(Math.max(tMinX, tMaxX), Math.max(tMinY, tMaxY));
|
|
421
|
+
if (tEnter <= tExit && tExit >= 0 && tEnter <= 1) {
|
|
422
|
+
const t = Math.max(0, Math.min(1, tEnter));
|
|
423
|
+
return {
|
|
424
|
+
x: p1.x + t * dx,
|
|
425
|
+
y: p1.y + t * dy
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
const closestToP1 = {
|
|
429
|
+
x: Math.max(minX, Math.min(maxX, p1.x)),
|
|
430
|
+
y: Math.max(minY, Math.min(maxY, p1.y))
|
|
431
|
+
};
|
|
432
|
+
const closestToP2 = {
|
|
433
|
+
x: Math.max(minX, Math.min(maxX, p2.x)),
|
|
434
|
+
y: Math.max(minY, Math.min(maxY, p2.y))
|
|
435
|
+
};
|
|
436
|
+
const distToP1Squared = (closestToP1.x - p1.x) ** 2 + (closestToP1.y - p1.y) ** 2;
|
|
437
|
+
const distToP2Squared = (closestToP2.x - p2.x) ** 2 + (closestToP2.y - p2.y) ** 2;
|
|
438
|
+
const edges = [
|
|
439
|
+
{ start: { x: minX, y: minY }, end: { x: maxX, y: minY } },
|
|
440
|
+
// Bottom edge
|
|
441
|
+
{ start: { x: maxX, y: minY }, end: { x: maxX, y: maxY } },
|
|
442
|
+
// Right edge
|
|
443
|
+
{ start: { x: maxX, y: maxY }, end: { x: minX, y: maxY } },
|
|
444
|
+
// Top edge
|
|
445
|
+
{ start: { x: minX, y: maxY }, end: { x: minX, y: minY } }
|
|
446
|
+
// Left edge
|
|
447
|
+
];
|
|
448
|
+
let minDistance = Math.min(distToP1Squared, distToP2Squared);
|
|
449
|
+
let closestPoint = distToP1Squared <= distToP2Squared ? closestToP1 : closestToP2;
|
|
450
|
+
const clamp2 = (value, min, max) => {
|
|
451
|
+
return Math.max(min, Math.min(max, value));
|
|
452
|
+
};
|
|
453
|
+
for (const edge of edges) {
|
|
454
|
+
const va = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
455
|
+
const vb = { x: edge.end.x - edge.start.x, y: edge.end.y - edge.start.y };
|
|
456
|
+
const w = { x: p1.x - edge.start.x, y: p1.y - edge.start.y };
|
|
457
|
+
const dotAA = va.x * va.x + va.y * va.y;
|
|
458
|
+
const dotAB = va.x * vb.x + va.y * vb.y;
|
|
459
|
+
const dotAW = va.x * w.x + va.y * w.y;
|
|
460
|
+
const dotBB = vb.x * vb.x + vb.y * vb.y;
|
|
461
|
+
const dotBW = vb.x * w.x + vb.y * w.y;
|
|
462
|
+
const denominator = dotAA * dotBB - dotAB * dotAB;
|
|
463
|
+
if (Math.abs(denominator) < 1e-10) continue;
|
|
464
|
+
let tA = (dotAB * dotBW - dotBB * dotAW) / denominator;
|
|
465
|
+
let tB = (dotAA * dotBW - dotAB * dotAW) / denominator;
|
|
466
|
+
tA = clamp2(tA, 0, 1);
|
|
467
|
+
tB = clamp2(tB, 0, 1);
|
|
468
|
+
const closestOnSegment = {
|
|
469
|
+
x: p1.x + tA * va.x,
|
|
470
|
+
y: p1.y + tA * va.y
|
|
471
|
+
};
|
|
472
|
+
const closestOnEdge = {
|
|
473
|
+
x: edge.start.x + tB * vb.x,
|
|
474
|
+
y: edge.start.y + tB * vb.y
|
|
475
|
+
};
|
|
476
|
+
const dx2 = closestOnSegment.x - closestOnEdge.x;
|
|
477
|
+
const dy2 = closestOnSegment.y - closestOnEdge.y;
|
|
478
|
+
const distSquared = dx2 * dx2 + dy2 * dy2;
|
|
479
|
+
if (distSquared < minDistance) {
|
|
480
|
+
minDistance = distSquared;
|
|
481
|
+
closestPoint = {
|
|
482
|
+
x: (closestOnSegment.x + closestOnEdge.x) / 2,
|
|
483
|
+
y: (closestOnSegment.y + closestOnEdge.y) / 2
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return closestPoint;
|
|
488
|
+
};
|
|
414
489
|
|
|
415
490
|
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegments.ts
|
|
416
491
|
var getClosestPointBetweenSegments = (segmentA, segmentB) => {
|
|
@@ -557,6 +632,43 @@ var clamp = (value, min, max) => {
|
|
|
557
632
|
return Math.max(min, Math.min(max, value));
|
|
558
633
|
};
|
|
559
634
|
|
|
635
|
+
// lib/check-each-pcb-trace-non-overlapping/getCollidableBounds.ts
|
|
636
|
+
import { getBoundsOfPcbElements as getBoundsOfPcbElements2 } from "@tscircuit/circuit-json-util";
|
|
637
|
+
var getCollidableBounds = (collidable) => {
|
|
638
|
+
if (collidable.type === "pcb_trace_segment") {
|
|
639
|
+
return {
|
|
640
|
+
minX: Math.min(collidable.x1, collidable.x2),
|
|
641
|
+
minY: Math.min(collidable.y1, collidable.y2),
|
|
642
|
+
maxX: Math.max(collidable.x1, collidable.x2),
|
|
643
|
+
maxY: Math.max(collidable.y1, collidable.y2)
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
return getBoundsOfPcbElements2([collidable]);
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
// lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
|
|
650
|
+
function getPcbPortIdsConnectedToTrace(trace) {
|
|
651
|
+
const connectedPcbPorts = /* @__PURE__ */ new Set();
|
|
652
|
+
for (const segment of trace.route) {
|
|
653
|
+
if (segment.route_type === "wire") {
|
|
654
|
+
if (segment.start_pcb_port_id)
|
|
655
|
+
connectedPcbPorts.add(segment.start_pcb_port_id);
|
|
656
|
+
if (segment.end_pcb_port_id)
|
|
657
|
+
connectedPcbPorts.add(segment.end_pcb_port_id);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return Array.from(connectedPcbPorts);
|
|
661
|
+
}
|
|
662
|
+
function getPcbPortIdsConnectedToTraces(traces) {
|
|
663
|
+
const connectedPorts = /* @__PURE__ */ new Set();
|
|
664
|
+
for (const trace of traces) {
|
|
665
|
+
for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
|
|
666
|
+
connectedPorts.add(portId);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return Array.from(connectedPorts);
|
|
670
|
+
}
|
|
671
|
+
|
|
560
672
|
// lib/check-each-pcb-trace-non-overlapping/getRadiusOfCircuitJsonElement.ts
|
|
561
673
|
var getRadiusOfCircuitJsonElement = (obj) => {
|
|
562
674
|
if (obj.type === "pcb_via") {
|
|
@@ -576,123 +688,6 @@ var getRadiusOfCircuitJsonElement = (obj) => {
|
|
|
576
688
|
);
|
|
577
689
|
};
|
|
578
690
|
|
|
579
|
-
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegmentAndBounds.ts
|
|
580
|
-
var getClosestPointBetweenSegmentAndBounds = (segment, bounds) => {
|
|
581
|
-
const p1 = { x: segment.x1, y: segment.y1 };
|
|
582
|
-
const p2 = { x: segment.x2, y: segment.y2 };
|
|
583
|
-
const minX = bounds.minX;
|
|
584
|
-
const minY = bounds.minY;
|
|
585
|
-
const maxX = bounds.maxX;
|
|
586
|
-
const maxY = bounds.maxY;
|
|
587
|
-
if (p1.x === p2.x && p1.y === p2.y) {
|
|
588
|
-
const closestX = Math.max(minX, Math.min(maxX, p1.x));
|
|
589
|
-
const closestY = Math.max(minY, Math.min(maxY, p1.y));
|
|
590
|
-
if (closestX === p1.x && closestY === p1.y) {
|
|
591
|
-
return { x: p1.x, y: p1.y };
|
|
592
|
-
}
|
|
593
|
-
return { x: closestX, y: closestY };
|
|
594
|
-
}
|
|
595
|
-
const dx = p2.x - p1.x;
|
|
596
|
-
const dy = p2.y - p1.y;
|
|
597
|
-
const tMinX = dx !== 0 ? (minX - p1.x) / dx : Number.NEGATIVE_INFINITY;
|
|
598
|
-
const tMaxX = dx !== 0 ? (maxX - p1.x) / dx : Number.POSITIVE_INFINITY;
|
|
599
|
-
const tMinY = dy !== 0 ? (minY - p1.y) / dy : Number.NEGATIVE_INFINITY;
|
|
600
|
-
const tMaxY = dy !== 0 ? (maxY - p1.y) / dy : Number.POSITIVE_INFINITY;
|
|
601
|
-
const tEnter = Math.max(Math.min(tMinX, tMaxX), Math.min(tMinY, tMaxY));
|
|
602
|
-
const tExit = Math.min(Math.max(tMinX, tMaxX), Math.max(tMinY, tMaxY));
|
|
603
|
-
if (tEnter <= tExit && tExit >= 0 && tEnter <= 1) {
|
|
604
|
-
const t = Math.max(0, Math.min(1, tEnter));
|
|
605
|
-
return {
|
|
606
|
-
x: p1.x + t * dx,
|
|
607
|
-
y: p1.y + t * dy
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
const closestToP1 = {
|
|
611
|
-
x: Math.max(minX, Math.min(maxX, p1.x)),
|
|
612
|
-
y: Math.max(minY, Math.min(maxY, p1.y))
|
|
613
|
-
};
|
|
614
|
-
const closestToP2 = {
|
|
615
|
-
x: Math.max(minX, Math.min(maxX, p2.x)),
|
|
616
|
-
y: Math.max(minY, Math.min(maxY, p2.y))
|
|
617
|
-
};
|
|
618
|
-
const distToP1Squared = (closestToP1.x - p1.x) ** 2 + (closestToP1.y - p1.y) ** 2;
|
|
619
|
-
const distToP2Squared = (closestToP2.x - p2.x) ** 2 + (closestToP2.y - p2.y) ** 2;
|
|
620
|
-
const edges = [
|
|
621
|
-
{ start: { x: minX, y: minY }, end: { x: maxX, y: minY } },
|
|
622
|
-
// Bottom edge
|
|
623
|
-
{ start: { x: maxX, y: minY }, end: { x: maxX, y: maxY } },
|
|
624
|
-
// Right edge
|
|
625
|
-
{ start: { x: maxX, y: maxY }, end: { x: minX, y: maxY } },
|
|
626
|
-
// Top edge
|
|
627
|
-
{ start: { x: minX, y: maxY }, end: { x: minX, y: minY } }
|
|
628
|
-
// Left edge
|
|
629
|
-
];
|
|
630
|
-
let minDistance = Math.min(distToP1Squared, distToP2Squared);
|
|
631
|
-
let closestPoint = distToP1Squared <= distToP2Squared ? closestToP1 : closestToP2;
|
|
632
|
-
const clamp2 = (value, min, max) => {
|
|
633
|
-
return Math.max(min, Math.min(max, value));
|
|
634
|
-
};
|
|
635
|
-
for (const edge of edges) {
|
|
636
|
-
const va = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
637
|
-
const vb = { x: edge.end.x - edge.start.x, y: edge.end.y - edge.start.y };
|
|
638
|
-
const w = { x: p1.x - edge.start.x, y: p1.y - edge.start.y };
|
|
639
|
-
const dotAA = va.x * va.x + va.y * va.y;
|
|
640
|
-
const dotAB = va.x * vb.x + va.y * vb.y;
|
|
641
|
-
const dotAW = va.x * w.x + va.y * w.y;
|
|
642
|
-
const dotBB = vb.x * vb.x + vb.y * vb.y;
|
|
643
|
-
const dotBW = vb.x * w.x + vb.y * w.y;
|
|
644
|
-
const denominator = dotAA * dotBB - dotAB * dotAB;
|
|
645
|
-
if (Math.abs(denominator) < 1e-10) continue;
|
|
646
|
-
let tA = (dotAB * dotBW - dotBB * dotAW) / denominator;
|
|
647
|
-
let tB = (dotAA * dotBW - dotAB * dotAW) / denominator;
|
|
648
|
-
tA = clamp2(tA, 0, 1);
|
|
649
|
-
tB = clamp2(tB, 0, 1);
|
|
650
|
-
const closestOnSegment = {
|
|
651
|
-
x: p1.x + tA * va.x,
|
|
652
|
-
y: p1.y + tA * va.y
|
|
653
|
-
};
|
|
654
|
-
const closestOnEdge = {
|
|
655
|
-
x: edge.start.x + tB * vb.x,
|
|
656
|
-
y: edge.start.y + tB * vb.y
|
|
657
|
-
};
|
|
658
|
-
const dx2 = closestOnSegment.x - closestOnEdge.x;
|
|
659
|
-
const dy2 = closestOnSegment.y - closestOnEdge.y;
|
|
660
|
-
const distSquared = dx2 * dx2 + dy2 * dy2;
|
|
661
|
-
if (distSquared < minDistance) {
|
|
662
|
-
minDistance = distSquared;
|
|
663
|
-
closestPoint = {
|
|
664
|
-
x: (closestOnSegment.x + closestOnEdge.x) / 2,
|
|
665
|
-
y: (closestOnSegment.y + closestOnEdge.y) / 2
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
return closestPoint;
|
|
670
|
-
};
|
|
671
|
-
|
|
672
|
-
// lib/util/getLayersOfPcbElement.ts
|
|
673
|
-
import { all_layers } from "circuit-json";
|
|
674
|
-
function getLayersOfPcbElement(obj) {
|
|
675
|
-
if (obj.type === "pcb_trace_segment") {
|
|
676
|
-
return [obj.layer];
|
|
677
|
-
}
|
|
678
|
-
if (obj.type === "pcb_smtpad") {
|
|
679
|
-
return [obj.layer];
|
|
680
|
-
}
|
|
681
|
-
if (obj.type === "pcb_plated_hole") {
|
|
682
|
-
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
683
|
-
}
|
|
684
|
-
if (obj.type === "pcb_hole") {
|
|
685
|
-
return [...all_layers];
|
|
686
|
-
}
|
|
687
|
-
if (obj.type === "pcb_via") {
|
|
688
|
-
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
689
|
-
}
|
|
690
|
-
if (obj.type === "pcb_keepout") {
|
|
691
|
-
return Array.isArray(obj.layers) ? obj.layers : [];
|
|
692
|
-
}
|
|
693
|
-
return [];
|
|
694
|
-
}
|
|
695
|
-
|
|
696
691
|
// lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
|
|
697
692
|
function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
698
693
|
connMap,
|
|
@@ -742,6 +737,12 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
742
737
|
getBounds: getCollidableBounds
|
|
743
738
|
});
|
|
744
739
|
const getReadableName = (id) => getReadableNameForElement2(circuitJson, id);
|
|
740
|
+
const constructErrorMessage = (traceName, otherName, gap) => {
|
|
741
|
+
if (gap < 0) {
|
|
742
|
+
return `PCB trace ${traceName} overlaps with ${otherName} (accidental contact)`;
|
|
743
|
+
}
|
|
744
|
+
return `PCB trace ${traceName} is too close to ${otherName} (gap: ${gap.toFixed(3)}mm)`;
|
|
745
|
+
};
|
|
745
746
|
const errorIds = /* @__PURE__ */ new Set();
|
|
746
747
|
for (const segmentA of pcbTraceSegments) {
|
|
747
748
|
const requiredMargin = minClearance;
|
|
@@ -775,7 +776,11 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
775
776
|
errors.push({
|
|
776
777
|
type: "pcb_trace_error",
|
|
777
778
|
error_type: "pcb_trace_error",
|
|
778
|
-
message:
|
|
779
|
+
message: constructErrorMessage(
|
|
780
|
+
getReadableName(segmentA.pcb_trace_id),
|
|
781
|
+
getReadableName(segmentB.pcb_trace_id),
|
|
782
|
+
gap2
|
|
783
|
+
),
|
|
779
784
|
pcb_trace_id: segmentA.pcb_trace_id,
|
|
780
785
|
source_trace_id: "",
|
|
781
786
|
pcb_trace_error_id,
|
|
@@ -810,7 +815,11 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
810
815
|
errors.push({
|
|
811
816
|
type: "pcb_trace_error",
|
|
812
817
|
error_type: "pcb_trace_error",
|
|
813
|
-
message:
|
|
818
|
+
message: constructErrorMessage(
|
|
819
|
+
getReadableName(segmentA.pcb_trace_id),
|
|
820
|
+
`${obj.type} "${getReadableName(getPrimaryId(obj))}"`,
|
|
821
|
+
gap2
|
|
822
|
+
),
|
|
814
823
|
pcb_trace_id: segmentA.pcb_trace_id,
|
|
815
824
|
center: getClosestPointBetweenSegmentAndBounds(
|
|
816
825
|
segmentA,
|
|
@@ -839,7 +848,11 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
839
848
|
errors.push({
|
|
840
849
|
type: "pcb_trace_error",
|
|
841
850
|
error_type: "pcb_trace_error",
|
|
842
|
-
message:
|
|
851
|
+
message: constructErrorMessage(
|
|
852
|
+
getReadableName(segmentA.pcb_trace_id),
|
|
853
|
+
`${obj.type} "${getReadableName(getPrimaryId(obj))}"`,
|
|
854
|
+
gap
|
|
855
|
+
),
|
|
843
856
|
pcb_trace_id: segmentA.pcb_trace_id,
|
|
844
857
|
source_trace_id: "",
|
|
845
858
|
pcb_trace_error_id,
|
|
@@ -2134,7 +2147,26 @@ function checkNoGroundPinDefined(circuitJson) {
|
|
|
2134
2147
|
|
|
2135
2148
|
// lib/check-connector-accessible-orientation.ts
|
|
2136
2149
|
import { getBoardBounds } from "@tscircuit/circuit-json-util";
|
|
2150
|
+
function getFacingDirectionFromInsertionDirection(component) {
|
|
2151
|
+
switch (component.insertion_direction) {
|
|
2152
|
+
case "from_left":
|
|
2153
|
+
return "x-";
|
|
2154
|
+
case "from_right":
|
|
2155
|
+
return "x+";
|
|
2156
|
+
case "from_front":
|
|
2157
|
+
return "y+";
|
|
2158
|
+
case "from_back":
|
|
2159
|
+
return "y-";
|
|
2160
|
+
case "from_above":
|
|
2161
|
+
return null;
|
|
2162
|
+
default:
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2137
2166
|
function getFacingDirection(component) {
|
|
2167
|
+
if (component.insertion_direction) {
|
|
2168
|
+
return getFacingDirectionFromInsertionDirection(component);
|
|
2169
|
+
}
|
|
2138
2170
|
if (!component.center || !component.cable_insertion_center) return null;
|
|
2139
2171
|
const dx = component.cable_insertion_center.x - component.center.x;
|
|
2140
2172
|
const dy = component.cable_insertion_center.y - component.center.y;
|
|
@@ -2173,7 +2205,6 @@ function checkConnectorAccessibleOrientation(circuitJson) {
|
|
|
2173
2205
|
(el) => el.type === "pcb_component"
|
|
2174
2206
|
);
|
|
2175
2207
|
for (const component of components) {
|
|
2176
|
-
if (!component.cable_insertion_center) continue;
|
|
2177
2208
|
const facingDirection = getFacingDirection(component);
|
|
2178
2209
|
const recommendedFacingDirection = getRecommendedFacingDirection(
|
|
2179
2210
|
component,
|