14#ifndef PLOT_HEXBIN_HPP
15#define PLOT_HEXBIN_HPP
30#include "attributes.hpp"
39 struct hex {
using value_type = tag::hex_t; };
43 template <
class... opt_t>
45 using value_type = tag::view_t;
46 std::vector<double> data;
47 std::size_t rows = 0, cols = 0;
48 std::tuple<opt_t...> opts;
50 std::pair<std::size_t,std::size_t> natural()
const {
51 return std::apply([](
const auto&... o){
52 return impl::natural_size(std::size_t{560}, std::size_t{460}, o...); }, opts);
54 double at(std::size_t i, std::size_t j)
const {
return data[i*cols + j]; }
56 void draw_into(canvas_t& cv,
float x,
float y,
float w,
float h)
const {
57 std::apply([&](
const auto&... o){
58 const theme_t& th = impl::resolve_theme(o...);
59 auto [title, xl, yl] = impl::texts(o...);
60 using attribute_t = plot::attribute::element_t;
62 double lo = std::numeric_limits<double>::infinity();
63 double hi = -std::numeric_limits<double>::infinity();
64 for(
double d : data){
if(d<lo) lo=d;
if(d>hi) hi=d; }
65 if( !(lo<=hi) ){ lo=0; hi=1; }
66 const double span = (hi>lo) ? (hi-lo) : 1.0;
68 cv.group(
static_cast<std::size_t
>(x),
static_cast<std::size_t
>(y), attribute_t{},
70 { attribute_t bg; bg.color = plot::attribute::color_t{ th.bg };
71 cv.rect(0,0, w, h, 0,0, bg); }
72 float top = title.empty() ? 8.0f : 26.0f;
74 attribute_t a; a.color = plot::attribute::color_t{ th.fg };
75 a.font = plot::attribute::font_t{
"Arial, sans-serif",
"bold", 13u};
76 a.align = plot::attribute::align_t::center;
77 cv.text(title, std::size_t(w/2), std::size_t(16), a);
79 if( rows == 0 || cols == 0 )
return;
81 const float pad = 8.0f;
82 const float availW = w - 2*pad;
83 const float availH = (h - top) - 2*pad;
88 const float sqrt3 = 1.7320508075688772f;
89 float rW = availW / (sqrt3 * (float(cols) + 0.5f));
90 float rH = availH / (1.5f * float(rows) + 0.5f);
91 float r = std::max(2.0f, std::min(rW, rH));
92 float hpitch = sqrt3 * r;
93 float vpitch = 1.5f * r;
94 float ox = pad + hpitch*0.5f;
95 float oy = top + pad + r;
97 for(std::size_t i=0;i<rows;++i)
98 for(std::size_t j=0;j<cols;++j){
99 float cx = ox + float(j)*hpitch + ((i & 1) ? hpitch*0.5f : 0.0f);
100 float cy = oy + float(i)*vpitch;
101 double t = (at(i,j) - lo)/span;
102 std::uint32_t col = impl::gradient3(th.gradient, t);
104 std::vector<float> X, Y;
105 for(
int k=0;k<6;++k){
106 double a = (3.141592653589793/180.0)*(60.0*
double(k) + 30.0);
107 X.push_back(cx + r*
float(std::cos(a)));
108 Y.push_back(cy + r*
float(std::sin(a)));
110 X.push_back(X.front()); Y.push_back(Y.front());
111 attribute_t ha; ha.color = plot::attribute::color_t{ col };
112 ha.stroke = plot::attribute::stroke_t{1.0f, 1.0f, {}, {}, {}};
113 cv.polygon(X, Y, ha);
122 template <
class T,
class... opt_t,
123 class = std::enable_if_t<std::is_arithmetic_v<T>>>
124 impl::hexbin_view<opt_t...> hexbin(
const mat<T>& grid, opt_t... opts){
125 impl::hexbin_view<opt_t...> v{ {}, grid.rows, grid.cols, std::make_tuple(opts...) };
126 v.data.assign(grid.begin(), grid.end());