fix(plot): a crosshair readout quotes a sample, never a value between two

The readout's y was a linear interpolation between the two samples adjacent to
the pointer, which answers "what is the signal at this instant" -- a number the
series does not contain. On a source whose samples are already averaged or
decimated at ingest that is a value nothing measured, and at a zoom past the
sample spacing it is visibly not the datum under the pointer.

`crosshair_span()`'s `t` becomes a selector rather than a blend factor: the
nearer end wins, a tie reading the earlier sample (the bias the span already
takes for a degenerate pair). `t` is measured on the samples' own x through
`neighbours()`/`x_at()`, so "nearer" is exact on a non-uniform clock too, and
the lookup still reads level 0, so the value is a stored sample and never an
LOD bucket's aggregate. `crosshair_interpolate()` had no other caller and is
gone.

`CrosshairRow::marker` is placed from the same y, so the dot follows the
reported sample: past the sample spacing it sits beside the polyline rather
than on it, deliberately -- one y feeding both keeps the mark and the number
from ever disagreeing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-10-05 13:42:57 +02:00
1 parent 26a7c82a80
commit c028f48fa0
10 files changed
+150 -105

No files matched your search

+3 -3
View File
@@ -72,9 +72,9 @@ PLOT_TEST(xy_series_reports_its_own_grid) {
}
PLOT_TEST(xy_series_neighbour_lookups_crosshair_style) {
// The crosshair asks neighbours() at an arbitrary x and interpolates between
// the two samples it gets back. On a non-uniform grid that needs real
// searches: a uniform-grid formula would land megabytes off here.
// The crosshair asks neighbours() at an arbitrary x and reports whichever of
// the two samples it gets back is nearer. On a non-uniform grid that needs
// real searches: a uniform-grid formula would land megabytes off here.
auto x = spread_x(1000);
const std::vector<f64> xs = x;
plot::data::XYSeries s(std::move(x), saw_y(1000));