fix(data): the gather origin is the caller's, so a deep zoom draws on the sample
`Series::gather()` stages x as f32 relative to `x0()` -- the start of the *retained window* -- so the value's ULP was a fraction of data the view need not even hold: 1.9 us over a 20 s ring. A readout quotes `x_at()` in exact f64, so at a 10 us view across 700 px that put more than a hundred pixels between where a sample is drawn and the x reported for it. The origin is now a parameter, placed before `out_xy` so every call site is a type error rather than a silent change of behaviour. `Renderer::draw_traces` passes the visible range's minimum, which makes the error a fixed 2^-24 of the span on screen -- 4e-5 of a pixel over a 700 px axis -- at every zoom. `stage_xy()` loses its second origin as a consequence: the gather origin and the draw origin are now always the same value, so the linear case hands the gathered buffer straight to `add_polyline_xy()` with no per-point copy. `Plot::crosshair_point()` names the query itself, the one origin that cannot lose precision for a caller that might. Guarded by `a_gather_origin_at_the_view_keeps_a_deep_zoom_on_the_sample_it_quotes`, which measures the error in pixels both ways: under 0.05 px with the view's minimum, over 10 px with `x0()`.
This commit is contained in:
1 parent
59c2e45af7
commit
c2c8c596f3
15 files changed
+150
-95
No files matched your search
@@ -723,11 +723,11 @@ class LyingGridSeries final : public plot::data::Series {
|
||||
if (x_at(i0) != x && i0 + 1u < kN) i1 = i0 + 1u;
|
||||
return true;
|
||||
}
|
||||
void gather(u32, u64 begin, u64 end, std::vector<f32>& out,
|
||||
void gather(u32, u64 begin, u64 end, f64 x_origin, std::vector<f32>& out,
|
||||
plot::data::GatherMode) const override {
|
||||
++gather_calls_;
|
||||
for (u64 i = begin; i < end; ++i) {
|
||||
out.push_back(static_cast<f32>(x_at(i) - x0()));
|
||||
out.push_back(static_cast<f32>(x_at(i) - x_origin));
|
||||
out.push_back(kY);
|
||||
}
|
||||
}
|
||||
@@ -1512,9 +1512,10 @@ PLOT_TEST(a_clamped_front_does_not_draw_a_segment_across_the_panel) {
|
||||
if (x_at(k) != x && k + 1u < 8u) i1 = k + 1u;
|
||||
return true;
|
||||
}
|
||||
void gather(u32, u64 begin, u64 end, std::vector<f32>& out, plot::data::GatherMode) const override {
|
||||
void gather(u32, u64 begin, u64 end, f64 x_origin, std::vector<f32>& out,
|
||||
plot::data::GatherMode) const override {
|
||||
for (u64 i = begin; i < end; ++i) {
|
||||
out.push_back(static_cast<f32>(x_at(i) - x0()));
|
||||
out.push_back(static_cast<f32>(x_at(i) - x_origin));
|
||||
out.push_back(i < 2u ? -1.0f : 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user