figure: rows can hold several plots (cells), cell weights and column gap
This commit is contained in:
1 parent
f79a97be9b
commit
7d8c453232
4 files changed
+341
-31
No files matched your search
@@ -16,6 +16,7 @@
|
||||
#include <plot/render/embedded_mono_font.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
@@ -1141,3 +1142,136 @@ PLOT_TEST(figure_crosshair_draws_a_horizontal_line_only_in_the_hovered_row) {
|
||||
PLOT_CHECK(figure.plot(1u).layout().crosshair.vertical.w > 0.0f);
|
||||
PLOT_CHECK(figure.plot(1u).layout().crosshair.horizontal.h == 0.0f);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ cell grid
|
||||
|
||||
namespace {
|
||||
|
||||
/// A figure whose rows hold `cells[r]` plots each (the flattened plots in row-major
|
||||
/// order), with an x and a y axis on every plot unless `axes` is off.
|
||||
plot::Figure split_figure(const std::vector<plot::u32>& cells, bool axes = true) {
|
||||
plot::Figure figure{std::span<const plot::u32>(cells)}; // braces: parentheses would be a vexing parse
|
||||
figure.set_viewport(whole_figure());
|
||||
if (axes) {
|
||||
for (plot::u32 i = 0; i < figure.plot_count(); ++i) {
|
||||
figure.plot(i).add_x_axis({"t", {0.0, 100.0}, false, plot::AxisPlace::Bottom, false});
|
||||
figure.plot(i).add_y_axis({"v", {-1.0, 1.0}, false, plot::AxisPlace::Left, false});
|
||||
}
|
||||
}
|
||||
return figure;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PLOT_TEST(figure_cells_all_ones_equals_rows) {
|
||||
plot::Figure split = split_figure({1, 1, 1});
|
||||
plot::Figure plain = figure_with_axes(3u);
|
||||
const plot::FigureLayout& sl = split.layout();
|
||||
const plot::FigureLayout& pl = plain.layout();
|
||||
PLOT_CHECK(split.row_count() == 3u && split.plot_count() == 3u);
|
||||
PLOT_CHECK(sl.cells.size() == 3u);
|
||||
for (plot::u32 i = 0; i < 3u; ++i) {
|
||||
PLOT_CHECK_NEAR(sl.cells[i].y, pl.rows[i].y, 0.01);
|
||||
PLOT_CHECK_NEAR(sl.cells[i].h, pl.rows[i].h, 0.01);
|
||||
PLOT_CHECK_NEAR(sl.cells[i].w, pl.rows[i].w, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
PLOT_TEST(figure_cells_tile_exactly) {
|
||||
plot::Figure figure = split_figure({1, 2, 1});
|
||||
figure.set_col_gap(10.0f);
|
||||
const plot::FigureLayout& fl = figure.layout();
|
||||
PLOT_CHECK(figure.row_count() == 3u && figure.plot_count() == 4u);
|
||||
PLOT_CHECK(figure.cells_in_row(1u) == 2u);
|
||||
PLOT_CHECK(figure.first_plot_of_row(1u) == 1u && figure.first_plot_of_row(3u) == 4u);
|
||||
PLOT_CHECK(figure.row_of_plot(2u) == 1u);
|
||||
PLOT_CHECK_NEAR(fl.cells[2].x - fl.cells[1].right(), 10.0, 0.01);
|
||||
PLOT_CHECK_NEAR(fl.cells[2].right(), fl.rows[1].right(), 0.001);
|
||||
PLOT_CHECK_NEAR(fl.cells[1].x, fl.rows[1].x, 0.001);
|
||||
PLOT_CHECK_NEAR(fl.cells[1].y, fl.cells[2].y, 0.001);
|
||||
PLOT_CHECK_NEAR(fl.cells[1].h, fl.cells[2].h, 0.001);
|
||||
PLOT_CHECK_NEAR(fl.cells[1].w, fl.cells[2].w, 0.01);
|
||||
PLOT_CHECK_NEAR(fl.col_gap, 10.0, 0.001);
|
||||
}
|
||||
|
||||
PLOT_TEST(figure_cell_weights_and_floor) {
|
||||
plot::Figure figure = split_figure({2});
|
||||
figure.set_col_gap(0.0f);
|
||||
const std::vector<plot::f32> w{3.0f, 1.0f};
|
||||
PLOT_CHECK(figure.set_cell_weights(0u, w));
|
||||
PLOT_CHECK(figure.has_cell_weights(0u));
|
||||
{
|
||||
const auto& c = figure.layout().cells;
|
||||
PLOT_CHECK_NEAR((c[0].w - 64.0), (c[1].w - 64.0) * 3.0, 0.01);
|
||||
}
|
||||
const std::vector<plot::f32> tiny{1000.0f, 0.001f};
|
||||
PLOT_CHECK(figure.set_cell_weights(0u, tiny));
|
||||
PLOT_CHECK(figure.layout().cells[1].w >= 64.0f - 0.001f);
|
||||
const std::vector<plot::f32> three{1.0f, 1.0f, 1.0f};
|
||||
const std::vector<plot::f32> zero{1.0f, 0.0f};
|
||||
PLOT_CHECK(!figure.set_cell_weights(0u, three));
|
||||
PLOT_CHECK(!figure.set_cell_weights(0u, zero));
|
||||
PLOT_CHECK(!figure.set_cell_weights(5u, w));
|
||||
figure.clear_cell_weights(0u);
|
||||
PLOT_CHECK(!figure.has_cell_weights(0u));
|
||||
const auto& c = figure.layout().cells;
|
||||
PLOT_CHECK_NEAR(c[0].w, c[1].w, 0.01);
|
||||
}
|
||||
|
||||
PLOT_TEST(figure_cells_narrow_degrades) {
|
||||
plot::Figure figure = split_figure({4}, false);
|
||||
figure.set_viewport(plot::Rect{0.0f, 0.0f, 20.0f, 100.0f});
|
||||
for (plot::u32 i = 0; i < 4u; ++i) {
|
||||
figure.plot(i).add_x_axis({"t", {0.0, 100.0}, false, plot::AxisPlace::Bottom, false});
|
||||
figure.plot(i).add_y_axis({"v", {-1.0, 1.0}, false, plot::AxisPlace::Left, false});
|
||||
}
|
||||
figure.set_col_gap(10.0f);
|
||||
const plot::FigureLayout& fl = figure.layout();
|
||||
double sum = 0.0;
|
||||
for (const plot::Rect& c : fl.cells) {
|
||||
PLOT_CHECK(c.w >= 0.0f && c.h >= 0.0f);
|
||||
PLOT_CHECK_NEAR(c.h, 100.0, 0.01);
|
||||
sum += c.w;
|
||||
}
|
||||
PLOT_CHECK_NEAR(sum, 20.0, 0.01);
|
||||
PLOT_CHECK_NEAR(fl.col_gap, 0.0, 0.001);
|
||||
}
|
||||
|
||||
PLOT_TEST(figure_cells_share_x_link_and_crosshair) {
|
||||
plot::Figure figure = split_figure({2, 1});
|
||||
const plot::u32 group = figure.add_x_link();
|
||||
for (plot::u32 i = 0; i < 3u; ++i) PLOT_CHECK(figure.link_x(i, group));
|
||||
figure.plot(1u).set_x_range(0u, {3.0, 9.0});
|
||||
figure.layout();
|
||||
for (plot::u32 i = 0; i < 3u; ++i) {
|
||||
PLOT_CHECK_NEAR(figure.plot(i).x_range(0u).min, 3.0, 1e-9);
|
||||
PLOT_CHECK_NEAR(figure.plot(i).x_range(0u).max, 9.0, 1e-9);
|
||||
}
|
||||
figure.set_crosshair(4.0, true);
|
||||
for (plot::u32 i = 0; i < 3u; ++i) {
|
||||
PLOT_CHECK(figure.plot(i).crosshair().active);
|
||||
PLOT_CHECK_NEAR(figure.plot(i).crosshair().x, 4.0, 1e-9);
|
||||
}
|
||||
figure.clear_crosshair();
|
||||
for (plot::u32 i = 0; i < 3u; ++i) PLOT_CHECK(!figure.plot(i).crosshair().active);
|
||||
}
|
||||
|
||||
PLOT_TEST(figure_cells_x_labels_bottom_row_only) {
|
||||
plot::Figure figure = split_figure({1, 2});
|
||||
const plot::FigureLayout& fl = figure.layout();
|
||||
PLOT_CHECK(figure.plot(0u).layout().x_label_area.h == 0.0f);
|
||||
PLOT_CHECK(figure.plot(1u).layout().x_label_area.h > 0.0f);
|
||||
PLOT_CHECK(figure.plot(2u).layout().x_label_area.h > 0.0f);
|
||||
PLOT_CHECK_NEAR(fl.x_axis_strip.h, figure.plot(2u).layout().x_label_area.h, 0.001);
|
||||
}
|
||||
|
||||
PLOT_TEST(figure_cells_common_y_gutter) {
|
||||
plot::Figure figure = split_figure({2}, false);
|
||||
give_magnitude_row(figure.plot(0u), 0u);
|
||||
give_magnitude_row(figure.plot(1u), 1u);
|
||||
const plot::FigureLayout& fl = figure.layout();
|
||||
const double g0 = figure.plot(0u).layout().axes.x - fl.cells[0].x;
|
||||
const double g1 = figure.plot(1u).layout().axes.x - fl.cells[1].x;
|
||||
PLOT_CHECK(g0 > 0.0);
|
||||
PLOT_CHECK_NEAR(g0, g1, 0.01);
|
||||
}
|
||||
Reference in new issue
Block a user