---
name: bambu-3d-design
description: 3D-Modelle für Bambu Lab A1 Mini erstellen. Kein OpenSCAD/CadQuery nötig — generiert ASCII-STL direkt via Python stdlib. Boxen, Gehäuse, Löcher, Fillets, Custom-Parts.
triggers:
  - User will STL für 3D-Druck
  - User hat Bambu Lab A1 Mini
  - 3D drucken oder STL oder Gehäuse oder Box oder Halterung oder Case
  - OpenSCAD nicht verfügbar, kein pip, ZimaOS headless
---

# Bambu Lab A1 Mini 3D-Design

Erzeugt druckfertige ASCII-STL-Dateien direkt via Python (kein pip, kein OpenSCAD nötig).

## Drucker-Specs (A1 Mini)

- **Bauraum**: 180 x 180 x 180 mm
- **Nozzle**: 0.4 mm Standard
- **Layerhöhe**: 0.08 – 0.28 mm (0.2 mm Standard)
- **Overhangs**: max. 45° ohne Support
- **Bridging**: ca. 30 mm problemlos
- **Wanddicke**: min. 1.2 mm (3 Perimeter @ 0.4 mm)
- **Löcher**: Designe 0.2–0.3 mm größer als benötigt (Shrinkage ABS/ASA/PA)

## Ausgabe

- **Format**: ASCII-STL (lesbar, keine Binary-Header-Probleme)
- **Speicherort**: Standard unter `/DATA/AppData/hermes/Projekte/` oder wie vom User gewünscht
- **Naming**: `projektname_v1.stl`

## Primitive Builder (Python stdlib)

Das Template `scripts/stl_builder.py` stellt eine Klasse `STLBuilder` bereit:

```python
from stl_builder import STLBuilder

b = STLBuilder()
b.hollow_box(0, 0, 0, 60, 40, 20, wall=2, floor=2)   # Hohlkörper (5 Platten)
b.drill_mark(30, 20, 0, 3.5)                          # Bohrmarkierung
b.wall_with_rect_hole(0, 0, 0, 40, 2, 20, 10, 5, 8, 4)  # Wand mit USB-Loch
b.write("/path/to/part.stl")
```

## CRITICAL Pitfalls

1. **Proaktives STL-Generieren vermeiden — WARTE auf explizites Go**
   NIE ein STL generieren nur weil ein Plan diskutiert wurde. Warte auf explizites Go: "bau das", "generiere", "druckfertig machen", "Modell erstellen", "STL jetzt".
   
   **Wenn der User sagt "Modell nur erstellen bitte wenn ich dich drum bitte"** → das ist eine dauerhafte Regel. Auch wenn ein Projekt technisch beschrieben wird (z.B. Schaltplan + Teileliste), erstelle das Gehäuse erst nach expliziter Aufforderung.
   
   **Erlaubte Trigger**: "bau das", "generiere", "druckfertig", "STL", "Modell erstellen", "mach das Gehäuse", "erstelle jetzt"
   
   **ABSOLUT VERBOTEN**: Einen Plan für ein Projekt erstellen und gleichzeitig sagen "Soll ich das STL jetzt bauen?" oder gar das STL ohne Frage generieren.
   
   **Wenn der User ein bestehendes STL modifizieren will** (z.B. "Löcher weg, Höhe ändern") → das IST ein expliziter Auftrag, ausführen ist erlaubt.

2. **Kein Mesh-Editing an importierten STLs**
   STL-Dateien sind reine Dreiecks-Meshes. Ich kann NICHT:
   - Löcher aus einem bestehenden Mesh "stopfen"
   - Features selektiv entfernen
   - Die Geometrie eines importierten STLs verändern
   
   **Was ich tun kann**: Ein bestehendes STL analysieren (Größe, Facets, Volumen), skalieren (X/Y/Z unterschiedlich), oder ein **neues, sauberes Modell** bauen.
   
   **Was ich NICHT tun kann**: Boolean-Operationen (CSG) auf importierten Meshes durchführen.
   
   **Wenn der User ein importiertes STL modifizieren will**: Sage sofort "Ich kann das bestehende STL nicht verändern, aber ich baue ein neues Modell mit den gewünschten Änderungen."

3. **Binary STL = Problem**
   Bambu Studio kann Binary-STL lesen, aber bei korrupten Headern crasht es. **Immer ASCII-STL verwenden** — lesbar, debuggbar, robust.

4. **Nicht aus dem Zentrum designen**
   STL hat kein Koordinatensystem-Konzept. Positioniere das Modell so, dass z=0 auf dem Druckbett liegt. Negative Z-Werte = Druck im Luft.

5. **Wall thickness < 1.2 mm**
   Unter 3 Perimeter wird es brüchig. Für mechanische Teile mindestens 2 mm Wand, besser 3–4 mm.

6. **Overhangs > 45° ohne Support**
   A1 Mini kann bis ca. 55° mit gutem Cooling, aber sicher ist 45°. Für steilere Winkel:
   - Chamfer (45° Abschrägung) statt scharfe Kante
   - oder Support in Bambu Studio aktivieren

