Files
adebaumann 3b1e244d55 Fix final-review findings: unit-label baseline, sqrt minor-tick math, dead code, edge cases
- Unit label was vertical-centered on a box derived from a baseline
  coordinate, shifting it 3.34mm too low and making the generated
  deliverables inconsistent with E440-Scale_template.svg. UNIT_Y is now
  used directly as the baseline; regenerated E440-Scale_paths.svg and
  E440-Scale_text.svg accordingly.
- sqrt scale's minor-tick angle formula double-applied the square-root
  mapping, badly misplacing minor ticks. Removed the special case so sqrt
  falls through to the already-correct generic value-interpolation branch.
  Corrected README's sqrt row (crowds toward the high end, not low).
- Removed dead code: unused _has_markup(), identity-transform wrapper and
  _UNIT_SCALE_X in _markup_unit_svg, unreachable max_val<=0 check,
  redundant math.isinf() in the minor-tick condition.
- Linear scale with min==max now raises ValueError like the other three
  mappings, instead of silently producing a degenerate dial.
- Form numeric parsing moved inside the try/except so bad input returns
  400 instead of crashing with 500.
- left_label/right_label now split on splitlines() to handle CRLF from
  browser textareas correctly.
- Formatting consistency: PIVOT_CIRCLE_R/R0 use :.5f like other constants;
  font_face indentation matches its sibling elements.
- LICENSE and CLAUDE.md: last M1730-Scale references and a doc inaccuracy
  about which labels are live text vs. outlined paths.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 00:48:54 +02:00

122 lines
4.9 KiB
Markdown
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.
# E440-Scale
SVG scale artwork and web generator for E440-style round-dial analog panel
meters. Scales are typeset in **Alte DIN 1451 Mittelschrift**.
## Repository layout
```
E440-Scale_template.svg Inkscape working file (case body, tick marks, labels)
E440-Scale_paths.svg Paths-only export — text converted to outlines
E440-Scale_text.svg Live-text export — embedded font, editable labels
fonts/ TTF fonts (required for Docker build)
web/ Flask web generator
k8s/ Kubernetes manifests
Dockerfile Container build
```
## SVG files
The canvas is **93.824249 × 57.215687 mm**. The coordinate origin is
offset: layer 1 carries `transform="translate(-60.717741,-107.14126)"`, so
absolute SVG coordinates begin around x=61, y=107.
The dial's case geometry — body outline, mounting ears, pivot point
(local `107.42845, 162.62819`), rim radius (`43.842751` mm), and angular
sweep (`±45.667°` from vertical) — is fixed across every generated scale.
Only the tick marks, numeric labels, unit label, and corner text vary.
| File | Purpose |
|---|---|
| `E440-Scale_template.svg` | Master Inkscape file. Edit this one. |
| `E440-Scale_paths.svg` | All text converted to outlines. Use for cutting plotters, laser engravers, or any workflow where fonts must not be embedded as live text. |
| `E440-Scale_text.svg` | Live `<text>` nodes with the font embedded as base64. Smaller file; requires an SVG viewer that supports embedded fonts. |
Open files in **Inkscape** (developed with v1.4.3). There is no build step
— edit the SVG directly or use the web generator.
## Web generator
A Flask app that generates arc-dial scale SVGs from a form. Supports two
output modes switchable in the UI:
- **Paths** — glyphs rendered as outlines via fontTools; opens cleanly in
Inkscape, Illustrator, and cutting software
- **Text** — live `<text>` elements with the selected font embedded as
base64
### Run locally
```bash
source .venv/bin/activate
cd web && python app.py # http://localhost:5000
```
Fonts are loaded at startup from the `fonts/` directory in the repo root.
### Form parameters
| Field | Description |
|---|---|
| Unit | Symbol shown centered above the arc (e.g. `uA`, `V`, `%`). Supports inline markup — see below |
| Left label / Right label | Up to 2 lines each, placed in the bottom-left/bottom-right corners of the dial |
| Mapping | **Linear**, **√** (square root), **Log**, or **1/x** (reciprocal). Major ticks are always evenly spaced angularly; the mapping controls their values and how minor ticks are placed within each interval. |
| Min / Max | Numeric range of the scale |
| Major intervals | Number of major tick intervals |
| Minor per interval | Minor ticks between each pair of major ticks. When odd, the exact midpoint subdivision is drawn as a taller "medium" tick, matching the reference dial's 3-tier tick scheme |
| Labels | Number of numeric labels; Labels 1 should divide evenly into Major intervals |
| Custom labels | Optional comma-separated labels that override the calculated numbers |
| Label size (mm) | Font size of the numeric labels, in millimetres (default `5.1126`) |
### Scale mappings
| Mapping | Major tick values | Minor tick placement | Constraints |
|---|---|---|---|
| Linear | Evenly spaced | Uniform | None |
| √ | Quadratic (0, 1, 4, 9 … × max) — compresses low values | Crowded toward the high end of each interval | Min ≥ 0 |
| Log | Geometric (min × r⁰, r¹, r² …) — each interval spans the same ratio | Crowded toward the high end of each interval | Min and Max > 0 |
| 1/x | Harmonic (values decrease left → right, e.g. ∞, 10, 5, 2, 1) — compresses high values | Uniform (in angle space, i.e. proportional to 1/v) | Min and Max > 0; Max may be ∞ |
### Unit markup
The Unit field accepts a lightweight shorthand (no LaTeX engine — everything
is drawn as glyph paths and auto-sized to fit above the arc):
| Markup | Result |
|---|---|
| `cm^2` | superscript (`^{...}` for multiple characters) |
| `H_2O` | subscript (`_{...}` for multiple characters) |
| `{1/2}` | stacked fraction with a horizontal rule; a bare `/` stays inline |
Constructs nest: `{m/s^2}` is a fraction with a superscript in the
denominator, `x^{1/2}` a superscripted fraction.
## Container
```bash
docker build -t e440-scale:latest .
docker run -p 5000:5000 e440-scale:latest
```
Fonts are loaded from `fonts/` in the repo root; they are bundled into the
image at build time.
The production image is at `git.baumann.gr/adebaumann/e440-generator`.
## Kubernetes
Manifests in `k8s/` deploy to the `works` namespace with a Traefik v2
IngressRoute at `works.baumann.gr/E440-generator`.
```bash
# Managed by ArgoCD — push to git to deploy
git push
```
Resources: namespace, deployment (1 replica, gunicorn), ClusterIP service,
Traefik IngressRoute + stripPrefix middleware.
## License
GPL-3.0 — see [LICENSE](LICENSE).