@tscircuit/checks 0.0.143 → 0.0.144

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 CHANGED
@@ -78,6 +78,15 @@ declare function checkViaTraceClearance(circuitJson: AnyCircuitElement[], { conn
78
78
  minClearance?: number;
79
79
  }): PcbViaTraceClearanceError[];
80
80
 
81
+ /**
82
+ * Removes generic pcb_trace_error records when a more specific pad-trace or
83
+ * via-trace clearance error describes the same physical pair.
84
+ *
85
+ * The specific record is retained because it includes the measured and
86
+ * required clearance. Trace-trace and all other generic errors are untouched.
87
+ */
88
+ declare const dedupePcbDrcErrors: <T extends AnyCircuitElement>(errors: T[]) => T[];
89
+
81
90
  type SourcePinMustBeConnectedError = {
82
91
  type: "source_pin_must_be_connected_error";
83
92
  source_pin_must_be_connected_error_id: string;
@@ -137,4 +146,4 @@ declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circui
137
146
 
138
147
  declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElement[]): PcbConnectorNotInAccessibleOrientationWarning[];
139
148
 
140
- export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverlap, checkPcbComponentsOutOfBoard, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTracesAreContiguous, checkViaTraceClearance, checkViasOffBoard, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks };
149
+ export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverlap, checkPcbComponentsOutOfBoard, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTracesAreContiguous, checkViaTraceClearance, checkViasOffBoard, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks };
package/dist/index.js CHANGED
@@ -193,6 +193,17 @@ function isPointOnSegment(point, segment) {
193
193
  const squaredLength = (segment.end.x - segment.start.x) ** 2 + (segment.end.y - segment.start.y) ** 2;
194
194
  return dotProduct <= squaredLength + POINT_ON_SEGMENT_TOLERANCE_MM;
195
195
  }
