Files
wenil 102cfcee64 tracks: new /tracks generator for IKEA Lillabo / Brio train tracks
Wraps torwanbukaj/ikea-brio-others-compatible-train-tracks-generator
( https://github.com/torwanbukaj/... ) as a third generator alongside
holder and the universal scad playground.

Approach
--------
The upstream .scad ships as "library + one active example call". Used
include<> (rather than use<>) so the library's top-level globals
(track_width, plug/nest dimensions, $fn = 150, etc.) are available
to the modules — `use<>` does NOT propagate variables. Commented out
the upstream `track_tester();` call so include<> doesn't also emit
the tester geometry every time.

Per-render the backend builds a tiny wrapper SCAD on the fly:

    include <scad/train_tracks.scad>
    track(length=100, end1="plug", end2="nest", cutout=true, ...);

and hands it to holder.render_source().

Part types exposed (9)
----------------------
- tester        Calibration block (15-60mm)
- track         Straight (length + chamfers + grooves + plug/nest ends)
- arc           Curved (radius + angle, IKEA/Brio/J'adore radii in help text)
- dogbone       Nest-nest connector
- intersection  Crossing (angle + 2 lengths + 4 ends)
- switch        Turnout (left/right radius+angle, straight branch, common end)
- snake         S-curve (raised default target_length to 200 — the upstream
                modules's natural curvy-span at angle=45/radius=86 is ~150
                and the assert fires below that)
- adapter       BRIO <-> IKEA system adapter (plug + nest side)
- bridge        Multi-part (overview/ground/slope/pillar — value_map
                translates the UI labels to the int 0..3 the SCAD wants)

Files
-----
- scad/train_tracks.scad      Downloaded upstream (57 999 bytes), only
                              modification is the // before the top-level
                              track_tester() call.
- tracks.py                   PART_SCHEMAS dict, build_wrapper_scad,
                              render() that delegates to render_source.
- app.py                      GET /api/tracks/params, POST /api/tracks/render,
                              GET /tracks page route.
- static/tracks.html          Page with part selector + dynamic param form +
                              shared viewer markup. Reuses holder.css.
- static/js/tracks-app.js     Controller. Switching the part select redraws
                              the form (each part has its own schema).
                              Ctrl+Enter renders, Cancel uses AbortController.

Nav
---
Tracks link added to topbar on holder / index / scad.

Smoke test
----------
All 9 parts render with default params on the Manifold backend in
under 0.5s each (output sizes 440 KB - 1.8 MB).
2026-05-25 13:38:29 +03:00

122 lines
4.5 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hex Holder Designer</title>
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="holder.css" />
<!-- CodeMirror 5 for the SCAD source editor -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css" />
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.165.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.165.0/examples/jsm/"
}
}
</script>
</head>
<body>
<header class="topbar">
<h1>Hex Holder Designer</h1>
<nav class="topbar-nav">
<a href="/holder" class="active">Holder</a>
<a href="/">Busbars</a>
<a href="/tracks">Tracks</a>
<a href="/scad">SCAD</a>
</nav>
<span id="status" class="topbar-status">— cells</span>
<div class="actions">
<button id="btn-render" class="primary" title="Render STL with current parameters">Render</button>
<button id="btn-cancel" title="Cancel running render" hidden>Cancel</button>
<button id="btn-download-stl" title="Download STL of the current configuration">Download STL</button>
<button id="btn-download-scad" title="Download the OpenSCAD source with current parameters baked in">Download .scad</button>
<span class="sep"></span>
<button id="btn-to-busbar" class="primary" title="Open Busbar Designer with these cell coordinates pre-loaded">Design busbars →</button>
</div>
</header>
<main>
<aside class="left holder-left">
<section class="panel">
<h2>Parameters</h2>
<div id="param-form" class="param-form">
<div class="hint">Loading parameter schema…</div>
</div>
</section>
<section class="panel">
<h2>Status</h2>
<p class="hint" id="render-status">idle</p>
<div id="render-progress" class="render-progress" hidden>
<div class="render-progress-bar"><div class="render-progress-fill"></div></div>
<span id="render-elapsed" class="render-elapsed">0.0s</span>
</div>
<p class="hint" id="render-time"></p>
<p class="hint" id="warning"></p>
</section>
<section class="panel">
<h2>Fit check</h2>
<label class="fit-toggle">
<input type="checkbox" id="show-max-box" checked>
<span>Show max bounding box</span>
</label>
<p class="hint" id="max-box-dims">— render first</p>
<hr class="fit-sep">
<label class="fit-toggle">
<input type="checkbox" id="show-enclosure">
<span>Show enclosure</span>
</label>
<div class="enc-inputs">
<input id="enc-w" type="number" min="1" step="1" placeholder="W">
<span>×</span>
<input id="enc-d" type="number" min="1" step="1" placeholder="D">
<span>×</span>
<input id="enc-h" type="number" min="1" step="1" placeholder="H">
<span class="unit">mm</span>
</div>
<p class="hint" id="fit-verdict"></p>
</section>
</aside>
<section class="right">
<div id="viewer3d" class="viewer3d"></div>
<div class="viewport-overlay">
<div id="hint-controls">left-drag: rotate · right-drag: pan · wheel: zoom</div>
</div>
<!-- Collapsible SCAD source editor (slides up from the bottom of the viewport) -->
<div id="scad-panel" class="scad-panel" hidden>
<div class="scad-panel-bar">
<span class="scad-panel-title">SCAD source <span id="scad-dirty-tag" class="scad-dirty" hidden>· modified</span></span>
<button id="btn-scad-reset" type="button" title="Discard edits and reload bundled hex_cell.scad">Reset</button>
<button id="btn-scad-close" type="button" title="Hide the editor (changes kept until reload)">Close</button>
</div>
<div id="scad-editor"></div>
</div>
<button id="btn-scad-toggle" class="scad-toggle" type="button"
title="Show / hide the bundled SCAD source. When edits are present, renders use your source instead of the bundled file.">
&lt;/&gt; Source
</button>
</section>
</main>
<script src="js/api.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/clike/clike.min.js"></script>
<script type="module" src="js/holder-viewer.js"></script>
<script type="module" src="js/holder-app.js"></script>
</body>
</html>