feat(plot): nice-number ticks, axes, grid, traces, cursors, measurement queries
This commit is contained in:
1 parent
b4e88fe0c1
commit
93fc06f050
18 files changed
+1582
No files matched your search
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <plot/core/types.hpp>
|
||||
|
||||
namespace plot {
|
||||
|
||||
/// One axis tick. `value` is in data coordinates; `major` marks the labelled
|
||||
/// ticks (minor ticks carry an empty label); `label` is UTF-8.
|
||||
struct Tick {
|
||||
f64 value = 0.0;
|
||||
bool major = true;
|
||||
std::string label;
|
||||
};
|
||||
|
||||
/// How an axis renders its tick labels.
|
||||
enum class TickFormat {
|
||||
Si, ///< SI-prefixed numbers, e.g. `1.5u`, `2.5G`, `1.23k`.
|
||||
Time, ///< clock strings, e.g. `1:30`, `1:00:00`.
|
||||
};
|
||||
|
||||
/// Writes an SI-prefixed rendering of `v` to `buf`, always NUL-terminated and
|
||||
/// never writing past `n` bytes (a too-small buffer truncates, it does not
|
||||
/// overflow). ASCII plus the UTF-8 micro sign U+00B5 (0xC2 0xB5) for 1e-6, so
|
||||
/// `plot::render::BitmapFont` renders it instead of mojibake.
|
||||
///
|
||||
/// `format_si(0.0)` is exactly `"0"`. Values use three significant digits, so
|
||||
/// `1234.0` renders as `1.23k`. The sign of a negative value is kept. A value
|
||||
/// whose engineering exponent falls outside the prefix table (or a label that
|
||||
/// would exceed 12 characters) falls back to `"%.3g"`, and a non-finite value
|
||||
/// always does -- `nan`/`inf` are never silently dropped, they are printed by the
|
||||
/// fallback exactly as `%.3g` prints them.
|
||||
///
|
||||
/// `unit` is appended after the prefix when non-null, which is how a caller
|
||||
/// spells a unit the library cannot know: `format_si(v, buf, n, "\xC2\xB0")` for
|
||||
/// degrees, `"\xCE\xA9"` for ohms.
|
||||
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"`.
|
||||
void format_time(f64 seconds, char* buf, usize n);
|
||||
|
||||
/// The hard cap on `generate_ticks` output, minor ticks included. A range dense
|
||||
/// enough to need more is truncated rather than allowed to grow without bound.
|
||||
inline constexpr usize kMaxTicks = 256;
|
||||
|
||||
/// Nice-number ticks for the closed interval `range` on an axis `px` pixels long,
|
||||
/// with major ticks at least `min_px` pixels apart. Steps are 1/2/5 x 10^n, chosen
|
||||
/// by rounding the ideal step *up* to the next nice value so major spacing really
|
||||
/// does meet `min_px`. Ticks are appended to `out`, which is cleared first, in
|
||||
/// ascending value order and labelled by `format_si`.
|
||||
///
|
||||
/// `include_minors` adds, for grid geometry, the minor ticks subdividing each
|
||||
/// major step by 5 (by 4 when the step's leading digit is 2). Without it `out`
|
||||
/// holds exactly the labelled major ticks -- the labelled set a caller draws
|
||||
/// numbers for, with no unlabelled entries to filter. Either way the total is
|
||||
/// capped at kMaxTicks.
|
||||
///
|
||||
/// Hostile input clears `out` and returns: a non-finite endpoint, `max <= min`
|
||||
/// (a zero or negative span, which includes the collapsed range of a
|
||||
/// single-sample series), a non-positive `px` or `min_px`, and a span whose step
|
||||
/// overflows to infinity.
|
||||
void generate_ticks(Range range, f32 px, f32 min_px, std::vector<Tick>& out,
|
||||
bool include_minors = false);
|
||||
|
||||
} // namespace plot
|
||||
Reference in new issue
Block a user