196
+ function isPointInPolygon(point, polygon) {
197
+ let inside = false;
198
+ for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
199
+ const pi = polygon[i];
200
+ const pj = polygon[j];
201
+ if (isPointOnSegment(point, { start: pi, end: pj })) return true;
202
+ const intersects = pi.y > point.y !== pj.y > point.y && point.x < (pj.x - pi.x) * (point.y - pi.y) / (pj.y - pi.y) + pi.x;
203
+ if (intersects) inside = !inside;
204
+ }
205
+ return inside;
206
+ }
196
207
  function isPointInPad(point, pad) {
197
208
  if (pad.type === "pcb_smtpad") {
198
209
  if (pad.shape === "circle") {
@@ -204,12 +215,7 @@ function isPointInPad(point, pad) {
204
215
  return Math.abs(point.x - pad.x) <= halfWidth && Math.abs(point.y - pad.y) <= halfHeight;
205
216
  }
206
217
  if (pad.shape === "rotated_rect") {
207
- const dx = point.x - pad.x;
208
- const dy = point.y - pad.y;
209
- const angle = -pad.ccw_rotation;
210
- const rotatedX = dx * Math.cos(angle) - dy * Math.sin(angle);
211
- const rotatedY = dx * Math.sin(angle) + dy * Math.cos(angle);
212
- return Math.abs(rotatedX) <= pad.width / 2 && Math.abs(rotatedY) <= pad.height / 2;
218
+ return isPointInPolygon(point, getPolygonPointsForPad(pad));
213
219
  }
214
220
  if (pad.shape === "pill" || pad.shape === "rotated_pill") {
215
221
  if (pad.shape === "rotated_pill") {
@@ -233,30 +239,19 @@ function isPointInPad(point, pad) {
233
239
  return cornerX * cornerX + cornerY * cornerY <= radius * radius;
234
240
  }
235
241
  if (pad.shape === "polygon") {
236
- let inside = false;
237
- for (let i = 0, j = pad.points.length - 1; i < pad.points.length; j = i++) {
238
- const pi = pad.points[i];
239
- const pj = pad.points[j];
240
- if (isPointOnSegment(point, { start: pi, end: pj })) return true;
241
- const intersects = pi.y > point.y !== pj.y > point.y && point.x < (pj.x - pi.x) * (point.y - pi.y) / (pj.y - pi.y) + pi.x;
242
- if (intersects) inside = !inside;
243
- }
244
- return inside;
242
+ return isPointInPolygon(point, pad.points);
245
243
  }
246
244
  }
247
245
  if (pad.type === "pcb_plated_hole") {
248
246
  if (pad.shape === "circle") {
249
247
  return getDistanceBetweenPoints(point, pad) <= pad.outer_diameter / 2;
250
248
  }
249
+ if ("rect_pad_width" in pad && "rect_pad_height" in pad) {
250
+ return isPointInPolygon(point, getPolygonPointsForPad(pad));
251
+ }
251
252
  if (pad.shape === "oval" || pad.shape === "pill") {
252
253
  return Math.abs(point.x - pad.x) <= pad.outer_width / 2 && Math.abs(point.y - pad.y) <= pad.outer_height / 2;
253
254
  }
254
- if (pad.shape === "circular_hole_with_rect_pad") {
255
- return Math.abs(point.x - pad.x) <= pad.rect_pad_width / 2 && Math.abs(point.y - pad.y) <= pad.rect_pad_height / 2;
256
- }
257
- if (pad.shape === "pill_hole_with_rect_pad") {
258
- return Math.abs(point.x - pad.x) <= pad.rect_pad_width / 2 && Math.abs(point.y - pad.y) <= pad.rect_pad_height / 2;
259
- }
260
255
  }
261
256
  return false;
262
257
  }
@@ -2652,6 +2647,27 @@ function checkViaTraceClearance(circuitJson, {
2652
2647
  return Array.from(errors.values()).map(({ error }) => error);
2653
2648
  }
2654
2649
 
2650
+ // lib/dedupe-pcb-drc-errors.ts
2651
+ var dedupePcbDrcErrors = (errors) => {
2652
+ const specificallyReportedPairIds = /* @__PURE__ */ new Set();
2653
+ for (const error of errors) {
2654
+ if (error.type === "pcb_pad_trace_clearance_error" && typeof error.pcb_trace_id === "string" && typeof error.pcb_pad_id === "string") {
2655
+ specificallyReportedPairIds.add(
2656
+ `overlap_${error.pcb_trace_id}_${error.pcb_pad_id}`
2657
+ );
2658
+ }
2659
+ if (error.type === "pcb_via_trace_clearance_error" && typeof error.pcb_trace_id === "string" && typeof error.pcb_via_id === "string") {
2660
+ specificallyReportedPairIds.add(
2661
+ `overlap_${error.pcb_trace_id}_${error.pcb_via_id}`
2662
+ );
2663
+ }
2664
+ }
2665
+ return errors.filter((element) => {
2666
+ const error = element;
2667
+ return !(error.type === "pcb_trace_error" && typeof error.pcb_trace_error_id === "string" && specificallyReportedPairIds.has(error.pcb_trace_error_id));
2668
+ });
2669
+ };
2670
+
2655
2671
  // lib/check-pin-must-be-connected.ts
2656
2672
  function checkPinMustBeConnected(circuitJson) {
2657
2673
  const errors = [];
@@ -3073,7 +3089,7 @@ async function runAllPinSpecificationChecks(circuitJson) {
3073
3089
  ];
3074
3090
  }
3075
3091
  async function runAllRoutingChecks(circuitJson) {
3076
- return [
3092
+ return dedupePcbDrcErrors([
3077
3093
  ...checkEachPcbPortConnectedToPcbTraces(circuitJson),
3078
3094
  ...checkSourceTracesHavePcbTraces(circuitJson),
3079
3095
  ...checkEachPcbTraceNonOverlapping(circuitJson),
@@ -3082,15 +3098,15 @@ async function runAllRoutingChecks(circuitJson) {
3082
3098
  ...checkDifferentNetViaSpacing(circuitJson),
3083
3099
  ...checkTracesAreContiguous(circuitJson),
3084
3100
  ...checkPcbTracesOutOfBoard(circuitJson)
3085
- ];
3101
+ ]);
3086
3102
  }
3087
3103
  async function runAllChecks(circuitJson) {
3088
- return [
3104
+ return dedupePcbDrcErrors([
3089
3105
  ...await runAllPlacementChecks(circuitJson),
3090
3106
  ...await runAllNetlistChecks(circuitJson),
3091
3107
  ...await runAllPinSpecificationChecks(circuitJson),
3092
3108
  ...await runAllRoutingChecks(circuitJson)
3093
- ];
3109
+ ]);
3094
3110
  }
3095
3111
  export {
3096
3112
  NetManager,
@@ -3113,6 +3129,7 @@ export {
3113
3129
  checkTracesAreContiguous,
3114
3130
  checkViaTraceClearance,
3115
3131
  checkViasOffBoard,
3132
+ dedupePcbDrcErrors,
3116
3133
  runAllChecks,
3117
3134
  runAllNetlistChecks,
3118
3135
  runAllPinSpecificationChecks,