• Python 74%
  • HTML 25.8%
  • Dockerfile 0.2%
Find a file
Adrian A. Baumann 09a6924894
Rename meters/85c1.py to m85c1.py for a valid module name
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.
2026-08-25 08:37:29 +02:00
artwork Add 85C1 windowed round-dial meter 2026-08-09 01:24:16 +02:00
fonts Consolidate 44-Scale and M1730-Scale into unified scale-generator 2026-08-09 00:59:03 +02:00
k8s add umami analytics and bump image to 0.7 2026-08-12 01:06:14 +02:00
meters Rename meters/85c1.py to m85c1.py for a valid module name 2026-08-25 08:37:29 +02:00
scalegenerator fix: make round dials use live <text> in text mode 2026-08-09 02:26:50 +02:00
web add umami analytics and bump image to 0.7 2026-08-12 01:06:14 +02:00
.dockerignore Consolidate 44-Scale and M1730-Scale into unified scale-generator 2026-08-09 00:59:03 +02:00
.gitignore Consolidate 44-Scale and M1730-Scale into unified scale-generator 2026-08-09 00:59:03 +02:00
CLAUDE.md Consolidate 44-Scale and M1730-Scale into unified scale-generator 2026-08-09 00:59:03 +02:00
Dockerfile Consolidate 44-Scale and M1730-Scale into unified scale-generator 2026-08-09 00:59:03 +02:00
LICENSE Consolidate 44-Scale and M1730-Scale into unified scale-generator 2026-08-09 00:59:03 +02:00
README.md docs: document 85C1 meter and fix stale README 2026-08-09 02:29:46 +02:00
requirements.txt Consolidate 44-Scale and M1730-Scale into unified scale-generator 2026-08-09 00:59:03 +02:00

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.