fix(figure): a following group keeps its whole window on the data
The offset of a following group was clamped to `retained` -- measured from the newest sample -- so a pan (or a zoom-in anchored near an edge) could put the window's *right* edge exactly on the oldest retained sample. That leaves the window's entire span to its left over data the scope never had: an empty margin as wide as the view. The bound is about the whole window, so it is `retained - span` -- but only while the window *can* sit on the data. When the members retain less than a window's worth (a ring still filling, or one just trimmed) nothing avoids a margin, and the older placement is the honest one and stays: right edge on the newest sample, the shortfall on the left. Test: a_following_group_keeps_its_whole_window_on_the_data -- asks to scroll ten spans past the oldest sample and asserts the window is still a window, with its left edge on the data. The existing `a_following_log_group_holds_decades` codified the old bound (`max == edge/10` after asking for a decade of pan with far less than that retained); its log-space subject is unchanged and the offset assertion is now the invariant above.
This commit is contained in:
1 parent
7dbe4e7183
commit
faef19ba60
4 files changed
+71
-6
No files matched your search
@@ -1788,6 +1788,47 @@ PLOT_TEST(a_middle_drag_on_a_figures_bottom_row_zooms_the_shared_x_axis) {
|
||||
// pointer) rather than on the live edge, and the window walked back off the newest sample
|
||||
// by a fifth of its width. These two cases pin the fix from the two ends: the gesture keeps
|
||||
// the edge, and the hint that makes it possible exists exactly while a group follows.
|
||||
/// A following group's window stays **on the data**: the offset bound is `retained - span`, not
|
||||
/// `retained`. With the loose bound, scrolling back put the window's *right* edge on the oldest
|
||||
/// retained sample, which leaves the window's whole span to its left over data the scope never
|
||||
/// had -- an empty margin as wide as the view, reached by a pan or by a zoom-in near that edge.
|
||||
/// That is the "sometimes zooming in, the left or right margin becomes empty" report, and it is
|
||||
/// why the bound has to be about the window and not about one edge of it.
|
||||
PLOT_TEST(a_following_group_keeps_its_whole_window_on_the_data) {
|
||||
plot::data::StreamSeries series(1u << 12, 0.0, 1.0 / 1000.0);
|
||||
plot::f32 samples[512];
|
||||
for (u32 i = 0; i < 512u; ++i) samples[i] = static_cast<plot::f32>(i % 7u);
|
||||
series.push(samples, 512u);
|
||||
series.acquire();
|
||||
|
||||
plot::Figure figure(1u);
|
||||
figure.set_viewport({0.0f, 0.0f, 800.0f, 600.0f});
|
||||
figure.plot(0u).add_x_axis({"t", {0.0, 1.0}, false, plot::AxisPlace::Bottom, false});
|
||||
figure.plot(0u).add_y_axis({"v", {-1.0, 1.0}, false, plot::AxisPlace::Left, false});
|
||||
figure.plot(0u).add_trace({&series, plot::Color::hex(0x4FA3FF), 1.5f, 0u, 0u, "s"});
|
||||
const u32 group = figure.add_x_link();
|
||||
PLOT_CHECK(figure.link_x(0u, group));
|
||||
PLOT_CHECK(figure.set_x_link_range(group, {0.0, 0.25}));
|
||||
PLOT_CHECK(figure.set_x_link_follow(group, plot::XFollow::Live));
|
||||
figure.layout();
|
||||
|
||||
const plot::Range data = series.x_bounds();
|
||||
const f64 span = figure.x_link_range(group).span();
|
||||
PLOT_CHECK(span > 0.0);
|
||||
// Ask to scroll far past the oldest sample, the way a drag or a zoom-in near the left edge does.
|
||||
PLOT_CHECK(figure.set_x_link_range(group, {data.min - 10.0 * span, data.min - 9.0 * span}));
|
||||
figure.layout();
|
||||
|
||||
const plot::Range after = figure.x_link_range(group);
|
||||
std::printf("[follow-bound] data=[%.4f..%.4f] span=%.4f after=[%.4f..%.4f]\n", data.min,
|
||||
data.max, span, after.min, after.max);
|
||||
// The window is still a window, and its *left* edge is on the data: that is the assertion the
|
||||
// loose bound failed, where `after.min` came out a whole span below `data.min`.
|
||||
PLOT_CHECK_NEAR(after.span(), span, 1e-9 * span);
|
||||
PLOT_CHECK(after.min >= data.min - 1e-9);
|
||||
PLOT_CHECK(after.max <= data.max + 1e-9);
|
||||
}
|
||||
|
||||
PLOT_TEST(a_wheel_on_a_following_figures_axis_strip_keeps_the_live_edge) {
|
||||
constexpr u32 kFigureRows = 3u;
|
||||
constexpr f64 kWheelDx = 1.0 / 1000.0;
|
||||
|
||||
Reference in new issue
Block a user