fix: a readout mark sits on the sample it quotes, not on the pointer's column

The value was already the nearest stored sample's, but every mark drawn for it was
placed at the *marker's* x with that sample's y -- so the dot the eye follows and the
number in the pane were a different datum whenever the marker fell between two samples.
Half a sample period is nothing across a whole window and the width of the panel once a
few samples span the axes, which is the only zoom at which anyone is asking which point
a number came from.

`place_crossings()` now goes through the plotter's new `Plot::crosshair_point()`, which
returns the quoted sample's x alongside its y -- one lookup for the mark and the number,
so they cannot name different samples. The dot consequently sits a little off its own
vertical cursor line: the line is where the marker is, the dot is the datum being quoted,
and between two samples those are two places.

Pin moves to the upstream commit that does the same for the library's own hover crosshair
and draws its mark larger than a trace's sample dots, and that keeps the old blend
reachable as `CrosshairValue::Interpolated` -- which udpscope never states.

Verified: plotter suite 370 cases 0 failed; `[cursors-probe]` lines=3 marks=6 with
`first mark at x=3.292400 y=-0.525175` against the pane's `-525.17 mV`; `[help]`
pages=14 parsed=14 closed ok.
This commit is contained in:
Martino Ferrari committed 2026-10-05 14:41:02 +02:00
1 parent d03c9fb443
commit 1f6738031a
5 files changed
+61 -16

No files matched your search

+4 -1
View File
@@ -25,7 +25,10 @@ owns a <b>Reset</b> button. Drag a marker to move it. The mode dropdown offers f
• A marker past the newest sample reads <tt>--</tt>. With only one marker over data the row
reads <tt>partial</tt>: a difference between a number and nothing is not a number.
• In <tt>mix</tt> each marker also places a crossing annotation per trace, which is what lets
you see on the plot which sample a number came from.
you see on the plot which sample a number came from. It is <i>on that sample</i>, so when the
marker falls between two it sits a little off its own line: the line is where you put the
marker, the dot is the datum being quoted. The hover crosshair's mark snaps the same way, and
is drawn larger than a trace's sample dots so it does not read as one more sample.
• The time row exists only in the modes that show the vertical pair. <tt>horizontal</tt> has no
time row, by design.
+16 -4
View File
@@ -396,18 +396,30 @@ void RowSet::place_crossings() {
if (ida >= r.plot->annotation_count() || idb >= r.plot->annotation_count()) continue;
plot::Annotation a = r.plot->annotation(ida);
plot::Annotation b = r.plot->annotation(idb);
double xa = 0.0;
double ya = 0.0;
double xb = 0.0;
double yb = 0.0;
const bool has_a = mix && r.plot->crosshair_value(static_cast<plot::u32>(s), cursor_a_x_, ya);
const bool has_b = mix && r.plot->crosshair_value(static_cast<plot::u32>(s), cursor_b_x_, yb);
// `crosshair_point()`, not `crosshair_value()`: the number beside this dot is a *stored
// sample's*, so the dot belongs on that sample and not on the marker's own column. The
// two differ by up to half a sample period, which is nothing at a whole-window view and
// the whole width of the panel once the view is zoomed to a handful of samples -- the
// state in which a reader is asking "which point is that?" in the first place. It leaves
// the dot a little off its vertical line by design: the line says *where the marker is*
// and the dot says *which datum is being quoted*, and when the marker is between two
// samples those are not the same place.
const bool has_a =
mix && r.plot->crosshair_point(static_cast<plot::u32>(s), cursor_a_x_, xa, ya);
const bool has_b =
mix && r.plot->crosshair_point(static_cast<plot::u32>(s), cursor_b_x_, xb, yb);
a.visible = has_a;
b.visible = has_b;
if (has_a) {
a.x = cursor_a_x_;
a.x = xa;
a.y = ya;
}
if (has_b) {
b.x = cursor_b_x_;
b.x = xb;
b.y = yb;
}
r.plot->set_annotation(ida, a);