7. **Löcher zu klein designt**
   PLA schrumpft minimal, aber PETG/ASA/PA deutlich. Schraubenlöcher um 0.2–0.4 mm aufbohren.

8. **Mesh validieren statt hoffen**
   Jedes Design kann anders scheitern (naked edges, planar holes, inverted normals, non-manifold edges).
   **Prinzipien zur Vermeidung:**
   - Wo immer möglich aus soliden Platten bauen statt geschlossene Hüllen zu kombinieren
   - Keine separate "innere" und "äußere" Schale ohne saubere Brücken
   - Nach dem Export: Prüfen (z.B. via https://www.formware.co/onlinestlrepair oder Bambu Studio's own mesh repair)
   - Wenn Reparatur nötig ist, Muster lernen und im nächsten Design anwenden

## Reference

- `scripts/stl_builder.py` — Builder-Klasse mit allen Primitiven
- `references/mesh-repair-case-study.md` — Lektion aus Session 2026-05-09: hollow-shell → solid-plate fix, naked edges vermeiden
- `references/hunyuan3d2-api.md` — Free image-to-3D via Tencent Hunyuan3D-2 on HuggingFace (GLB → STL, organic shapes / avatars / characters)

Siehe `scripts/stl_builder.py` für die vollständige Builder-Klasse mit:
- `box()`, `cylinder()`, `sphere()`, `chamfer_box()`
- `hollow_box()` — watertight Hülle aus 5 Platten (für Boxen)
- `wall_with_rect_hole()` — Wand mit Loch, manifold durch 4-Streifen-Bauweise
- `drill_mark()` — Ring-Markierung zum manuellen Bohren/Slicen
- `scripts/generate_part.py` — Oneshot-Generator für custom Geometrie mit non-rectangulären Features (Halbkreis-Taschen, gerundete Greifmulden) — baut das Mesh aus soliden Platten und grid-Approximation statt Boolean-Operationen
- `rotate()`, `translate()`, `scale()`, `mirror()`

## Non-Rectangular Features (Grid Approximation)

When a feature is round, angled, or organic and the builder has no true boolean subtraction (CSG), use **grid approximation**:

1. Define the **2D footprint** (projection) of the feature and the **extrusion axis**.
2. Iterate a grid; each cell becomes a `_box()`.
3. Test the **cell centre** against the shape equation (e.g. `(x-cx)² + (y-cy)² <= r²`).
4. Place a box only when the cell is **outside** the cutout. If the pocket does not go all the way through, place a shorter box that ends at the pocket floor.
5. Use a **fine step** (e.g. `0.2–0.5 mm`) inside the feature boundary for smooth curves; use a **coarse step** (e.g. `1 mm`) everywhere else to keep facets reasonable.

### Pitfall: Blocky circles at coarse step
If the user says "not square inside, make it fully round," reduce the grid step in the feature zone to `0.2 mm`. This pushes facet counts up (e.g. ~90 k for a small box) but yields truly round-looking geometry in the slicer and on the print.

### Two-resolution grid
```python
fine_x0, fine_x1 = cx - r, cx + r          # horizontal span of the feature
coarse_step = 1.0
fine_step   = 0.2

# Coarse band left of feature
add_boxes(step=coarse_step, x0=slot_x0, x1=fine_x0)
# Fine band inside feature
add_boxes(step=fine_step,   x0=fine_x0, x1=fine_x1)
# Coarse band right of feature
add_boxes(step=coarse_step, x0=fine_x1, x1=slot_x1)
```

Keep `r + margin` away from the outer box walls so the grid never carves past the shell boundary.

## CRITICAL Pitfall: Open Slots / Holes in Wrong Directions
When cutting a slot or pocket into a wall, ensure the opening faces ONLY the intended direction.
- **Only top-open**: Build 4 enclosing walls around the slot (left, right, front, back) plus a solid floor. Never leave the slot open on sides that touch the outer box face.
- **Verification**: After generating, mentally trace the slot boundaries. If the slot_x0 equals the outer wall x0, the slot is flush with the outer face and will print open. Always keep a wall band between slot edge and box edge.

## CRITICAL Pitfall: Feature Too Close to Outer Walls
Round or rectangular pockets carved via grid approximation must stay fully inside the shell.
- **Margin rule**: Feature radius/width + grid step must not exceed the wall thickness. If the wall band between slot edge and box edge is thinner than the feature radius, the grid will carve past the wall into the outside.
- **Fix**: Shrink the feature or increase the wall thickness (e.g. `slot_x0 = (L - slot_L) / 2` gives symmetric 5.5 mm walls for a 175 mm box with 164 mm slot — safe for a 6 mm radius pocket, but not for a 10 mm one).

## CRITICAL Pitfall: Parameter Improvisation — Never Change User-Specified Dimensions
When a user gives exact dimensions (slot count, slot width, wall thickness, height), **use them verbatim**. Do not suggest alternatives, round numbers, or "improvements".

- **Example from 2026-05-10 session**: User said "12 thin slots like the template". Agent suggested 4 slots → user frustration: *"Ich will keine 4 fächer, ich will es genau so wie in der vorlage mit 12 dünnen schlitzen!"*
- **Second example**: User corrected slot width from 2.2 mm to 1.5 mm. Agent must accept immediately and recalculate dependent values (wall thickness) — no debate.

**Rule**: If the math doesn't work (e.g. 12 slots of 1.5 mm + 2 mm margins in 41.6 mm → negative wall space), calculate anyway, show the result, and ask: "Das ergibt Wandstärke X mm — passt das, oder weniger Schlitze?" Never silently change slot count or width.

## CRITICAL Pitfall: Version Confusion / Wrong File Attachment
When iterating STL versions, always re-run the script before sending the file. A stale file attachment is a common silent failure.
- **Rule**: After every code edit → run script → verify console output (facet count, dimensions) → then attach the newly generated file.
- **Never** attach a file path that existed before the last code change.

## CRITICAL Pitfall: Depth from Top Surface vs Bottom
When a user says "slot depth" (e.g. "Schlitze 13 mm tief"), they **always** mean from the **top face downward**.

- **WRONG**: Build a box of total height = slot depth, then carve from the bottom upward.
- **RIGHT**: Keep the **total box height** the user gave (or default 32 mm for Gridfinity), build a **solid lower block** of height `TOTAL_Z - SLOT_DEPTH`, and place slot walls starting at `z = TOTAL_Z - SLOT_DEPTH` going up to `z = TOTAL_Z`.

**Formula:**
```python
LOWER_SOLID = TOTAL_Z - SLOT_DEPTH   # massiv
SLOT_START  = LOWER_SOLID            # Schlitz beginnt hier
SLOT_END    = TOTAL_Z                # Schlitz endet oben
# Boden (massiv unten)
b.box(0, 0, 0, TOTAL_X, TOTAL_Y, LOWER_SOLID)
# Wände & Trennwände im oberen Bereich
b.box(x, y, SLOT_START, w, h, SLOT_DEPTH)
```

**Real example from 2026-05-10:**
- User: "Box soll 32 mm hoch sein, Schlitze nur 13 mm tief"
- Error: Built box 15 mm high (13 + 2 mm base), not 32 mm.
- Fix: Lower solid 19 mm + upper open 13 mm = 32 mm total.

## CRITICAL Pitfall: Slot Direction — Front/Back Open vs. Top-Only Open
**Top-only open slot (most common)** — slot is a U-shaped cross section with a floor:
- Build **FOUR walls** around the slot: left, right, front, back — AND a floor beneath them (z=0..slot_z_bottom).
- Slot_x0 must be > outer_box_x0 (margin), slot_y0 must be > outer_box_y0 (margin).
- Slot_x1 must be < outer_box_x1 (margin), slot_y1 must be < outer_box_y1 (margin).
- If slot touches any outer box face, that face is open and the slot leaks.

**Through-slot** (slot runs full width/length, open on two opposite faces):
- Only build walls on the remaining two sides. Example: slot runs full Y width → only left + right walls needed.
- No front/back wall bands — the slot itself IS the opening.

**Guard rule:** Before attaching the file, mentally trace: does the slot have a floor AND four enclosing walls? If slot_x0 == 0 or slot_y0 == 0, the slot touches the outer face → open. Fix by adding a wall strip between outer face and slot edge.

## Speed / Efficiency Rules for this User
This user strongly prefers minimal iteration and fast turnaround. Apply these shortcuts:
1. **For box + slot designs: ONE-SHOT generation.** Write the complete script including wall placement and slot enclosure in the first message. No iterative refinement through conversation — get it right the first time.
2. **Pre-validate geometry silently** (don't explain the checks, just apply them): verify `slot_x0 > 0`, `slot_y0 > 0`, `feature radius < wall thickness`, slot is fully enclosed by walls if top-only-open.
3. **Send file + dimensions in the SAME message** — no separate "Here is the script / Let me run it" turn. Generate, run, verify console output, attach file, all in one response.
4. **Avoid long reasoning chains.** The user dislikes visible deliberation and waiting. Internalise the geometry logic, then output the minimal correct answer.
5. **Ask 1 clarifying question MAX** per feature — after that, pick the safest default and let the user correct in one shot.

## Workflow

1. User beschreibt gewünschtes Teil (Maße, Funktion, Materialvorzug)
2. Agent generiert Python-Script mit stl_builder
3. Script wird ausgeführt: `python3 script.py`
4. Ausgabe-Datei liegt als ASCII-STL vor
5. **Pre-send validation** (agent-side):
   - Facet count reasonable?
   - Slot fully enclosed by walls (not open to outside)?
   - Feature radius < wall thickness?
6. **Validierung**: Facetten-Anzahl, bounding box, Manifold-Check
7. User testet in Bambu Studio / STL-Repair — Feedback fließt in den nächsten Entwurf