Add web SVG generator, container, and Kubernetes manifests

- Flask app (web/) generates M1730 scale SVGs from a form; embeds
  GOST typ A font as base64 so output is self-contained
- Dockerfile builds the app into git.baumann.gr/adebaumann/m1730-generator
- k8s/ deploys as a ClusterIP service for NPM to proxy at
  works.adebaumann.com/M1730-generator/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 00:29:55 +02:00
parent 10d25462be
commit 9e7223a1f5
13 changed files with 1193 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
.venv/
.git/
k8s/
web/__pycache__/
__pycache__/
+3
View File
@@ -0,0 +1,3 @@
.venv/
__pycache__/
*.pyc
+55
View File
@@ -0,0 +1,55 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
SVG scale artwork for M1730 analog meters. The scales are designed in Inkscape (v1.4.3) using the **ГОСТ тип А** (GOST type A) font, a Russian technical drafting standard typeface.
All canvas dimensions are **157.18373 mm × 26.683672 mm**. The coordinate origin is offset: `transform="translate(-37.352226,-90.454928)"` is applied to `layer1` in all files, so absolute SVG coordinates start around x=37, y=90 rather than 0,0.
## File Roles
The three SVG files represent layers of the same design, intended to be combined or used separately:
- **`M1730-Scale_template.svg`** — Inkscape working template. Contains the background rect+cutout path, the zero tick mark, an end tick mark, the "U" axis label, numeric labels `0` and `X` (placeholder for the full-scale value), and a `5mA` range label. Also contains a `<rect id="rect5">` inside `<defs>` used as a text flow shape (`shape-inside:url(#rect5)`) for the title text block (`id="text5"`).
- **`M1730-Scale_paths.svg`** — Paths-only version: all tick marks as `<path>` elements, no text nodes (or text converted to paths). Used for cutting/printing workflows where fonts must not be embedded as live text.
- **`M1730-Scale_text.svg`** — Text-overlay version: tick mark paths plus live `<text>` elements for numeric labels. The `sodipodi:docname` is `M1730-Scale.svg`, suggesting this is the "final" named file.
## Key Design Parameters
- Stroke colors: `#1a1a1a` (dark near-black) for all scale lines and text; fill `#f9f9f9` for the background panel, `#ffffff` for tick mark strokes.
- Major tick stroke-width: `0.555`; border stroke-width: `0.184`.
- Scale bar (the colored strip below tick marks): `y` range 107.547113.746 mm absolute, `x` range 58.444183.644.
- Zero tick at absolute x=60.844; full-scale tick at x=180.251.
## Web Generator (`web/`)
A Flask app that generates scale SVGs from a form. The venv lives at the repo root.
```
source .venv/bin/activate
cd web && python app.py # runs on http://localhost:5000
```
`app.py` has one route (`GET /`) serving the form and one (`POST /generate`) that returns SVG. All SVG geometry is computed in `generate_svg()` using the same coordinate constants as the hand-drawn files. The form exposes: unit label, min/max values, major tick intervals, minor ticks per interval, number of numeric labels, and range label.
The ГОСТ тип А font is loaded at startup from `/usr/local/share/fonts/г/ГОСТ_тип_А.ttf` and embedded as base64 in every generated SVG so output files are self-contained.
## Container & Kubernetes
```
docker build -t m1730-scale:latest .
```
`fonts/ГОСТ_тип_А.ttf` must exist in the repo root before building (copy from `/usr/local/share/fonts/г/`). The image runs gunicorn on port 5000.
```
kubectl apply -f k8s/
```
NPM should proxy `https://works.adebaumann.com/M1730-generator/``http://m1730-generator/` **with the prefix stripped** (trailing slash on `proxy_pass`). The frontend uses a relative `fetch('generate', ...)` URL so it works correctly under any subpath.
## Editing SVG files directly
Open files in **Inkscape**. There is no build, lint, or test tooling — changes are made directly to the SVG XML or via Inkscape's GUI. When modifying tick positions or labels, keep all three files consistent.
+14
View File
@@ -0,0 +1,14 @@
FROM python:3.12-slim
WORKDIR /app
COPY web/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt gunicorn
COPY fonts/ГОСТ_тип_А.ttf /usr/local/share/fonts/г/ГОСТ_тип_А.ttf
COPY web/ .
EXPOSE 5000
CMD ["gunicorn", "-w", "2", "-b", "0.0.0.0:5000", "app:app"]
+292
View File
@@ -0,0 +1,292 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="157.18373mm"
height="26.683672mm"
viewBox="0 0 157.18373 26.683672"
version="1.1"
id="svg1"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
sodipodi:docname="M1730-Scale_paths.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.6029029"
inkscape:cx="274.8139"
inkscape:cy="80.167052"
inkscape:window-width="2048"
inkscape:window-height="1208"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-37.352226,-90.454928)">
<path
id="rect1"
style="fill:#f9f9f9;stroke:#1a1a1a;stroke-width:0.184;stroke-linecap:round;stroke-miterlimit:10;stroke-dasharray:none"
d="M 37.444226,90.546928 V 117.0466 H 194.44395 V 90.546928 Z M 58.443978,107.54692 H 183.64409 v 6.19963 H 58.443978 Z" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 60.84413,107.5467 v -5.0895"
id="path5" />
<path
d="m 51.148481,105.39399 q -0.504831,0 -0.862803,0.35797 -0.348793,0.34879 -0.348793,0.85362 0,0.49566 0.357972,0.85363 0.357971,0.35797 0.853624,0.35797 0.504832,0 0.853625,-0.34879 0.357972,-0.35797 0.357972,-0.86281 0,-0.51401 -0.348793,-0.8628 -0.348793,-0.34879 -0.862804,-0.34879 z m 0,-1.2116 q 1.009664,0 1.716428,0.70677 0.706765,0.70676 0.706765,1.71642 0,1.00967 -0.706765,1.71643 -0.706764,0.70677 -1.716428,0.70677 -1.009663,0 -1.716428,-0.70677 -0.706764,-0.70676 -0.706764,-1.71643 0,-1.00966 0.706764,-1.71642 0.706765,-0.70677 1.716428,-0.70677 z M 45.0905,98.124411 q -0.504832,0 -0.862803,0.357972 -0.348793,0.348793 -0.348793,0.853624 0,0.495653 0.357972,0.853623 0.357971,0.35797 0.853624,0.35797 0.504832,0 0.853625,-0.34879 0.357971,-0.357971 0.357971,-0.862803 0,-0.51401 -0.348792,-0.862803 -0.348793,-0.348793 -0.862804,-0.348793 z m 0,-1.211596 q 1.009664,0 1.716428,0.706764 0.706765,0.706765 0.706765,1.716428 0,1.009663 -0.706765,1.716433 -0.706764,0.70676 -1.716428,0.70676 -1.009663,0 -1.716428,-0.70676 -0.706764,-0.70677 -0.706764,-1.716433 0,-1.009663 0.706764,-1.716428 0.706765,-0.706764 1.716428,-0.706764 z m -2.423192,11.519345 q 0,-0.22947 0.156039,-0.40387 l 9.683591,-10.895185 q 0.183575,-0.211111 0.458938,-0.211111 0.247826,0 0.422223,0.183575 0.183575,0.174396 0.183575,0.422223 0,0.229469 -0.156039,0.403865 l -9.683591,10.895183 q -0.183575,0.21112 -0.458938,0.21112 -0.247827,0 -0.431402,-0.18358 -0.174396,-0.18357 -0.174396,-0.42222 z"
id="text1"
style="font-size:18.7981px;font-family:'ГОСТ тип В';-inkscape-font-specification:'ГОСТ тип В, Normal';fill:#1a1a1a;stroke-width:0.724858"
transform="scale(0.96486402,1.0364155)"
aria-label="%" />
<path
d="m 61.703801,98.630413 q 0,-0.71205 -0.151962,-1.341607 -0.230114,-0.950847 -0.707708,-0.950847 -0.473253,0 -0.703367,0.955189 -0.156303,0.642582 -0.156303,1.337265 0,0.707708 0.151961,1.341606 0.230114,0.950851 0.707709,0.950851 0.477594,0 0.707708,-0.950851 0.151962,-0.633898 0.151962,-1.341606 z m 0.573113,0 q 0,1.024657 -0.251823,1.771437 -0.36905,1.09413 -1.18096,1.09413 -0.811911,0 -1.180961,-1.08978 -0.251823,-0.746788 -0.251823,-1.775787 0,-1.028999 0.251823,-1.775783 0.36905,-1.089784 1.180961,-1.089784 0.81191,0 1.18096,1.094125 0.251823,0.746785 0.251823,1.771442 z"
id="text2"
style="font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';fill:#1a1a1a;stroke-width:0.180022"
aria-label="0" />
<path
d="m 82.719657,95.764846 q 0.594822,0 1.011632,0.421151 0.421151,0.41681 0.421151,1.011632 0,0.408127 -0.260506,0.824936 l -1.806175,2.900305 h 1.780125 q 0.286556,0 0.286556,0.28655 0,0.28656 -0.286556,0.28656 H 81.57343 q -0.286556,0 -0.286556,-0.28656 0,-0.0868 0.04776,-0.16498 l 2.101416,-3.373558 q 0.143278,-0.230114 0.143278,-0.473253 0,-0.356025 -0.251823,-0.607847 -0.251822,-0.251823 -0.607847,-0.251823 -0.486278,0 -0.898746,0.720734 -0.07815,0.138936 -0.247481,0.138936 -0.286556,0 -0.286556,-0.286556 0,-0.06513 0.02605,-0.117228 0.534038,-1.028999 1.406733,-1.028999 z m 4.871463,2.865567 q 0,-0.71205 -0.151962,-1.341607 -0.230113,-0.950847 -0.707708,-0.950847 -0.473253,0 -0.703366,0.955189 -0.156304,0.642582 -0.156304,1.337265 0,0.707708 0.151962,1.341606 0.230114,0.950851 0.707708,0.950851 0.477595,0 0.707708,-0.950851 0.151962,-0.633898 0.151962,-1.341606 z m 0.573113,0 q 0,1.024657 -0.251822,1.771437 -0.36905,1.09413 -1.180961,1.09413 -0.81191,0 -1.180961,-1.08978 -0.251822,-0.746788 -0.251822,-1.775787 0,-1.028999 0.251822,-1.775783 0.369051,-1.089784 1.180961,-1.089784 0.811911,0 1.180961,1.094125 0.251822,0.746785 0.251822,1.771442 z"
id="text3"
style="font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';fill:#1a1a1a;stroke-width:0.180022"
aria-label="20" />
<path
d="m 104.88173,100.0632 q 0,-0.0478 0.009,-0.07816 l 1.14623,-4.011793 q 0.0608,-0.208405 0.27787,-0.208405 0.28656,0 0.28656,0.286557 0,0.03908 -0.013,0.08249 l -1.04202,3.642743 h 1.34161 v -0.85967 q 0,-0.286556 0.28655,-0.286556 0.28656,0 0.28656,0.286556 v 0.85967 h 0.57311 q 0.28656,0 0.28656,0.286561 0,0.28655 -0.28656,0.28655 h -0.57311 v 0.85967 q 0,0.28656 -0.28656,0.28656 -0.28655,0 -0.28655,-0.28656 v -0.85967 h -1.71934 q -0.28656,0 -0.28656,-0.28655 z m 6.87736,-1.432787 q 0,-0.71205 -0.15196,-1.341607 -0.23012,-0.950847 -0.70771,-0.950847 -0.47325,0 -0.70337,0.955189 -0.1563,0.642582 -0.1563,1.337265 0,0.707708 0.15196,1.341606 0.23012,0.950851 0.70771,0.950851 0.47759,0 0.70771,-0.950851 0.15196,-0.633898 0.15196,-1.341606 z m 0.57311,0 q 0,1.024657 -0.25182,1.771437 -0.36905,1.09413 -1.18096,1.09413 -0.81191,0 -1.18096,-1.08978 -0.25182,-0.746788 -0.25182,-1.775787 0,-1.028999 0.25182,-1.775783 0.36905,-1.089784 1.18096,-1.089784 0.81191,0 1.18096,1.094125 0.25182,0.746785 0.25182,1.771442 z"
id="text4"
style="font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';fill:#1a1a1a;stroke-width:0.180022"
aria-label="40" />
<path
d="m 129.62282,98.630413 v 1.432787 q 0,0.36036 0.24748,0.61219 0.25182,0.24748 0.61219,0.24748 0.36037,0 0.60785,-0.25183 0.25182,-0.25182 0.25182,-0.60784 v -0.573117 q 0,-0.360367 -0.25182,-0.607848 -0.25183,-0.251822 -0.60785,-0.251822 z m 1.43278,-2.865567 q 0.28656,0 0.28656,0.286557 0,0.212746 -0.14328,0.24748 -0.63824,0.160646 -1.11583,0.764152 -0.37774,0.477594 -0.43852,0.994264 h 0.83796 q 0.60785,0 1.02032,0.41681 0.41246,0.41681 0.41246,1.015974 v 0.573117 q 0,0.59916 -0.42115,1.01597 -0.41681,0.41681 -1.01163,0.41681 -0.59916,0 -1.01597,-0.41247 -0.41681,-0.41681 -0.41681,-1.01163 v -1.728024 q 0,-0.972556 0.64692,-1.706315 0.50364,-0.568771 1.09847,-0.807568 0.16933,-0.06513 0.2605,-0.06513 z m 4.29835,2.865567 q 0,-0.71205 -0.15196,-1.341607 -0.23011,-0.950847 -0.70771,-0.950847 -0.47325,0 -0.70336,0.955189 -0.15631,0.642582 -0.15631,1.337265 0,0.707708 0.15196,1.341606 0.23012,0.950851 0.70771,0.950851 0.4776,0 0.70771,-0.950851 0.15196,-0.633898 0.15196,-1.341606 z m 0.57312,0 q 0,1.024657 -0.25183,1.771437 -0.36905,1.09413 -1.18096,1.09413 -0.81191,0 -1.18096,-1.08978 -0.25182,-0.746788 -0.25182,-1.775787 0,-1.028999 0.25182,-1.775783 0.36905,-1.089784 1.18096,-1.089784 0.81191,0 1.18096,1.094125 0.25183,0.746785 0.25183,1.771442 z"
id="text6"
style="font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';fill:#1a1a1a;stroke-width:0.180022"
aria-label="60" />
<path
d="m 154.36391,100.92287 q 0.36037,0 0.60785,-0.24748 0.25182,-0.25183 0.25182,-0.61219 v -0.573117 q 0,-0.356025 -0.25182,-0.607848 -0.25182,-0.251822 -0.60785,-0.251822 -0.36036,0 -0.61219,0.251822 -0.24748,0.247481 -0.24748,0.607848 v 0.573117 q 0,0.36036 0.24748,0.61219 0.25183,0.24748 0.61219,0.24748 z m 0,0.57311 q -0.59482,0 -1.01597,-0.41681 -0.41681,-0.42115 -0.41681,-1.01597 v -0.573117 q 0,-0.71205 0.57311,-1.146227 -0.57311,-0.434177 -0.57311,-1.146227 0,-0.594822 0.41681,-1.011632 0.42115,-0.421151 1.01597,-0.421151 0.59483,0 1.01164,0.421151 0.42115,0.41681 0.42115,1.011632 0,0.71205 -0.57312,1.146227 0.41247,0.312607 0.52102,0.768493 0.0521,0.230114 0.0521,0.950851 0,0.59482 -0.42115,1.01597 -0.41681,0.41681 -1.01164,0.41681 z m 0,-3.438681 q 0.36037,0 0.60785,-0.24748 0.25182,-0.251823 0.25182,-0.61219 0,-0.356025 -0.25182,-0.607847 -0.25182,-0.251823 -0.60785,-0.251823 -0.36036,0 -0.61219,0.251823 -0.24748,0.247481 -0.24748,0.607847 0,0.360367 0.24748,0.61219 0.25183,0.24748 0.61219,0.24748 z m 4.87147,0.573114 q 0,-0.71205 -0.15197,-1.341607 -0.23011,-0.950847 -0.7077,-0.950847 -0.47326,0 -0.70337,0.955189 -0.1563,0.642582 -0.1563,1.337265 0,0.707708 0.15196,1.341606 0.23011,0.950851 0.70771,0.950851 0.47759,0 0.7077,-0.950851 0.15197,-0.633898 0.15197,-1.341606 z m 0.57311,0 q 0,1.024657 -0.25182,1.771437 -0.36905,1.09413 -1.18096,1.09413 -0.81191,0 -1.18096,-1.08978 -0.25183,-0.746788 -0.25183,-1.775787 0,-1.028999 0.25183,-1.775783 0.36905,-1.089784 1.18096,-1.089784 0.81191,0 1.18096,1.094125 0.25182,0.746785 0.25182,1.771442 z"
id="text7"
style="font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';fill:#1a1a1a;stroke-width:0.180022"
aria-label="80" />
<path
d="m 176.526,96.741744 -0.65995,0.659948 q -0.0825,0.08249 -0.19972,0.08249 -0.28656,0 -0.28656,-0.286557 0,-0.117227 0.0825,-0.199721 l 1.12018,-1.120176 q 0.11288,-0.112886 0.23011,-0.112886 0.28656,0 0.28656,0.286557 v 5.158017 q 0,0.28656 -0.28656,0.28656 -0.28655,0 -0.28655,-0.28656 z m 4.01179,1.888669 q 0,-0.71205 -0.15196,-1.341607 -0.23012,-0.950847 -0.70771,-0.950847 -0.47325,0 -0.70337,0.955189 -0.1563,0.642582 -0.1563,1.337265 0,0.707708 0.15196,1.341606 0.23011,0.950851 0.70771,0.950851 0.47759,0 0.70771,-0.950851 0.15196,-0.633898 0.15196,-1.341606 z m 0.57311,0 q 0,1.024657 -0.25182,1.771437 -0.36905,1.09413 -1.18096,1.09413 -0.81191,0 -1.18096,-1.08978 -0.25182,-0.746788 -0.25182,-1.775787 0,-1.028999 0.25182,-1.775783 0.36905,-1.089784 1.18096,-1.089784 0.81191,0 1.18096,1.094125 0.25182,0.746785 0.25182,1.771442 z m 3.43868,0 q 0,-0.71205 -0.15196,-1.341607 -0.23011,-0.950847 -0.70771,-0.950847 -0.47325,0 -0.70336,0.955189 -0.15631,0.642582 -0.15631,1.337265 0,0.707708 0.15196,1.341606 0.23012,0.950851 0.70771,0.950851 0.4776,0 0.70771,-0.950851 0.15196,-0.633898 0.15196,-1.341606 z m 0.57312,0 q 0,1.024657 -0.25183,1.771437 -0.36905,1.09413 -1.18096,1.09413 -0.81191,0 -1.18096,-1.08978 -0.25182,-0.746788 -0.25182,-1.775787 0,-1.028999 0.25182,-1.775783 0.36905,-1.089784 1.18096,-1.089784 0.81191,0 1.18096,1.094125 0.25183,0.746785 0.25183,1.771442 z"
id="text8"
style="font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';fill:#1a1a1a;stroke-width:0.180022"
aria-label="100" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 72.78484,107.5467 v -5.0895"
id="path8" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 84.72555,107.5467 v -5.0895"
id="path9" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 156.36981,107.66705 v -5.0895"
id="path10" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 96.66626,107.66705 v -5.0895"
id="path11" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 108.60697,107.66705 v -5.0895"
id="path12" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 120.54768,107.66705 v -5.0895"
id="path13" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 132.48839,107.66705 v -5.0895"
id="path14" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 144.4291,107.66705 v -5.0895"
id="path15" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 168.31052,107.66705 v -5.0895"
id="path16" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 180.25123,107.66705 v -5.0895"
id="path17" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 63.232272,107.5467 v -2.6683"
id="path18" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 65.620414,107.5467 v -2.6683"
id="path19" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 68.008556,107.5467 v -2.6683"
id="path20" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 70.396698,107.5467 v -2.6683"
id="path21" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 75.172982,107.5467 v -2.6683"
id="path22" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 77.561124,107.5467 v -2.6683"
id="path23" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 79.949266,107.5467 v -2.6683"
id="path24" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 82.337408,107.5467 v -2.6683"
id="path25" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 87.113692,107.5467 v -2.6683"
id="path26" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 89.501834,107.5467 v -2.6683"
id="path27" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 91.889976,107.5467 v -2.6683"
id="path28" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 94.278118,107.5467 v -2.6683"
id="path29" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 99.054402,107.5467 v -2.6683"
id="path30" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 101.44254,107.5467 v -2.6683"
id="path31" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 103.83069,107.5467 v -2.6683"
id="path32" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 106.21883,107.5467 v -2.6683"
id="path33" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 110.99511,107.5467 v -2.6683"
id="path34" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 113.38325,107.5467 v -2.6683"
id="path35" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 115.7714,107.5467 v -2.6683"
id="path36" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 118.15954,107.5467 v -2.6683"
id="path37" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 122.93582,107.5467 v -2.6683"
id="path38" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 125.32396,107.5467 v -2.6683"
id="path39" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 127.71211,107.5467 v -2.6683"
id="path40" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 130.10025,107.5467 v -2.6683"
id="path41" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 134.87653,107.5467 v -2.6683"
id="path42" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 137.26467,107.5467 v -2.6683"
id="path43" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 139.65282,107.5467 v -2.6683"
id="path44" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 142.04096,107.5467 v -2.6683"
id="path45" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 146.81724,107.5467 v -2.6683"
id="path46" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 149.20538,107.5467 v -2.6683"
id="path47" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 151.59353,107.5467 v -2.6683"
id="path48" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 153.98167,107.5467 v -2.6683"
id="path49" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 158.75795,107.5467 v -2.6683"
id="path50" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 161.14609,107.5467 v -2.6683"
id="path51" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 163.53424,107.5467 v -2.6683"
id="path52" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 165.92238,107.5467 v -2.6683"
id="path53" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 170.69866,107.5467 v -2.6683"
id="path54" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 173.0868,107.5467 v -2.6683"
id="path55" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 175.47495,107.5467 v -2.6683"
id="path56" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 177.86309,107.5467 v -2.6683"
id="path57" />
<path
style="font-size:3.60539px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';fill:#1a1a1a;stroke-width:0.0734797"
d="m 185.02945,112.39742 v -0.92952 q 0,-0.11619 0.11619,-0.11619 h 0.81333 q 0.11619,0 0.11619,0.11619 0,0.11619 -0.11619,0.11619 h -0.69714 v 0.69714 h 0.34857 q 0.24118,0 0.41018,0.17076 0.17077,0.17076 0.17077,0.41018 v 0.23238 q 0,0.24118 -0.17077,0.41195 -0.17076,0.169 -0.41018,0.169 h -0.46476 q -0.11619,0 -0.11619,-0.11619 0,-0.11619 0.11619,-0.11619 h 0.46476 q 0.14612,0 0.24646,-0.10035 0.10211,-0.1021 0.10211,-0.24822 v -0.23238 q 0,-0.14435 -0.10211,-0.24646 -0.1021,-0.1021 -0.24646,-0.1021 h -0.46476 q -0.11619,0 -0.11619,-0.11619 z m 1.74284,-0.34857 h 1.04571 q 0.19541,0 0.3292,0.13555 0.13555,0.1338 0.13555,0.32921 v 1.0457 q 0,0.11619 -0.11619,0.11619 -0.11619,0 -0.11619,-0.11619 v -1.0457 q 0,-0.0986 -0.0669,-0.16549 -0.0669,-0.0669 -0.16548,-0.0669 h -0.23238 v 1.27808 q 0,0.11619 -0.11619,0.11619 -0.11619,0 -0.11619,-0.11619 v -1.27808 h -0.46476 v 1.27808 q 0,0.11619 -0.11619,0.11619 -0.11619,0 -0.11619,-0.11619 v -1.39427 q 0,-0.11619 0.11619,-0.11619 z m 2.78855,-0.21125 -0.34153,1.02457 h 0.68305 z m 0.81332,1.72171 q 0,0.11619 -0.11619,0.11619 -0.0845,0 -0.11091,-0.0792 l -0.16724,-0.50173 h -0.83797 l -0.16724,0.50173 q -0.0264,0.0792 -0.11091,0.0792 -0.11619,0 -0.11619,-0.11619 0,-0.0211 0.005,-0.037 l 0.69186,-2.07732 q 0.0317,-0.0933 0.11619,-0.0933 0.0845,0 0.11442,0.0898 l 0.69362,2.08084 q 0.005,0.0158 0.005,0.037 z"
id="text57"
aria-label="5mA" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

