# ZimaOS Headless-Umgebung — 3D-Druck Pipeline

> Stand: Mai 2026 | Skill: 3d-druck-kiwi
> Betriebsumgebung: ZimaOS-Server, headless, kein Display, keine GL-Libs.

## Dateisystem & Berechtigungen

- **User**: `az-a` (uid=999), `HOME=/DATA`
- **Problem**: `/DATA` gehört `root` → `~/3D-Druck` (=/DATA/3D-Druck) führt zu `PermissionError: [Errno 13]`
- **Lösung**: Schreibpfad ist `/DATA/AppData/hermes/Projekte/3D-Druck/` (gehört `az-a:samba`)
- **Env-Override**: `OUTPUT_DIR` im Skript setzen, falls User woanders speichern will

## Python-Umgebung

- **Venv**: `/DATA/AppData/hermes/venv/` (Python 3.11)
- **Aktivierung**: `source /DATA/AppData/hermes/venv/bin/activate`
- **PIP**: `trimesh==4.12.2`, `manifold3d==3.4.1`, `numpy==2.4.4`, `shapely==2.1.2`, `matplotlib` mit `Agg`-Backend
- **Kein bpy**: Blender-Python-Module nicht verfügbar; keine CAD-App notwendig.

## Headless-GL-Pitfalls

### CadQuery
- **Status**: Installiert via pip, aber **runtime-broken**
- **Fehler**: `ImportError: libGL.so.1: cannot open shared object file`
- **Ursache**: ZimaOS hat keine Mesa-GL-Libs (kein Display-Server)
- **Fix**: **Nicht nutzbar.** → trimesh + manifold3d als primärer Stack.

### OpenSCAD
- **Status**: AppImage bereit unter `/tmp/bin/openscad`
- **Problem**: Headless-GL bei Vorschau/Rendering (nicht bei STL-Export)
- **Workaround**: `MESA_GL_VERSION_OVERRIDE=3.0 LIBGL_ALWAYS_SOFTWARE=1 openscad -o ...`
- **Empfehlung**: Nur als Fallback, nicht primär. manifold3d ist schneller und robuster.

### matplotlib
- **Problem**: `matplotlib.use('Agg')` erforderlich; Default-Backend versucht Qt/X und crash
- **Zusatz**: `MPLCONFIGDIR=/tmp/mplconf` setzen wegen Schreibrechten (`/DATA/.config` gehört root)
- **Pattern**:
  ```python
  import matplotlib
  matplotlib.use('Agg')
  import matplotlib.pyplot as plt
  ```

## manifold3d API — Session-Erkenntnis

**Die Python-Bindings sind streng typisiert.**

- `m3d.Mesh(vert_properties=..., tri_verts=...)` akzeptiert **nur**:
  - `vert_properties`: `numpy.ndarray` mit `dtype=float32`
  - `tri_verts`: `numpy.ndarray` mit `dtype=uint32`
- **Fehler bei falsch Typ**: `TypeError: ... must be real number, not numpy.ndarray`
- **Korrektes Pattern**:
  ```python
  verts = np.asarray(mesh.vertices, dtype=np.float32)
  faces = np.asarray(mesh.faces, dtype=np.uint32)
  m3d.Manifold(m3d.Mesh(vert_properties=verts, tri_verts=faces))
  ```

## trimesh.section() — fehlende Abhängigkeit

- `trimesh.path.Path3D` → `polygons_closed` / `enclosure_directed` braucht `networkx`
- **Fehler**: `ModuleNotFoundError: No module named 'networkx'`
- **Fix**: `pip install networkx` im venv; als Workaround ohne Installation kann die Kontur-Analyse direkt auf Vertices/Normals arbeiten statt `section()` zu nutzen.

## Einheiten-Korrekturen (Session-Bugfixes)

- **Volumen**: `trimesh` gibt mm³ → `/1000` für cm³
- **Oberfläche**: `trimesh` gibt mm² → `/100` für cm² (nicht `/10000`, da `cm = mm/10`, `cm² = mm²/100`)
- **Maße**: Alle Design-Werte in **mm** entwerfen.

## trimesh Primitives — Session-Erkenntnis

- `trimesh.creation.sphere` existiert **nicht**.
- Nutze stattdessen:
  - `trimesh.primitives.Sphere(radius=..., subdivisions=...)` — UV-Sphere
  - `trimesh.creation.icosphere(radius=...)` — Icosahedron-Sphere (gleichmäßig)

## shapely — Optionaler Import

- `shapely.geometry.Polygon` braucht `from shapely.geometry import Polygon`
- Falls nicht installiert: `try/except ImportError` mit Fallback auf `None`
- Im aktuellen venv ist shapely 2.1.2 verfügbar.

## Session-Archiv

- **Erstes Testmodell**: `beispiel_box_m5.stl` (50×30×10 mm, M5-Gleitpassungsloch 5.2 mm)
- **Validierung**: `Watertight: True`, `Volume: 14.79 cm³`, `Faces: 144`
- **Generierungsbefehl** (für Reproduktion):
  ```bash
  source /DATA/AppData/hermes/venv/bin/activate
  MPLCONFIGDIR=/tmp/mplconf python3 /DATA/.hermes/skills/3d-printing/3d-druck-kiwi/scripts/generate_model.py
  ```
- **Visitenkarten-Box** (2026-05-11): Box 89×49×32 mm, Wand 2 mm, innere Ecken unten scharf, obere Innenkanten R3 mm abgerundet via Zwei-Teile-Bauweise (Unterteil + Oberring).
