Files
plotter/src/plot/grid.cpp
T

46 lines
1.6 KiB
C++

#include <plot/plot/grid.hpp>
#include <algorithm>
#include <cmath>
namespace plot {
namespace {
/// True when `v` lies in `r`, allowing the rounding slack a generated tick can
/// carry at the range's edge: a tick that is within 1e-9 relative of the edge is
/// the edge, and dropping it would leave the frame un-drawn.
bool inside(f64 v, Range r) noexcept {
const f64 tolerance = std::max(std::fabs(r.min), std::fabs(r.max)) * 1e-9 + 1e-12;
return v >= r.min - tolerance && v <= r.max + tolerance;
}
} // namespace
void Grid::build(const std::vector<Tick>& x_ticks, Range x_range,
const std::vector<Tick>& y_ticks, Range y_range) {
lines_.clear();
if (!std::isfinite(x_range.min) || !std::isfinite(x_range.max) ||
!std::isfinite(y_range.min) || !std::isfinite(y_range.max)) {
return;
}
// Segments stay in data space: the renderer applies the transform, so a pan or
// zoom needs no grid rebuild other than for a changed tick set.
if (vertical) {
for (const Tick& tick : x_ticks) {
if (!tick.major && !show_minor) continue;
if (!std::isfinite(tick.value) || !inside(tick.value, x_range)) continue;
lines_.push_back(GridLine{tick.value, y_range.min, tick.value, y_range.max, tick.major});
}
}
if (horizontal) {
for (const Tick& tick : y_ticks) {
if (!tick.major && !show_minor) continue;
if (!std::isfinite(tick.value) || !inside(tick.value, y_range)) continue;
lines_.push_back(GridLine{x_range.min, tick.value, x_range.max, tick.value, tick.major});
}
}
}
} // namespace plot