@tscircuit/checks 0.0.147 → 0.0.149
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 +2 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +76 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ and output an array of arrays for any issues found.
|
|
|
10
10
|
| Function | Description |
|
|
11
11
|
| --- | --- |
|
|
12
12
|
| [`checkConnectorAccessibleOrientation`](./lib/check-connector-accessible-orientation.ts) | Returns `pcb_accessibility_error` for connectors whose orientation makes them inaccessible. |
|
|
13
|
+
| [`checkTestPointAccessibility`](./lib/check-testpoint-accessibility.ts) | Returns `pcb_placement_error` when a test point is inside another component's courtyard on the same PCB side. |
|
|
13
14
|
| [`checkAllPinsInComponentAreUnderspecified`](./lib/check-all-pins-in-component-are-underspecified.ts) | Returns `source_component_pins_underspecified_warning` when every pin on a chip lacks pin attributes. |
|
|
14
15
|
| [`checkNoPowerPinDefined`](./lib/check-no-power-pin-defined.ts) | Returns `source_no_power_pin_defined_warning` when a chip has no pin with `requires_power=true`. |
|
|
15
16
|
| [`checkNoGroundPinDefined`](./lib/check-no-ground-pin-defined.ts) | Returns `source_no_ground_pin_defined_warning` when a chip has no pin with `requires_ground=true`. |
|
|
@@ -31,7 +32,7 @@ and output an array of arrays for any issues found.
|
|
|
31
32
|
|
|
32
33
|
| Function | Description |
|
|
33
34
|
| --- | --- |
|
|
34
|
-
| [`runAllPlacementChecks`](./lib/run-all-checks.ts) | Runs placement checks (`checkViasOffBoard`, `checkPcbComponentsOutOfBoard`, `checkPcbComponentOverlap`, `checkPadPadClearance`,
|
|
35
|
+
| [`runAllPlacementChecks`](./lib/run-all-checks.ts) | Runs placement checks (`checkViasOffBoard`, `checkPcbComponentsOutOfBoard`, `checkPcbComponentOverlap`, `checkPadPadClearance`, `checkCourtyardOverlap`, `checkConnectorAccessibleOrientation`, and `checkTestPointAccessibility`). |
|
|
35
36
|
| [`runAllNetlistChecks`](./lib/run-all-checks.ts) | Runs netlist connectivity checks (currently `checkPinMustBeConnected`). |
|
|
36
37
|
| [`runAllPinSpecificationChecks`](./lib/run-all-checks.ts) | Runs pin specification checks (e.g. `checkAllPinsInComponentAreUnderspecified`, `checkNoPowerPinDefined`, and `checkNoGroundPinDefined`). |
|
|
37
38
|
| [`runAllRoutingChecks`](./lib/run-all-checks.ts) | Runs all routing checks currently enabled (`checkEachPcbPortConnectedToPcbTraces`, `checkSourceTracesHavePcbTraces`, `checkEachPcbTraceNonOverlapping`, `checkPadTraceClearance`, `checkViaTraceClearance`, same/different net via spacing, and `checkPcbTracesOutOfBoard`). Trace-obstacle pairs are classified before aggregation, so each pair produces one overlap or clearance diagnostic, never both. |
|
package/dist/index.d.ts
CHANGED
|
@@ -152,4 +152,11 @@ declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circui
|
|
|
152
152
|
|
|
153
153
|
declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElement[]): PcbConnectorNotInAccessibleOrientationWarning[];
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
/**
|
|
156
|
+
* Test points are intended to be contacted from their PCB side. A test point
|
|
157
|
+
* whose access center is covered by another component's courtyard cannot be
|
|
158
|
+
* reliably reached by a probe after assembly.
|
|
159
|
+
*/
|
|
160
|
+
declare function checkTestPointAccessibility(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
|
|
161
|
+
|
|
162
|
+
export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverlap, checkPcbComponentsOutOfBoard, checkPcbTraceLengths, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTestPointAccessibility, checkTracesAreContiguous, checkViaTraceClearance, checkViasOffBoard, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks };
|
package/dist/index.js
CHANGED
|
@@ -3179,6 +3179,79 @@ function checkCourtyardOverlap(circuitJson) {
|
|
|
3179
3179
|
return errors;
|
|
3180
3180
|
}
|
|
3181
3181
|
|
|
3182
|
+
// lib/check-testpoint-accessibility.ts
|
|
3183
|
+
import { isPointInsidePolygon as isPointInsidePolygon3 } from "@tscircuit/math-utils";
|
|
3184
|
+
var isCourtyardElement2 = (element) => element.type === "pcb_courtyard_circle" || element.type === "pcb_courtyard_outline" || element.type === "pcb_courtyard_polygon" || element.type === "pcb_courtyard_rect";
|
|
3185
|
+
var isPointInsideCourtyard = (point, courtyard) => {
|
|
3186
|
+
if (courtyard.type === "pcb_courtyard_circle") {
|
|
3187
|
+
const dx = point.x - courtyard.center.x;
|
|
3188
|
+
const dy = point.y - courtyard.center.y;
|
|
3189
|
+
return dx * dx + dy * dy <= courtyard.radius * courtyard.radius;
|
|
3190
|
+
}
|
|
3191
|
+
if (courtyard.type === "pcb_courtyard_rect") {
|
|
3192
|
+
const angle = -1 * (courtyard.ccw_rotation ?? 0) * Math.PI / 180;
|
|
3193
|
+
const dx = point.x - courtyard.center.x;
|
|
3194
|
+
const dy = point.y - courtyard.center.y;
|
|
3195
|
+
const localX = dx * Math.cos(angle) - dy * Math.sin(angle);
|
|
3196
|
+
const localY = dx * Math.sin(angle) + dy * Math.cos(angle);
|
|
3197
|
+
return Math.abs(localX) <= courtyard.width / 2 && Math.abs(localY) <= courtyard.height / 2;
|
|
3198
|
+
}
|
|
3199
|
+
const polygon = courtyard.type === "pcb_courtyard_polygon" ? courtyard.points : courtyard.outline;
|
|
3200
|
+
return isPointInsidePolygon3(point, polygon);
|
|
3201
|
+
};
|
|
3202
|
+
var getPcbComponentName = (circuitJson, pcbComponentId) => {
|
|
3203
|
+
const pcbComponent = circuitJson.find(
|
|
3204
|
+
(element) => element.type === "pcb_component" && element.pcb_component_id === pcbComponentId
|
|
3205
|
+
);
|
|
3206
|
+
const sourceComponent = circuitJson.find(
|
|
3207
|
+
(element) => element.type === "source_component" && element.source_component_id === pcbComponent?.source_component_id
|
|
3208
|
+
);
|
|
3209
|
+
return (sourceComponent && "name" in sourceComponent ? sourceComponent.name : void 0) ?? getReadableNameForComponent(circuitJson, pcbComponentId);
|
|
3210
|
+
};
|
|
3211
|
+
function checkTestPointAccessibility(circuitJson) {
|
|
3212
|
+
const sourceTestPoints = circuitJson.filter(
|
|
3213
|
+
(element) => element.type === "source_component" && element.ftype === "simple_test_point"
|
|
3214
|
+
);
|
|
3215
|
+
const sourceTestPointIds = new Set(
|
|
3216
|
+
sourceTestPoints.map((testPoint) => testPoint.source_component_id)
|
|
3217
|
+
);
|
|
3218
|
+
const testPointNames = new Map(
|
|
3219
|
+
sourceTestPoints.map((testPoint) => [
|
|
3220
|
+
testPoint.source_component_id,
|
|
3221
|
+
testPoint.name
|
|
3222
|
+
])
|
|
3223
|
+
);
|
|
3224
|
+
const testPointComponents = circuitJson.filter(
|
|
3225
|
+
(element) => element.type === "pcb_component" && sourceTestPointIds.has(element.source_component_id)
|
|
3226
|
+
);
|
|
3227
|
+
const courtyards = circuitJson.filter(isCourtyardElement2);
|
|
3228
|
+
const errors = [];
|
|
3229
|
+
const reportedComponentPairs = /* @__PURE__ */ new Set();
|
|
3230
|
+
for (const testPoint of testPointComponents) {
|
|
3231
|
+
for (const courtyard of courtyards) {
|
|
3232
|
+
if (courtyard.pcb_component_id === testPoint.pcb_component_id) continue;
|
|
3233
|
+
if (courtyard.layer !== testPoint.layer) continue;
|
|
3234
|
+
if (!isPointInsideCourtyard(testPoint.center, courtyard)) continue;
|
|
3235
|
+
const componentPair = `${testPoint.pcb_component_id}:${courtyard.pcb_component_id}`;
|
|
3236
|
+
if (reportedComponentPairs.has(componentPair)) continue;
|
|
3237
|
+
reportedComponentPairs.add(componentPair);
|
|
3238
|
+
const testPointName = testPointNames.get(testPoint.source_component_id) ?? "Test point";
|
|
3239
|
+
const obstructingComponentName = getPcbComponentName(
|
|
3240
|
+
circuitJson,
|
|
3241
|
+
courtyard.pcb_component_id
|
|
3242
|
+
);
|
|
3243
|
+
errors.push({
|
|
3244
|
+
type: "pcb_placement_error",
|
|
3245
|
+
pcb_placement_error_id: `testpoint_in_courtyard_${testPoint.pcb_component_id}_${courtyard.pcb_component_id}`,
|
|
3246
|
+
error_type: "pcb_placement_error",
|
|
3247
|
+
message: `Test point ${testPointName} is not accessible because it is inside the courtyard of ${obstructingComponentName}`,
|
|
3248
|
+
subcircuit_id: testPoint.subcircuit_id
|
|
3249
|
+
});
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
return errors;
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3182
3255
|
// lib/run-all-checks.ts
|
|
3183
3256
|
async function runAllPlacementChecks(circuitJson) {
|
|
3184
3257
|
return [
|
|
@@ -3187,7 +3260,8 @@ async function runAllPlacementChecks(circuitJson) {
|
|
|
3187
3260
|
...checkPcbComponentOverlap(circuitJson),
|
|
3188
3261
|
...checkPadPadClearance(circuitJson),
|
|
3189
3262
|
...checkCourtyardOverlap(circuitJson),
|
|
3190
|
-
...checkConnectorAccessibleOrientation(circuitJson)
|
|
3263
|
+
...checkConnectorAccessibleOrientation(circuitJson),
|
|
3264
|
+
...checkTestPointAccessibility(circuitJson)
|
|
3191
3265
|
];
|
|
3192
3266
|
}
|
|
3193
3267
|
async function runAllNetlistChecks(circuitJson) {
|
|
@@ -3241,6 +3315,7 @@ export {
|
|
|
3241
3315
|
checkSameNetViaSpacing,
|
|
3242
3316
|
checkSourceTracesHavePcbTraces,
|
|
3243
3317
|
checkSourceTracesMatchPcbTraceThickness,
|
|
3318
|
+
checkTestPointAccessibility,
|
|
3244
3319
|
checkTracesAreContiguous,
|
|
3245
3320
|
checkViaTraceClearance,
|
|
3246
3321
|
checkViasOffBoard,
|