+112
View File
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="157.18373mm"
height="26.683672mm"
viewBox="0 0 157.18373 26.683672"
version="1.1"
id="svg1"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
sodipodi:docname="M1730-Scale_template.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.7493043"
inkscape:cx="252.67188"
inkscape:cy="106.89964"
inkscape:window-width="2327"
inkscape:window-height="1233"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1">
<rect
x="56.771998"
y="0"
width="495.35128"
height="37.782155"
id="rect5" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-37.352226,-90.454928)">
<path
id="rect1"
style="fill:#f9f9f9;stroke:#1a1a1a;stroke-width:0.184;stroke-linecap:round;stroke-miterlimit:10;stroke-dasharray:none"
d="M 37.444226,90.546928 V 117.0466 H 194.44395 V 90.546928 Z M 58.443978,107.54692 H 183.64409 v 6.19963 H 58.443978 Z" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 60.84413,107.5467 v -5.0895"
id="path5" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.7981px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.724858"
x="41.455711"
y="109.03796"
id="text1"
transform="scale(0.96486402,1.0364155)"><tspan
sodipodi:role="line"
id="tspan1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.7981px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#1a1a1a;stroke-width:0.724858"
x="41.455711"
y="109.03796">U</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;direction:ltr;text-anchor:middle;fill:#1a1a1a;stroke-width:0.180022"
x="60.844131"
y="100.87395"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.180022"
x="60.844131"
y="100.87395">0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;direction:ltr;text-anchor:middle;fill:#1a1a1a;stroke-width:0.180022"
x="180.25124"
y="100.87395"
id="text8"><tspan
sodipodi:role="line"
id="tspan8"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.180022"
x="180.25124"
y="100.87395">X</tspan></text>
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 180.25123,107.66705 v -5.0895"
id="path17" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.60539px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.0734799;stroke-linecap:butt;stroke-dasharray:none"
x="184.79707"
y="113.6755"
id="text57"><tspan
sodipodi:role="line"
id="tspan57"
style="stroke-width:0.0734797"
x="184.79707"
y="113.6755">5mA</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,37.352226,90.454928)"
id="text5"
style="text-orientation:auto;-inkscape-font-specification:'ГОСТ тип А, Normal';font-family:'ГОСТ тип А';font-size:33.60733414px;stroke:#1a1a1a;writing-mode:lr-tb;direction:ltr;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;white-space:pre;shape-inside:url(#rect5)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

