- Python 74%
- HTML 25.8%
- Dockerfile 0.2%
85c1 isn't a legal Python identifier, so it required importlib.import_module instead of a normal import. METER_ID stays "85c1" so form/route behavior is unchanged. |
||
|---|---|---|
| artwork | ||
| fonts | ||
| k8s | ||
| meters | ||
| scalegenerator | ||
| web | ||
| .dockerignore | ||
| .gitignore | ||
| CLAUDE.md | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| requirements.txt | ||
Scale Generator
SVG scale artwork and a Flask web generator for analog panel meters. One app hosts every supported meter type — picked at runtime from a thumbnail selector — on a shared core: font embedding, an inline-markup engine, and the scale-mapping math.
This repo is the consolidation of the former 44-Scale (E440 round dial) and
M1730-Scale (M1730 strip dial) repos: identical dependencies, font corpus,
Docker/kubernetes pattern and the bulk of the generator code, now shared.
Repository layout
scalegenerator/ Shared core (fonts, markup engine, mapping math)
meters/ Per-meter type: m1730 (strip), e440 + 85c1 (round)
m1730.py Strip-dial generator
e440.py Round-dial generator
85c1.py Windowed round-dial generator
web/ Flask web generator (single app, meter selector)
app.py
templates/index.html
tests/ stdlib unittest suite
fonts/ TTF fonts (required for Docker build)
artwork/ Hand-drawn Inkscape source SVGs (metadata + planar)
k8s/ Kubernetes manifests
Dockerfile Container build
Meter types
Select the meter at the top of the form; the app dispatches to its generator.
| Meter | id | Style | Default geometry |
|---|---|---|---|
| M1730 strip | m1730 |
Linear strip dial | viewBox 157.18 × 26.68 mm, scale bar 119.41 mm |
| E440 round dial | e440 |
Pivoted needle over a round arc | viewBox 93.8 × 57.2 mm, pivot (107.43, 162.63), ±45.667° |
| 85C1 round dial | 85c1 |
Long arc in a windowed rectangular case | viewBox 60.12 × 35.68 mm, pivot (29.85, 39.83), ±45.667° |
All three emit a paths mode (glyphs outlined via fontTools, for
plotters / laser engravers) and a text mode (live <text> with the font
embedded as base64). Labels using inline markup are always emitted as glyph
paths, in both modes.
Run locally
.venv/bin/pip install -r requirements.txt # once
cd web && ../.venv/bin/python app.py # http://localhost:5000
Fonts are loaded from fonts/ at the repo root.
Form parameters
| Field | Description |
|---|---|
| Scale type | Select the meter (with thumbnail) |
| Unit | Symbol on the dial. Supports inline markup — see below |
| Mapping | Linear, √, Log, or 1/x |
| Min / Max | Numeric range; Max may be ∞ for 1/x |
| Major intervals | Number of major tick intervals |
| Minor per interval | Minor ticks between major ticks; odd ⇒ a taller medium tick |
| Labels | Number of numeric labels |
| Custom labels | Comma-separated labels that override the calculated numbers |
| Label size (mm) | Font size of numeric labels |
| Font | Per-element font + size, from every .ttf in fonts/ |
| Tick size | Length and thickness of major/medium/small ticks |
| Colour bar / arc | Optional coloured segments behind the ticks |
| Output mode | Paths or Text |
All meters accept the union of fields; each ignores the ones it doesn't use (e.g. left/right corner labels apply to the round dials, the half-height unit to the strip dial). Thumbnails in the picker are rendered live from each meter's generator — there are no static thumbnail files.
Scale mappings
| Mapping | Major tick values | Minor placement |
|---|---|---|
| Linear | Evenly spaced | Uniform |
| √ | Squares of equally spaced √ steps | Crowded toward high end |
| Log | Geometric — each interval same ratio | Crowded toward high end |
| 1/x | Harmonic (∞ … decreasing) | Uniform in reciprocal space |
Inline text markup
The unit and numeric-label fields accept lightweight shorthand (no LaTeX):
| Markup | Result |
|---|---|
cm^2 |
superscript (^{...} for groups) |
H_2O |
subscript (_{...} for groups) |
{1/2} |
stacked fraction with a rule; a bare / stays inline |
[AC] [DC] [ACDC] |
drawn AC/DC/combined symbols |
Constructs nest, e.g. {m/s^2} is a fraction with a superscript denominator.
Glyphs missing from a font (e.g. Ω, ∞) fall back across the bundled
Free*/SIEMENS fonts so they always render.
Testing
cd web && ../.venv/bin/python -m unittest discover -s tests -v
Container
docker build -t scale-generator:latest .
docker run -p 5000:5000 scale-generator:latest
Kubernetes
Manifests in k8s/ deploy to the works namespace with a Traefik v2
IngressRoute under works.baumann.gr. Managed by ArgoCD — push to deploy.
License
GPL-3.0 — see LICENSE.