Fix reciprocal minor tick spacing; bump to 0.84

Minor ticks on 1/x scales were using linear value interpolation between
harmonically-spaced major ticks. Because 1/v is highly convex, equal value
steps near a large major-value (left side of the first interval) map to tiny
physical steps, piling all ticks against the left wall. At a 1:1000 ratio the
first four minor ticks land at 0%/0%/1%/2% of the interval.

Fix: interpolate in position space (uniform physical spacing) for all
reciprocal intervals, matching how major ticks are laid out (also equal
physical steps) and matching the already-correct ∞-first-interval handling.

Also documents 1/x scale and ∞ max in README.
This commit is contained in:
2026-07-14 23:33:55 +02:00
parent f19c462c1b
commit 8d45a6d10f
3 changed files with 8 additions and 6 deletions
+5 -4
View File
@@ -8,7 +8,7 @@ from fontTools.pens.svgPathPen import SVGPathPen
app = Flask(__name__)
VERSION = "0.83"
VERSION = "0.84"
_LOGO_PATH = pathlib.Path(__file__).parent / 'static' / 'logo.png'
_LOGO_B64 = base64.b64encode(_LOGO_PATH.read_bytes()).decode()
@@ -487,9 +487,10 @@ def generate_svg(unit, min_val, max_val, range_label, big_ticks, small_ticks, la
for j in range(1, small_ticks + 1):
if scale_type == 'sqrt':
x = big_xs[i] + (j / sub) ** 2 * (big_xs[i + 1] - big_xs[i])
elif math.isinf(big_vals[i]):
# First interval with ∞ at the left: interpolate in position space
# (linear value interpolation is undefined from ∞).
elif scale_type == 'reciprocal' or math.isinf(big_vals[i]):
# Reciprocal: interpolate in position space (= linear in 1/v).
# Linear value interpolation would map huge early value ranges
# through 1/v and pile all ticks against the left wall.
x = big_xs[i] + (j / sub) * (big_xs[i + 1] - big_xs[i])
else:
v = big_vals[i] + j * (big_vals[i + 1] - big_vals[i]) / sub