+340
View File
@@ -0,0 +1,340 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="157.18373mm"
height="26.683672mm"
viewBox="0 0 157.18373 26.683672"
version="1.1"
id="svg1"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
sodipodi:docname="M1730-Scale.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.6029029"
inkscape:cx="274.8139"
inkscape:cy="80.167051"
inkscape:window-width="2048"
inkscape:window-height="1208"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-37.352226,-90.454928)">
<path
id="rect1"
style="fill:#f9f9f9;stroke:#1a1a1a;stroke-width:0.184;stroke-linecap:round;stroke-miterlimit:10;stroke-dasharray:none"
d="M 37.444226,90.546928 V 117.0466 H 194.44395 V 90.546928 Z M 58.443978,107.54692 H 183.64409 v 6.19963 H 58.443978 Z" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 60.84413,107.5467 v -5.0895"
id="path5" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.7981px;font-family:'ГОСТ тип В';-inkscape-font-specification:'ГОСТ тип В, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.724858"
x="41.455711"
y="109.03796"
id="text1"
transform="scale(0.96486402,1.0364155)"><tspan
sodipodi:role="line"
id="tspan1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.7981px;font-family:'ГОСТ тип В';-inkscape-font-specification:'ГОСТ тип В, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#1a1a1a;stroke-width:0.724858"
x="41.455711"
y="109.03796">%</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.180022"
x="58.838234"
y="101.49598"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.180022"
x="58.838234"
y="101.49598">0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.180022"
x="80.71376"
y="101.49598"
id="text3"><tspan
sodipodi:role="line"
id="tspan3"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.180022"
x="80.71376"
y="101.49598">20</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.180022"
x="104.30862"
y="101.49598"
id="text4"><tspan
sodipodi:role="line"
style="stroke-width:0.180022"
x="104.30862"
y="101.49598"
id="tspan5">40</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.180022"
x="128.47659"
y="101.49598"
id="text6"><tspan
sodipodi:role="line"
id="tspan6"
style="stroke-width:0.180022"
x="128.47659"
y="101.49598">60</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.180022"
x="152.35802"
y="101.49598"
id="text7"><tspan
sodipodi:role="line"
id="tspan7"
style="stroke-width:0.180022"
x="152.35802"
y="101.49598">80</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.89194px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.180022"
x="174.80666"
y="101.49598"
id="text8"><tspan
sodipodi:role="line"
id="tspan8"
style="stroke-width:0.180022"
x="174.80666"
y="101.49598">100</tspan></text>
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 72.78484,107.5467 v -5.0895"
id="path8" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 84.72555,107.5467 v -5.0895"
id="path9" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 156.36981,107.66705 v -5.0895"
id="path10" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 96.66626,107.66705 v -5.0895"
id="path11" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 108.60697,107.66705 v -5.0895"
id="path12" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 120.54768,107.66705 v -5.0895"
id="path13" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 132.48839,107.66705 v -5.0895"
id="path14" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 144.4291,107.66705 v -5.0895"
id="path15" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 168.31052,107.66705 v -5.0895"
id="path16" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 180.25123,107.66705 v -5.0895"
id="path17" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 63.232272,107.5467 v -2.6683"
id="path18" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 65.620414,107.5467 v -2.6683"
id="path19" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 68.008556,107.5467 v -2.6683"
id="path20" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 70.396698,107.5467 v -2.6683"
id="path21" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 75.172982,107.5467 v -2.6683"
id="path22" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 77.561124,107.5467 v -2.6683"
id="path23" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 79.949266,107.5467 v -2.6683"
id="path24" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 82.337408,107.5467 v -2.6683"
id="path25" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 87.113692,107.5467 v -2.6683"
id="path26" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 89.501834,107.5467 v -2.6683"
id="path27" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 91.889976,107.5467 v -2.6683"
id="path28" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 94.278118,107.5467 v -2.6683"
id="path29" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 99.054402,107.5467 v -2.6683"
id="path30" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 101.44254,107.5467 v -2.6683"
id="path31" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 103.83069,107.5467 v -2.6683"
id="path32" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 106.21883,107.5467 v -2.6683"
id="path33" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 110.99511,107.5467 v -2.6683"
id="path34" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 113.38325,107.5467 v -2.6683"
id="path35" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 115.7714,107.5467 v -2.6683"
id="path36" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 118.15954,107.5467 v -2.6683"
id="path37" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 122.93582,107.5467 v -2.6683"
id="path38" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 125.32396,107.5467 v -2.6683"
id="path39" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 127.71211,107.5467 v -2.6683"
id="path40" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 130.10025,107.5467 v -2.6683"
id="path41" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 134.87653,107.5467 v -2.6683"
id="path42" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 137.26467,107.5467 v -2.6683"
id="path43" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 139.65282,107.5467 v -2.6683"
id="path44" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 142.04096,107.5467 v -2.6683"
id="path45" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 146.81724,107.5467 v -2.6683"
id="path46" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 149.20538,107.5467 v -2.6683"
id="path47" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 151.59353,107.5467 v -2.6683"
id="path48" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 153.98167,107.5467 v -2.6683"
id="path49" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 158.75795,107.5467 v -2.6683"
id="path50" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 161.14609,107.5467 v -2.6683"
id="path51" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 163.53424,107.5467 v -2.6683"
id="path52" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 165.92238,107.5467 v -2.6683"
id="path53" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 170.69866,107.5467 v -2.6683"
id="path54" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 173.0868,107.5467 v -2.6683"
id="path55" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 175.47495,107.5467 v -2.6683"
id="path56" />
<path
style="fill:#ffffff;stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt;stroke-miterlimit:10;stroke-dasharray:none"
d="m 177.86309,107.5467 v -2.6683"
id="path57" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.60539px;font-family:'ГОСТ тип А';-inkscape-font-specification:'ГОСТ тип А, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;writing-mode:lr-tb;direction:ltr;fill:#1a1a1a;stroke-width:0.0734799;stroke-linecap:butt;stroke-dasharray:none"
x="184.79707"
y="113.6755"
id="text57"><tspan
sodipodi:role="line"
id="tspan57"
style="stroke-width:0.0734797"
x="184.79707"
y="113.6755">5mA</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.
+28
View File
@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: m1730-generator
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: m1730-generator
template:
metadata:
labels:
app: m1730-generator
spec:
containers:
- name: m1730-generator
image: git.baumann.gr/adebaumann/m1730-generator:0.1
imagePullPolicy: Always
ports:
- containerPort: 5000
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"
+12
View File
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: m1730-generator
namespace: default
spec:
selector:
app: m1730-generator
ports:
- port: 80
targetPort: 5000
type: ClusterIP
+117
View File
@@ -0,0 +1,117 @@
import base64
import pathlib
from flask import Flask, render_template, request, Response
from html import escape
app = Flask(__name__)
_FONT_PATH = pathlib.Path('/usr/local/share/fonts/г/ГОСТ_тип_А.ttf')
_FONT_B64 = base64.b64encode(_FONT_PATH.read_bytes()).decode()
_FONT_FACE = (
'<defs><style>'
'@font-face {'
'font-family:"ГОСТ тип А";'
f'src:url("data:font/truetype;base64,{_FONT_B64}") format("truetype");'
'}'
'</style></defs>'
)
# SVG absolute coordinate constants (1 user unit = 1 mm)
ZERO_X = 60.844130 # x of the zero/left tick
MAX_X = 180.251230 # x of the full-scale/right tick
BAR_Y = 107.54670 # y at the top of the scale bar (tick baseline)
SCALE_LEN = MAX_X - ZERO_X # 119.4071 mm
BIG_H = 5.0895 # major tick height
SMALL_H = 2.6683 # minor tick height
def _fmt(v: float) -> str:
if v == int(v):
return str(int(v))
return f"{v:.4g}"
def generate_svg(unit, min_val, max_val, range_label, big_ticks, small_ticks, label_count):
big_interval = SCALE_LEN / big_ticks
big_xs = [ZERO_X + i * big_interval for i in range(big_ticks + 1)]
label_count = max(2, min(label_count, big_ticks + 1))
label_indices = [round(k * big_ticks / (label_count - 1)) for k in range(label_count)]
parts = [
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>',
'<svg width="157.18373mm" height="26.683672mm"'
' viewBox="0 0 157.18373 26.683672" version="1.1"'
' xmlns="http://www.w3.org/2000/svg">',
_FONT_FACE,
' <g transform="translate(-37.352226,-90.454928)">',
# Background rect with scale-bar cutout
' <path style="fill:#f9f9f9;stroke:#1a1a1a;stroke-width:0.184;'
'stroke-linecap:round;stroke-miterlimit:10"'
' d="M 37.444226,90.546928 V 117.0466 H 194.44395 V 90.546928 Z'
' M 58.443978,107.54692 H 183.64409 v 6.19963 H 58.443978 Z" />',
# Unit label (large letter in left panel)
f' <text style="font-size:18.7981px;font-family:\'ГОСТ тип А\',monospace;fill:#1a1a1a"'
f' x="41.455711" y="109.03796"'
f' transform="scale(0.96486402,1.0364155)">{escape(unit)}</text>',
# Range label inside the strip on the right
f' <text style="font-size:3.60539px;font-family:\'ГОСТ тип А\',monospace;fill:#1a1a1a"'
f' x="184.79707" y="113.6755">{escape(range_label)}</text>',
]
# Major ticks
for x in big_xs:
parts.append(
f' <line x1="{x:.5f}" y1="{BAR_Y}" x2="{x:.5f}" y2="{BAR_Y - BIG_H:.5f}"'
f' style="stroke:#1a1a1a;stroke-width:0.555;stroke-linecap:butt" />'
)
# Minor ticks
if small_ticks > 0:
sub = small_ticks + 1
for i in range(big_ticks):
for j in range(1, small_ticks + 1):
x = big_xs[i] + j * big_interval / sub
parts.append(
f' <line x1="{x:.5f}" y1="{BAR_Y}" x2="{x:.5f}" y2="{BAR_Y - SMALL_H:.5f}"'
f' style="stroke:#1a1a1a;stroke-width:0.302;stroke-linecap:butt" />'
)
# Numeric labels (centered on their tick, above the tick area)
for idx in label_indices:
x = big_xs[idx]
val = min_val + (max_val - min_val) * idx / big_ticks
parts.append(
f' <text style="font-size:8.89194px;font-family:\'ГОСТ тип А\',monospace;fill:#1a1a1a"'
f' text-anchor="middle" x="{x:.5f}" y="101.49598">{escape(_fmt(val))}</text>'
)
parts += [' </g>', '</svg>']
return '\n'.join(parts)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/generate', methods=['POST'])
def generate():
unit = request.form.get('unit', '%')
min_val = float(request.form.get('min', 0))
max_val = float(request.form.get('max', 100))
range_label = request.form.get('range_label', '5mA')
big_ticks = max(1, min(50, int(request.form.get('big_ticks', 10))))
small_ticks = max(0, min(20, int(request.form.get('small_ticks', 4))))
label_count = max(2, int(request.form.get('label_count', 6)))
svg = generate_svg(unit, min_val, max_val, range_label, big_ticks, small_ticks, label_count)
return Response(svg, mimetype='image/svg+xml')
if __name__ == '__main__':
app.run(debug=True)
+2
View File
@@ -0,0 +1,2 @@
flask
gunicorn
+213
View File
@@ -0,0 +1,213 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>M1730 Scale Generator</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: system-ui, sans-serif;
background: #f4f4f5;
color: #222;
min-height: 100vh;
padding: 2rem 1.5rem;
}
.container { max-width: 840px; margin: 0 auto; }
h1 { font-size: 1.3rem; font-weight: 600; margin-bottom: 1.5rem; }
.card {
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem 2rem;
}
@media (max-width: 560px) { .grid { grid-template-columns: 1fr; } }
label {
display: flex;
flex-direction: column;
gap: 0.3rem;
font-size: 0.88rem;
font-weight: 600;
}
label small { font-weight: normal; color: #666; font-size: 0.8rem; }
input[type="text"],
input[type="number"] {
padding: 0.4rem 0.65rem;
border: 1px solid #bbb;
border-radius: 4px;
font-size: 0.95rem;
width: 100%;
transition: border-color 0.15s;
}
input:focus { outline: 2px solid #0070f3; outline-offset: 1px; border-color: transparent; }
.actions {
grid-column: 1 / -1;
display: flex;
gap: 0.75rem;
align-items: center;
margin-top: 0.5rem;
}
button {
padding: 0.45rem 1.2rem;
font-size: 0.9rem;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
}
#btn-generate { background: #0070f3; color: #fff; }
#btn-generate:hover { background: #005fd4; }
#btn-download { background: #e5e5e5; color: #222; }
#btn-download:hover:not(:disabled) { background: #d4d4d4; }
#btn-download:disabled { opacity: 0.45; cursor: not-allowed; }
#status { font-size: 0.82rem; color: #888; }
.preview-card {
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 1.5rem;
}
.preview-label {
font-size: 0.8rem;
font-weight: 600;
color: #888;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 1rem;
}
#preview svg { width: 100%; height: auto; display: block; }
#preview-placeholder { font-size: 0.9rem; color: #aaa; }
</style>
</head>
<body>
<div class="container">
<h1>M1730 Scale Generator</h1>
<div class="card">
<form id="form" class="grid">
<label>
Unit
<small>Large letter left of scale</small>
<input name="unit" type="text" value="%" required>
</label>
<label>
Range label
<small>Small text in the strip (e.g. 5mA, 10V)</small>
<input name="range_label" type="text" value="5mA" required>
</label>
<label>
Min value
<small>Value at the left (zero) end</small>
<input name="min" type="number" step="any" value="0" required>
</label>
<label>
Max value
<small>Value at the right end</small>
<input name="max" type="number" step="any" value="100" required>
</label>
<label>
Major tick intervals
<small>Number of divisions (e.g. 10 → 0, 10, 20 … 100)</small>
<input name="big_ticks" type="number" min="1" max="50" value="10" required>
</label>
<label>
Minor ticks per interval
<small>Small ticks between each major pair</small>
<input name="small_ticks" type="number" min="0" max="20" value="4" required>
</label>
<label>
Number of labels
<small>Numeric values to print; best when (count1) divides intervals</small>
<input name="label_count" type="number" min="2" value="6" required>
</label>
<div class="actions">
<button type="submit" id="btn-generate">Generate</button>
<button type="button" id="btn-download" disabled>Download SVG</button>
<span id="status"></span>
</div>
</form>
</div>
<div class="preview-card">
<div class="preview-label">Preview</div>
<div id="preview">
<p id="preview-placeholder">Fill in the form and click Generate.</p>
</div>
</div>
</div>
<script>
let lastSvg = '';
async function doGenerate() {
const status = document.getElementById('status');
status.textContent = 'Generating…';
try {
const resp = await fetch('generate', {
method: 'POST',
body: new FormData(document.getElementById('form')),
});
if (!resp.ok) throw new Error(await resp.text());
lastSvg = await resp.text();
document.getElementById('preview').innerHTML = lastSvg;
document.getElementById('btn-download').disabled = false;
status.textContent = '';
} catch (err) {
status.textContent = 'Error: ' + err.message;
}
}
document.getElementById('form').addEventListener('submit', e => {
e.preventDefault();
doGenerate();
});
document.getElementById('btn-download').addEventListener('click', () => {
if (!lastSvg) return;
const a = Object.assign(document.createElement('a'), {
href: URL.createObjectURL(new Blob([lastSvg], { type: 'image/svg+xml' })),
download: 'M1730-Scale.svg',
});
a.click();
URL.revokeObjectURL(a.href);
});
// Show default scale on load
doGenerate();
</script>
</body>
</html>