@tscircuit/checks 0.0.27 → 0.0.29

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/README.md CHANGED
@@ -26,7 +26,7 @@ and pcb traces here are the relevant elements (the types are produced below)
26
26
 
27
27
  ```ts
28
28
  // You can import these types from the @tscircuit/soup package e.g.
29
- // import type { PCBPort, PCBTrace, AnySoupElement } from "@tscircuit/soup"
29
+ // import type { PCBPort, PCBTrace, AnySoupElement } from "circuit-json"
30
30
 
31
31
  import { z } from "zod"
32
32
  import { distance } from "../units"
@@ -1,8 +1,11 @@
1
1
  import { AnyCircuitElement, PcbTraceError } from 'circuit-json';
2
+ import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
2
3
 
3
4
  declare function checkEachPcbPortConnected(soup: AnyCircuitElement[]): PcbTraceError[];
4
5
 
5
- declare function checkEachPcbTraceNonOverlapping(soup: AnyCircuitElement[]): PcbTraceError[];
6
+ declare function checkEachPcbTraceNonOverlapping(circuitJson: AnyCircuitElement[], { connMap, }?: {
7
+ connMap?: ConnectivityMap;
8
+ }): PcbTraceError[];
6
9
 
7
10
  declare class NetManager {
8
11
  private networks;
package/dist/index.js ADDED
@@ -0,0 +1,330 @@
1
+ // lib/add-start-and-end-port-ids-if-missing.ts
2
+ function distance(x1, y1, x2, y2) {
3
+ return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
4
+ }
5
+ var addStartAndEndPortIdsIfMissing = (soup) => {
6
+ const pcbPorts = soup.filter((item) => item.type === "pcb_port");
7
+ const pcbSmtPads = soup.filter(
8
+ (item) => item.type === "pcb_smtpad"
9
+ );
10
+ const pcbTraces = soup.filter((item) => item.type === "pcb_trace");
11
+ function findPortIdOverlappingPoint(point, options = {}) {
12
+ const traceWidth = options.traceWidth || 0;
13
+ const directPort = pcbPorts.find(
14
+ (port) => distance(port.x, port.y, point.x, point.y) < 0.01
15
+ );
16
+ if (directPort) return directPort.pcb_port_id;
17
+ if (options.isFirstOrLastPoint) {
18
+ const smtPad = pcbSmtPads.find((pad) => {
19
+ if (pad.shape === "rect") {
20
+ return Math.abs(point.x - pad.x) < pad.width / 2 + traceWidth / 2 && Math.abs(point.y - pad.y) < pad.height / 2 + traceWidth / 2;
21
+ } else if (pad.shape === "circle") {
22
+ return distance(point.x, point.y, pad.x, pad.y) < pad.radius;
23
+ }
24
+ });
25
+ if (smtPad) return smtPad.pcb_port_id ?? null;
26
+ }
27
+ return null;
28
+ }
29
+ for (const trace of pcbTraces) {
30
+ for (let index = 0; index < trace.route.length; index++) {
31
+ const segment = trace.route[index];
32
+ const isFirstOrLastPoint = index === 0 || index === trace.route.length - 1;
33
+ if (segment.route_type === "wire") {
34
+ if (!segment.start_pcb_port_id && index === 0) {
35
+ const startPortId = findPortIdOverlappingPoint(segment, {
36
+ isFirstOrLastPoint,
37
+ traceWidth: segment.width
38
+ });
39
+ if (startPortId) {
40
+ segment.start_pcb_port_id = startPortId;
41
+ }
42
+ }
43
+ if (!segment.end_pcb_port_id && index === trace.route.length - 1) {
44
+ const endPortId = findPortIdOverlappingPoint(segment, {
45
+ isFirstOrLastPoint,
46
+ traceWidth: segment.width
47
+ });
48
+ if (endPortId) {
49
+ segment.end_pcb_port_id = endPortId;
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
55
+ };
56
+
57
+ // lib/check-each-pcb-port-connected.ts
58
+ import { getReadableNameForPcbPort } from "@tscircuit/circuit-json-util";
59
+ function checkEachPcbPortConnected(soup) {
60
+ addStartAndEndPortIdsIfMissing(soup);
61
+ const pcbPorts = soup.filter((item) => item.type === "pcb_port");
62
+ const pcbTraces = soup.filter((item) => item.type === "pcb_trace");
63
+ const sourceTraces = soup.filter(
64
+ (item) => item.type === "source_trace"
65
+ );
66
+ const errors = [];
67
+ for (const port of pcbPorts) {
68
+ const connectedTraces = pcbTraces.filter(
69
+ (trace) => trace.route.some(
70
+ (segment) => segment.route_type === "wire" && (segment.start_pcb_port_id === port.pcb_port_id || segment.end_pcb_port_id === port.pcb_port_id)
71
+ )
72
+ );
73
+ const sourceTrace = sourceTraces.find(
74
+ (trace) => trace.connected_source_port_ids?.includes(port.source_port_id)
75
+ );
76
+ const hasSourceTraceWithConnections = sourceTrace && sourceTrace.connected_source_port_ids?.length > 0;
77
+ if (connectedTraces.length === 0 && hasSourceTraceWithConnections) {
78
+ errors.push({
79
+ type: "pcb_trace_error",
80
+ message: `pcb_trace_error: PCB port ${getReadableNameForPcbPort(soup, port.pcb_port_id)} is not connected by a PCB trace`,
81
+ source_trace_id: sourceTrace.source_trace_id,
82
+ error_type: "pcb_trace_error",
83
+ pcb_trace_id: "",
84
+ pcb_trace_error_id: "",
85
+ pcb_component_ids: [],
86
+ pcb_port_ids: [port.pcb_port_id]
87
+ });
88
+ }
89
+ }
90
+ return errors;
91
+ }
92
+
93
+ // lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
94
+ import { getReadableNameForElement, cju } from "@tscircuit/circuit-json-util";
95
+ import {
96
+ SpatialObjectIndex
97
+ } from "lib/data-structures/SpatialIndex";
98
+ import {
99
+ getFullConnectivityMapFromCircuitJson
100
+ } from "circuit-json-to-connectivity-map";
101
+
102
+ // lib/check-each-pcb-trace-non-overlapping/getCollidableBounds.ts
103
+ import { getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
104
+ var getCollidableBounds = (collidable) => {
105
+ if (collidable.type === "pcb_trace_segment") {
106
+ return {
107
+ minX: Math.min(collidable.x1, collidable.x2),
108
+ minY: Math.min(collidable.y1, collidable.y2),
109
+ maxX: Math.max(collidable.x1, collidable.x2),
110
+ maxY: Math.max(collidable.y1, collidable.y2)
111
+ };
112
+ }
113
+ return getBoundsOfPcbElements([collidable]);
114
+ };
115
+
116
+ // lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
117
+ import { segmentToBoundsMinDistance } from "@tscircuit/math-utils";
118
+ import {
119
+ DEFAULT_TRACE_MARGIN,
120
+ DEFAULT_TRACE_THICKNESS,
121
+ EPSILON
122
+ } from "lib/drc-defaults";
123
+
124
+ // lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
125
+ function getPcbPortIdsConnectedToTrace(trace) {
126
+ const connectedPcbPorts = /* @__PURE__ */ new Set();
127
+ for (const segment of trace.route) {
128
+ if (segment.route_type === "wire") {
129
+ if (segment.start_pcb_port_id)
130
+ connectedPcbPorts.add(segment.start_pcb_port_id);
131
+ if (segment.end_pcb_port_id)
132
+ connectedPcbPorts.add(segment.end_pcb_port_id);
133
+ }
134
+ }
135
+ return Array.from(connectedPcbPorts);
136
+ }
137
+ function getPcbPortIdsConnectedToTraces(traces) {
138
+ const connectedPorts = /* @__PURE__ */ new Set();
139
+ for (const trace of traces) {
140
+ for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
141
+ connectedPorts.add(portId);
142
+ }
143
+ }
144
+ return Array.from(connectedPorts);
145
+ }
146
+
147
+ // lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
148
+ import { segmentToSegmentMinDistance } from "@tscircuit/math-utils";
149
+ import { getPrimaryId } from "@tscircuit/circuit-json-util";
150
+
151
+ // lib/check-each-pcb-trace-non-overlapping/getCenterOfPcbTraceSegments.ts
152
+ var getCenterOfPcbTraceSegments = (segmentA, segmentB) => {
153
+ return {
154
+ x: (Math.min(segmentA.x1, segmentA.x2, segmentB.x1, segmentB.x2) + Math.max(segmentA.x1, segmentA.x2, segmentB.x1, segmentB.x2)) / 2,
155
+ y: (Math.min(segmentA.y1, segmentA.y2, segmentB.y1, segmentB.y2) + Math.max(segmentA.y1, segmentA.y2, segmentB.y1, segmentB.y2)) / 2
156
+ };
157
+ };
158
+
159
+ // lib/check-each-pcb-trace-non-overlapping/getCenterOfBounds.ts
160
+ var getCenterOfBounds = (bounds) => {
161
+ return {
162
+ x: (bounds.minX + bounds.maxX) / 2,
163
+ y: (bounds.minY + bounds.maxY) / 2
164
+ };
165
+ };
166
+
167
+ // lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
168
+ function checkEachPcbTraceNonOverlapping(circuitJson, {
169
+ connMap
170
+ } = {}) {
171
+ const errors = [];
172
+ connMap ??= getFullConnectivityMapFromCircuitJson(circuitJson);
173
+ const pcbTraces = cju(circuitJson).pcb_trace.list();
174
+ const pcbTraceSegments = pcbTraces.flatMap((pcbTrace) => {
175
+ const segments = [];
176
+ for (let i = 0; i < pcbTrace.route.length - 1; i++) {
177
+ const p1 = pcbTrace.route[i];
178
+ const p2 = pcbTrace.route[i + 1];
179
+ segments.push({
180
+ type: "pcb_trace_segment",
181
+ pcb_trace_id: pcbTrace.pcb_trace_id,
182
+ _pcbTrace: pcbTrace,
183
+ thickness: "width" in p1 ? p1.width : "width" in p2 ? p2.width : DEFAULT_TRACE_THICKNESS,
184
+ x1: p1.x,
185
+ y1: p1.y,
186
+ x2: p2.x,
187
+ y2: p2.y
188
+ });
189
+ }
190
+ return segments;
191
+ });
192
+ const pcbSmtPads = cju(circuitJson).pcb_smtpad.list();
193
+ const pcbPlatedHoles = cju(circuitJson).pcb_plated_hole.list();
194
+ const pcbHoles = cju(circuitJson).pcb_hole.list();
195
+ const pcbVias = cju(circuitJson).pcb_via.list();
196
+ const pcbKeepouts = cju(circuitJson).pcb_keepout.list();
197
+ const allObjects = [
198
+ ...pcbTraceSegments,
199
+ ...pcbSmtPads,
200
+ ...pcbPlatedHoles,
201
+ ...pcbHoles,
202
+ ...pcbVias,
203
+ ...pcbKeepouts
204
+ ];
205
+ const spatialIndex = new SpatialObjectIndex({
206
+ objects: allObjects,
207
+ getBounds: getCollidableBounds
208
+ });
209
+ const getReadableName = (id) => getReadableNameForElement(circuitJson, id);
210
+ const errorIds = /* @__PURE__ */ new Set();
211
+ for (const segmentA of pcbTraceSegments) {
212
+ const requiredMargin = DEFAULT_TRACE_MARGIN;
213
+ const bounds = getCollidableBounds(segmentA);
214
+ const nearbyObjects = spatialIndex.getObjectsInBounds(
215
+ bounds,
216
+ requiredMargin + segmentA.thickness / 2
217
+ );
218
+ if (segmentA.x1 === segmentA.x2 && segmentA.y1 === segmentA.y2) continue;
219
+ for (const obj of nearbyObjects) {
220
+ if (obj.type === "pcb_trace_segment") {
221
+ const segmentB = obj;
222
+ if (connMap.areIdsConnected(segmentA.pcb_trace_id, segmentB.pcb_trace_id))
223
+ continue;
224
+ if (segmentToSegmentMinDistance(
225
+ { x: segmentA.x1, y: segmentA.y1 },
226
+ { x: segmentA.x2, y: segmentA.y2 },
227
+ { x: segmentB.x1, y: segmentB.y1 },
228
+ { x: segmentB.x2, y: segmentB.y2 }
229
+ ) - segmentA.thickness / 2 - segmentB.thickness / 2 > DEFAULT_TRACE_MARGIN - EPSILON)
230
+ continue;
231
+ const pcb_trace_error_id = `overlap_${segmentA.pcb_trace_id}_${segmentB.pcb_trace_id}`;
232
+ const pcb_trace_error_id_reverse = `overlap_${segmentB.pcb_trace_id}_${segmentA.pcb_trace_id}`;
233
+ if (errorIds.has(pcb_trace_error_id)) continue;
234
+ if (errorIds.has(pcb_trace_error_id_reverse)) continue;
235
+ errorIds.add(pcb_trace_error_id);
236
+ errors.push({
237
+ type: "pcb_trace_error",
238
+ error_type: "pcb_trace_error",
239
+ message: `PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${getReadableName(segmentB.pcb_trace_id)}`,
240
+ pcb_trace_id: segmentA.pcb_trace_id,
241
+ source_trace_id: "",
242
+ pcb_trace_error_id,
243
+ pcb_component_ids: [],
244
+ center: getCenterOfPcbTraceSegments(segmentA, segmentB),
245
+ pcb_port_ids: getPcbPortIdsConnectedToTraces([
246
+ segmentA._pcbTrace,
247
+ segmentB._pcbTrace
248
+ ])
249
+ });
250
+ continue;
251
+ }
252
+ const primaryObjId = getPrimaryId(obj);
253
+ const gap = segmentToBoundsMinDistance(
254
+ { x: segmentA.x1, y: segmentA.y1 },
255
+ { x: segmentA.x2, y: segmentA.y2 },
256
+ getCollidableBounds(obj)
257
+ ) - segmentA.thickness / 2;
258
+ if (!connMap.areIdsConnected(segmentA.pcb_trace_id, primaryObjId) && gap + EPSILON < requiredMargin) {
259
+ const pcb_trace_error_id = `overlap_${segmentA.pcb_trace_id}_${primaryObjId}`;
260
+ if (errorIds.has(pcb_trace_error_id)) continue;
261
+ errorIds.add(pcb_trace_error_id);
262
+ errors.push({
263
+ type: "pcb_trace_error",
264
+ error_type: "pcb_trace_error",
265
+ message: `PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${obj.type} "${getReadableName(getPrimaryId(obj))}" ${gap < 0 ? "(accidental contact)" : `(gap: ${gap.toFixed(3)}mm)`}`,
266
+ pcb_trace_id: segmentA.pcb_trace_id,
267
+ source_trace_id: "",
268
+ pcb_trace_error_id,
269
+ pcb_component_ids: [
270
+ "pcb_component_id" in obj ? obj.pcb_component_id : void 0
271
+ ].filter(Boolean),
272
+ center: getCenterOfBounds(getCollidableBounds(obj)),
273
+ pcb_port_ids: [
274
+ ...getPcbPortIdsConnectedToTraces([segmentA._pcbTrace]),
275
+ "pcb_port_id" in obj ? obj.pcb_port_id : void 0
276
+ ].filter(Boolean)
277
+ });
278
+ }
279
+ }
280
+ }
281
+ return errors;
282
+ }
283
+
284
+ // lib/net-manager.ts
285
+ var NetManager = class {
286
+ networks = /* @__PURE__ */ new Set();
287
+ setConnected(nodes) {
288
+ if (nodes.length < 2) return;
289
+ let targetNetwork = null;
290
+ for (const network of this.networks) {
291
+ for (const node of nodes) {
292
+ if (network.has(node)) {
293
+ if (targetNetwork === null) {
294
+ targetNetwork = network;
295
+ } else if (targetNetwork !== network) {
296
+ for (const mergeNode of network) {
297
+ targetNetwork.add(mergeNode);
298
+ }
299
+ this.networks.delete(network);
300
+ }
301
+ break;
302
+ }
303
+ }
304
+ if (targetNetwork !== null && targetNetwork !== network) break;
305
+ }
306
+ if (targetNetwork === null) {
307
+ targetNetwork = new Set(nodes);
308
+ this.networks.add(targetNetwork);
309
+ } else {
310
+ for (const node of nodes) {
311
+ targetNetwork.add(node);
312
+ }
313
+ }
314
+ }
315
+ isConnected(nodes) {
316
+ if (nodes.length < 2) return true;
317
+ for (const network of this.networks) {
318
+ if (nodes.every((node) => network.has(node))) {
319
+ return true;
320
+ }
321
+ }
322
+ return false;
323
+ }
324
+ };
325
+ export {
326
+ NetManager,
327
+ checkEachPcbPortConnected,
328
+ checkEachPcbTraceNonOverlapping
329
+ };
330
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../lib/add-start-and-end-port-ids-if-missing.ts","../lib/check-each-pcb-port-connected.ts","../lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts","../lib/check-each-pcb-trace-non-overlapping/getCollidableBounds.ts","../lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts","../lib/check-each-pcb-trace-non-overlapping/getCenterOfPcbTraceSegments.ts","../lib/check-each-pcb-trace-non-overlapping/getCenterOfBounds.ts","../lib/net-manager.ts"],"sourcesContent":["import type {\n PcbPort,\n PcbTrace,\n AnyCircuitElement,\n PcbSmtPad,\n} from \"circuit-json\"\n\nfunction distance(x1: number, y1: number, x2: number, y2: number): number {\n return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)\n}\n\n/**\n * HACK: this whole method and all usage of it is a hack because of this issue:\n * https://github.com/tscircuit/tscircuit/issues/291\n */\nexport const addStartAndEndPortIdsIfMissing = (\n soup: AnyCircuitElement[],\n): void => {\n const pcbPorts: PcbPort[] = soup.filter((item) => item.type === \"pcb_port\")\n const pcbSmtPads: PcbSmtPad[] = soup.filter(\n (item) => item.type === \"pcb_smtpad\",\n )\n const pcbTraces: PcbTrace[] = soup.filter((item) => item.type === \"pcb_trace\")\n\n function findPortIdOverlappingPoint(\n point: {\n x: number\n y: number\n },\n options: { isFirstOrLastPoint?: boolean; traceWidth?: number } = {},\n ): string | null {\n const traceWidth = options.traceWidth || 0\n const directPort = pcbPorts.find(\n (port) => distance(port.x, port.y, point.x, point.y) < 0.01,\n )\n if (directPort) return directPort.pcb_port_id\n\n // If it starts or ends inside an smtpad, we'll connect it to the por\n if (options.isFirstOrLastPoint) {\n const smtPad = pcbSmtPads.find((pad) => {\n if (pad.shape === \"rect\") {\n return (\n Math.abs(point.x - pad.x) < pad.width / 2 + traceWidth / 2 &&\n Math.abs(point.y - pad.y) < pad.height / 2 + traceWidth / 2\n )\n // biome-ignore lint/style/noUselessElse: <explanation>\n } else if (pad.shape === \"circle\") {\n return distance(point.x, point.y, pad.x, pad.y) < pad.radius\n }\n })\n if (smtPad) return smtPad.pcb_port_id ?? null\n }\n\n return null\n }\n\n // Add start_pcb_port_id and end_pcb_port_id if not present\n for (const trace of pcbTraces) {\n for (let index = 0; index < trace.route.length; index++) {\n const segment = trace.route[index]\n const isFirstOrLastPoint = index === 0 || index === trace.route.length - 1\n if (segment.route_type === \"wire\") {\n if (!segment.start_pcb_port_id && index === 0) {\n const startPortId = findPortIdOverlappingPoint(segment, {\n isFirstOrLastPoint,\n traceWidth: segment.width,\n })\n if (startPortId) {\n segment.start_pcb_port_id = startPortId\n }\n }\n if (!segment.end_pcb_port_id && index === trace.route.length - 1) {\n const endPortId = findPortIdOverlappingPoint(segment, {\n isFirstOrLastPoint,\n traceWidth: segment.width,\n })\n if (endPortId) {\n segment.end_pcb_port_id = endPortId\n }\n }\n }\n }\n }\n}\n","import type {\n PcbPort,\n PcbTrace,\n SourceTrace,\n AnyCircuitElement,\n PcbTraceError,\n} from \"circuit-json\"\nimport { addStartAndEndPortIdsIfMissing } from \"./add-start-and-end-port-ids-if-missing\"\nimport { getReadableNameForPcbPort } from \"@tscircuit/circuit-json-util\"\n\nfunction checkEachPcbPortConnected(soup: AnyCircuitElement[]): PcbTraceError[] {\n addStartAndEndPortIdsIfMissing(soup)\n const pcbPorts: PcbPort[] = soup.filter((item) => item.type === \"pcb_port\")\n const pcbTraces: PcbTrace[] = soup.filter((item) => item.type === \"pcb_trace\")\n const sourceTraces: SourceTrace[] = soup.filter(\n (item) => item.type === \"source_trace\",\n )\n const errors: PcbTraceError[] = []\n\n for (const port of pcbPorts) {\n const connectedTraces = pcbTraces.filter((trace) =>\n trace.route.some(\n (segment: any) =>\n segment.route_type === \"wire\" &&\n (segment.start_pcb_port_id === port.pcb_port_id ||\n segment.end_pcb_port_id === port.pcb_port_id),\n ),\n )\n\n const sourceTrace = sourceTraces.find((trace) =>\n trace.connected_source_port_ids?.includes(port.source_port_id),\n )\n\n const hasSourceTraceWithConnections =\n sourceTrace && sourceTrace.connected_source_port_ids?.length > 0\n\n if (connectedTraces.length === 0 && hasSourceTraceWithConnections) {\n errors.push({\n type: \"pcb_trace_error\",\n message: `pcb_trace_error: PCB port ${getReadableNameForPcbPort(soup, port.pcb_port_id)} is not connected by a PCB trace`,\n source_trace_id: sourceTrace.source_trace_id,\n error_type: \"pcb_trace_error\",\n pcb_trace_id: \"\",\n pcb_trace_error_id: \"\",\n pcb_component_ids: [],\n pcb_port_ids: [port.pcb_port_id],\n })\n }\n }\n\n return errors\n}\n\nexport { checkEachPcbPortConnected }\n","import type { AnyCircuitElement, PcbTraceError } from \"circuit-json\"\nimport { getReadableNameForElement, cju } from \"@tscircuit/circuit-json-util\"\nimport {\n SpatialObjectIndex,\n type Bounds,\n} from \"lib/data-structures/SpatialIndex\"\nimport {\n getFullConnectivityMapFromCircuitJson,\n type ConnectivityMap,\n} from \"circuit-json-to-connectivity-map\"\nimport {\n getCollidableBounds,\n type Collidable,\n type PcbTraceSegment,\n} from \"./getCollidableBounds\"\nimport { segmentToBoundsMinDistance } from \"@tscircuit/math-utils\"\nimport {\n DEFAULT_TRACE_MARGIN,\n DEFAULT_TRACE_THICKNESS,\n EPSILON,\n} from \"lib/drc-defaults\"\nimport { getPcbPortIdsConnectedToTraces } from \"./getPcbPortIdsConnectedToTraces\"\nimport { segmentToSegmentMinDistance } from \"@tscircuit/math-utils\"\nimport { areBoundsOverlapping } from \"./areBoundsOverlapping\"\nimport { getPrimaryId } from \"@tscircuit/circuit-json-util\"\nimport { getCenterOfBoundsPair } from \"./getCenterOfBoundsPair\"\nimport { getCenterOfPcbTraceSegments } from \"./getCenterOfPcbTraceSegments\"\nimport { getCenterOfBounds } from \"./getCenterOfBounds\"\n\nexport function checkEachPcbTraceNonOverlapping(\n circuitJson: AnyCircuitElement[],\n {\n connMap,\n }: {\n connMap?: ConnectivityMap\n } = {},\n): PcbTraceError[] {\n const errors: PcbTraceError[] = []\n connMap ??= getFullConnectivityMapFromCircuitJson(circuitJson)\n\n const pcbTraces = cju(circuitJson).pcb_trace.list()\n const pcbTraceSegments = pcbTraces.flatMap((pcbTrace) => {\n const segments: PcbTraceSegment[] = []\n for (let i = 0; i < pcbTrace.route.length - 1; i++) {\n const p1 = pcbTrace.route[i]\n const p2 = pcbTrace.route[i + 1]\n segments.push({\n type: \"pcb_trace_segment\",\n pcb_trace_id: pcbTrace.pcb_trace_id,\n _pcbTrace: pcbTrace,\n thickness:\n \"width\" in p1\n ? p1.width\n : \"width\" in p2\n ? p2.width\n : DEFAULT_TRACE_THICKNESS,\n x1: p1.x,\n y1: p1.y,\n x2: p2.x,\n y2: p2.y,\n } as PcbTraceSegment)\n }\n return segments\n })\n const pcbSmtPads = cju(circuitJson).pcb_smtpad.list()\n const pcbPlatedHoles = cju(circuitJson).pcb_plated_hole.list()\n const pcbHoles = cju(circuitJson).pcb_hole.list()\n const pcbVias = cju(circuitJson).pcb_via.list()\n const pcbKeepouts = cju(circuitJson).pcb_keepout.list()\n\n const allObjects: Collidable[] = [\n ...pcbTraceSegments,\n ...pcbSmtPads,\n ...pcbPlatedHoles,\n ...pcbHoles,\n ...pcbVias,\n ...pcbKeepouts,\n ]\n\n const spatialIndex = new SpatialObjectIndex<Collidable>({\n objects: allObjects,\n getBounds: getCollidableBounds,\n })\n\n const getReadableName = (id: string) =>\n getReadableNameForElement(circuitJson, id)\n\n const errorIds = new Set<string>()\n\n // For each segment, check it if overlaps with anything collidable\n for (const segmentA of pcbTraceSegments) {\n const requiredMargin = DEFAULT_TRACE_MARGIN\n const bounds = getCollidableBounds(segmentA)\n const nearbyObjects = spatialIndex.getObjectsInBounds(\n bounds,\n requiredMargin + segmentA.thickness / 2,\n )\n if (segmentA.x1 === segmentA.x2 && segmentA.y1 === segmentA.y2) continue\n\n for (const obj of nearbyObjects) {\n if (obj.type === \"pcb_trace_segment\") {\n const segmentB = obj\n // Check if the segments are overlapping\n if (\n connMap.areIdsConnected(segmentA.pcb_trace_id, segmentB.pcb_trace_id)\n )\n continue\n\n if (\n segmentToSegmentMinDistance(\n { x: segmentA.x1, y: segmentA.y1 },\n { x: segmentA.x2, y: segmentA.y2 },\n { x: segmentB.x1, y: segmentB.y1 },\n { x: segmentB.x2, y: segmentB.y2 },\n ) -\n segmentA.thickness / 2 -\n segmentB.thickness / 2 >\n DEFAULT_TRACE_MARGIN - EPSILON\n )\n continue\n\n const pcb_trace_error_id = `overlap_${segmentA.pcb_trace_id}_${segmentB.pcb_trace_id}`\n const pcb_trace_error_id_reverse = `overlap_${segmentB.pcb_trace_id}_${segmentA.pcb_trace_id}`\n if (errorIds.has(pcb_trace_error_id)) continue\n if (errorIds.has(pcb_trace_error_id_reverse)) continue\n\n errorIds.add(pcb_trace_error_id)\n errors.push({\n type: \"pcb_trace_error\",\n error_type: \"pcb_trace_error\",\n message: `PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${getReadableName(segmentB.pcb_trace_id)}`,\n pcb_trace_id: segmentA.pcb_trace_id,\n source_trace_id: \"\",\n pcb_trace_error_id,\n pcb_component_ids: [],\n center: getCenterOfPcbTraceSegments(segmentA, segmentB),\n pcb_port_ids: getPcbPortIdsConnectedToTraces([\n segmentA._pcbTrace,\n segmentB._pcbTrace,\n ]),\n })\n continue\n }\n const primaryObjId = getPrimaryId(obj as any)\n const gap =\n segmentToBoundsMinDistance(\n { x: segmentA.x1, y: segmentA.y1 },\n { x: segmentA.x2, y: segmentA.y2 },\n getCollidableBounds(obj),\n ) -\n segmentA.thickness / 2\n if (\n !connMap.areIdsConnected(segmentA.pcb_trace_id, primaryObjId) &&\n gap + EPSILON < requiredMargin\n ) {\n const pcb_trace_error_id = `overlap_${segmentA.pcb_trace_id}_${primaryObjId}`\n if (errorIds.has(pcb_trace_error_id)) continue\n errorIds.add(pcb_trace_error_id)\n errors.push({\n type: \"pcb_trace_error\",\n error_type: \"pcb_trace_error\",\n message: `PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${obj.type} \"${getReadableName(getPrimaryId(obj as any))}\" ${gap < 0 ? \"(accidental contact)\" : `(gap: ${gap.toFixed(3)}mm)`}`,\n pcb_trace_id: segmentA.pcb_trace_id,\n source_trace_id: \"\",\n pcb_trace_error_id,\n pcb_component_ids: [\n \"pcb_component_id\" in obj ? obj.pcb_component_id : undefined,\n ].filter(Boolean) as string[],\n center: getCenterOfBounds(getCollidableBounds(obj)),\n pcb_port_ids: [\n ...getPcbPortIdsConnectedToTraces([segmentA._pcbTrace]),\n \"pcb_port_id\" in obj ? obj.pcb_port_id : undefined,\n ].filter(Boolean) as string[],\n })\n }\n }\n }\n return errors\n}\n","import { getBoundsOfPcbElements } from \"@tscircuit/circuit-json-util\"\nimport type {\n AnyCircuitElement,\n PcbHole,\n PCBKeepout,\n PcbPlatedHole,\n PcbSmtPad,\n PcbTrace,\n PcbTraceError,\n PcbVia,\n} from \"circuit-json\"\n\ninterface Bounds {\n minX: number\n minY: number\n maxX: number\n maxY: number\n}\n\nexport type PcbTraceSegment = {\n type: \"pcb_trace_segment\"\n _pcbTrace: PcbTrace\n pcb_trace_id: string\n thickness: number\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\nexport type Collidable =\n | PcbTraceSegment\n | PcbSmtPad\n | PcbPlatedHole\n | PcbHole\n | PcbVia\n | PCBKeepout\n\nexport const getCollidableBounds = (collidable: Collidable): Bounds => {\n if (collidable.type === \"pcb_trace_segment\") {\n return {\n minX: Math.min(collidable.x1, collidable.x2),\n minY: Math.min(collidable.y1, collidable.y2),\n maxX: Math.max(collidable.x1, collidable.x2),\n maxY: Math.max(collidable.y1, collidable.y2),\n }\n }\n return getBoundsOfPcbElements([collidable as any])\n}\n","import type { PcbTrace } from \"circuit-json\"\n\nexport function getPcbPortIdsConnectedToTrace(trace: PcbTrace) {\n const connectedPcbPorts = new Set<string>()\n for (const segment of trace.route) {\n if (segment.route_type === \"wire\") {\n if (segment.start_pcb_port_id)\n connectedPcbPorts.add(segment.start_pcb_port_id)\n if (segment.end_pcb_port_id)\n connectedPcbPorts.add(segment.end_pcb_port_id)\n }\n }\n\n return Array.from(connectedPcbPorts)\n}\n\nexport function getPcbPortIdsConnectedToTraces(traces: PcbTrace[]) {\n const connectedPorts = new Set<string>()\n for (const trace of traces) {\n for (const portId of getPcbPortIdsConnectedToTrace(trace)) {\n connectedPorts.add(portId)\n }\n }\n return Array.from(connectedPorts)\n}\n","import type { PcbTraceSegment } from \"./getCollidableBounds\"\n\n/**\n * Get the center point between two PCB trace segments\n */\nexport const getCenterOfPcbTraceSegments = (\n segmentA: PcbTraceSegment,\n segmentB: PcbTraceSegment,\n) => {\n return {\n x:\n (Math.min(segmentA.x1, segmentA.x2, segmentB.x1, segmentB.x2) +\n Math.max(segmentA.x1, segmentA.x2, segmentB.x1, segmentB.x2)) /\n 2,\n y:\n (Math.min(segmentA.y1, segmentA.y2, segmentB.y1, segmentB.y2) +\n Math.max(segmentA.y1, segmentA.y2, segmentB.y1, segmentB.y2)) /\n 2,\n }\n}\n","import type { Bounds } from \"lib/data-structures/SpatialIndex\"\n\n/**\n * Get the center point of a bounds object\n */\nexport const getCenterOfBounds = (bounds: Bounds) => {\n return {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n }\n}\n","export class NetManager {\n private networks: Set<Set<string>> = new Set()\n\n setConnected(nodes: string[]): void {\n if (nodes.length < 2) return\n\n let targetNetwork: Set<string> | null = null\n\n // Check if any of the nodes are already in a network\n for (const network of this.networks) {\n for (const node of nodes) {\n if (network.has(node)) {\n if (targetNetwork === null) {\n targetNetwork = network\n } else if (targetNetwork !== network) {\n // Merge networks\n for (const mergeNode of network) {\n targetNetwork.add(mergeNode)\n }\n this.networks.delete(network)\n }\n break\n }\n }\n if (targetNetwork !== null && targetNetwork !== network) break\n }\n\n // If no existing network found, create a new one\n if (targetNetwork === null) {\n targetNetwork = new Set(nodes)\n this.networks.add(targetNetwork)\n } else {\n // Add all nodes to the target network\n for (const node of nodes) {\n targetNetwork.add(node)\n }\n }\n }\n\n isConnected(nodes: string[]): boolean {\n if (nodes.length < 2) return true\n\n for (const network of this.networks) {\n if (nodes.every((node) => network.has(node))) {\n return true\n }\n }\n\n return false\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@tscircuit/checks",
3
- "module": "index.ts",
4
3
  "type": "module",
