Files
3DPrintMeetup/Articles/ai-cad-skill-pack/.agents/skills/freecad-step-builder/SKILL.md

103 lines
11 KiB
Markdown
Raw Normal View History

---
name: freecad-step-builder
description: Parametric 3D CAD solid modeling skill using headless FreeCAD OpenCASCADE (FreeCADCmd) to generate watertight STEP, FCStd, printable STL files, and standalone 3D WebGL assembly viewers for any CAD project (<ProjectName>).
---
# FreeCAD OpenCASCADE B-Rep, Printable STL & 3D Viewer Skill (`freecad-step-builder`)
This skill governs parametric 3D OpenCASCADE B-Rep solid modeling, boolean interference verification, `.step`/`.stl` export, and standalone interactive 3D WebGL viewer generation (`<ProjectName>_3D_Assembly_Viewer.html`) for **any CAD project (`<ProjectName>`)** using headless FreeCAD (`FreeCADCmd`).
---
## 0. Step 0: Resolve `FreeCADCmd` via `.cad-tools.json` or User Prompt
**Do NOT search the filesystem to guess how FreeCAD is installed.**
1. Check `.cad-tools.json` in the workspace root for `"freecad_cmd"` (or check if the user already provided the FreeCAD command/path in the conversation or project `AGENTS.md`).
2. If not yet configured, ask the user (or have the Designer / QA Inspector agent ask via `ask_question`) how FreeCAD is installed:
- Flatpak: `flatpak run --command=FreeCADCmd org.freecad.FreeCAD <script.py>`
- Native package: `freecadcmd <script.py>` or `FreeCADCmd <script.py>`
- AppImage / Custom path: `/path/to/FreeCAD.AppImage -c <script.py>`
- Or Not installed (use `SolidCraft` only).
3. Save the command in `.cad-tools.json` and guard script entrypoints with:
```python
if __name__ in ("__main__", "<script_stem>"):
build_and_export()
```
because `FreeCADCmd` sets `__name__` to the script filename stem rather than `"__main__"`.
---
## 1. Standard Project Output Structure (`<ProjectName>`)
> **Blueprint-First Gate**: Do NOT build 3D FreeCAD solids until the 1:1 mm orthographic 2D SVG blueprints (`<ProjectName>_Side_View.svg`, `<ProjectName>_Front_View.svg`, `<ProjectName>_Top_View.svg`) have been generated and reviewed by the user.
All 3D deliverables are modeled in millimeters ($1\text{ unit} = 1.0\text{ mm}$) in assembled world coordinates inside `<ProjectName>/CAD/`:
| Deliverable Type | Path Pattern | Purpose |
| :--- | :--- | :--- |
| **Parametric FreeCAD Project** | `CAD/<ProjectName>_Full_Assembly.FCStd` & `CAD/FCStd/<PartName>.FCStd` | Native FreeCAD document with a `Params` **`Spreadsheet::Sheet`** and separate **`PartDesign::Body`** containers holding sequential `Sketcher::SketchObject` + `PartDesign::Pad` / `PartDesign::Pocket` features for human editing. |
| **Individual Component STEP** | `CAD/STEP/<PartName>.step` | Exact OpenCASCADE B-Rep solid for CAD interchange. |
| **Individual Component STL** | `CAD/STL/<PartName>.stl` | High-resolution watertight mesh (`LinearDeflection=0.15`, `AngularDeflection=0.35`) for 3D printing. |
| **Sub-Assembly STEP** | `CAD/STEP/<ProjectName>_Parts_Assembly.step` | Multi-body STEP assembly of all printable components. |
| **Full Hardware Assembly** | `CAD/STEP/<ProjectName>_Full_Assembly.step` | Complete assembly including host hardware and payload reference solids. |
| **Interactive 3D WebGL Viewer** | `<ProjectName>_3D_Assembly_Viewer.html` | Zero-dependency standalone HTML/WebGL viewer with Orbit/Pan/Zoom, Explode slider (`0%..100%`), camera presets, and per-part visibility toggles. |
---
## 2. Mandatory Step-by-Step Parametric `PartDesign::Body` Build History Standard
**CRITICAL RULE: Never Export a Collapsed Static `Part::Feature` Solid as the Primary `.FCStd` Model**:
Instead of fusing/cutting raw `Part.Shape` objects in Python memory and assigning the final shape to a single non-editable `Part::Feature` (`obj.Shape = final_shape`), **always construct each part as a native `PartDesign::Body` with a step-by-step feature history driven by a `Spreadsheet::Sheet` (`Params`)**:
1. **Create a Parametric `Spreadsheet::Sheet` (`Params`)**:
- Add a `Spreadsheet::Sheet` named `"Params"` to the FreeCAD document and register every key dimension (board/payload lengths, fan hole spacing, PSU cradle width/height, wall thicknesses, clip overhangs, dovetail clearances) with human-readable labels in Column A, numeric values in Column B, and **aliases** via `sheet.setAlias("B2", "fan_hole_spacing")`.
2. **Build Each Component as a Separate `PartDesign::Body`**:
- Create one `PartDesign::Body` per printable part (`doc.addObject("PartDesign::Body", part_name)`).
- Add sequential features inside each `PartDesign::Body` so a human opening the `.FCStd` file in FreeCAD GUI sees every step in the Model Tree and can double-click any sketch or pad/pocket to edit it:
- **Step A (`Sketcher::SketchObject`)**: `sk = body.newObject("Sketcher::SketchObject", "Sketch_<FeatureName>")`, attach to the appropriate plane (`XY_Plane`, `XZ_Plane`, `YZ_Plane` or a datum plane offset), add closed wire geometry (`Part.LineSegment`, `Part.Circle`, `Part.ArcOfCircle`), and apply `Sketcher.Constraint('Coincident', ...)` constraints.
- **Step B (`PartDesign::Pad` Additive Extrusion)**: `pad = body.newObject("PartDesign::Pad", "Pad_<FeatureName>")`, set `pad.Profile = sk`, `pad.Length = ...` (or bind to spreadsheet via `pad.setExpression("Length", "<<Params>>.wall_thickness")`).
- **Step C (`PartDesign::Pocket` Subtractive Cutout / Bore / Duct / Mortise)**: `pocket = body.newObject("PartDesign::Pocket", "Pocket_<FeatureName>")`, set `pocket.Profile = sk_cut`, `pocket.Type = 0` (Dimension) or `1` (ThroughAll), and `pocket.Reversed = True/False`.
3. **Group Reference Hardware Separately**:
- Place non-printed reference hardware solids (e.g., SBC board + heatsink, PSU brick, 120 mm fans, host printer) inside a `App::DocumentObjectGroup` named `"Reference_Hardware"` so they are cleanly separated from the editable `PartDesign::Body` components.
---
## 3. Technical CAD & DFM Design Patterns (User Intent to Engineering Implementation)
1. **Step-by-Step `PartDesign::Body` Sketch-to-Pad/Pocket Modeling**:
- Construct cantilever webs, fan shrouds/plenums, PSU cradles, snap-fit clips, clevis hooks, and dovetail tenons/mortises as individual named `Sketcher::SketchObject` + `PartDesign::Pad` / `PartDesign::Pocket` steps inside each part's `PartDesign::Body`.
2. **Cantilever Snap-Fit Retention Clips & Overhang Ledges (`Snap-Fit Retention Tabs`)**:
- *User intent*: *"Hold the power supply or board in place with overhangs or clips."*
- *CAD implementation*: Model vertical **Cradle Side-Walls** that constrain lateral $(X, Y)$ translation, topped by **Cantilever Snap-Fit Retention Ledges (Overhang Hooks)** with a $1.5\text{ to }2.5\text{ mm}$ inward catch lip, a $30^\circ\text{--}45^\circ$ top **Lead-In Insertion Chamfer** (so the component snaps down past the flex tab during installation), and a $0.30\text{ mm}$ vertical/lateral clearance allowance around the payload envelope.
3. **Coplanar Build-Plate Datum Face (Zero-Stickout Flush Bosses)**:
- *User intent*: *"Make the round hole part flush with the arm so it's flat on the bed to print."*
- *CAD implementation*: Make the axial length of cylindrical mounting bosses equal to the structural web thickness and align their outer faces to be strictly **coplanar** ($\Delta X = 0$). Eliminating out-of-plane boss stickout ensures the entire outer side face serves as a flat $Z_{\text{print}} = 0$ build-plate datum requiring zero supports.
4. **Orthogonal Anti-Rotation Return Flange (Corner-Wrapping Reaction Pad)**:
- *User intent*: *"Wrap the front corner so the sleeve on the round peg can't rotate."*
- *CAD implementation*: Extending a $90^\circ$ **Orthogonal Return Flange** around the chassis corner onto a flat orthogonal datum face constrains rotation ($\theta = 0$) and resolves cantilevered bending moment ($M = F \cdot d$) into a tension-at-pin / compression-at-pad force couple.
5. **Interlocking Cleat & Shrouded Clevis Gravity Joint**:
- *User intent*: *"Have the top piece hook straight down over the front leg."*
- *CAD implementation*: Terminate the lower return flange in an upward **Male Cleat Tang** with a rear **Receiver Channel** and a lower **Horizontal Bearing Shoulder (Step Ledge)**. Form a mating **Female Clevis Saddle** on the upper cantilever rail flanked by **Axial Retention End-Cheeks (Shrouded Side Flanges)** that capture the cleat laterally and prevent the lower brace from sliding off its mounting boss.
6. **Shouldered Half-Lap Dovetail Ledger Joint (Blind Mortises + Integral Drop-In Tenons)**:
- *User intent*: *"Have a lip that the center piece rests on with dovetails on top instead of separate bowties."*
- *CAD implementation*: Step the inner mating edge into a **Lower Half-Lap Bearing Ledger** (carrying vertical shear in direct compression) and cut **Blind (Stopped) Female Dovetail Mortises** into the upper half. Extrude **Integral Male Dovetail Tenons** ($0.20\text{ mm}$ XY clearance allowance) on the ends of the spanning cross-member so it drops straight in from the top and locks lateral tension ($F_X$) and in-plane racking without separate butterfly/dutchman keys.
7. **Stepped Edge Rabbet Relief (`Rabbet` / `Rebate Cut`) for Overhanging Lids**:
- *User intent*: *"Reverse L notch at the top back to clear a cover that overhangs the front by 5 mm."*
- *CAD implementation*: Cut a two-sided rectangular **Edge Rabbet Relief** (e.g., $6\text{ mm}$ deep x $5\text{ mm}$ high) along the upper-rear edge to clear the overhanging cover lip while preserving a lower **Undercut Datum Contact Toe** that reaches back to bear against the primary machine datum plane.
8. **FDM Bore Shrinkage Allowance & Coaxial Flange Counterbore**:
- *User intent*: *"Open up a tight spool holder hole by 0.5 mm radius."*
- *CAD implementation*: Apply an **ISO Free-Running Slip-Fit Clearance Allowance** ($\Delta R = +0.50\text{ to }+0.80\text{ mm}$, or $+1.0\text{ to }+1.6\text{ mm}$ diametral clearance) on large FDM-printed bores ($\varnothing 30\text{--}75\text{ mm}$) to compensate for inner-perimeter shrinkage and seam bulge, paired with a coaxial **Counterbore** clearing the mounting base flange.
---
## 4. Dual Automated Verification Gates
- **Gate 1 (Manifold & Zero-Clash Gate)**:
- Assert `solid.isValid() == True` and `solid.Volume > 0` for every component.
- Assert `part_solid.common(host_reference_solid).Volume < 0.001` ($0.0000\text{ mm}^3$ interference with the host machine, overhanging covers, doors, and keep-out envelopes).
- Assert `part_i.common(part_j).Volume < 0.001` ($0.0000\text{ mm}^3$ boolean overlap across all mating components).
- **Gate 2 (Conditional Print Bed Bounding-Box Gate ONLY when `"is_3d_printed": true`)**:
- When `"is_3d_printed": true` in `.cad-tools.json`, assert `bbox.XLength <= SAFE_LIMIT and bbox.YLength <= SAFE_LIMIT and bbox.ZLength <= SAFE_LIMIT`.
- When `"is_3d_printed": false` (e.g., Game Design, Digital Twin, CNC, or Unconstrained CAD), skip print-bed bounding-box limits.