Add hex holder designer page (/holder)

Server-side OpenSCAD renders STL from bundled hex_cell.scad with parameter
overrides via -D. Frontend is a Three.js viewer with auto-form generated
from /api/holder/params. 'Design busbars →' button posts the computed
cell coordinates to /api/projects and redirects to the busbar editor with
the holder cells pre-loaded.

  - holder.py:                openscad subprocess wrapper + compute_cells()
                              (Python mirror of get_hex_center_points_*)
  - scad/hex_cell.scad:       verbatim copy of Addy/Hex-Cell-Holder source
  - app.py:                   /holder route + /api/holder/{params,render,cells}
  - static/holder.html etc:   parameter form + Three.js STL viewer
  - Dockerfile / install.sh:  apt install openscad
  - static/index.html:        nav link Holder ↔ Busbars in topbar
This commit is contained in:
wenil
2026-05-24 19:27:50 +03:00
parent d8cb0dc06d
commit 6bc922cabf
13 changed files with 2371 additions and 9 deletions
+12 -3
View File
@@ -12,10 +12,15 @@ The hard requirement is a working **STEP export**. STEP is generated by OpenCASC
```
Browser (static/) ──fetch──> Flask (app.py)
├── busbar_export.py → build123d → STEP/DXF/SVG
├── busbar_export.py → build123d → STEP/DXF/SVG (busbars page)
├── holder.py → openscad subprocess → STL (holder page)
└── storage.py → SQLite (projects/presets/snapshots)
```
Two pages:
- `/` → busbar designer (cell-import, panel/wire shapes, export STEP)
- `/holder` → hex-holder designer (parameter form, openscad render, STL download, "Design busbars →" hand-off)
- **Frontend** is plain HTML + JS (no build step). State lives in memory but is auto-synced to the server every 1.5 s; the active project ID is in the URL (`?p=42`) so refresh and other devices resume the same state.
- **Backend** is a Flask app with three groups of endpoints:
- **CAD export**: `POST /api/export/{step,dxf,svg}` — stateless; takes a busbar payload and returns bytes via build123d.
@@ -76,10 +81,14 @@ If the user reports coordinates "off by half a hex," check `rect`-vs-`para` and
## File map
- `app.py` — Flask app. Serves `static/`, dispatches export endpoints, exposes REST CRUD for projects/presets/snapshots. Single-file; no blueprints.
- `app.py` — Flask app. Serves `static/`, dispatches export endpoints, exposes REST CRUD for projects/presets/snapshots/holder. Single-file; no blueprints.
- `busbar_export.py` — pure functions. Input: payload dict. Output: bytes. No Flask import here.
- `holder.py``subprocess.run(["openscad", "-D ...", "hex_cell.scad"])` wrapper that returns STL bytes; also has `compute_cells()` Python-side (mirrors the SCAD formulas) so the busbar hand-off doesn't need a second openscad call.
- `scad/hex_cell.scad` — verbatim copy of Addy777/Hex-Cell-Holder script. Source of truth for hex holder geometry. Update via git (no submodule for now).
- `storage.py` — SQLite layer for projects, presets, snapshots. Connection-per-call inside a context manager; no Flask import.
- `static/index.html`single page; left sidebar (import / params / busbars) + right pane (canvas + live SVG preview) + top bar (project switcher + history + exports) + history modal.
- `static/index.html`busbar designer page; left sidebar (import / params / busbars) + right pane (canvas + live SVG preview) + top bar (project switcher + history + exports) + history modal.
- `static/holder.html` — hex-holder designer page; parameter form (left) + Three.js viewer (right).
- `static/js/holder-app.js`, `holder-viewer.js`, `holder.css` — UI for `/holder`. holder-viewer is an ES module (Three.js imported via importmap from jsdelivr).
- `static/js/app.js` — top-level controller; owns in-memory state, hooks auto-save + URL routing.
- `static/js/api.js` — thin fetch-based REST client (Api.listProjects, getProject, ...).
- `static/js/importer.js` — paste-text parser + generator.