5
- "main": "./dist/index.cjs",
6
- "version": "0.0.27",
4
+ "main": "./dist/index.js",
5
+ "version": "0.0.29",
7
6
  "files": [
8
7
  "dist"
9
8
  ],
10
9
  "scripts": {
11
- "build": "tsup index.ts --dts --sourcemap",
10
+ "build": "tsup-node index.ts --format esm --dts --sourcemap",
12
11
  "format:check": "biome format .",
13
12
  "format": "biome format . --write"
14
13
  },
15
14
  "devDependencies": {
16
15
  "@biomejs/biome": "^1.9.0",
16
+ "@tscircuit/circuit-json-util": "^0.0.45",
17
17
  "@tscircuit/log-soup": "^1.0.2",
18
18
  "@types/bun": "latest",
19
- "circuit-json": "^0.0.85",
20
19
  "@types/debug": "^4.1.12",
20
+ "circuit-json": "^0.0.153",
21
21
  "debug": "^4.3.5",
22
22
  "tsup": "^8.2.3"
23
23
  },
@@ -26,7 +26,7 @@
26
26
  "typescript": "^5.5.3"
27
27
  },
28
28
  "dependencies": {
29
- "@tscircuit/soup-util": "0.0.36",
30
- "circuit-json-to-connectivity-map": "^0.0.17"
29
+ "@tscircuit/math-utils": "^0.0.12",
30
+ "circuit-json-to-connectivity-map": "^0.0.19"
31
31
  }
32
32
  }