@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 +10 -1
- package/dist/index.js +42 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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,
|