@tscircuit/checks 0.0.208 → 0.0.210
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 +7 -4
- package/dist/index.js +369 -217
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,325 @@
|
|
|
1
|
+
// lib/check-pcb-trace-self-shorts.ts
|
|
2
|
+
import { cju } from "@tscircuit/circuit-json-util";
|
|
3
|
+
import { segmentToSegmentMinDistance } from "@tscircuit/math-utils";
|
|
4
|
+
import {
|
|
5
|
+
all_layers
|
|
6
|
+
} from "circuit-json";
|
|
7
|
+
|
|
8
|
+
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegments.ts
|
|
9
|
+
var getClosestPointBetweenSegments = (segmentA, segmentB) => {
|
|
10
|
+
const a1 = { x: segmentA.x1, y: segmentA.y1 };
|
|
11
|
+
const a2 = { x: segmentA.x2, y: segmentA.y2 };
|
|
12
|
+
const b1 = { x: segmentB.x1, y: segmentB.y1 };
|
|
13
|
+
const b2 = { x: segmentB.x2, y: segmentB.y2 };
|
|
14
|
+
const va = { x: a2.x - a1.x, y: a2.y - a1.y };
|
|
15
|
+
const vb = { x: b2.x - b1.x, y: b2.y - b1.y };
|
|
16
|
+
const lenSqrA = va.x * va.x + va.y * va.y;
|
|
17
|
+
const lenSqrB = vb.x * vb.x + vb.y * vb.y;
|
|
18
|
+
if (lenSqrA === 0 || lenSqrB === 0) {
|
|
19
|
+
if (lenSqrA === 0 && lenSqrB === 0) {
|
|
20
|
+
return {
|
|
21
|
+
x: (a1.x + b1.x) / 2,
|
|
22
|
+
y: (a1.y + b1.y) / 2
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (lenSqrA === 0) {
|
|
26
|
+
const t2 = clamp(
|
|
27
|
+
((a1.x - b1.x) * vb.x + (a1.y - b1.y) * vb.y) / lenSqrB,
|
|
28
|
+
0,
|
|
29
|
+
1
|
|
30
|
+
);
|
|
31
|
+
const closestOnB2 = {
|
|
32
|
+
x: b1.x + t2 * vb.x,
|
|
33
|
+
y: b1.y + t2 * vb.y
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
x: (a1.x + closestOnB2.x) / 2,
|
|
37
|
+
y: (a1.y + closestOnB2.y) / 2
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const t = clamp(
|
|
41
|
+
((b1.x - a1.x) * va.x + (b1.y - a1.y) * va.y) / lenSqrA,
|
|
42
|
+
0,
|
|
43
|
+
1
|
|
44
|
+
);
|
|
45
|
+
const closestOnA2 = {
|
|
46
|
+
x: a1.x + t * va.x,
|
|
47
|
+
y: a1.y + t * va.y
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
x: (closestOnA2.x + b1.x) / 2,
|
|
51
|
+
y: (closestOnA2.y + b1.y) / 2
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const w = { x: a1.x - b1.x, y: a1.y - b1.y };
|
|
55
|
+
const dotAA = va.x * va.x + va.y * va.y;
|
|
56
|
+
const dotAB = va.x * vb.x + va.y * vb.y;
|
|
57
|
+
const dotAW = va.x * w.x + va.y * w.y;
|
|
58
|
+
const dotBB = vb.x * vb.x + vb.y * vb.y;
|
|
59
|
+
const dotBW = vb.x * w.x + vb.y * w.y;
|
|
60
|
+
const denominator = dotAA * dotBB - dotAB * dotAB;
|
|
61
|
+
if (denominator < 1e-10) {
|
|
62
|
+
return closestPointsParallelSegments(
|
|
63
|
+
a1,
|
|
64
|
+
a2,
|
|
65
|
+
b1,
|
|
66
|
+
b2,
|
|
67
|
+
va,
|
|
68
|
+
vb,
|
|
69
|
+
lenSqrA,
|
|
70
|
+
lenSqrB
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
let tA = (dotAB * dotBW - dotBB * dotAW) / denominator;
|
|
74
|
+
let tB = (dotAA * dotBW - dotAB * dotAW) / denominator;
|
|
75
|
+
tA = clamp(tA, 0, 1);
|
|
76
|
+
tB = clamp(tB, 0, 1);
|
|
77
|
+
tB = (tA * dotAB + dotBW) / dotBB;
|
|
78
|
+
tB = clamp(tB, 0, 1);
|
|
79
|
+
tA = (tB * dotAB - dotAW) / dotAA;
|
|
80
|
+
tA = clamp(tA, 0, 1);
|
|
81
|
+
const closestOnA = {
|
|
82
|
+
x: a1.x + tA * va.x,
|
|
83
|
+
y: a1.y + tA * va.y
|
|
84
|
+
};
|
|
85
|
+
const closestOnB = {
|
|
86
|
+
x: b1.x + tB * vb.x,
|
|
87
|
+
y: b1.y + tB * vb.y
|
|
88
|
+
};
|
|
89
|
+
const dx = closestOnA.x - closestOnB.x;
|
|
90
|
+
const dy = closestOnA.y - closestOnB.y;
|
|
91
|
+
const distance3 = Math.sqrt(dx * dx + dy * dy);
|
|
92
|
+
const averagePoint = {
|
|
93
|
+
x: (closestOnA.x + closestOnB.x) / 2,
|
|
94
|
+
y: (closestOnA.y + closestOnB.y) / 2
|
|
95
|
+
};
|
|
96
|
+
return averagePoint;
|
|
97
|
+
};
|
|
98
|
+
var closestPointsParallelSegments = (a1, a2, b1, b2, va, vb, lenSqrA, lenSqrB) => {
|
|
99
|
+
let tA = ((b1.x - a1.x) * va.x + (b1.y - a1.y) * va.y) / lenSqrA;
|
|
100
|
+
tA = clamp(tA, 0, 1);
|
|
101
|
+
const pointOnA1 = { x: a1.x + tA * va.x, y: a1.y + tA * va.y };
|
|
102
|
+
let tA2 = ((b2.x - a1.x) * va.x + (b2.y - a1.y) * va.y) / lenSqrA;
|
|
103
|
+
tA2 = clamp(tA2, 0, 1);
|
|
104
|
+
const pointOnA2 = { x: a1.x + tA2 * va.x, y: a1.y + tA2 * va.y };
|
|
105
|
+
let tB = ((a1.x - b1.x) * vb.x + (a1.y - b1.y) * vb.y) / lenSqrB;
|
|
106
|
+
tB = clamp(tB, 0, 1);
|
|
107
|
+
const pointOnB1 = { x: b1.x + tB * vb.x, y: b1.y + tB * vb.y };
|
|
108
|
+
let tB2 = ((a2.x - b1.x) * vb.x + (a2.y - b1.y) * vb.y) / lenSqrB;
|
|
109
|
+
tB2 = clamp(tB2, 0, 1);
|
|
110
|
+
const pointOnB2 = { x: b1.x + tB2 * vb.x, y: b1.y + tB2 * vb.y };
|
|
111
|
+
const distances = [
|
|
112
|
+
{
|
|
113
|
+
pointA: pointOnA1,
|
|
114
|
+
pointB: b1,
|
|
115
|
+
distance: Math.sqrt(
|
|
116
|
+
(pointOnA1.x - b1.x) ** 2 + (pointOnA1.y - b1.y) ** 2
|
|
117
|
+
)
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
pointA: pointOnA2,
|
|
121
|
+
pointB: b2,
|
|
122
|
+
distance: Math.sqrt(
|
|
123
|
+
(pointOnA2.x - b2.x) ** 2 + (pointOnA2.y - b2.y) ** 2
|
|
124
|
+
)
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
pointA: a1,
|
|
128
|
+
pointB: pointOnB1,
|
|
129
|
+
distance: Math.sqrt(
|
|
130
|
+
(a1.x - pointOnB1.x) ** 2 + (a1.y - pointOnB1.y) ** 2
|
|
131
|
+
)
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
pointA: a2,
|
|
135
|
+
pointB: pointOnB2,
|
|
136
|
+
distance: Math.sqrt(
|
|
137
|
+
(a2.x - pointOnB2.x) ** 2 + (a2.y - pointOnB2.y) ** 2
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
];
|
|
141
|
+
const closestPair = distances.reduce(
|
|
142
|
+
(closest, current) => current.distance < closest.distance ? current : closest
|
|
143
|
+
);
|
|
144
|
+
return {
|
|
145
|
+
x: (closestPair.pointA.x + closestPair.pointB.x) / 2,
|
|
146
|
+
y: (closestPair.pointA.y + closestPair.pointB.y) / 2
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
var clamp = (value, min, max) => {
|
|
150
|
+
return Math.max(min, Math.min(max, value));
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
|
|
154
|
+
function getPcbPortIdsConnectedToRoutePoint(routePoint) {
|
|
155
|
+
if (routePoint.route_type !== "wire") return [];
|
|
156
|
+
return [routePoint.start_pcb_port_id, routePoint.end_pcb_port_id].filter(
|
|
157
|
+
(portId) => Boolean(portId)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
function getPcbPortIdsConnectedToTrace(trace) {
|
|
161
|
+
const connectedPcbPorts = /* @__PURE__ */ new Set();
|
|
162
|
+
for (const segment of trace.route) {
|
|
163
|
+
for (const portId of getPcbPortIdsConnectedToRoutePoint(segment)) {
|
|
164
|
+
connectedPcbPorts.add(portId);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return Array.from(connectedPcbPorts);
|
|
168
|
+
}
|
|
169
|
+
function getPcbPortIdsConnectedToTraces(traces) {
|
|
170
|
+
const connectedPorts = /* @__PURE__ */ new Set();
|
|
171
|
+
for (const trace of traces) {
|
|
172
|
+
for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
|
|
173
|
+
connectedPorts.add(portId);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return Array.from(connectedPorts);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// lib/check-pcb-trace-self-shorts.ts
|
|
180
|
+
function checkPcbTraceSelfShorts(circuitJson) {
|
|
181
|
+
const matchedSourceTraceIds = new Set(
|
|
182
|
+
circuitJson.flatMap(
|
|
183
|
+
(element) => element.type === "source_bus" && element.max_length_skew !== void 0 ? element.source_trace_ids : []
|
|
184
|
+
)
|
|
185
|
+
);
|
|
186
|
+
const db = cju(circuitJson);
|
|
187
|
+
const errors = [];
|
|
188
|
+
for (const trace of circuitJson) {
|
|
189
|
+
if (trace.type !== "pcb_trace") continue;
|
|
190
|
+
if (!trace.source_trace_id || !matchedSourceTraceIds.has(trace.source_trace_id))
|
|
191
|
+
continue;
|
|
192
|
+
const segments = [];
|
|
193
|
+
const routeDistances = [];
|
|
194
|
+
let distance3 = 0;
|
|
195
|
+
let run = 0;
|
|
196
|
+
for (let i = 0; i < trace.route.length - 1; i++) {
|
|
197
|
+
routeDistances[i] = distance3;
|
|
198
|
+
const a = trace.route[i];
|
|
199
|
+
const b = trace.route[i + 1];
|
|
200
|
+
if (a.route_type !== "wire" || b.route_type !== "wire" || a.layer !== b.layer) {
|
|
201
|
+
run++;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const length = Math.hypot(b.x - a.x, b.y - a.y);
|
|
205
|
+
if (length === 0) continue;
|
|
206
|
+
segments.push({
|
|
207
|
+
type: "pcb_trace_segment",
|
|
208
|
+
_pcbTrace: trace,
|
|
209
|
+
pcb_trace_id: trace.pcb_trace_id,
|
|
210
|
+
thickness: a.width,
|
|
211
|
+
layer: a.layer,
|
|
212
|
+
x1: a.x,
|
|
213
|
+
y1: a.y,
|
|
214
|
+
x2: b.x,
|
|
215
|
+
y2: b.y,
|
|
216
|
+
run,
|
|
217
|
+
startDistance: distance3,
|
|
218
|
+
endDistance: distance3 + length
|
|
219
|
+
});
|
|
220
|
+
distance3 += length;
|
|
221
|
+
}
|
|
222
|
+
routeDistances[trace.route.length - 1] = distance3;
|
|
223
|
+
let shortCenter;
|
|
224
|
+
pairs: for (let i = 0; i < segments.length; i++) {
|
|
225
|
+
const a = segments[i];
|
|
226
|
+
for (let j = i + 1; j < segments.length; j++) {
|
|
227
|
+
const b = segments[j];
|
|
228
|
+
if (a.layer !== b.layer) continue;
|
|
229
|
+
const contactDistance = (a.thickness + b.thickness) / 2;
|
|
230
|
+
const dot = (a.x2 - a.x1) * (b.x2 - b.x1) + (a.y2 - a.y1) * (b.y2 - b.y1);
|
|
231
|
+
const cross = (a.x2 - a.x1) * (b.y2 - b.y1) - (a.y2 - a.y1) * (b.x2 - b.x1);
|
|
232
|
+
const directionLengthProduct = Math.hypot(a.x2 - a.x1, a.y2 - a.y1) * Math.hypot(b.x2 - b.x1, b.y2 - b.y1);
|
|
233
|
+
const isForwardOrRightAngle = dot >= -1e-9 * directionLengthProduct;
|
|
234
|
+
const adjacent = a.run === b.run && b.startDistance === a.endDistance;
|
|
235
|
+
if (adjacent && !(dot < 0 && Math.abs(cross) < 1e-9)) continue;
|
|
236
|
+
if (!adjacent && a.run === b.run && // A right-angle connector can have sqrt(2) times the straight-line
|
|
237
|
+
// distance. Its local copper overlap is still part of the same bend.
|
|
238
|
+
b.startDistance - a.endDistance <= Math.SQRT2 * contactDistance && isForwardOrRightAngle)
|
|
239
|
+
continue;
|
|
240
|
+
const gap = segmentToSegmentMinDistance(
|
|
241
|
+
{ x: a.x1, y: a.y1 },
|
|
242
|
+
{ x: a.x2, y: a.y2 },
|
|
243
|
+
{ x: b.x1, y: b.y1 },
|
|
244
|
+
{ x: b.x2, y: b.y2 }
|
|
245
|
+
) - contactDistance;
|
|
246
|
+
if (gap > 1e-9) continue;
|
|
247
|
+
shortCenter = getClosestPointBetweenSegments(a, b);
|
|
248
|
+
break pairs;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (!shortCenter) {
|
|
252
|
+
const board = circuitJson.find((e) => e.type === "pcb_board");
|
|
253
|
+
const stack = [
|
|
254
|
+
"top",
|
|
255
|
+
...all_layers.filter((layer) => layer.startsWith("inner")).slice(0, board ? Math.max(0, board.num_layers - 2) : void 0),
|
|
256
|
+
...board?.num_layers === 1 ? [] : ["bottom"]
|
|
257
|
+
];
|
|
258
|
+
vias: for (let i = 0; i < trace.route.length; i++) {
|
|
259
|
+
const point2 = trace.route[i];
|
|
260
|
+
if (point2.route_type !== "via") continue;
|
|
261
|
+
const materialized = db.pcb_via.list().find(
|
|
262
|
+
(via) => (via.pcb_trace_id === trace.pcb_trace_id || !via.pcb_trace_id && via.source_trace_id === trace.source_trace_id) && Math.hypot(via.x - point2.x, via.y - point2.y) <= 1e-9
|
|
263
|
+
);
|
|
264
|
+
const diameter = materialized?.outer_diameter ?? point2.outer_diameter;
|
|
265
|
+
if (diameter === void 0 || !Number.isFinite(diameter) || diameter <= 0)
|
|
266
|
+
continue;
|
|
267
|
+
const from = stack.indexOf(point2.from_layer);
|
|
268
|
+
const to = stack.indexOf(point2.to_layer);
|
|
269
|
+
const layers = materialized?.layers ?? (from >= 0 && to >= 0 ? stack.slice(Math.min(from, to), Math.max(from, to) + 1) : []);
|
|
270
|
+
for (const segment of segments) {
|
|
271
|
+
if (!layers.includes(segment.layer)) continue;
|
|
272
|
+
const reach = (diameter + segment.thickness) / 2;
|
|
273
|
+
const alongRouteGap = Math.max(
|
|
274
|
+
segment.startDistance - routeDistances[i],
|
|
275
|
+
routeDistances[i] - segment.endDistance,
|
|
276
|
+
0
|
|
277
|
+
);
|
|
278
|
+
if (alongRouteGap <= reach + 1e-9) continue;
|
|
279
|
+
const viaSegment = {
|
|
280
|
+
...segment,
|
|
281
|
+
x1: point2.x,
|
|
282
|
+
y1: point2.y,
|
|
283
|
+
x2: point2.x,
|
|
284
|
+
y2: point2.y
|
|
285
|
+
};
|
|
286
|
+
const gap = segmentToSegmentMinDistance(
|
|
287
|
+
point2,
|
|
288
|
+
point2,
|
|
289
|
+
{ x: segment.x1, y: segment.y1 },
|
|
290
|
+
{ x: segment.x2, y: segment.y2 }
|
|
291
|
+
) - reach;
|
|
292
|
+
if (gap > 1e-9) continue;
|
|
293
|
+
shortCenter = getClosestPointBetweenSegments(segment, viaSegment);
|
|
294
|
+
break vias;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (shortCenter) {
|
|
299
|
+
const sourceTrace = db.source_trace.get(trace.source_trace_id);
|
|
300
|
+
const endpointNames = (sourceTrace?.connected_source_port_ids ?? []).map((id) => {
|
|
301
|
+
const port = db.source_port.get(id);
|
|
302
|
+
const component = port?.source_component_id ? db.source_component.get(port.source_component_id) : void 0;
|
|
303
|
+
return component?.name && port?.name ? `${component.name}.${port.name}` : void 0;
|
|
304
|
+
}).filter((name) => Boolean(name));
|
|
305
|
+
const traceName = sourceTrace?.name || sourceTrace?.display_name || endpointNames.join(" \u2192 ") || "unnamed";
|
|
306
|
+
errors.push({
|
|
307
|
+
type: "pcb_trace_error",
|
|
308
|
+
error_type: "pcb_trace_error",
|
|
309
|
+
pcb_trace_error_id: `self_short_${trace.pcb_trace_id}`,
|
|
310
|
+
pcb_trace_id: trace.pcb_trace_id,
|
|
311
|
+
source_trace_id: trace.source_trace_id,
|
|
312
|
+
message: `PCB trace "${traceName}" shorts to itself, bypassing part of its length-matched route`,
|
|
313
|
+
center: shortCenter,
|
|
314
|
+
pcb_component_ids: [],
|
|
315
|
+
pcb_port_ids: getPcbPortIdsConnectedToTraces([trace]),
|
|
316
|
+
subcircuit_id: trace.subcircuit_id
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return errors;
|
|
321
|
+
}
|
|
322
|
+
|
|
1
323
|
// lib/check-copper-pour-shorts.ts
|
|
2
324
|
import Flatbush from "flatbush";
|
|
3
325
|
import "@flatten-js/core";
|
|
@@ -717,7 +1039,7 @@ import {
|
|
|
717
1039
|
import Flatbush3 from "flatbush";
|
|
718
1040
|
|
|
719
1041
|
// lib/util/get-via-and-pour-connections.ts
|
|
720
|
-
import { all_layers } from "circuit-json";
|
|
1042
|
+
import { all_layers as all_layers2 } from "circuit-json";
|
|
721
1043
|
import {
|
|
722
1044
|
getPourPolygon,
|
|
723
1045
|
getTraceSegmentPolygon,
|
|
@@ -798,7 +1120,7 @@ function getViaAndPourConnections(circuit) {
|
|
|
798
1120
|
const board = circuit.find((e) => e.type === "pcb_board");
|
|
799
1121
|
const stack = [
|
|
800
1122
|
"top",
|
|
801
|
-
...
|
|
1123
|
+
...all_layers2.filter((l) => l.startsWith("inner")).slice(0, board ? Math.max(0, board.num_layers - 2) : void 0),
|
|
802
1124
|
...board?.num_layers === 1 ? [] : ["bottom"]
|
|
803
1125
|
];
|
|
804
1126
|
for (const copper of circuit) {
|
|
@@ -974,7 +1296,7 @@ import {
|
|
|
974
1296
|
getSegmentIntersection,
|
|
975
1297
|
isPointInsidePolygon,
|
|
976
1298
|
pointToSegmentClosestPoint,
|
|
977
|
-
segmentToSegmentMinDistance
|
|
1299
|
+
segmentToSegmentMinDistance as segmentToSegmentMinDistance2
|
|
978
1300
|
} from "@tscircuit/math-utils";
|
|
979
1301
|
var rotatePoint = (point2, angleDegrees) => {
|
|
980
1302
|
const angle = angleDegrees * Math.PI / 180;
|
|
@@ -1074,7 +1396,7 @@ var getClosestPointsBetweenSegments = (a1, a2, b1, b2) => {
|
|
|
1074
1396
|
}
|
|
1075
1397
|
}
|
|
1076
1398
|
return {
|
|
1077
|
-
distance:
|
|
1399
|
+
distance: segmentToSegmentMinDistance2(a1, a2, b1, b2),
|
|
1078
1400
|
pointOnA: best.pointOnA,
|
|
1079
1401
|
pointOnB: best.pointOnB,
|
|
1080
1402
|
center: {
|
|
@@ -1695,20 +2017,20 @@ function checkEachPcbPortConnectedToPcbTraces(circuitJson, {
|
|
|
1695
2017
|
}
|
|
1696
2018
|
|
|
1697
2019
|
// lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
|
|
1698
|
-
import { cju as
|
|
2020
|
+
import { cju as cju3, getReadableNameForElement as getReadableNameForElement3 } from "@tscircuit/circuit-json-util";
|
|
1699
2021
|
import { getPrimaryId as getPrimaryId2 } from "@tscircuit/circuit-json-util";
|
|
1700
2022
|
import {
|
|
1701
2023
|
segmentToBoundsMinDistance,
|
|
1702
2024
|
segmentToCircleMinDistance as segmentToCircleMinDistance2
|
|
1703
2025
|
} from "@tscircuit/math-utils";
|
|
1704
|
-
import { segmentToSegmentMinDistance as
|
|
2026
|
+
import { segmentToSegmentMinDistance as segmentToSegmentMinDistance4 } from "@tscircuit/math-utils";
|
|
1705
2027
|
import {
|
|
1706
2028
|
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson3
|
|
1707
2029
|
} from "circuit-json-to-connectivity-map";
|
|
1708
2030
|
|
|
1709
2031
|
// lib/check-pad-clearance/common.ts
|
|
1710
2032
|
import {
|
|
1711
|
-
cju,
|
|
2033
|
+
cju as cju2,
|
|
1712
2034
|
distanceBetweenCircleAndCircle,
|
|
1713
2035
|
distanceBetweenCircleAndPolygon,
|
|
1714
2036
|
distanceBetweenPolygonAndPolygon,
|
|
@@ -1718,7 +2040,7 @@ import {
|
|
|
1718
2040
|
midpoint,
|
|
1719
2041
|
pointToSegmentClosestPoint as pointToSegmentClosestPoint2,
|
|
1720
2042
|
segmentToCircleMinDistance,
|
|
1721
|
-
segmentToSegmentMinDistance as
|
|
2043
|
+
segmentToSegmentMinDistance as segmentToSegmentMinDistance3
|
|
1722
2044
|
} from "@tscircuit/math-utils";
|
|
1723
2045
|
|
|
1724
2046
|
// node_modules/@tscircuit/jlcpcb-manufacturing-specs/lib/jlcpcb-manufacturing-specs.ts
|
|
@@ -1885,7 +2207,7 @@ var getPadToPadGap = (padA, padB) => {
|
|
|
1885
2207
|
if (isPillPad(padA) && isPillPad(padB)) {
|
|
1886
2208
|
const pillA = getPillCenterLineForPad(padA);
|
|
1887
2209
|
const pillB = getPillCenterLineForPad(padB);
|
|
1888
|
-
return
|
|
2210
|
+
return segmentToSegmentMinDistance3(
|
|
1889
2211
|
pillA.start,
|
|
1890
2212
|
pillA.end,
|
|
1891
2213
|
pillB.start,
|
|
@@ -1940,11 +2262,11 @@ var getPadToPadGap = (padA, padB) => {
|
|
|
1940
2262
|
);
|
|
1941
2263
|
};
|
|
1942
2264
|
var getPads = (circuitJson) => [
|
|
1943
|
-
...
|
|
1944
|
-
...
|
|
2265
|
+
...cju2(circuitJson).pcb_smtpad.list(),
|
|
2266
|
+
...cju2(circuitJson).pcb_plated_hole.list()
|
|
1945
2267
|
];
|
|
1946
2268
|
var getTraceSegments = (circuitJson) => {
|
|
1947
|
-
const pcbTraces =
|
|
2269
|
+
const pcbTraces = cju2(circuitJson).pcb_trace.list();
|
|
1948
2270
|
return pcbTraces.flatMap((pcbTrace) => {
|
|
1949
2271
|
const segments = [];
|
|
1950
2272
|
for (let i = 0; i < pcbTrace.route.length - 1; i++) {
|
|
@@ -2162,7 +2484,7 @@ var SpatialObjectIndex = class {
|
|
|
2162
2484
|
};
|
|
2163
2485
|
|
|
2164
2486
|
// lib/util/getLayersOfPcbElement.ts
|
|
2165
|
-
import { all_layers as
|
|
2487
|
+
import { all_layers as all_layers3 } from "circuit-json";
|
|
2166
2488
|
function getLayersOfPcbElement(obj) {
|
|
2167
2489
|
if (obj.type === "pcb_trace_segment") {
|
|
2168
2490
|
return [obj.layer];
|
|
@@ -2171,13 +2493,13 @@ function getLayersOfPcbElement(obj) {
|
|
|
2171
2493
|
return [obj.layer];
|
|
2172
2494
|
}
|
|
2173
2495
|
if (obj.type === "pcb_plated_hole") {
|
|
2174
|
-
return Array.isArray(obj.layers) ? obj.layers : [...
|
|
2496
|
+
return Array.isArray(obj.layers) ? obj.layers : [...all_layers3];
|
|
2175
2497
|
}
|
|
2176
2498
|
if (obj.type === "pcb_hole") {
|
|
2177
|
-
return [...
|
|
2499
|
+
return [...all_layers3];
|
|
2178
2500
|
}
|
|
2179
2501
|
if (obj.type === "pcb_via") {
|
|
2180
|
-
return Array.isArray(obj.layers) ? obj.layers : [...
|
|
2502
|
+
return Array.isArray(obj.layers) ? obj.layers : [...all_layers3];
|
|
2181
2503
|
}
|
|
2182
2504
|
if (obj.type === "pcb_keepout") {
|
|
2183
2505
|
return Array.isArray(obj.layers) ? obj.layers : [];
|
|
@@ -2278,151 +2600,6 @@ var getClosestPointBetweenSegmentAndBounds = (segment, bounds) => {
|
|
|
2278
2600
|
return closestPoint;
|
|
2279
2601
|
};
|
|
2280
2602
|
|
|
2281
|
-
// lib/check-each-pcb-trace-non-overlapping/getClosestPointBetweenSegments.ts
|
|
2282
|
-
var getClosestPointBetweenSegments = (segmentA, segmentB) => {
|
|
2283
|
-
const a1 = { x: segmentA.x1, y: segmentA.y1 };
|
|
2284
|
-
const a2 = { x: segmentA.x2, y: segmentA.y2 };
|
|
2285
|
-
const b1 = { x: segmentB.x1, y: segmentB.y1 };
|
|
2286
|
-
const b2 = { x: segmentB.x2, y: segmentB.y2 };
|
|
2287
|
-
const va = { x: a2.x - a1.x, y: a2.y - a1.y };
|
|
2288
|
-
const vb = { x: b2.x - b1.x, y: b2.y - b1.y };
|
|
2289
|
-
const lenSqrA = va.x * va.x + va.y * va.y;
|
|
2290
|
-
const lenSqrB = vb.x * vb.x + vb.y * vb.y;
|
|
2291
|
-
if (lenSqrA === 0 || lenSqrB === 0) {
|
|
2292
|
-
if (lenSqrA === 0 && lenSqrB === 0) {
|
|
2293
|
-
return {
|
|
2294
|
-
x: (a1.x + b1.x) / 2,
|
|
2295
|
-
y: (a1.y + b1.y) / 2
|
|
2296
|
-
};
|
|
2297
|
-
}
|
|
2298
|
-
if (lenSqrA === 0) {
|
|
2299
|
-
const t2 = clamp(
|
|
2300
|
-
((a1.x - b1.x) * vb.x + (a1.y - b1.y) * vb.y) / lenSqrB,
|
|
2301
|
-
0,
|
|
2302
|
-
1
|
|
2303
|
-
);
|
|
2304
|
-
const closestOnB2 = {
|
|
2305
|
-
x: b1.x + t2 * vb.x,
|
|
2306
|
-
y: b1.y + t2 * vb.y
|
|
2307
|
-
};
|
|
2308
|
-
return {
|
|
2309
|
-
x: (a1.x + closestOnB2.x) / 2,
|
|
2310
|
-
y: (a1.y + closestOnB2.y) / 2
|
|
2311
|
-
};
|
|
2312
|
-
}
|
|
2313
|
-
const t = clamp(
|
|
2314
|
-
((b1.x - a1.x) * va.x + (b1.y - a1.y) * va.y) / lenSqrA,
|
|
2315
|
-
0,
|
|
2316
|
-
1
|
|
2317
|
-
);
|
|
2318
|
-
const closestOnA2 = {
|
|
2319
|
-
x: a1.x + t * va.x,
|
|
2320
|
-
y: a1.y + t * va.y
|
|
2321
|
-
};
|
|
2322
|
-
return {
|
|
2323
|
-
x: (closestOnA2.x + b1.x) / 2,
|
|
2324
|
-
y: (closestOnA2.y + b1.y) / 2
|
|
2325
|
-
};
|
|
2326
|
-
}
|
|
2327
|
-
const w = { x: a1.x - b1.x, y: a1.y - b1.y };
|
|
2328
|
-
const dotAA = va.x * va.x + va.y * va.y;
|
|
2329
|
-
const dotAB = va.x * vb.x + va.y * vb.y;
|
|
2330
|
-
const dotAW = va.x * w.x + va.y * w.y;
|
|
2331
|
-
const dotBB = vb.x * vb.x + vb.y * vb.y;
|
|
2332
|
-
const dotBW = vb.x * w.x + vb.y * w.y;
|
|
2333
|
-
const denominator = dotAA * dotBB - dotAB * dotAB;
|
|
2334
|
-
if (denominator < 1e-10) {
|
|
2335
|
-
return closestPointsParallelSegments(
|
|
2336
|
-
a1,
|
|
2337
|
-
a2,
|
|
2338
|
-
b1,
|
|
2339
|
-
b2,
|
|
2340
|
-
va,
|
|
2341
|
-
vb,
|
|
2342
|
-
lenSqrA,
|
|
2343
|
-
lenSqrB
|
|
2344
|
-
);
|
|
2345
|
-
}
|
|
2346
|
-
let tA = (dotAB * dotBW - dotBB * dotAW) / denominator;
|
|
2347
|
-
let tB = (dotAA * dotBW - dotAB * dotAW) / denominator;
|
|
2348
|
-
tA = clamp(tA, 0, 1);
|
|
2349
|
-
tB = clamp(tB, 0, 1);
|
|
2350
|
-
tB = (tA * dotAB + dotBW) / dotBB;
|
|
2351
|
-
tB = clamp(tB, 0, 1);
|
|
2352
|
-
tA = (tB * dotAB - dotAW) / dotAA;
|
|
2353
|
-
tA = clamp(tA, 0, 1);
|
|
2354
|
-
const closestOnA = {
|
|
2355
|
-
x: a1.x + tA * va.x,
|
|
2356
|
-
y: a1.y + tA * va.y
|
|
2357
|
-
};
|
|
2358
|
-
const closestOnB = {
|
|
2359
|
-
x: b1.x + tB * vb.x,
|
|
2360
|
-
y: b1.y + tB * vb.y
|
|
2361
|
-
};
|
|
2362
|
-
const dx = closestOnA.x - closestOnB.x;
|
|
2363
|
-
const dy = closestOnA.y - closestOnB.y;
|
|
2364
|
-
const distance3 = Math.sqrt(dx * dx + dy * dy);
|
|
2365
|
-
const averagePoint = {
|
|
2366
|
-
x: (closestOnA.x + closestOnB.x) / 2,
|
|
2367
|
-
y: (closestOnA.y + closestOnB.y) / 2
|
|
2368
|
-
};
|
|
2369
|
-
return averagePoint;
|
|
2370
|
-
};
|
|
2371
|
-
var closestPointsParallelSegments = (a1, a2, b1, b2, va, vb, lenSqrA, lenSqrB) => {
|
|
2372
|
-
let tA = ((b1.x - a1.x) * va.x + (b1.y - a1.y) * va.y) / lenSqrA;
|
|
2373
|
-
tA = clamp(tA, 0, 1);
|
|
2374
|
-
const pointOnA1 = { x: a1.x + tA * va.x, y: a1.y + tA * va.y };
|
|
2375
|
-
let tA2 = ((b2.x - a1.x) * va.x + (b2.y - a1.y) * va.y) / lenSqrA;
|
|
2376
|
-
tA2 = clamp(tA2, 0, 1);
|
|
2377
|
-
const pointOnA2 = { x: a1.x + tA2 * va.x, y: a1.y + tA2 * va.y };
|
|
2378
|
-
let tB = ((a1.x - b1.x) * vb.x + (a1.y - b1.y) * vb.y) / lenSqrB;
|
|
2379
|
-
tB = clamp(tB, 0, 1);
|
|
2380
|
-
const pointOnB1 = { x: b1.x + tB * vb.x, y: b1.y + tB * vb.y };
|
|
2381
|
-
let tB2 = ((a2.x - b1.x) * vb.x + (a2.y - b1.y) * vb.y) / lenSqrB;
|
|
2382
|
-
tB2 = clamp(tB2, 0, 1);
|
|
2383
|
-
const pointOnB2 = { x: b1.x + tB2 * vb.x, y: b1.y + tB2 * vb.y };
|
|
2384
|
-
const distances = [
|
|
2385
|
-
{
|
|
2386
|
-
pointA: pointOnA1,
|
|
2387
|
-
pointB: b1,
|
|
2388
|
-
distance: Math.sqrt(
|
|
2389
|
-
(pointOnA1.x - b1.x) ** 2 + (pointOnA1.y - b1.y) ** 2
|
|
2390
|
-
)
|
|
2391
|
-
},
|
|
2392
|
-
{
|
|
2393
|
-
pointA: pointOnA2,
|
|
2394
|
-
pointB: b2,
|
|
2395
|
-
distance: Math.sqrt(
|
|
2396
|
-
(pointOnA2.x - b2.x) ** 2 + (pointOnA2.y - b2.y) ** 2
|
|
2397
|
-
)
|
|
2398
|
-
},
|
|
2399
|
-
{
|
|
2400
|
-
pointA: a1,
|
|
2401
|
-
pointB: pointOnB1,
|
|
2402
|
-
distance: Math.sqrt(
|
|
2403
|
-
(a1.x - pointOnB1.x) ** 2 + (a1.y - pointOnB1.y) ** 2
|
|
2404
|
-
)
|
|
2405
|
-
},
|
|
2406
|
-
{
|
|
2407
|
-
pointA: a2,
|
|
2408
|
-
pointB: pointOnB2,
|
|
2409
|
-
distance: Math.sqrt(
|
|
2410
|
-
(a2.x - pointOnB2.x) ** 2 + (a2.y - pointOnB2.y) ** 2
|
|
2411
|
-
)
|
|
2412
|
-
}
|
|
2413
|
-
];
|
|
2414
|
-
const closestPair = distances.reduce(
|
|
2415
|
-
(closest, current) => current.distance < closest.distance ? current : closest
|
|
2416
|
-
);
|
|
2417
|
-
return {
|
|
2418
|
-
x: (closestPair.pointA.x + closestPair.pointB.x) / 2,
|
|
2419
|
-
y: (closestPair.pointA.y + closestPair.pointB.y) / 2
|
|
2420
|
-
};
|
|
2421
|
-
};
|
|
2422
|
-
var clamp = (value, min, max) => {
|
|
2423
|
-
return Math.max(min, Math.min(max, value));
|
|
2424
|
-
};
|
|
2425
|
-
|
|
2426
2603
|
// lib/check-each-pcb-trace-non-overlapping/getCollidableBounds.ts
|
|
2427
2604
|
import { getBoundsOfPcbElements as getBoundsOfPcbElements3 } from "@tscircuit/circuit-json-util";
|
|
2428
2605
|
var getCollidableBounds = (collidable) => {
|
|
@@ -2458,32 +2635,6 @@ var getCollidableBounds = (collidable) => {
|
|
|
2458
2635
|
return getBoundsOfPcbElements3([collidable]);
|
|
2459
2636
|
};
|
|
2460
2637
|
|
|
2461
|
-
// lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
|
|
2462
|
-
function getPcbPortIdsConnectedToRoutePoint(routePoint) {
|
|
2463
|
-
if (routePoint.route_type !== "wire") return [];
|
|
2464
|
-
return [routePoint.start_pcb_port_id, routePoint.end_pcb_port_id].filter(
|
|
2465
|
-
(portId) => Boolean(portId)
|
|
2466
|
-
);
|
|
2467
|
-
}
|
|
2468
|
-
function getPcbPortIdsConnectedToTrace(trace) {
|
|
2469
|
-
const connectedPcbPorts = /* @__PURE__ */ new Set();
|
|
2470
|
-
for (const segment of trace.route) {
|
|
2471
|
-
for (const portId of getPcbPortIdsConnectedToRoutePoint(segment)) {
|
|
2472
|
-
connectedPcbPorts.add(portId);
|
|
2473
|
-
}
|
|
2474
|
-
}
|
|
2475
|
-
return Array.from(connectedPcbPorts);
|
|
2476
|
-
}
|
|
2477
|
-
function getPcbPortIdsConnectedToTraces(traces) {
|
|
2478
|
-
const connectedPorts = /* @__PURE__ */ new Set();
|
|
2479
|
-
for (const trace of traces) {
|
|
2480
|
-
for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
|
|
2481
|
-
connectedPorts.add(portId);
|
|
2482
|
-
}
|
|
2483
|
-
}
|
|
2484
|
-
return Array.from(connectedPorts);
|
|
2485
|
-
}
|
|
2486
|
-
|
|
2487
2638
|
// lib/check-each-pcb-trace-non-overlapping/getRadiusOfCircuitJsonElement.ts
|
|
2488
2639
|
var getRadiusOfCircuitJsonElement = (obj) => {
|
|
2489
2640
|
if (obj.type === "pcb_via") {
|
|
@@ -2513,12 +2664,12 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
2513
2664
|
connMap,
|
|
2514
2665
|
minClearance
|
|
2515
2666
|
} = {}) {
|
|
2516
|
-
const errors =
|
|
2667
|
+
const errors = checkPcbTraceSelfShorts(circuitJson);
|
|
2517
2668
|
addStartAndEndPortIdsIfMissing(circuitJson);
|
|
2518
2669
|
connMap ??= getFullConnectivityMapFromCircuitJson3(circuitJson);
|
|
2519
2670
|
const board = getPcbBoard(circuitJson);
|
|
2520
2671
|
minClearance ??= getBoardDrcValue(board, "min_trace_to_pad_edge_clearance") ?? DEFAULT_TRACE_MARGIN;
|
|
2521
|
-
const pcbTraces =
|
|
2672
|
+
const pcbTraces = cju3(circuitJson).pcb_trace.list();
|
|
2522
2673
|
const pcbTraceSegments = pcbTraces.flatMap((pcbTrace) => {
|
|
2523
2674
|
const segments = [];
|
|
2524
2675
|
for (let i = 0; i < pcbTrace.route.length - 1; i++) {
|
|
@@ -2541,12 +2692,12 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
2541
2692
|
}
|
|
2542
2693
|
return segments;
|
|
2543
2694
|
});
|
|
2544
|
-
const pcbSmtPads =
|
|
2545
|
-
const pcbPlatedHoles =
|
|
2546
|
-
const pcbPorts =
|
|
2547
|
-
const pcbHoles =
|
|
2548
|
-
const pcbVias =
|
|
2549
|
-
const pcbKeepouts =
|
|
2695
|
+
const pcbSmtPads = cju3(circuitJson).pcb_smtpad.list();
|
|
2696
|
+
const pcbPlatedHoles = cju3(circuitJson).pcb_plated_hole.list();
|
|
2697
|
+
const pcbPorts = cju3(circuitJson).pcb_port.list();
|
|
2698
|
+
const pcbHoles = cju3(circuitJson).pcb_hole.list();
|
|
2699
|
+
const pcbVias = cju3(circuitJson).pcb_via.list();
|
|
2700
|
+
const pcbKeepouts = cju3(circuitJson).pcb_keepout.list().filter((keepout) => !keepout.allow_traces);
|
|
2550
2701
|
const pcbComponentConnectionElements = [
|
|
2551
2702
|
...pcbPorts,
|
|
2552
2703
|
...pcbSmtPads,
|
|
@@ -2607,7 +2758,7 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
2607
2758
|
if (segmentA.layer !== segmentB.layer) continue;
|
|
2608
2759
|
if (connMap.areIdsConnected(segmentA.pcb_trace_id, segmentB.pcb_trace_id))
|
|
2609
2760
|
continue;
|
|
2610
|
-
const gap2 =
|
|
2761
|
+
const gap2 = segmentToSegmentMinDistance4(
|
|
2611
2762
|
{ x: segmentA.x1, y: segmentA.y1 },
|
|
2612
2763
|
{ x: segmentA.x2, y: segmentA.y2 },
|
|
2613
2764
|
{ x: segmentB.x1, y: segmentB.y1 },
|
|
@@ -3266,7 +3417,7 @@ function checkPcbComponentOverCutout(circuitJson) {
|
|
|
3266
3417
|
}
|
|
3267
3418
|
|
|
3268
3419
|
// lib/check-pcb-copper-over-keepout.ts
|
|
3269
|
-
import { cju as
|
|
3420
|
+
import { cju as cju4, getPrimaryId as getPrimaryId3 } from "@tscircuit/circuit-json-util";
|
|
3270
3421
|
var getErrorOwnerId = (copper) => "pcb_component_id" in copper && copper.pcb_component_id ? copper.pcb_component_id : getPrimaryId3(copper);
|
|
3271
3422
|
var getReadableCopperName = (circuitJson, copper) => {
|
|
3272
3423
|
if ("pcb_component_id" in copper && copper.pcb_component_id) {
|
|
@@ -3282,11 +3433,11 @@ var getReadableCopperName = (circuitJson, copper) => {
|
|
|
3282
3433
|
return copper.type === "pcb_via" ? `via ${copper.pcb_via_id}` : `${copper.type} ${getPrimaryId3(copper)}`;
|
|
3283
3434
|
};
|
|
3284
3435
|
function checkPcbCopperOverKeepout(circuitJson) {
|
|
3285
|
-
const keepouts =
|
|
3436
|
+
const keepouts = cju4(circuitJson).pcb_keepout.list();
|
|
3286
3437
|
if (keepouts.length === 0) return [];
|
|
3287
3438
|
const copper = [
|
|
3288
3439
|
...getPads(circuitJson),
|
|
3289
|
-
...
|
|
3440
|
+
...cju4(circuitJson).pcb_via.list()
|
|
3290
3441
|
];
|
|
3291
3442
|
const errors = /* @__PURE__ */ new Map();
|
|
3292
3443
|
for (const keepout of keepouts) {
|
|
@@ -3463,11 +3614,11 @@ function checkDifferentNetViaSpacing(circuitJson, {
|
|
|
3463
3614
|
}
|
|
3464
3615
|
|
|
3465
3616
|
// lib/check-source-traces-match-pcb-trace-thickness.ts
|
|
3466
|
-
import { cju as
|
|
3617
|
+
import { cju as cju5 } from "@tscircuit/circuit-json-util";
|
|
3467
3618
|
import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson6 } from "circuit-json-to-connectivity-map";
|
|
3468
3619
|
function checkSourceTracesMatchPcbTraceThickness(circuitJson) {
|
|
3469
3620
|
const warnings = [];
|
|
3470
|
-
const db =
|
|
3621
|
+
const db = cju5(circuitJson);
|
|
3471
3622
|
const sourceTraces = db.source_trace.list();
|
|
3472
3623
|
const pcbTraces = db.pcb_trace.list();
|
|
3473
3624
|
const pcbPorts = db.pcb_port.list();
|
|
@@ -3606,7 +3757,7 @@ import {
|
|
|
3606
3757
|
|
|
3607
3758
|
// lib/check-traces-are-contiguous/via-contact-index.ts
|
|
3608
3759
|
import {
|
|
3609
|
-
all_layers as
|
|
3760
|
+
all_layers as all_layers4
|
|
3610
3761
|
} from "circuit-json";
|
|
3611
3762
|
import { getPrimaryId as getPrimaryId4 } from "@tscircuit/circuit-json-util";
|
|
3612
3763
|
import { pointToSegmentDistance as pointToSegmentDistance2 } from "@tscircuit/math-utils";
|
|
@@ -3618,7 +3769,7 @@ function getViaContactIndex(circuitJson, connectivity) {
|
|
|
3618
3769
|
const vias = circuitJson.filter((element) => element.type === "pcb_via");
|
|
3619
3770
|
const board = circuitJson.find((element) => element.type === "pcb_board");
|
|
3620
3771
|
const layerCount = board?.num_layers;
|
|
3621
|
-
const innerLayers =
|
|
3772
|
+
const innerLayers = all_layers4.filter((layer) => layer.startsWith("inner"));
|
|
3622
3773
|
const stack = [
|
|
3623
3774
|
"top",
|
|
3624
3775
|
...innerLayers.slice(
|
|
@@ -4144,8 +4295,8 @@ function checkTracesAreContiguous(circuitJson, {
|
|
|
4144
4295
|
}
|
|
4145
4296
|
|
|
4146
4297
|
// lib/check-trace-out-of-board/checkTraceOutOfBoard.ts
|
|
4147
|
-
import { cju as
|
|
4148
|
-
import { segmentToSegmentMinDistance as
|
|
4298
|
+
import { cju as cju6 } from "@tscircuit/circuit-json-util";
|
|
4299
|
+
import { segmentToSegmentMinDistance as segmentToSegmentMinDistance5 } from "@tscircuit/math-utils";
|
|
4149
4300
|
function getBoardPolygonPoints(board) {
|
|
4150
4301
|
if (board.outline && board.outline.length > 0) {
|
|
4151
4302
|
return board.outline.map((p) => ({ x: p.x, y: p.y }));
|
|
@@ -4175,7 +4326,7 @@ function checkPcbTracesOutOfBoard(circuitJson, config = {}) {
|
|
|
4175
4326
|
const margin = config.margin ?? getBoardDrcValue(board, "min_board_edge_clearance") ?? jlcMinTolerances.min_board_edge_clearance;
|
|
4176
4327
|
const boardPoints = getBoardPolygonPoints(board);
|
|
4177
4328
|
if (!boardPoints) return errors;
|
|
4178
|
-
const pcbTraces =
|
|
4329
|
+
const pcbTraces = cju6(circuitJson).pcb_trace.list();
|
|
4179
4330
|
for (const trace of pcbTraces) {
|
|
4180
4331
|
if (trace.route.length < 2) continue;
|
|
4181
4332
|
for (let i = 0; i < trace.route.length - 1; i++) {
|
|
@@ -4189,7 +4340,7 @@ function checkPcbTracesOutOfBoard(circuitJson, config = {}) {
|
|
|
4189
4340
|
for (let j = 0; j < boardPoints.length; j++) {
|
|
4190
4341
|
const edgeStart = boardPoints[j];
|
|
4191
4342
|
const edgeEnd = boardPoints[(j + 1) % boardPoints.length];
|
|
4192
|
-
const distance3 =
|
|
4343
|
+
const distance3 = segmentToSegmentMinDistance5(
|
|
4193
4344
|
segmentStart,
|
|
4194
4345
|
segmentEnd,
|
|
4195
4346
|
edgeStart,
|
|
@@ -4224,7 +4375,7 @@ function checkPcbTracesOutOfBoard(circuitJson, config = {}) {
|
|
|
4224
4375
|
|
|
4225
4376
|
// lib/check-pcb-components-overlap/checkPcbComponentOverlap.ts
|
|
4226
4377
|
import {
|
|
4227
|
-
cju as
|
|
4378
|
+
cju as cju7,
|
|
4228
4379
|
getBoundsOfPcbElements as getBoundsOfPcbElements5,
|
|
4229
4380
|
getPrimaryId as getPrimaryId5
|
|
4230
4381
|
} from "@tscircuit/circuit-json-util";
|
|
@@ -4322,9 +4473,9 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
4322
4473
|
)
|
|
4323
4474
|
);
|
|
4324
4475
|
const connMap = getFullConnectivityMapFromCircuitJson9(circuitJson);
|
|
4325
|
-
const smtPads =
|
|
4326
|
-
const platedHoles =
|
|
4327
|
-
const holes =
|
|
4476
|
+
const smtPads = cju7(circuitJson).pcb_smtpad.list();
|
|
4477
|
+
const platedHoles = cju7(circuitJson).pcb_plated_hole.list();
|
|
4478
|
+
const holes = cju7(circuitJson).pcb_hole.list();
|
|
4328
4479
|
const courtyards = circuitJson.filter(isCourtyardElement2);
|
|
4329
4480
|
const componentMap = /* @__PURE__ */ new Map();
|
|
4330
4481
|
for (const pad of smtPads) {
|
|
@@ -5066,7 +5217,7 @@ function checkTwoTerminalSwitchContactsOnDifferentNets(circuitJson) {
|
|
|
5066
5217
|
}
|
|
5067
5218
|
|
|
5068
5219
|
// lib/check-all-pins-in-component-are-underspecified.ts
|
|
5069
|
-
import { cju as
|
|
5220
|
+
import { cju as cju8 } from "@tscircuit/circuit-json-util";
|
|
5070
5221
|
var PIN_ATTRIBUTE_KEYS = [
|
|
5071
5222
|
"must_be_connected",
|
|
5072
5223
|
"provides_power",
|
|
@@ -5111,7 +5262,7 @@ function hasAnyPinAttribute(port) {
|
|
|
5111
5262
|
}
|
|
5112
5263
|
function checkAllPinsInComponentAreUnderspecified(circuitJson) {
|
|
5113
5264
|
const warnings = [];
|
|
5114
|
-
const db =
|
|
5265
|
+
const db = cju8(circuitJson);
|
|
5115
5266
|
const sourceComponents = db.source_component.list();
|
|
5116
5267
|
const sourcePorts = db.source_port.list();
|
|
5117
5268
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -5143,7 +5294,7 @@ function checkAllPinsInComponentAreUnderspecified(circuitJson) {
|
|
|
5143
5294
|
}
|
|
5144
5295
|
|
|
5145
5296
|
// lib/check-no-power-pin-defined.ts
|
|
5146
|
-
import { cju as
|
|
5297
|
+
import { cju as cju9 } from "@tscircuit/circuit-json-util";
|
|
5147
5298
|
|
|
5148
5299
|
// lib/util/should-check-chip-power-ground-pins.ts
|
|
5149
5300
|
var shouldCheckChipPowerGroundPins = (component, ports) => component.ftype === "simple_chip" && ports.filter((port) => port.do_not_connect !== true).length >= 2;
|
|
@@ -5151,7 +5302,7 @@ var shouldCheckChipPowerGroundPins = (component, ports) => component.ftype === "
|
|
|
5151
5302
|
// lib/check-no-power-pin-defined.ts
|
|
5152
5303
|
function checkNoPowerPinDefined(circuitJson) {
|
|
5153
5304
|
const warnings = [];
|
|
5154
|
-
const db =
|
|
5305
|
+
const db = cju9(circuitJson);
|
|
5155
5306
|
const sourceComponents = db.source_component.list();
|
|
5156
5307
|
const sourcePorts = db.source_port.list();
|
|
5157
5308
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -5182,10 +5333,10 @@ function checkNoPowerPinDefined(circuitJson) {
|
|
|
5182
5333
|
}
|
|
5183
5334
|
|
|
5184
5335
|
// lib/check-no-ground-pin-defined.ts
|
|
5185
|
-
import { cju as
|
|
5336
|
+
import { cju as cju10 } from "@tscircuit/circuit-json-util";
|
|
5186
5337
|
function checkNoGroundPinDefined(circuitJson) {
|
|
5187
5338
|
const warnings = [];
|
|
5188
|
-
const db =
|
|
5339
|
+
const db = cju10(circuitJson);
|
|
5189
5340
|
const sourceComponents = db.source_component.list();
|
|
5190
5341
|
const sourcePorts = db.source_port.list();
|
|
5191
5342
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -6046,6 +6197,7 @@ export {
|
|
|
6046
6197
|
checkPcbComponentsOutOfBoard,
|
|
6047
6198
|
checkPcbCopperOverKeepout,
|
|
6048
6199
|
checkPcbTraceLengths,
|
|
6200
|
+
checkPcbTraceSelfShorts,
|
|
6049
6201
|
checkPcbTraceViaCounts,
|
|
6050
6202
|
checkPcbTracesOutOfBoard,
|
|
6051
6203
|
checkPinMustBeConnected,
|