author | Francesco Abbate <francesco.bbt@gmail.com> | 2013年01月30日 18:16:12 +0100 |
---|---|---|
committer | Francesco Abbate <francesco.bbt@gmail.com> | 2013年02月03日 22:30:35 +0100 |
commit | a366fbb4d0ede381163976dc46d39ab4a1e9fdba (patch) | |
tree | 95e1e5beb1e77bb31fc6c1a843409081c10bae45 /agg-plot | |
parent | 44b1bffb2220da2220aee2588143e11026e10083 (diff) | |
download | gsl-shell-a366fbb4d0ede381163976dc46d39ab4a1e9fdba.tar.gz |
-rw-r--r-- | agg-plot/factor_labels.h | 28 | ||||
-rw-r--r-- | agg-plot/lua-plot.cpp | 40 | ||||
-rw-r--r-- | agg-plot/plot.h | 102 | ||||
-rw-r--r-- | agg-plot/units.h | 1 | ||||
-rw-r--r-- | agg-plot/utils.h | 4 |
diff --git a/agg-plot/factor_labels.h b/agg-plot/factor_labels.h new file mode 100644 index 00000000..27f6ef47 --- /dev/null +++ b/agg-plot/factor_labels.h @@ -0,0 +1,28 @@ +#include "agg_array.h" +#include "utils.h" +#include "strpp.h" + +class factor_labels +{ +public: + factor_labels(double delta): m_mark_delta(delta) {} + + double mark(int k) const { return m_mark_index[k] * m_mark_delta; } + const char *label_text(int k) const { return m_label_text[k]->cstr(); } + int labels_number() const { return m_label_text.size(); } + + void add_mark(int index, const char *text) + { + m_mark_index.add(index); + if (text) + { + str* text_str = new str(text); + m_label_text.add(text_str); + } + } + +private: + double m_mark_delta; + agg::pod_bvector<short> m_mark_index; + ptr_list<str> m_label_text; +}; diff --git a/agg-plot/lua-plot.cpp b/agg-plot/lua-plot.cpp index 42961d46..7194a0b3 100644 --- a/agg-plot/lua-plot.cpp +++ b/agg-plot/lua-plot.cpp @@ -70,6 +70,7 @@ static int plot_ylab_angle_get (lua_State *L); static int plot_set_categories (lua_State *L); static int plot_set_legend (lua_State *L); static int plot_get_legend (lua_State *L); +static int plot_xaxis_hol_set (lua_State *L); static int plot_sync_mode_get (lua_State *L); static int plot_sync_mode_set (lua_State *L); @@ -109,6 +110,7 @@ static const struct luaL_Reg plot_methods[] = { {"set_categories", plot_set_categories}, {"set_legend", plot_set_legend}, {"get_legend", plot_get_legend}, + {"set_hol", plot_xaxis_hol_set}, {NULL, NULL} }; @@ -467,6 +469,44 @@ plot_units_get (lua_State *L) return plot_bool_property_get(L, &sg_plot::use_units); } +int plot_xaxis_hol_set (lua_State *L) +{ + sg_plot *p = object_check<sg_plot>(L, 1, GS_PLOT); + double delta = lua_tonumber(L, 2); + + if (!lua_istable(L, 3)) + return luaL_error(L, "expect labels table specification"); + + ptr_list<factor_labels>* hol = p->get_xaxis_hol(); + bool create_hol = (hol == 0); + if (create_hol) + hol = new ptr_list<factor_labels>(); + + factor_labels* fl = new factor_labels(delta); + int n = lua_objlen(L, 3); + for (int k = 1; k <= n; k += 2) + { + lua_rawgeti(L, 3, k); + int idx = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_rawgeti(L, 3, k + 1); + const char* str = lua_tostring(L, -1); + fl->add_mark(idx, str); + lua_pop(L, 1); + + if (!str) + break; + } + + hol->add(fl); + + if (create_hol) + p->set_xaxis_hol(hol); + + return 0; +} + void plot_update_raw (lua_State *L, sg_plot *p, int plot_index) { diff --git a/agg-plot/plot.h b/agg-plot/plot.h index 06d0d35a..49a61587 100644 --- a/agg-plot/plot.h +++ b/agg-plot/plot.h @@ -36,6 +36,7 @@ #include "text.h" #include "categories.h" #include "sg_object.h" +#include "factor_labels.h" #include "agg_array.h" #include "agg_bounding_rect.h" @@ -239,7 +240,8 @@ public: m_drawing_queue(0), m_clip_flag(true), m_need_redraw(true), m_rect(), m_use_units(use_units), m_pad_units(false), m_title(), - m_sync_mode(true), m_x_axis(x_axis), m_y_axis(y_axis) + m_sync_mode(true), m_x_axis(x_axis), m_y_axis(y_axis), + m_xaxis_hol(0) { m_layers.add(&m_root_layer); compute_user_trans(); @@ -256,6 +258,8 @@ public: if (k > 0) delete layer; } + + delete m_xaxis_hol; }; str& title() { @@ -301,6 +305,14 @@ public: void set_limits(const agg::rect_base<double>& r); void unset_limits(); + ptr_list<factor_labels>* get_xaxis_hol() { return m_xaxis_hol; } + + void set_xaxis_hol(ptr_list<factor_labels>* hol) + { + delete m_xaxis_hol; + m_xaxis_hol = hol; + } + virtual void add(sg_object* vs, agg::rgba8& color, bool outline); virtual void before_draw() { } @@ -421,6 +433,11 @@ protected: ptr_list<draw::text>& labels, double scale, agg::path_storage& mark, agg::path_storage& ln); + double draw_xaxis_factors(units& u, const agg::trans_affine& user_mtx, + ptr_list<draw::text>& labels, + ptr_list<factor_labels>* f_labels, double scale, + agg::path_storage& mark, agg::path_storage& ln); + void draw_elements(canvas_type &canvas, const plot_layout& layout); void draw_element(item& c, canvas_type &canvas, const agg::trans_affine& m); void draw_axis(canvas_type& can, plot_layout& layout, const agg::rect_i* clip = 0); @@ -486,6 +503,8 @@ private: axis m_x_axis, m_y_axis; plot* m_legend[4]; + + ptr_list<factor_labels>* m_xaxis_hol; }; static double compute_scale(const agg::trans_affine& m) @@ -695,6 +714,7 @@ double plot<RM>::draw_axis_m(axis_e dir, units& u, const double text_label_size = get_default_font_size(text_axis_labels, scale); const double eps = 1.0e-3; + // used to store the bounding box of text labels opt_rect<double> bb; agg::rect_base<double> r; @@ -764,6 +784,77 @@ double plot<RM>::draw_axis_m(axis_e dir, units& u, return label_size; } +template <class RM> +double plot<RM>::draw_xaxis_factors(units& u, + const agg::trans_affine& user_mtx, + ptr_list<draw::text>& labels, + ptr_list<factor_labels>* f_labels, double scale, + agg::path_storage& mark, agg::path_storage& ln) +{ + const double text_label_size = get_default_font_size(text_axis_labels, scale); + const double eps = 1.0e-3; + + const double y_spacing = 0.05; + const unsigned layers_number = f_labels->size(); + double p_lab = - double(layers_number) * y_spacing; + for (unsigned layer = 0; layer < layers_number; layer++) + { + factor_labels* factor = f_labels->at(layer); + for (int k = 0; k < factor->labels_number(); k++) + { + double x_lab_a = factor->mark(k); + double x_lab_b = factor->mark(k+1); + + double x_a = x_lab_a, y_a = 0.0; + user_mtx.transform(&x_a, &y_a); + double q_a = x_a; + + double x_lab = (x_lab_a + x_lab_b) / 2, y_lab = 0.0; + user_mtx.transform(&x_lab, &y_lab); + double q_lab = x_lab; + + mark.move_to(q_a, p_lab); + mark.line_to(q_a, p_lab + y_spacing); + + const char* text = factor->label_text(k); + draw::text* label = new draw::text(text, text_label_size, 0.5, -0.2); + + label->set_point(q_lab, p_lab); + label->angle(0.0); + + labels.add(label); + } + + double x_lab = factor->mark(layers_number); + double x_a = x_lab, y_a = 0.0; + user_mtx.transform(&x_a, &y_a); + double q_a = x_a; + mark.move_to(q_a, p_lab); + mark.line_to(q_a, p_lab + y_spacing); + + p_lab += y_spacing; + } + + // NB: IMPORTANT + // the following code should be factored in a separate routine + int jinf = u.begin(), jsup = u.end(); + for (int j = jinf+1; j < jsup; j++) + { + double uq = u.mark_value(j); + double x = uq, y = 0.0; + user_mtx.transform(&x, &y); + double q = x; + + if (q >= -eps && q <= 1.0 + eps) + { + ln.move_to(q, 0.0); + ln.line_to(q, 1.0); + } + } + + return y_spacing * layers_number; +} + static inline double approx_text_height(double text_size) { return text_size * 1.5; @@ -936,11 +1027,16 @@ void plot<RM>::draw_axis(canvas_type& canvas, plot_layout& layout, const agg::re ptr_list<draw::text> labels; - double dy_label = draw_axis_m(x_axis, m_ux, m_trans, labels, scale, mark, ln); + double dy_label = 0, pdy_label = 0; + if (this->m_xaxis_hol) + pdy_label = draw_xaxis_factors(m_ux, m_trans, labels, this->m_xaxis_hol, scale, mark, ln); + else + dy_label = draw_axis_m(x_axis, m_ux, m_trans, labels, scale, mark, ln); + double dx_label = draw_axis_m(y_axis, m_uy, m_trans, labels, scale, mark, ln); double ppad_left = plpad, ppad_right = plpad; - double ppad_bottom = plpad, ppad_top = plpad; + double ppad_bottom = plpad + pdy_label, ppad_top = plpad; double dx_left = dx_label, dx_right = 0.0; double dy_bottom = dy_label, dy_top = 0.0; diff --git a/agg-plot/units.h b/agg-plot/units.h index f315d804..b929e38d 100644 --- a/agg-plot/units.h +++ b/agg-plot/units.h @@ -90,7 +90,6 @@ public: val = m_units.mark_value(m_index); text = m_buffer; - text = m_buffer; m_index ++; return true; } diff --git a/agg-plot/utils.h b/agg-plot/utils.h index d1274d32..1e66be31 100644 --- a/agg-plot/utils.h +++ b/agg-plot/utils.h @@ -40,6 +40,10 @@ public: return m_list[k]; } + T* at(unsigned k) const { + return m_list[k]; + } + unsigned size() const { return m_list.size(); } |