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:
1 parent
d03c9fb443
commit
1f6738031a
5 files changed
+61
-16
No files matched your search
@@ -756,12 +756,27 @@ far the largest file.
|
|||||||
average* over `time_stride` samples, so a number between two stored samples is a second
|
average* over `time_stride` samples, so a number between two stored samples is a second
|
||||||
estimate laid over the first that nothing on screen or in an export holds; and past the sample
|
estimate laid over the first that nothing on screen or in an export holds; and past the sample
|
||||||
spacing the polyline is a line the renderer drew, so a point on it reports the drawing. The
|
spacing the polyline is a line the renderer drew, so a point on it reports the drawing. The
|
||||||
change is in `deps/plotter` and unconditional — no setting, because the library had no business
|
change is in `deps/plotter`, which keeps the blend as `CrosshairValue::Interpolated` for a host
|
||||||
offering a readout the data does not contain. `CrosshairRow::marker` is placed from the same y,
|
whose x is a quantity it is willing to interpolate — the nearest sample is the **default** and
|
||||||
so the dot lands on the quoted sample and **sits beside the polyline at a deep zoom, by
|
**udpscope never states the other**, so a `set_crosshair_value_mode()` call appearing here is a
|
||||||
design**: one y feeding both is what keeps the mark and the number from disagreeing. The guards
|
regression, not a feature.
|
||||||
are the library's `crosshair_value_is_the_nearest_sample` and `[cursors-probe]`'s `first mark at
|
**Both the mark and the number come from one call, `Plot::crosshair_point()`**, which returns
|
||||||
x=.. y=..` agreeing with the pane's first value.
|
the quoted sample's own **x** as well as its y — so every mark this app draws for a readout is
|
||||||
|
*snapped to the sample it quotes*. The library's `CrosshairRow::marker` and the cursors pane's
|
||||||
|
`mix` crossing annotations (`place_crossings()`, which must use `crosshair_point()` and not
|
||||||
|
`crosshair_value()`) are both placed from it. Two consequences that look like defects and are
|
||||||
|
not: the mark **sits beside the polyline at a deep zoom** (one y feeding both the number and the
|
||||||
|
dot is what keeps them from disagreeing), and a crossing dot **sits a little off its own
|
||||||
|
vertical cursor line** — up to half a sample period, invisible at a whole-window view and the
|
||||||
|
width of the panel at a few samples across, which is the only zoom at which anyone is asking
|
||||||
|
which point it is. The line says where the *marker* is; the dot says which *datum* is quoted.
|
||||||
|
The hover mark is also deliberately *larger* than a trace's own sample dots
|
||||||
|
(`Style::crosshair_marker_px` 9 against `marker_px` 3), because a snapped mark lands among them
|
||||||
|
and at their size reads as one more sample. The guards are the library's
|
||||||
|
`crosshair_value_is_the_nearest_sample`, `the_crosshair_marker_snaps_to_the_sample_it_reports`,
|
||||||
|
`crosshair_interpolated_mode_blends_the_two_samples` and
|
||||||
|
`the_crosshair_mark_is_bigger_than_a_sample_dot`, plus `[cursors-probe]`'s `first mark at x=..
|
||||||
|
y=..` agreeing with the pane's first value.
|
||||||
- **The cursors are read back from the plots only while a gesture is on that row.** `Cursor::x`
|
- **The cursors are read back from the plots only while a gesture is on that row.** `Cursor::x`
|
||||||
is the *free* pointer position while a drag runs and the snapped value otherwise -- which is
|
is the *free* pointer position while a drag runs and the snapped value otherwise -- which is
|
||||||
what the app itself wrote a frame earlier, or the snap of it. A tick that reads a row on
|
what the app itself wrote a frame earlier, or the snap of it. A tick that reads a row on
|
||||||
|
|||||||
@@ -1153,10 +1153,25 @@ second, undeclared estimate laid over the first, and nothing on screen or in an
|
|||||||
holds it. And at a zoom past the sample spacing it is visibly not the datum the pointer
|
holds it. And at a zoom past the sample spacing it is visibly not the datum the pointer
|
||||||
is over: the polyline between two samples is a straight line the renderer drew, and
|
is over: the polyline between two samples is a straight line the renderer drew, and
|
||||||
quoting a point on it reports the drawing rather than the data. A tie reads the earlier
|
quoting a point on it reports the drawing rather than the data. A tie reads the earlier
|
||||||
sample. The fix is upstream and unconditional (`deps/plotter`, `crosshair_span()`'s `t`
|
sample. The fix is upstream (`deps/plotter`, `crosshair_span()`'s `t` is a selector rather
|
||||||
is now a selector rather than a blend factor), so the library's own hover crosshair
|
than a blend factor), so the library's own hover crosshair changed with the pane — which is
|
||||||
changed with the pane — which is the point, since both are the same lookup and a user
|
the point, since both are the same lookup and a user comparing them must not see two
|
||||||
comparing them must not see two numbers.
|
numbers. Upstream keeps the blend as `CrosshairValue::Interpolated` for hosts whose x is a
|
||||||
|
quantity they are willing to interpolate; the nearest sample is the default and udpscope
|
||||||
|
never states the other.
|
||||||
|
|
||||||
|
**The crossing dot is on the sample, not on the marker's column.** The dot is placed
|
||||||
|
through `Plot::crosshair_point()` — the same lookup as the value, returning the quoted
|
||||||
|
sample's own x as well as its y — so the mark the eye follows and the number in the pane
|
||||||
|
are the same datum. The two x's differ by up to half a sample period: nothing at a
|
||||||
|
whole-window view, and the whole width of the panel once a few samples span the axes, which
|
||||||
|
is exactly the state in which a reader is asking "which point is that?". It therefore leaves
|
||||||
|
the dot a little off its own 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 two places. The library's hover crosshair snaps the same way and draws its mark
|
||||||
|
`Style::crosshair_marker_px` across (9 logical px against a trace's own 3 px sample dots),
|
||||||
|
since a snapped mark lands among those dots and at their size would read as one more sample
|
||||||
|
instead of as the answer to the question the hover asks.
|
||||||
|
|
||||||
The readouts are a **table**: a header naming the columns, then one row per instrument —
|
The readouts are a **table**: a header naming the columns, then one row per instrument —
|
||||||
`| who | A | B | delta |`. The first row is the two times and their difference, and the
|
`| who | A | B | delta |`. The first row is the two times and their difference, and the
|
||||||
|
|||||||
Vendored
+1
-1
Submodule deps/plotter updated: c028f48fa0...c960decaea.
@@ -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
|
• 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.
|
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
|
• 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
|
• The time row exists only in the modes that show the vertical pair. <tt>horizontal</tt> has no
|
||||||
time row, by design.
|
time row, by design.
|
||||||
|
|
||||||
|
|||||||
+16
-4
@@ -396,18 +396,30 @@ void RowSet::place_crossings() {
|
|||||||
if (ida >= r.plot->annotation_count() || idb >= r.plot->annotation_count()) continue;
|
if (ida >= r.plot->annotation_count() || idb >= r.plot->annotation_count()) continue;
|
||||||
plot::Annotation a = r.plot->annotation(ida);
|
plot::Annotation a = r.plot->annotation(ida);
|
||||||
plot::Annotation b = r.plot->annotation(idb);
|
plot::Annotation b = r.plot->annotation(idb);
|
||||||
|
double xa = 0.0;
|
||||||
double ya = 0.0;
|
double ya = 0.0;
|
||||||
|
double xb = 0.0;
|
||||||
double yb = 0.0;
|
double yb = 0.0;
|
||||||
const bool has_a = mix && r.plot->crosshair_value(static_cast<plot::u32>(s), cursor_a_x_, ya);
|
// `crosshair_point()`, not `crosshair_value()`: the number beside this dot is a *stored
|
||||||
const bool has_b = mix && r.plot->crosshair_value(static_cast<plot::u32>(s), cursor_b_x_, yb);
|
// 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;
|
a.visible = has_a;
|
||||||
b.visible = has_b;
|
b.visible = has_b;
|
||||||
if (has_a) {
|
if (has_a) {
|
||||||
a.x = cursor_a_x_;
|
a.x = xa;
|
||||||
a.y = ya;
|
a.y = ya;
|
||||||
}
|
}
|
||||||
if (has_b) {
|
if (has_b) {
|
||||||
b.x = cursor_b_x_;
|
b.x = xb;
|
||||||
b.y = yb;
|
b.y = yb;
|
||||||
}
|
}
|
||||||
r.plot->set_annotation(ida, a);
|
r.plot->set_annotation(ida, a);
|
||||||
|
|||||||
Reference in new issue
Block a user