diff --git a/busbar_export.py b/busbar_export.py index 602e4a7..d2d8a03 100644 --- a/busbar_export.py +++ b/busbar_export.py @@ -46,6 +46,7 @@ from build123d import ( Sketch, add, export_step, + export_stl, extrude, ) @@ -299,8 +300,29 @@ def to_svg(payload: dict) -> bytes: return path.read_bytes() +def to_stl(payload: dict) -> bytes: + """STL with the busbars extruded to a printable plate. + + STL is inherently 3D, so extrusion is forced regardless of the payload + flag. Thickness defaults to 2 mm when missing or <0.5 mm (slicers can't + do 0.2 mm sheet — that figure is for the 'thin nickel strip' STEP case). + """ + busbars, extrude_flag, thickness = parse_payload(payload) + if thickness < 0.5: + thickness = 2.0 + shapes = build_shapes(busbars, extrude_flag=True, thickness=thickness) + compound = _as_compound(shapes) + with TemporaryDirectory() as tmp: + path = Path(tmp) / "busbars.stl" + # build123d's export_stl takes a single shape; the Compound carries + # all busbars together so the slicer sees them as one job. + export_stl(compound, str(path)) + return path.read_bytes() + + WRITERS = { "step": (to_step, "application/step", "step"), "dxf": (to_dxf, "image/vnd.dxf", "dxf"), "svg": (to_svg, "image/svg+xml", "svg"), + "stl": (to_stl, "model/stl", "stl"), } diff --git a/static/index.html b/static/index.html index 1ccbd91..c8ee782 100644 --- a/static/index.html +++ b/static/index.html @@ -115,7 +115,23 @@ - + + +
+

+ FDM test print +

+
+ +
+ + +
+
diff --git a/static/js/app.js b/static/js/app.js index f03b378..4ea9aad 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -157,6 +157,16 @@ $("btn-export-dxf" ).addEventListener("click", () => Exporter.exportFormat("dxf", state, params)); $("btn-export-svg" ).addEventListener("click", () => Exporter.exportFormat("svg", state, params)); + // ---- FDM test print ----------------------------------------------------- + // Forces extrusion at the FDM thickness, regardless of the 'Extrude solid' + // checkbox above (which keeps owning the thin nickel-strip case). + function _exportFdm(fmt) { + const t = Math.max(0.5, +$("p-fdm-thickness").value || 2); + Exporter.exportFormat(fmt, state, { ...params, extrude: true, thickness: t }); + } + $("btn-export-fdm-stl") .addEventListener("click", () => _exportFdm("stl")); + $("btn-export-fdm-step").addEventListener("click", () => _exportFdm("step")); + // ---- viewport init ------------------------------------------------------ Viewport.init($("viewport"), state, params, { onCellClick: (cellId, mods) => { diff --git a/static/styles.css b/static/styles.css index 24e9c0b..7ad5de2 100644 --- a/static/styles.css +++ b/static/styles.css @@ -420,6 +420,36 @@ label.checkbox { color: var(--text); } +/* FDM test-print block inside the Params panel */ +.fdm-block { + margin-top: 10px; + padding-top: 10px; + border-top: 1px solid var(--border); +} +.fdm-title { + font-size: 11px; + font-weight: 600; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.05em; + margin: 0 0 6px; +} +.fdm-row { + display: flex; + align-items: end; + gap: 10px; +} +.fdm-row label { + flex: 1; +} +.fdm-buttons { + display: flex; + gap: 4px; +} +.fdm-buttons button { + min-width: 50px; +} + input[type=number], input[type=text], select, textarea { background: var(--bg); color: var(--text);