@tscircuit/checks 0.0.122 → 0.0.124
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 +206 -184
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
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,31 +347,6 @@ 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,
|
|
@@ -379,39 +363,131 @@ var jlcMinTolerances = {
|
|
|
379
363
|
var DEFAULT_TRACE_MARGIN = 0.1;
|
|
380
364
|
var DEFAULT_TRACE_THICKNESS = jlcMinTolerances.min_trace_width;
|
|
381
365
|
var DEFAULT_VIA_DIAMETER = jlcMinTolerances.min_via_pad_diameter;
|
|
382
|
-
var DEFAULT_VIA_BOARD_MARGIN =
|
|
366
|
+
var DEFAULT_VIA_BOARD_MARGIN = jlcMinTolerances.min_board_edge_clearance;
|
|
383
367
|
var DEFAULT_SAME_NET_VIA_MARGIN = jlcMinTolerances.min_via_hole_edge_to_via_hole_edge_clearance;
|
|
384
368
|
var DEFAULT_DIFFERENT_NET_VIA_MARGIN = jlcMinTolerances.min_via_hole_edge_to_via_hole_edge_clearance;
|
|
385
369
|
var DEFAULT_PAD_PAD_CLEARANCE = jlcMinTolerances.min_pad_edge_to_pad_edge_clearance;
|
|
386
370
|
var DEFAULT_PAD_TRACE_CLEARANCE = jlcMinTolerances.min_trace_to_pad_edge_clearance;
|
|
387
371
|
var EPSILON = 5e-3;
|
|
372
|
+
var getPcbBoard = (circuitJson) => circuitJson.find((el) => el.type === "pcb_board");
|
|
373
|
+
var getBoardDrcValue = (board, key) => board?.[key];
|
|
388
374
|
|
|
389
|
-
// lib/
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (segment.start_pcb_port_id)
|
|
395
|
-
connectedPcbPorts.add(segment.start_pcb_port_id);
|
|
396
|
-
if (segment.end_pcb_port_id)
|
|
397
|
-
connectedPcbPorts.add(segment.end_pcb_port_id);
|
|
398
|
-
}
|
|
375
|
+
// lib/util/getLayersOfPcbElement.ts
|
|
376
|
+
import { all_layers } from "circuit-json";
|
|
377
|
+
function getLayersOfPcbElement(obj) {
|
|
378
|
+
if (obj.type === "pcb_trace_segment") {
|
|
379
|
+
return [obj.layer];
|
|
399
380
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
function getPcbPortIdsConnectedToTraces(traces) {
|
|
403
|
-
const connectedPorts = /* @__PURE__ */ new Set();
|
|
404
|
-
for (const trace of traces) {
|
|
405
|
-
for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
|
|
406
|
-
connectedPorts.add(portId);
|
|
407
|
-
}
|
|
381
|
+
if (obj.type === "pcb_smtpad") {
|
|
382
|
+
return [obj.layer];
|
|
408
383
|
}
|
|
409
|
-
|
|
384
|
+
if (obj.type === "pcb_plated_hole") {
|
|
385
|
+
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
386
|
+
}
|
|
387
|
+
if (obj.type === "pcb_hole") {
|
|
388
|
+
return [...all_layers];
|
|
389
|
+
}
|
|
390
|
+
if (obj.type === "pcb_via") {
|
|
391
|
+
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
392
|
+
}
|
|
393
|
+
if (obj.type === "pcb_keepout") {
|
|
394
|
+
return Array.isArray(obj.layers) ? obj.layers : [];
|
|
395
|
+
}
|
|
396
|
+
return [];
|
|
410
397
|
}
|
|
411
398
|
|
|
412
|
-
// lib/check-each-pcb-trace-non-overlapping/
|
|
413
|
-
|
|
414
|
-
|
|
399
|
+
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegmentAndBounds.ts
|
|
400
|
+
var getClosestPointBetweenSegmentAndBounds = (segment, bounds) => {
|
|
401
|
+
const p1 = { x: segment.x1, y: segment.y1 };
|
|
402
|
+
const p2 = { x: segment.x2, y: segment.y2 };
|
|
403
|
+
const minX = bounds.minX;
|
|
404
|
+
const minY = bounds.minY;
|
|
405
|
+
const maxX = bounds.maxX;
|
|
406
|
+
const maxY = bounds.maxY;
|
|
407
|
+
if (p1.x === p2.x && p1.y === p2.y) {
|
|
408
|
+
const closestX = Math.max(minX, Math.min(maxX, p1.x));
|
|
409
|
+
const closestY = Math.max(minY, Math.min(maxY, p1.y));
|
|
410
|
+
if (closestX === p1.x && closestY === p1.y) {
|
|
411
|
+
return { x: p1.x, y: p1.y };
|
|
412
|
+
}
|
|
413
|
+
return { x: closestX, y: closestY };
|
|
414
|
+
}
|
|
415
|
+
const dx = p2.x - p1.x;
|
|
416
|
+
const dy = p2.y - p1.y;
|
|
417
|
+
const tMinX = dx !== 0 ? (minX - p1.x) / dx : Number.NEGATIVE_INFINITY;
|
|
418
|
+
const tMaxX = dx !== 0 ? (maxX - p1.x) / dx : Number.POSITIVE_INFINITY;
|
|
419
|
+
const tMinY = dy !== 0 ? (minY - p1.y) / dy : Number.NEGATIVE_INFINITY;
|
|
420
|
+
const tMaxY = dy !== 0 ? (maxY - p1.y) / dy : Number.POSITIVE_INFINITY;
|
|
421
|
+
const tEnter = Math.max(Math.min(tMinX, tMaxX), Math.min(tMinY, tMaxY));
|
|
422
|
+
const tExit = Math.min(Math.max(tMinX, tMaxX), Math.max(tMinY, tMaxY));
|
|
423
|
+
if (tEnter <= tExit && tExit >= 0 && tEnter <= 1) {
|
|
424
|
+
const t = Math.max(0, Math.min(1, tEnter));
|
|
425
|
+
return {
|
|
426
|
+
x: p1.x + t * dx,
|
|
427
|
+
y: p1.y + t * dy
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
const closestToP1 = {
|
|
431
|
+
x: Math.max(minX, Math.min(maxX, p1.x)),
|
|
432
|
+
y: Math.max(minY, Math.min(maxY, p1.y))
|
|
433
|
+
};
|
|
434
|
+
const closestToP2 = {
|
|
435
|
+
x: Math.max(minX, Math.min(maxX, p2.x)),
|
|
436
|
+
y: Math.max(minY, Math.min(maxY, p2.y))
|
|
437
|
+
};
|
|
438
|
+
const distToP1Squared = (closestToP1.x - p1.x) ** 2 + (closestToP1.y - p1.y) ** 2;
|
|
439
|
+
const distToP2Squared = (closestToP2.x - p2.x) ** 2 + (closestToP2.y - p2.y) ** 2;
|
|
440
|
+
const edges = [
|
|
441
|
+
{ start: { x: minX, y: minY }, end: { x: maxX, y: minY } },
|
|
442
|
+
// Bottom edge
|
|
443
|
+
{ start: { x: maxX, y: minY }, end: { x: maxX, y: maxY } },
|
|
444
|
+
// Right edge
|
|
445
|
+
{ start: { x: maxX, y: maxY }, end: { x: minX, y: maxY } },
|
|
446
|
+
// Top edge
|
|
447
|
+
{ start: { x: minX, y: maxY }, end: { x: minX, y: minY } }
|
|
448
|
+
// Left edge
|
|
449
|
+
];
|
|
450
|
+
let minDistance = Math.min(distToP1Squared, distToP2Squared);
|
|
451
|
+
let closestPoint = distToP1Squared <= distToP2Squared ? closestToP1 : closestToP2;
|
|
452
|
+
const clamp2 = (value, min, max) => {
|
|
453
|
+
return Math.max(min, Math.min(max, value));
|
|
454
|
+
};
|
|
455
|
+
for (const edge of edges) {
|
|
456
|
+
const va = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
457
|
+
const vb = { x: edge.end.x - edge.start.x, y: edge.end.y - edge.start.y };
|
|
458
|
+
const w = { x: p1.x - edge.start.x, y: p1.y - edge.start.y };
|
|
459
|
+
const dotAA = va.x * va.x + va.y * va.y;
|
|
460
|
+
const dotAB = va.x * vb.x + va.y * vb.y;
|
|
461
|
+
const dotAW = va.x * w.x + va.y * w.y;
|
|
462
|
+
const dotBB = vb.x * vb.x + vb.y * vb.y;
|
|
463
|
+
const dotBW = vb.x * w.x + vb.y * w.y;
|
|
464
|
+
const denominator = dotAA * dotBB - dotAB * dotAB;
|
|
465
|
+
if (Math.abs(denominator) < 1e-10) continue;
|
|
466
|
+
let tA = (dotAB * dotBW - dotBB * dotAW) / denominator;
|
|
467
|
+
let tB = (dotAA * dotBW - dotAB * dotAW) / denominator;
|
|
468
|
+
tA = clamp2(tA, 0, 1);
|
|
469
|
+
tB = clamp2(tB, 0, 1);
|
|
470
|
+
const closestOnSegment = {
|
|
471
|
+
x: p1.x + tA * va.x,
|
|
472
|
+
y: p1.y + tA * va.y
|
|
473
|
+
};
|
|
474
|
+
const closestOnEdge = {
|
|
475
|
+
x: edge.start.x + tB * vb.x,
|
|
476
|
+
y: edge.start.y + tB * vb.y
|
|
477
|
+
};
|
|
478
|
+
const dx2 = closestOnSegment.x - closestOnEdge.x;
|
|
479
|
+
const dy2 = closestOnSegment.y - closestOnEdge.y;
|
|
480
|
+
const distSquared = dx2 * dx2 + dy2 * dy2;
|
|
481
|
+
if (distSquared < minDistance) {
|
|
482
|
+
minDistance = distSquared;
|
|
483
|
+
closestPoint = {
|
|
484
|
+
x: (closestOnSegment.x + closestOnEdge.x) / 2,
|
|
485
|
+
y: (closestOnSegment.y + closestOnEdge.y) / 2
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return closestPoint;
|
|
490
|
+
};
|
|
415
491
|
|
|
416
492
|
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegments.ts
|
|
417
493
|
var getClosestPointBetweenSegments = (segmentA, segmentB) => {
|
|
@@ -558,6 +634,43 @@ var clamp = (value, min, max) => {
|
|
|
558
634
|
return Math.max(min, Math.min(max, value));
|
|
559
635
|
};
|
|
560
636
|
|
|
637
|
+
// lib/check-each-pcb-trace-non-overlapping/getCollidableBounds.ts
|
|
638
|
+
import { getBoundsOfPcbElements as getBoundsOfPcbElements2 } from "@tscircuit/circuit-json-util";
|
|
639
|
+
var getCollidableBounds = (collidable) => {
|
|
640
|
+
if (collidable.type === "pcb_trace_segment") {
|
|
641
|
+
return {
|
|
642
|
+
minX: Math.min(collidable.x1, collidable.x2),
|
|
643
|
+
minY: Math.min(collidable.y1, collidable.y2),
|
|
644
|
+
maxX: Math.max(collidable.x1, collidable.x2),
|
|
645
|
+
maxY: Math.max(collidable.y1, collidable.y2)
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
return getBoundsOfPcbElements2([collidable]);
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
// lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
|
|
652
|
+
function getPcbPortIdsConnectedToTrace(trace) {
|
|
653
|
+
const connectedPcbPorts = /* @__PURE__ */ new Set();
|
|
654
|
+
for (const segment of trace.route) {
|
|
655
|
+
if (segment.route_type === "wire") {
|
|
656
|
+
if (segment.start_pcb_port_id)
|
|
657
|
+
connectedPcbPorts.add(segment.start_pcb_port_id);
|
|
658
|
+
if (segment.end_pcb_port_id)
|
|
659
|
+
connectedPcbPorts.add(segment.end_pcb_port_id);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return Array.from(connectedPcbPorts);
|
|
663
|
+
}
|
|
664
|
+
function getPcbPortIdsConnectedToTraces(traces) {
|
|
665
|
+
const connectedPorts = /* @__PURE__ */ new Set();
|
|
666
|
+
for (const trace of traces) {
|
|
667
|
+
for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
|
|
668
|
+
connectedPorts.add(portId);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return Array.from(connectedPorts);
|
|
672
|
+
}
|
|
673
|
+
|
|
561
674
|
// lib/check-each-pcb-trace-non-overlapping/getRadiusOfCircuitJsonElement.ts
|
|
562
675
|
var getRadiusOfCircuitJsonElement = (obj) => {
|
|
563
676
|
if (obj.type === "pcb_via") {
|
|
@@ -577,123 +690,6 @@ var getRadiusOfCircuitJsonElement = (obj) => {
|
|
|
577
690
|
);
|
|
578
691
|
};
|
|
579
692
|
|
|
580
|
-
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegmentAndBounds.ts
|
|
581
|
-
var getClosestPointBetweenSegmentAndBounds = (segment, bounds) => {
|
|
582
|
-
const p1 = { x: segment.x1, y: segment.y1 };
|
|
583
|
-
const p2 = { x: segment.x2, y: segment.y2 };
|
|
584
|
-
const minX = bounds.minX;
|
|
585
|
-
const minY = bounds.minY;
|
|
586
|
-
const maxX = bounds.maxX;
|
|
587
|
-
const maxY = bounds.maxY;
|
|
588
|
-
if (p1.x === p2.x && p1.y === p2.y) {
|
|
589
|
-
const closestX = Math.max(minX, Math.min(maxX, p1.x));
|
|
590
|
-
const closestY = Math.max(minY, Math.min(maxY, p1.y));
|
|
591
|
-
if (closestX === p1.x && closestY === p1.y) {
|
|
592
|
-
return { x: p1.x, y: p1.y };
|
|
593
|
-
}
|
|
594
|
-
return { x: closestX, y: closestY };
|
|
595
|
-
}
|
|
596
|
-
const dx = p2.x - p1.x;
|
|
597
|
-
const dy = p2.y - p1.y;
|
|
598
|
-
const tMinX = dx !== 0 ? (minX - p1.x) / dx : Number.NEGATIVE_INFINITY;
|
|
599
|
-
const tMaxX = dx !== 0 ? (maxX - p1.x) / dx : Number.POSITIVE_INFINITY;
|
|
600
|
-
const tMinY = dy !== 0 ? (minY - p1.y) / dy : Number.NEGATIVE_INFINITY;
|
|
601
|
-
const tMaxY = dy !== 0 ? (maxY - p1.y) / dy : Number.POSITIVE_INFINITY;
|
|
602
|
-
const tEnter = Math.max(Math.min(tMinX, tMaxX), Math.min(tMinY, tMaxY));
|
|
603
|
-
const tExit = Math.min(Math.max(tMinX, tMaxX), Math.max(tMinY, tMaxY));
|
|
604
|
-
if (tEnter <= tExit && tExit >= 0 && tEnter <= 1) {
|
|
605
|
-
const t = Math.max(0, Math.min(1, tEnter));
|
|
606
|
-
return {
|
|
607
|
-
x: p1.x + t * dx,
|
|
608
|
-
y: p1.y + t * dy
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
const closestToP1 = {
|
|
612
|
-
x: Math.max(minX, Math.min(maxX, p1.x)),
|
|
613
|
-
y: Math.max(minY, Math.min(maxY, p1.y))
|
|
614
|
-
};
|
|
615
|
-
const closestToP2 = {
|
|
616
|
-
x: Math.max(minX, Math.min(maxX, p2.x)),
|
|
617
|
-
y: Math.max(minY, Math.min(maxY, p2.y))
|
|
618
|
-
};
|
|
619
|
-
const distToP1Squared = (closestToP1.x - p1.x) ** 2 + (closestToP1.y - p1.y) ** 2;
|
|
620
|
-
const distToP2Squared = (closestToP2.x - p2.x) ** 2 + (closestToP2.y - p2.y) ** 2;
|
|
621
|
-
const edges = [
|
|
622
|
-
{ start: { x: minX, y: minY }, end: { x: maxX, y: minY } },
|
|
623
|
-
// Bottom edge
|
|
624
|
-
{ start: { x: maxX, y: minY }, end: { x: maxX, y: maxY } },
|
|
625
|
-
// Right edge
|
|
626
|
-
{ start: { x: maxX, y: maxY }, end: { x: minX, y: maxY } },
|
|
627
|
-
// Top edge
|
|
628
|
-
{ start: { x: minX, y: maxY }, end: { x: minX, y: minY } }
|
|
629
|
-
// Left edge
|
|
630
|
-
];
|
|
631
|
-
let minDistance = Math.min(distToP1Squared, distToP2Squared);
|
|
632
|
-
let closestPoint = distToP1Squared <= distToP2Squared ? closestToP1 : closestToP2;
|
|
633
|
-
const clamp2 = (value, min, max) => {
|
|
634
|
-
return Math.max(min, Math.min(max, value));
|
|
635
|
-
};
|
|
636
|
-
for (const edge of edges) {
|
|
637
|
-
const va = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
638
|
-
const vb = { x: edge.end.x - edge.start.x, y: edge.end.y - edge.start.y };
|
|
639
|
-
const w = { x: p1.x - edge.start.x, y: p1.y - edge.start.y };
|
|
640
|
-
const dotAA = va.x * va.x + va.y * va.y;
|
|
641
|
-
const dotAB = va.x * vb.x + va.y * vb.y;
|
|
642
|
-
const dotAW = va.x * w.x + va.y * w.y;
|
|
643
|
-
const dotBB = vb.x * vb.x + vb.y * vb.y;
|
|
644
|
-
const dotBW = vb.x * w.x + vb.y * w.y;
|
|
645
|
-
const denominator = dotAA * dotBB - dotAB * dotAB;
|
|
646
|
-
if (Math.abs(denominator) < 1e-10) continue;
|
|
647
|
-
let tA = (dotAB * dotBW - dotBB * dotAW) / denominator;
|
|
648
|
-
let tB = (dotAA * dotBW - dotAB * dotAW) / denominator;
|
|
649
|
-
tA = clamp2(tA, 0, 1);
|
|
650
|
-
tB = clamp2(tB, 0, 1);
|
|
651
|
-
const closestOnSegment = {
|
|
652
|
-
x: p1.x + tA * va.x,
|
|
653
|
-
y: p1.y + tA * va.y
|
|
654
|
-
};
|
|
655
|
-
const closestOnEdge = {
|
|
656
|
-
x: edge.start.x + tB * vb.x,
|
|
657
|
-
y: edge.start.y + tB * vb.y
|
|
658
|
-
};
|
|
659
|
-
const dx2 = closestOnSegment.x - closestOnEdge.x;
|
|
660
|
-
const dy2 = closestOnSegment.y - closestOnEdge.y;
|
|
661
|
-
const distSquared = dx2 * dx2 + dy2 * dy2;
|
|
662
|
-
if (distSquared < minDistance) {
|
|
663
|
-
minDistance = distSquared;
|
|
664
|
-
closestPoint = {
|
|
665
|
-
x: (closestOnSegment.x + closestOnEdge.x) / 2,
|
|
666
|
-
y: (closestOnSegment.y + closestOnEdge.y) / 2
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
return closestPoint;
|
|
671
|
-
};
|
|
672
|
-
|
|
673
|
-
// lib/util/getLayersOfPcbElement.ts
|
|
674
|
-
import { all_layers } from "circuit-json";
|
|
675
|
-
function getLayersOfPcbElement(obj) {
|
|
676
|
-
if (obj.type === "pcb_trace_segment") {
|
|
677
|
-
return [obj.layer];
|
|
678
|
-
}
|
|
679
|
-
if (obj.type === "pcb_smtpad") {
|
|
680
|
-
return [obj.layer];
|
|
681
|
-
}
|
|
682
|
-
if (obj.type === "pcb_plated_hole") {
|
|
683
|
-
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
684
|
-
}
|
|
685
|
-
if (obj.type === "pcb_hole") {
|
|
686
|
-
return [...all_layers];
|
|
687
|
-
}
|
|
688
|
-
if (obj.type === "pcb_via") {
|
|
689
|
-
return Array.isArray(obj.layers) ? obj.layers : [...all_layers];
|
|
690
|
-
}
|
|
691
|
-
if (obj.type === "pcb_keepout") {
|
|
692
|
-
return Array.isArray(obj.layers) ? obj.layers : [];
|
|
693
|
-
}
|
|
694
|
-
return [];
|
|
695
|
-
}
|
|
696
|
-
|
|
697
693
|
// lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
|
|
698
694
|
function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
699
695
|
connMap,
|
|
@@ -743,6 +739,12 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
743
739
|
getBounds: getCollidableBounds
|
|
744
740
|
});
|
|
745
741
|
const getReadableName = (id) => getReadableNameForElement2(circuitJson, id);
|
|
742
|
+
const constructErrorMessage = (traceName, otherName, gap) => {
|
|
743
|
+
if (gap < 0) {
|
|
744
|
+
return `PCB trace ${traceName} overlaps with ${otherName} (accidental contact)`;
|
|
745
|
+
}
|
|
746
|
+
return `PCB trace ${traceName} is too close to ${otherName} (gap: ${gap.toFixed(3)}mm)`;
|
|
747
|
+
};
|
|
746
748
|
const errorIds = /* @__PURE__ */ new Set();
|
|
747
749
|
for (const segmentA of pcbTraceSegments) {
|
|
748
750
|
const requiredMargin = minClearance;
|
|
@@ -776,7 +778,11 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
776
778
|
errors.push({
|
|
777
779
|
type: "pcb_trace_error",
|
|
778
780
|
error_type: "pcb_trace_error",
|
|
779
|
-
message:
|
|
781
|
+
message: constructErrorMessage(
|
|
782
|
+
getReadableName(segmentA.pcb_trace_id),
|
|
783
|
+
getReadableName(segmentB.pcb_trace_id),
|
|
784
|
+
gap2
|
|
785
|
+
),
|
|
780
786
|
pcb_trace_id: segmentA.pcb_trace_id,
|
|
781
787
|
source_trace_id: "",
|
|
782
788
|
pcb_trace_error_id,
|
|
@@ -811,7 +817,11 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
811
817
|
errors.push({
|
|
812
818
|
type: "pcb_trace_error",
|
|
813
819
|
error_type: "pcb_trace_error",
|
|
814
|
-
message:
|
|
820
|
+
message: constructErrorMessage(
|
|
821
|
+
getReadableName(segmentA.pcb_trace_id),
|
|
822
|
+
`${obj.type} "${getReadableName(getPrimaryId(obj))}"`,
|
|
823
|
+
gap2
|
|
824
|
+
),
|
|
815
825
|
pcb_trace_id: segmentA.pcb_trace_id,
|
|
816
826
|
center: getClosestPointBetweenSegmentAndBounds(
|
|
817
827
|
segmentA,
|
|
@@ -840,7 +850,11 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
840
850
|
errors.push({
|
|
841
851
|
type: "pcb_trace_error",
|
|
842
852
|
error_type: "pcb_trace_error",
|
|
843
|
-
message:
|
|
853
|
+
message: constructErrorMessage(
|
|
854
|
+
getReadableName(segmentA.pcb_trace_id),
|
|
855
|
+
`${obj.type} "${getReadableName(getPrimaryId(obj))}"`,
|
|
856
|
+
gap
|
|
857
|
+
),
|
|
844
858
|
pcb_trace_id: segmentA.pcb_trace_id,
|
|
845
859
|
source_trace_id: "",
|
|
846
860
|
pcb_trace_error_id,
|
|
@@ -907,11 +921,12 @@ var NetManager = class {
|
|
|
907
921
|
// lib/check-pcb-components-out-of-board/checkViasOffBoard.ts
|
|
908
922
|
import { getReadableNameForElement as getReadableNameForElement3 } from "@tscircuit/circuit-json-util";
|
|
909
923
|
function checkViasOffBoard(circuitJson) {
|
|
910
|
-
const board = circuitJson
|
|
924
|
+
const board = getPcbBoard(circuitJson);
|
|
911
925
|
if (!board) return [];
|
|
912
926
|
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
913
927
|
if (vias.length === 0) return [];
|
|
914
928
|
if (board.width === void 0 || board.height === void 0) return [];
|
|
929
|
+
const boardEdgeClearance = getBoardDrcValue(board, "min_board_edge_clearance") ?? jlcMinTolerances.min_board_edge_clearance;
|
|
915
930
|
const boardMinX = board.center.x - board.width / 2;
|
|
916
931
|
const boardMaxX = board.center.x + board.width / 2;
|
|
917
932
|
const boardMinY = board.center.y - board.height / 2;
|
|
@@ -923,7 +938,7 @@ function checkViasOffBoard(circuitJson) {
|
|
|
923
938
|
const viaMaxX = via.x + viaRadius;
|
|
924
939
|
const viaMinY = via.y - viaRadius;
|
|
925
940
|
const viaMaxY = via.y + viaRadius;
|
|
926
|
-
if (viaMinX < boardMinX +
|
|
941
|
+
if (viaMinX < boardMinX + boardEdgeClearance || viaMaxX > boardMaxX - boardEdgeClearance || viaMinY < boardMinY + boardEdgeClearance || viaMaxY > boardMaxY - boardEdgeClearance) {
|
|
927
942
|
const viaName = getReadableNameForElement3(circuitJson, via.pcb_via_id);
|
|
928
943
|
errors.push({
|
|
929
944
|
type: "pcb_placement_error",
|
|
@@ -1187,10 +1202,12 @@ function viasAreAtSameLocation(a, b) {
|
|
|
1187
1202
|
// lib/check-same-net-via-spacing.ts
|
|
1188
1203
|
function checkSameNetViaSpacing(circuitJson, {
|
|
1189
1204
|
connMap,
|
|
1190
|
-
minClearance
|
|
1205
|
+
minClearance
|
|
1191
1206
|
} = {}) {
|
|
1192
1207
|
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
1193
1208
|
if (vias.length < 2) return [];
|
|
1209
|
+
const board = getPcbBoard(circuitJson);
|
|
1210
|
+
minClearance ??= getBoardDrcValue(board, "min_via_hole_edge_to_via_hole_edge_clearance") ?? jlcMinTolerances.min_via_hole_edge_to_via_hole_edge_clearance;
|
|
1194
1211
|
connMap ??= getFullConnectivityMapFromCircuitJson3(circuitJson);
|
|
1195
1212
|
const errors = [];
|
|
1196
1213
|
const reported = /* @__PURE__ */ new Set();
|
|
@@ -1200,7 +1217,7 @@ function checkSameNetViaSpacing(circuitJson, {
|
|
|
1200
1217
|
const viaB = vias[j];
|
|
1201
1218
|
if (viasAreAtSameLocation(viaA, viaB)) continue;
|
|
1202
1219
|
if (!connMap.areIdsConnected(viaA.pcb_via_id, viaB.pcb_via_id)) continue;
|
|
1203
|
-
const gap = distance2(viaA, viaB) - viaA.
|
|
1220
|
+
const gap = distance2(viaA, viaB) - viaA.hole_diameter / 2 - viaB.hole_diameter / 2;
|
|
1204
1221
|
if (gap + EPSILON >= minClearance) continue;
|
|
1205
1222
|
const pairId = [viaA.pcb_via_id, viaB.pcb_via_id].sort().join("_");
|
|
1206
1223
|
if (reported.has(pairId)) continue;
|
|
@@ -1236,10 +1253,12 @@ import {
|
|
|
1236
1253
|
} from "circuit-json-to-connectivity-map";
|
|
1237
1254
|
function checkDifferentNetViaSpacing(circuitJson, {
|
|
1238
1255
|
connMap,
|
|
1239
|
-
minClearance
|
|
1256
|
+
minClearance
|
|
1240
1257
|
} = {}) {
|
|
1241
1258
|
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
1242
1259
|
if (vias.length < 2) return [];
|
|
1260
|
+
const board = getPcbBoard(circuitJson);
|
|
1261
|
+
minClearance ??= getBoardDrcValue(board, "min_via_hole_edge_to_via_hole_edge_clearance") ?? jlcMinTolerances.min_via_hole_edge_to_via_hole_edge_clearance;
|
|
1243
1262
|
connMap ??= getFullConnectivityMapFromCircuitJson4(circuitJson);
|
|
1244
1263
|
const errors = [];
|
|
1245
1264
|
const reported = /* @__PURE__ */ new Set();
|
|
@@ -1249,7 +1268,7 @@ function checkDifferentNetViaSpacing(circuitJson, {
|
|
|
1249
1268
|
const viaB = vias[j];
|
|
1250
1269
|
if (viasAreAtSameLocation(viaA, viaB)) continue;
|
|
1251
1270
|
if (connMap.areIdsConnected(viaA.pcb_via_id, viaB.pcb_via_id)) continue;
|
|
1252
|
-
const gap = distance2(viaA, viaB) - viaA.
|
|
1271
|
+
const gap = distance2(viaA, viaB) - viaA.hole_diameter / 2 - viaB.hole_diameter / 2;
|
|
1253
1272
|
if (gap + EPSILON >= minClearance) continue;
|
|
1254
1273
|
const pairId = [viaA.pcb_via_id, viaB.pcb_via_id].sort().join("_");
|
|
1255
1274
|
if (reported.has(pairId)) continue;
|
|
@@ -1402,7 +1421,6 @@ function checkSourceTracesHavePcbTraces(circuitJson) {
|
|
|
1402
1421
|
// lib/check-trace-out-of-board/checkTraceOutOfBoard.ts
|
|
1403
1422
|
import { cju as cju3 } from "@tscircuit/circuit-json-util";
|
|
1404
1423
|
import { segmentToSegmentMinDistance as segmentToSegmentMinDistance2 } from "@tscircuit/math-utils";
|
|
1405
|
-
var DEFAULT_BOARD_MARGIN = 0.2;
|
|
1406
1424
|
function getBoardPolygonPoints(board) {
|
|
1407
1425
|
if (board.outline && board.outline.length > 0) {
|
|
1408
1426
|
return board.outline.map((p) => ({ x: p.x, y: p.y }));
|
|
@@ -1427,11 +1445,9 @@ function getBoardPolygonPoints(board) {
|
|
|
1427
1445
|
}
|
|
1428
1446
|
function checkPcbTracesOutOfBoard(circuitJson, config = {}) {
|
|
1429
1447
|
const errors = [];
|
|
1430
|
-
const
|
|
1431
|
-
const board = circuitJson.find(
|
|
1432
|
-
(el) => el.type === "pcb_board"
|
|
1433
|
-
);
|
|
1448
|
+
const board = getPcbBoard(circuitJson);
|
|
1434
1449
|
if (!board) return errors;
|
|
1450
|
+
const margin = config.margin ?? getBoardDrcValue(board, "min_board_edge_clearance") ?? jlcMinTolerances.min_board_edge_clearance;
|
|
1435
1451
|
const boardPoints = getBoardPolygonPoints(board);
|
|
1436
1452
|
if (!boardPoints) return errors;
|
|
1437
1453
|
const pcbTraces = cju3(circuitJson).pcb_trace.list();
|
|
@@ -1444,7 +1460,7 @@ function checkPcbTracesOutOfBoard(circuitJson, config = {}) {
|
|
|
1444
1460
|
const traceWidth = "width" in p1 ? p1.width : "width" in p2 ? p2.width : 0.1;
|
|
1445
1461
|
const segmentStart = { x: p1.x, y: p1.y };
|
|
1446
1462
|
const segmentEnd = { x: p2.x, y: p2.y };
|
|
1447
|
-
let minDistance =
|
|
1463
|
+
let minDistance = Number.POSITIVE_INFINITY;
|
|
1448
1464
|
for (let j = 0; j < boardPoints.length; j++) {
|
|
1449
1465
|
const edgeStart = boardPoints[j];
|
|
1450
1466
|
const edgeEnd = boardPoints[(j + 1) % boardPoints.length];
|
|
@@ -1729,10 +1745,12 @@ var getTraceSegments = (circuitJson) => {
|
|
|
1729
1745
|
// lib/check-pad-pad-clearance.ts
|
|
1730
1746
|
function checkPadPadClearance(circuitJson, {
|
|
1731
1747
|
connMap,
|
|
1732
|
-
minClearance
|
|
1748
|
+
minClearance
|
|
1733
1749
|
} = {}) {
|
|
1734
1750
|
const pads = getPads(circuitJson);
|
|
1735
1751
|
if (pads.length < 2) return [];
|
|
1752
|
+
const board = getPcbBoard(circuitJson);
|
|
1753
|
+
minClearance ??= getBoardDrcValue(board, "min_pad_edge_to_pad_edge_clearance") ?? jlcMinTolerances.min_pad_edge_to_pad_edge_clearance;
|
|
1736
1754
|
connMap ??= getFullConnectivityMapFromCircuitJson7(circuitJson);
|
|
1737
1755
|
const spatialIndex = new SpatialObjectIndex({
|
|
1738
1756
|
objects: pads,
|
|
@@ -1795,11 +1813,13 @@ import {
|
|
|
1795
1813
|
} from "circuit-json-to-connectivity-map";
|
|
1796
1814
|
function checkPadTraceClearance(circuitJson, {
|
|
1797
1815
|
connMap,
|
|
1798
|
-
minClearance
|
|
1816
|
+
minClearance
|
|
1799
1817
|
} = {}) {
|
|
1800
1818
|
const pads = getPads(circuitJson);
|
|
1801
1819
|
const segments = getTraceSegments(circuitJson);
|
|
1802
1820
|
if (pads.length === 0 || segments.length === 0) return [];
|
|
1821
|
+
const board = getPcbBoard(circuitJson);
|
|
1822
|
+
minClearance ??= getBoardDrcValue(board, "min_trace_to_pad_edge_clearance") ?? jlcMinTolerances.min_trace_to_pad_edge_clearance;
|
|
1803
1823
|
connMap ??= getFullConnectivityMapFromCircuitJson8(circuitJson);
|
|
1804
1824
|
const spatialIndex = new SpatialObjectIndex({
|
|
1805
1825
|
objects: pads,
|
|
@@ -1876,11 +1896,13 @@ var getClosestPointOnSegment = (point, segmentStart, segmentEnd) => {
|
|
|
1876
1896
|
};
|
|
1877
1897
|
function checkViaTraceClearance(circuitJson, {
|
|
1878
1898
|
connMap,
|
|
1879
|
-
minClearance
|
|
1899
|
+
minClearance
|
|
1880
1900
|
} = {}) {
|
|
1881
1901
|
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
1882
1902
|
const segments = getTraceSegments(circuitJson);
|
|
1883
1903
|
if (vias.length === 0 || segments.length === 0) return [];
|
|
1904
|
+
const board = getPcbBoard(circuitJson);
|
|
1905
|
+
minClearance ??= getBoardDrcValue(board, "min_trace_to_pad_edge_clearance") ?? jlcMinTolerances.min_trace_to_pad_edge_clearance;
|
|
1884
1906
|
connMap ??= getFullConnectivityMapFromCircuitJson9(circuitJson);
|
|
1885
1907
|
const errors = /* @__PURE__ */ new Map();
|
|
1886
1908
|
for (const via of vias) {
|