fix(plot): single-rounding clock labels, log-axis fits that refuse non-positive data

This commit is contained in:
Martino Ferrari committed 2026-09-27 22:28:56 +02:00
1 parent 93fc06f050
commit 606e40a9f1
7 files changed
+258 -73

No files matched your search

+14 -2
View File
@@ -109,6 +109,13 @@ class Plot {
/// Fits every x axis to the union of the series bounds of the traces bound to
/// it, padded by 2% of the span, and re-arms auto scale on the axes it fitted.
/// An axis with no visible trace is left exactly as it was.
///
/// A log axis is fitted in log space and needs a positive value to show. When
/// its traces hold none (every sample negative or zero) the fit is refused: the
/// axis keeps its current range, auto scale is not re-armed, and the next
/// auto-fit tries again -- so a stream that starts at zero begins fitting on its
/// own once it goes positive. A log axis is therefore never left with `min >=
/// max` or a non-positive bound by an auto-fit.
void auto_fit_x();
/// Same for one y axis, over that axis' traces' y bounds.
void auto_fit_y(u32 axis);
@@ -161,10 +168,15 @@ class Plot {
mutable u64 last_size = 0;
};
/// Fit one axis to its traces' bounds, leaving auto_scale alone. False when no
/// visible trace is bound to the axis, in which case the range is untouched.
/// Fit one axis to its traces' bounds, leaving auto_scale alone. False when the
/// axis cannot be fitted (no visible trace bound to it, or a log axis whose
/// traces hold no positive value), in which case the range is untouched.
bool fit_x_axis(u32 axis);
bool fit_y_axis(u32 axis);
/// Union of the bounds of the visible traces bound to one axis (`x_side`
/// selects x or y). False when there is no such trace; `out` then retains
/// whatever it held.
bool trace_bounds_union(bool x_side, u32 axis, Range& out) const;
/// Refit every axis that is still on auto scale. layout() runs this, so a
/// growing stream stays framed until a caller gesture turns auto scale off.
void autoscale_axes();
+12 -2
View File
@@ -38,8 +38,18 @@ enum class TickFormat {
void format_si(f64 v, char* buf, usize n, const char* unit = nullptr);
/// Writes `seconds` as a compact clock string to `buf`, NUL-terminated and never
/// past `n` bytes. Shapes: `500ms`, `1.5s`, `1:30`, `1:00:00`, `2.5d`; negatives
/// keep their sign. A non-finite value falls back to `"%.3g"`.
/// past `n` bytes. Negatives keep their sign; a non-finite value falls back to
/// `"%.3g"`.
///
/// The whole value is rounded to a single whole-second count first and every
/// field is derived from that one number, so no field can ever reach its radix:
/// 119.5 s is `2:00`, not `1:60`, and 3599.5 s is `1:00:00`.
///
/// Shapes, by magnitude: below 1 s `500ms`; below 60 s `1.5s`; below 1 h `1:30`;
/// at or above 24 h, as a decimal day count `2.5d`. Between 1 h and 24 h the
/// shape is `1:01:01` -- and because a value that rounds up to 24 h takes the day
/// shape, the hour field of that shape is always below 24. The 60 s and 1 h
/// boundaries are inclusive of the rounded value: 59.5 s is `1:00`.
void format_time(f64 seconds, char* buf, usize n);
/// The hard cap on `generate_ticks` output, minor ticks included. A range dense