fix(plot,glfw): layer the crosshair under the handles, sync it across a figure, and harden the lookup
This commit is contained in:
1 parent
8e27e22ebe
commit
29824b6919
5 files changed
+183
-63
No files matched your search
+19
-9
@@ -1162,23 +1162,33 @@ CrosshairSpan crosshair_span(const data::Series& series, f64 x) noexcept {
|
||||
if (x < x0 || x > newest) return span;
|
||||
|
||||
// Index arithmetic, not a search: the grid is uniform, so the sample at or before `x` is
|
||||
// `floor((x - x0) / dx)` and there is nothing to look up. Two special cases keep the span
|
||||
// honest at the ends and under rounding -- an index past the last sample collapses onto
|
||||
// it, and a `t` that rounds up to 1.0 (a query one ulp above a sample) collapses onto the
|
||||
// sample it has reached rather than reporting an interpolation of width zero.
|
||||
// `floor((x - x0) / dx)` and there is nothing to look up. The two bounds are checked
|
||||
// *before* the cast, which is also what keeps it defined: `index` is a quotient of two
|
||||
// caller-supplied doubles and can overflow to infinity for an extreme origin and spacing,
|
||||
// and casting that to `u64` is undefined. `!(index > 0.0)` is the NaN test as well.
|
||||
const f64 index = (x - x0) / dx;
|
||||
const u64 i = index <= 0.0 ? 0u : static_cast<u64>(std::floor(index));
|
||||
if (i >= n - 1u) {
|
||||
span.begin = span.end = n - 1u;
|
||||
if (!(index > 0.0)) {
|
||||
span.begin = span.end = 0u; // the oldest sample, or a rounding step below it
|
||||
span.t = 0.0;
|
||||
span.valid = true;
|
||||
return span;
|
||||
}
|
||||
if (index >= static_cast<f64>(n - 1u)) {
|
||||
span.begin = span.end = n - 1u; // the newest sample, or a step past it
|
||||
span.t = 0.0;
|
||||
span.valid = true;
|
||||
return span;
|
||||
}
|
||||
// `index` is finite and inside `(0, n-1)`, so truncating it is a floor on a value a `u64`
|
||||
// holds. Two rounding cases keep the span honest at a sample: a `t` that lands on 0 is the
|
||||
// query sitting *on* sample `i`, and one that rounds up to 1.0 is it sitting on the sample
|
||||
// after it -- neither is an interpolation with no width.
|
||||
const u64 i = static_cast<u64>(index);
|
||||
const f64 t = index - static_cast<f64>(i);
|
||||
if (!(t > 0.0)) {
|
||||
span.begin = span.end = i; // exactly on sample `i`
|
||||
span.begin = span.end = i;
|
||||
} else if (t >= 1.0) {
|
||||
span.begin = span.end = i + 1u; // exactly on the sample after it
|
||||
span.begin = span.end = i + 1u;
|
||||
} else {
|
||||
span.begin = i;
|
||||
span.end = i + 1u;
|
||||
|
||||
Reference in new issue
Block a user