Merge branch 'factor-labels' into gdt-new - gsl-shell.git - gsl-shell

index : gsl-shell.git
gsl-shell
summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrancesco Abbate <francesco.bbt@gmail.com>2013年02月04日 21:46:49 +0100
committerFrancesco Abbate <francesco.bbt@gmail.com>2013年02月04日 21:46:49 +0100
commit858c66cac8902ad7fd32d10ae82bb885f9774904 (patch)
treed9d5e118f3cc21336da56263470a6ffd3462f47d
parentfe5cea0c67ac178d6476beb64f2bd5fcf4acb0f0 (diff)
parent9b63ca608ee573a2588ad14a3a46a5ca9f00f9a2 (diff)
downloadgsl-shell-858c66cac8902ad7fd32d10ae82bb885f9774904.tar.gz
Merge branch 'factor-labels' into gdt-new
Diffstat
-rw-r--r--.gitignore 1
-rw-r--r--agg-plot/Makefile 2
-rw-r--r--agg-plot/factor_labels.h 28
-rw-r--r--agg-plot/lua-plot-cpp.h 4
-rw-r--r--agg-plot/lua-plot.cpp 54
-rw-r--r--agg-plot/plot-auto.cpp 114
-rw-r--r--agg-plot/plot-auto.h 134
-rw-r--r--agg-plot/plot.cpp 660
-rw-r--r--agg-plot/plot.h 645
-rw-r--r--agg-plot/units.h 1
-rw-r--r--agg-plot/utils.h 4
-rw-r--r--fox-gui/lua_plot_window.cpp 2
-rw-r--r--iter.lua 14
-rw-r--r--matrix.lua 23
-rwxr-xr-xscripts/dos2unix.py 34
-rw-r--r--scripts/enum2lua.py 12
16 files changed, 973 insertions, 759 deletions
diff --git a/.gitignore b/.gitignore
index 5ddc7521..83d1718f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
*.dll
luajit2/lib/vmdef.lua
*~
+*.sublime*
gsl-shell
gsl-shell.exe
.deps
diff --git a/agg-plot/Makefile b/agg-plot/Makefile
index f68b3cd8..5f2c1a48 100644
--- a/agg-plot/Makefile
+++ b/agg-plot/Makefile
@@ -39,7 +39,7 @@ endif
INCLUDES += $(FREETYPE_INCLUDES) $(AGG_INCLUDES) -I$(GSH_BASE_DIR) -I$(GSH_BASE_DIR)/lua-gsl -I$(LUADIR)/src -I$(GSH_BASE_DIR)/cpp-utils
-AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) printf_check.cpp fonts.cpp gamma.cpp agg_font_freetype.cpp utils.cpp units.cpp colors.cpp markers.cpp draw_svg.cpp canvas_svg.cpp lua-draw.cpp lua-text.cpp text.cpp agg-parse-trans.cpp window_registry.cpp window.cpp lua-plot.cpp canvas-window.cpp bitmap-plot.cpp lua-graph.cpp
+AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) printf_check.cpp fonts.cpp gamma.cpp agg_font_freetype.cpp plot.cpp plot-auto.cpp utils.cpp units.cpp colors.cpp markers.cpp draw_svg.cpp canvas_svg.cpp lua-draw.cpp lua-text.cpp text.cpp agg-parse-trans.cpp window_registry.cpp window.cpp lua-plot.cpp canvas-window.cpp bitmap-plot.cpp lua-graph.cpp
AGGPLOT_OBJ_FILES := $(AGGPLOT_SRC_FILES:%.cpp=%.o)
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.h b/agg-plot/lua-plot-cpp.h
index 5f92e499..0aa7bca4 100644
--- a/agg-plot/lua-plot-cpp.h
+++ b/agg-plot/lua-plot-cpp.h
@@ -10,7 +10,7 @@ extern "C" {
#include "plot-auto.h"
#include "resource-manager.h"
-typedef plot<manage_owner> sg_plot;
-typedef plot_auto<manage_owner> sg_plot_auto;
+typedef plot sg_plot;
+typedef plot_auto sg_plot_auto;
#endif
diff --git a/agg-plot/lua-plot.cpp b/agg-plot/lua-plot.cpp
index 42961d46..5053dbaa 100644
--- a/agg-plot/lua-plot.cpp
+++ b/agg-plot/lua-plot.cpp
@@ -70,6 +70,8 @@ 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_xaxis_hol_clear(lua_State *L);
static int plot_sync_mode_get (lua_State *L);
static int plot_sync_mode_set (lua_State *L);
@@ -109,6 +111,8 @@ static const struct luaL_Reg plot_methods[] = {
{"set_categories", plot_set_categories},
{"set_legend", plot_set_legend},
{"get_legend", plot_get_legend},
+ {"set_multi_labels", plot_xaxis_hol_set},
+ {"clear_multi_labels", plot_xaxis_hol_clear},
{NULL, NULL}
};
@@ -467,6 +471,56 @@ 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;
+ }
+
+ AGG_LOCK();
+ hol->add(fl);
+ if (create_hol)
+ p->set_xaxis_hol(hol);
+ AGG_UNLOCK();
+
+ plot_update_raw (L, p, 1);
+ return 0;
+}
+
+int plot_xaxis_hol_clear (lua_State *L)
+{
+ sg_plot *p = object_check<sg_plot>(L, 1, GS_PLOT);
+ AGG_LOCK();
+ p->set_xaxis_hol(0);
+ AGG_UNLOCK();
+ plot_update_raw (L, p, 1);
+ return 0;
+}
+
void
plot_update_raw (lua_State *L, sg_plot *p, int plot_index)
{
diff --git a/agg-plot/plot-auto.cpp b/agg-plot/plot-auto.cpp
new file mode 100644
index 00000000..e7ae8869
--- /dev/null
+++ b/agg-plot/plot-auto.cpp
@@ -0,0 +1,114 @@
+#include "plot-auto.h"
+
+void plot_auto::add(sg_object* vs, agg::rgba8& color, bool outline)
+{
+ item d(vs, color, outline);
+
+ if (!this->fit_inside(vs))
+ {
+ this->m_bbox_updated = false;
+ this->m_need_redraw = true;
+ this->m_enlarged_layer = true;
+ }
+
+ list<item> *nn = new list<item>(d);
+ this->m_drawing_queue = list<item>::push_back(this->m_drawing_queue, nn);
+
+ RM::acquire(vs);
+}
+
+void plot_auto::check_bounding_box()
+{
+ this->calc_bounding_box();
+ this->update_units();
+ this->m_bbox_updated = true;
+}
+
+void plot_auto::calc_layer_bounding_box(plot_auto::item_list* layer,
+ opt_rect<double>& rect)
+{
+ for (unsigned j = 0; j < layer->size(); j++)
+ {
+ item& d = (*layer)[j];
+ agg::rect_base<double> r;
+
+ d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
+ rect.add<rect_union>(r);
+ }
+}
+
+void plot_auto::calc_bounding_box()
+{
+ opt_rect<double> box;
+
+ unsigned n = this->nb_layers();
+ for (unsigned j = 0; j < n-1; j++)
+ {
+ box.add<rect_union>(this->get_layer(j)->bounding_box());
+ }
+
+ calc_layer_bounding_box(this->get_layer(n-1), box);
+ for (list<item> *t = this->m_drawing_queue; t; t = t->next())
+ {
+ const item& d = t->content();
+ agg::rect_base<double> r;
+ d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
+ box.add<rect_union>(r);
+ }
+
+ this->m_rect = box;
+}
+
+bool plot_auto::fit_inside(sg_object* obj) const
+{
+ if (!this->m_bbox_updated || !this->m_rect.is_defined())
+ return false;
+
+ agg::rect_base<double> r;
+ obj->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
+
+ const agg::rect_base<double>& bb = this->m_rect.rect();
+ return bb.hit_test(r.x1, r.y1) && bb.hit_test(r.x2, r.y2);
+}
+
+void plot_auto::set_opt_limits(const opt_rect<double>& r)
+{
+ if (r.is_defined())
+ this->set_limits(r.rect());
+ else
+ this->unset_limits();
+}
+
+bool plot_auto::push_layer()
+{
+ bool retval = this->plot::push_layer();
+ if (this->m_rect.is_defined())
+ this->parent_layer()->set_bounding_box(this->m_rect.rect());
+ this->m_bbox_updated = true;
+ this->m_enlarged_layer = false;
+ return retval;
+}
+
+bool plot_auto::pop_layer()
+{
+ bool retval = this->plot::pop_layer();
+ if (this->m_enlarged_layer)
+ this->m_bbox_updated = false;
+ this->m_enlarged_layer = true;
+ return retval;
+}
+
+void plot_auto::clear_current_layer()
+{
+ this->plot::clear_current_layer();
+ if (this->m_enlarged_layer)
+ {
+ item_list* parent = this->parent_layer();
+ if (parent)
+ set_opt_limits(parent->bounding_box());
+ else
+ this->unset_limits();
+ }
+ this->m_bbox_updated = true;
+ this->m_enlarged_layer = false;
+}
diff --git a/agg-plot/plot-auto.h b/agg-plot/plot-auto.h
index 52e40de2..a6321840 100644
--- a/agg-plot/plot-auto.h
+++ b/agg-plot/plot-auto.h
@@ -27,15 +27,13 @@
#include "agg_array.h"
#include "agg_basics.h"
-template<class resource_manager>
-class plot_auto : public plot<resource_manager> {
- typedef typename plot<resource_manager>::item item;
- typedef typename plot<resource_manager>::item_list item_list;
+class plot_auto : public plot {
+ typedef typename plot::item item;
+ typedef typename plot::item_list item_list;
public:
plot_auto() :
- plot<resource_manager>(true),
- m_bbox_updated(true), m_enlarged_layer(false)
+ plot(true), m_bbox_updated(true), m_enlarged_layer(false)
{ };
virtual ~plot_auto() { };
@@ -43,7 +41,7 @@ public:
virtual void add(sg_object* vs, agg::rgba8& color, bool outline);
virtual void before_draw()
{
- plot<resource_manager>::before_draw();
+ plot::before_draw();
if (!m_bbox_updated)
check_bounding_box();
};
@@ -65,126 +63,4 @@ private:
bool m_enlarged_layer;
};
-template <class RM>
-void plot_auto<RM>::add(sg_object* vs, agg::rgba8& color, bool outline)
-{
- item d(vs, color, outline);
-
- if (!this->fit_inside(vs))
- {
- this->m_bbox_updated = false;
- this->m_need_redraw = true;
- this->m_enlarged_layer = true;
- }
-
- list<item> *nn = new list<item>(d);
- this->m_drawing_queue = list<item>::push_back(this->m_drawing_queue, nn);
-
- RM::acquire(vs);
-}
-
-template<class RM>
-void plot_auto<RM>::check_bounding_box()
-{
- this->calc_bounding_box();
- this->update_units();
- this->m_bbox_updated = true;
-}
-
-template<class RM>
-void plot_auto<RM>::calc_layer_bounding_box(plot_auto<RM>::item_list* layer,
- opt_rect<double>& rect)
-{
- for (unsigned j = 0; j < layer->size(); j++)
- {
- item& d = (*layer)[j];
- agg::rect_base<double> r;
-
- d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
- rect.add<rect_union>(r);
- }
-}
-
-template<class RM>
-void plot_auto<RM>::calc_bounding_box()
-{
- opt_rect<double> box;
-
- unsigned n = this->nb_layers();
- for (unsigned j = 0; j < n-1; j++)
- {
- box.add<rect_union>(this->get_layer(j)->bounding_box());
- }
-
- calc_layer_bounding_box(this->get_layer(n-1), box);
- for (list<item> *t = this->m_drawing_queue; t; t = t->next())
- {
- const item& d = t->content();
- agg::rect_base<double> r;
- d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
- box.add<rect_union>(r);
- }
-
- this->m_rect = box;
-}
-
-template<class RM>
-bool plot_auto<RM>::fit_inside(sg_object* obj) const
-{
- if (!this->m_bbox_updated || !this->m_rect.is_defined())
- return false;
-
- agg::rect_base<double> r;
- obj->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
-
- const agg::rect_base<double>& bb = this->m_rect.rect();
- return bb.hit_test(r.x1, r.y1) && bb.hit_test(r.x2, r.y2);
-}
-
-template<class RM>
-void plot_auto<RM>::set_opt_limits(const opt_rect<double>& r)
-{
- if (r.is_defined())
- this->set_limits(r.rect());
- else
- this->unset_limits();
-}
-
-template<class RM>
-bool plot_auto<RM>::push_layer()
-{
- bool retval = this->plot<RM>::push_layer();
- if (this->m_rect.is_defined())
- this->parent_layer()->set_bounding_box(this->m_rect.rect());
- this->m_bbox_updated = true;
- this->m_enlarged_layer = false;
- return retval;
-}
-
-template<class RM>
-bool plot_auto<RM>::pop_layer()
-{
- bool retval = this->plot<RM>::pop_layer();
- if (this->m_enlarged_layer)
- this->m_bbox_updated = false;
- this->m_enlarged_layer = true;
- return retval;
-}
-
-template<class RM>
-void plot_auto<RM>::clear_current_layer()
-{
- this->plot<RM>::clear_current_layer();
- if (this->m_enlarged_layer)
- {
- item_list* parent = this->parent_layer();
- if (parent)
- set_opt_limits(parent->bounding_box());
- else
- this->unset_limits();
- }
- this->m_bbox_updated = true;
- this->m_enlarged_layer = false;
-}
-
#endif
diff --git a/agg-plot/plot.cpp b/agg-plot/plot.cpp
new file mode 100644
index 00000000..95f3f743
--- /dev/null
+++ b/agg-plot/plot.cpp
@@ -0,0 +1,660 @@
+#include "plot.h"
+
+static double compute_scale(const agg::trans_affine& m)
+{
+ return m.scale() / 480.0;
+}
+
+static double
+std_line_width(double scale, double w = 1.0)
+{
+#if 0
+ const double dsf = M_LN10;
+ double ls = log(scale) / dsf;
+ return exp(round(ls) * dsf) * w * 1.5;
+#else
+ return w * 1.5;
+#endif
+}
+
+void plot::commit_pending_draw()
+{
+ push_drawing_queue();
+ m_need_redraw = false;
+ m_changes_pending.clear();
+}
+
+void plot::add(sg_object* vs, agg::rgba8& color, bool outline)
+{
+ item d(vs, color, outline);
+ list<item> *new_node = new list<item>(d);
+ m_drawing_queue = list<item>::push_back(m_drawing_queue, new_node);
+ RM::acquire(vs);
+}
+
+void plot::push_drawing_queue()
+{
+ item_list* layer = current_layer();
+ for (list<item> *c = m_drawing_queue; c != 0; c = c->next())
+ {
+ layer->add(c->content());
+ }
+
+ while (m_drawing_queue)
+ m_drawing_queue = list<item>::pop(m_drawing_queue);
+}
+
+void plot::clear_drawing_queue()
+{
+ while (m_drawing_queue)
+ {
+ item& d = m_drawing_queue->content();
+ RM::dispose(d.vs);
+ m_drawing_queue = list<item>::pop(m_drawing_queue);
+ }
+}
+
+static bool area_is_valid(const agg::trans_affine& b)
+{
+ const double thresold = 40.0;
+ return (b.sx > thresold && b.sy > thresold);
+}
+
+void plot::draw_virtual_canvas(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
+{
+ before_draw();
+ draw_legends(canvas, layout);
+
+ if (area_is_valid(layout.plot_area))
+ {
+ draw_axis(canvas, layout, clip);
+ draw_elements(canvas, layout);
+ }
+};
+
+void plot::draw_simple(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
+{
+ before_draw();
+ draw_axis(canvas, layout, clip);
+ draw_elements(canvas, layout);
+};
+
+void plot::draw_element(item& c, canvas_type& canvas, const agg::trans_affine& m)
+{
+ sg_object& vs = c.content();
+ vs.apply_transform(m, 1.0);
+
+ if (c.outline)
+ canvas.draw_outline(vs, c.color);
+ else
+ canvas.draw(vs, c.color);
+}
+
+agg::trans_affine plot::get_model_matrix(const plot_layout& layout)
+{
+ agg::trans_affine m = m_trans;
+ trans_affine_compose (m, layout.plot_active_area);
+ return m;
+}
+
+void plot::clip_plot_area(canvas_type& canvas, const agg::trans_affine& area_mtx)
+{
+ if (this->clip_is_active())
+ {
+ agg::rect_base<int> clip = rect_of_slot_matrix<int>(area_mtx);
+ canvas.clip_box(clip);
+ }
+}
+
+void plot::draw_elements(canvas_type& canvas, const plot_layout& layout)
+{
+ const agg::trans_affine m = get_model_matrix(layout);
+
+ this->clip_plot_area(canvas, layout.plot_active_area);
+
+ for (unsigned k = 0; k < m_layers.size(); k++)
+ {
+ item_list& layer = *(m_layers[k]);
+ for (unsigned j = 0; j < layer.size(); j++)
+ {
+ draw_element(layer[j], canvas, m);
+ }
+ }
+
+ canvas.reset_clipping();
+}
+
+void plot::compute_user_trans()
+{
+ agg::rect_base<double> r;
+
+ if (m_use_units && m_pad_units)
+ {
+ int ixi, ixs, iyi, iys;
+ double xd, yd;
+ m_ux.limits(ixi, ixs, xd);
+ r.x1 = ixi * xd;
+ r.x2 = ixs * xd;
+
+ m_uy.limits(iyi, iys, yd);
+ r.y1 = iyi * yd;
+ r.y2 = iys * yd;
+ }
+ else
+ {
+ r = m_rect.is_defined() ? m_rect.rect() : agg::rect_base<double>(0.0, 0.0, 1.0, 1.0);
+ }
+
+ double dx = r.x2 - r.x1, dy = r.y2 - r.y1;
+ double fx = (dx == 0 ? 1.0 : 1/dx), fy = (dy == 0 ? 1.0 : 1/dy);
+ this->m_trans = agg::trans_affine(fx, 0.0, 0.0, fy, -r.x1 * fx, -r.y1 * fy);
+}
+
+void plot::draw_grid(const axis_e dir, const units& u,
+ const agg::trans_affine& user_mtx,
+ agg::path_storage& ln)
+{
+ const double eps = 1.0e-3;
+ const bool isx = (dir == x_axis);
+
+ int jinf = u.begin(), jsup = u.end();
+ for (int j = jinf+1; j < jsup; j++)
+ {
+ double uq = u.mark_value(j);
+ double x = (isx ? uq : 0), y = (isx ? 0.0 : uq);
+ user_mtx.transform(&x, &y);
+ const double q = (isx ? x : y);
+
+ if (q >= -eps && q <= 1.0 + eps)
+ {
+ ln.move_to(isx ? q : 0.0, isx ? 0.0 : q);
+ ln.line_to(isx ? q : 1.0, isx ? 1.0 : q);
+ }
+ }
+}
+
+
+double plot::draw_axis_m(axis_e dir, units& u,
+ const agg::trans_affine& user_mtx,
+ ptr_list<draw::text>& labels, double scale,
+ agg::path_storage& mark, agg::path_storage& ln)
+{
+ const double ppad = double(axis_label_prop_space) / 1000.0;
+ 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;
+
+ bool isx = (dir == x_axis);
+
+ const axis& ax = get_axis(dir);
+ double hj = ax.labels_hjustif(), vj = ax.labels_vjustif();
+ double langle = ax.labels_angle();
+
+ category_map::iterator clabels(ax.categories);
+ units_iterator ulabels(u, ax.format_tag, ax.label_format());
+
+ label_iterator* ilabels = (ax.use_categories ? (label_iterator*) &clabels : (label_iterator*) &ulabels);
+
+ double uq;
+ const char* text;
+ while (ilabels->next(uq, text))
+ {
+ double x = (isx ? uq : 0.0), y = (isx ? 0.0 : uq);
+ user_mtx.transform(&x, &y);
+
+ double q = (isx ? x : y);
+
+ if (q < -eps || q > 1.0 + eps)
+ continue;
+
+ draw::text* label = new draw::text(text, text_label_size, hj, vj);
+
+ label->set_point(isx ? q : -ppad, isx ? -ppad : q);
+ label->angle(langle);
+
+ agg::bounding_rect_single(*label, 0, &r.x1, &r.y1, &r.x2, &r.y2);
+ bb.add<rect_union>(r);
+
+ labels.add(label);
+
+ mark.move_to(isx ? q : 0.0 , isx ? 0.0 : q);
+ mark.line_to(isx ? q : -0.01, isx ? -0.01 : q);
+ }
+
+ this->draw_grid(dir, u, user_mtx, ln);
+
+ double label_size;
+ if (bb.is_defined())
+ {
+ const agg::rect_base<double>& br = bb.rect();
+ label_size = (isx ? br.y2 - br.y1 : br.x2 - br.x1);
+ }
+ else
+ {
+ label_size = 0.0;
+ }
+
+ return label_size;
+}
+
+double plot::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 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;
+ }
+
+ this->draw_grid(x_axis, u, user_mtx, ln);
+
+ return y_spacing * layers_number;
+}
+
+static inline double approx_text_height(double text_size)
+{
+ return text_size * 1.5;
+}
+
+plot_layout plot::compute_plot_layout(const agg::trans_affine& canvas_mtx, bool do_legends)
+{
+ plot_layout layout;
+
+ const double sx = canvas_mtx.sx, sy = canvas_mtx.sy;
+ const double ppad = double(canvas_margin_prop_space) / 1000.0;
+ const double fpad = double(canvas_margin_fixed_space);
+ const double size_frac_x = 0.125, size_frac_y = 0.05;
+
+ double dxl, dxr, dyb, dyt;
+
+ dxl = dxr = fpad + ppad * sx;
+ dyb = dyt = fpad + ppad * sy;
+
+ if (!str_is_null(&m_title))
+ {
+ const double scale = compute_scale(canvas_mtx);
+ const double ptpad = double(axis_title_prop_space) / 1000.0;
+ const double title_text_size = get_default_font_size(text_plot_title, scale);
+ const double th = approx_text_height(title_text_size);
+
+ double x = 0.5, y = 1.0;
+ canvas_mtx.transform(&x, &y);
+ y -= ptpad + dyt + title_text_size;
+
+ layout.title_pos = plot_layout::point(x, y);
+ layout.title_font_size = title_text_size;
+
+ dyt += 2 * ptpad + th;
+ }
+
+ for (int k = 0; k < 4 && do_legends; k++)
+ {
+ plot* mp = m_legend[k];
+
+ if (mp)
+ {
+ agg::rect_base<double> bb;
+ mp->get_bounding_rect(bb);
+
+ double bb_dx = bb.x2 - bb.x1, bb_dy = bb.y2 - bb.y1;
+ double dx, dy;
+ double px, py;
+ switch (k)
+ {
+ case right:
+ dx = max(sx * size_frac_x, bb_dx);
+ dy = dx * bb_dy / bb_dx;
+ px = sx - dx - ppad * sx - dxr;
+ py = (sy - dy) / 2;
+ dxr += dx + 2 * ppad * sx;
+ break;
+ case left:
+ dx = max(sx * size_frac_x, bb_dx);
+ dy = dx * bb_dy / bb_dx;
+ px = ppad * sx + dxr;
+ py = (sy - dy) / 2;
+ dxl += dx + 2 * ppad * sx;
+ break;
+ case bottom:
+ dy = sy * size_frac_y;
+ dx = dy * bb_dx / bb_dy;
+ py = ppad * sy + dyb;
+ px = (sx - dx) / 2;
+ dyb += dy + 2 * ppad * sy;
+ break;
+ case top:
+ dy = sy * size_frac_y;
+ dx = dy * bb_dx / bb_dy;
+ py = sy - dy - ppad * sy - dyt;
+ px = (sx - dx) / 2;
+ dyt += dy + 2 * ppad * sy;
+ break;
+ default:
+ /* */
+ ;
+ }
+
+ if (px >= 0 && py >= 0 && px + dx < sx && py + dy < sy)
+ {
+ const double x0 = canvas_mtx.tx + px, y0 = canvas_mtx.ty + py;
+ layout.legend_area[k] = agg::trans_affine(dx, 0.0, 0.0, dy, x0, y0);
+ }
+ else
+ {
+ plot_layout::set_area_undefined(layout.legend_area[k]);
+ }
+ }
+ }
+
+ double x0 = canvas_mtx.tx + dxl, y0 = canvas_mtx.ty + dyb;
+ double ssx = sx - (dxl + dxr), ssy = sy - (dyb + dyt);
+ layout.plot_area = agg::trans_affine(ssx, 0.0, 0.0, ssy, x0, y0);
+
+ return layout;
+}
+
+void plot::draw_legends(canvas_type& canvas, const plot_layout& layout)
+{
+ if (!str_is_null(&m_title))
+ {
+ const plot_layout::point& pos = layout.title_pos;
+ draw::text title(m_title.cstr(), layout.title_font_size, 0.5, 0.0);
+ title.set_point(pos.x, pos.y);
+ title.apply_transform(identity_matrix, 1.0);
+ canvas.draw(title, colors::black);
+ }
+
+ for (int k = 0; k < 4; k++)
+ {
+ plot* mp = m_legend[k];
+ const agg::trans_affine& mtx = layout.legend_area[k];
+
+ if (mp && plot_layout::is_area_defined(mtx))
+ {
+ agg::rect_i clip = rect_of_slot_matrix<int>(mtx);
+ plot_layout mp_layout = mp->compute_plot_layout(mtx, false);
+ mp->draw_simple(canvas, mp_layout, &clip);
+ }
+ }
+}
+
+// Draw the axis elements and labels and set layout.plot_active_area
+// to the actual plotting are matrix.
+void plot::draw_axis(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
+{
+ if (!m_use_units)
+ {
+ layout.plot_active_area = layout.plot_area;
+ return;
+ }
+
+ double scale = compute_scale(layout.plot_area);
+
+ if (clip)
+ canvas.clip_box(*clip);
+
+ const agg::trans_affine& m = layout.plot_active_area;
+
+ agg::path_storage box;
+ sg_object_gen<agg::conv_transform<agg::path_storage> > boxtr(box, m);
+ trans::stroke_a boxvs(&boxtr);
+
+ box.move_to(0.0, 0.0);
+ box.line_to(0.0, 1.0);
+ box.line_to(1.0, 1.0);
+ box.line_to(1.0, 0.0);
+ box.close_polygon();
+
+ agg::path_storage mark;
+ sg_object_gen<agg::conv_transform<agg::path_storage> > mark_tr(mark, m);
+ trans::stroke_a mark_stroke(&mark_tr);
+
+ agg::path_storage ln;
+ sg_object_gen<agg::conv_transform<agg::path_storage> > ln_tr(ln, m);
+ trans::dash_a lndash(&ln_tr);
+ trans::stroke_a lns(&lndash);
+
+ const double label_text_size = get_default_font_size(text_axis_title, scale);
+ const double plpad = double(axis_label_prop_space) / 1000.0;
+ const double ptpad = double(axis_title_prop_space) / 1000.0;
+
+ ptr_list<draw::text> labels;
+
+ 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 + pdy_label, ppad_top = plpad;
+ double dx_left = dx_label, dx_right = 0.0;
+ double dy_bottom = dy_label, dy_top = 0.0;
+
+ if (!str_is_null(&m_y_axis.title))
+ {
+ dx_left += approx_text_height(label_text_size);
+ ppad_left += ptpad;
+ }
+
+ if (!str_is_null(&m_x_axis.title))
+ {
+ dy_bottom += approx_text_height(label_text_size);
+ ppad_bottom += ptpad;
+ }
+
+ const double sx = layout.plot_area.sx, sy = layout.plot_area.sy;
+ const double x0 = layout.plot_area.tx, y0 = layout.plot_area.ty;
+
+ const double xppad = (ppad_left + ppad_right);
+ const double lsx = (dx_left + dx_right + xppad * sx) / (1 + xppad);
+
+ const double yppad = (ppad_bottom + ppad_top);
+ const double lsy = (dy_bottom + dy_top + yppad * sy) / (1 + yppad);
+
+ const double sxr = sx - lsx;
+ const double syr = sy - lsy;
+
+ const double aax = x0 + dx_left + ppad_left * sxr;
+ const double aay = y0 + dy_bottom + ppad_bottom * syr;
+ layout.set_plot_active_area(sxr, syr, aax, aay);
+
+ for (unsigned j = 0; j < labels.size(); j++)
+ {
+ draw::text* label = labels[j];
+ label->apply_transform(m, 1.0);
+ canvas.draw(*label, colors::black);
+ }
+
+ lndash.add_dash(7.0, 3.0);
+
+ lns.width(std_line_width(scale, 0.15));
+ canvas.draw(lns, colors::black);
+
+ mark_stroke.width(std_line_width(scale, 0.75));
+ canvas.draw(mark_stroke, colors::black);
+
+ boxvs.width(std_line_width(scale, 0.75));
+ canvas.draw(boxvs, colors::black);
+
+ if (!str_is_null(&m_x_axis.title))
+ {
+ double labx = m.sx * 0.5 + m.tx;
+ double laby = y0;
+
+ const char* text = m_x_axis.title.cstr();
+ draw::text xlabel(text, label_text_size, 0.5, 0.0);
+ xlabel.set_point(labx, laby);
+ xlabel.apply_transform(identity_matrix, 1.0);
+
+ canvas.draw(xlabel, colors::black);
+ }
+
+ if (!str_is_null(&m_y_axis.title))
+ {
+ double labx = x0;
+ double laby = m.sy * 0.5 + m.ty;
+
+ const char* text = m_y_axis.title.cstr();
+ draw::text ylabel(text, label_text_size, 0.5, 1.0);
+ ylabel.set_point(labx, laby);
+ ylabel.angle(M_PI/2.0);
+ ylabel.apply_transform(identity_matrix, 1.0);
+
+ canvas.draw(ylabel, colors::black);
+ }
+
+ if (clip)
+ canvas.reset_clipping();
+}
+
+void plot::set_axis_labels_angle(axis_e axis_dir, double angle)
+{
+ get_axis(axis_dir).set_labels_angle(angle);
+ m_need_redraw = true;
+ compute_user_trans();
+}
+
+void plot::set_units(bool use_units)
+{
+ if (m_use_units != use_units)
+ {
+ m_use_units = use_units;
+ m_need_redraw = true;
+ compute_user_trans();
+ }
+}
+
+void plot::update_units()
+{
+ if (m_rect.is_defined())
+ {
+ const rect_base<double>& r = m_rect.rect();
+ m_ux = units(r.x1, r.x2);
+ m_uy = units(r.y1, r.y2);
+ }
+ else
+ {
+ m_ux = units();
+ m_uy = units();
+ }
+
+ compute_user_trans();
+}
+
+void plot::set_limits(const agg::rect_base<double>& r)
+{
+ m_rect.set(r);
+ update_units();
+ m_need_redraw = true;
+}
+
+void plot::unset_limits()
+{
+ m_rect.clear();
+ update_units();
+ m_need_redraw = true;
+}
+
+void plot::layer_dispose_elements(plot::item_list* layer)
+{
+ unsigned n = layer->size();
+ for (unsigned k = 0; k < n; k++)
+ {
+ RM::dispose(layer->at(k).vs);
+ }
+}
+
+bool plot::push_layer()
+{
+ if (m_layers.size() >= max_layers)
+ return false;
+
+ item_list *new_layer = new(std::nothrow) item_list();
+ if (new_layer)
+ {
+ before_draw();
+ push_drawing_queue();
+ m_layers.add(new_layer);
+ return true;
+ }
+
+ return false;
+}
+
+bool plot::pop_layer()
+{
+ if (m_layers.size() <= 1)
+ return false;
+
+ unsigned n = m_layers.size();
+ item_list* layer = m_layers[n-1];
+ m_layers.inc_size(-1);
+ layer_dispose_elements(layer);
+ delete layer;
+
+ clear_drawing_queue();
+ m_need_redraw = true;
+
+ return true;
+}
+
+void plot::clear_current_layer()
+{
+ item_list* current = current_layer();
+ clear_drawing_queue();
+ layer_dispose_elements(current);
+ current->clear();
+ m_changes_pending = m_changes_accu;
+ m_changes_accu.clear();
+}
+
+int plot::current_layer_index()
+{
+ return m_layers.size();
+}
diff --git a/agg-plot/plot.h b/agg-plot/plot.h
index 06d0d35a..25b0ce72 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"
@@ -123,7 +124,8 @@ struct plot_item {
};
};
-template<class ResourceManager>
+typedef manage_owner RM;
+
class plot {
static const unsigned max_layers = 8;
@@ -239,7 +241,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 +259,8 @@ public:
if (k > 0)
delete layer;
}
+
+ delete m_xaxis_hol;
};
str& title() {
@@ -301,6 +306,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() { }
@@ -417,10 +430,19 @@ protected:
void draw_virtual_canvas(canvas_type& canvas, plot_layout& layout, const agg::rect_i* r);
void draw_simple(canvas_type& canvas, plot_layout& layout, const agg::rect_i* r);
+ void draw_grid(const axis_e dir, const units& u,
+ const agg::trans_affine& user_mtx,
+ agg::path_storage& ln);
+
double draw_axis_m(axis_e dir, units& u, const agg::trans_affine& user_mtx,
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,144 +508,12 @@ private:
axis m_x_axis, m_y_axis;
plot* m_legend[4];
-};
-
-static double compute_scale(const agg::trans_affine& m)
-{
- return m.scale() / 480.0;
-}
-
-static double
-std_line_width(double scale, double w = 1.0)
-{
-#if 0
- const double dsf = M_LN10;
- double ls = log(scale) / dsf;
- return exp(round(ls) * dsf) * w * 1.5;
-#else
- return w * 1.5;
-#endif
-}
-
-template <class RM>
-void plot<RM>::commit_pending_draw()
-{
- push_drawing_queue();
- m_need_redraw = false;
- m_changes_pending.clear();
-}
-
-template <class RM>
-void plot<RM>::add(sg_object* vs, agg::rgba8& color, bool outline)
-{
- item d(vs, color, outline);
- list<item> *new_node = new list<item>(d);
- m_drawing_queue = list<item>::push_back(m_drawing_queue, new_node);
- RM::acquire(vs);
-}
-
-template <class RM>
-void plot<RM>::push_drawing_queue()
-{
- item_list* layer = current_layer();
- for (list<item> *c = m_drawing_queue; c != 0; c = c->next())
- {
- layer->add(c->content());
- }
-
- while (m_drawing_queue)
- m_drawing_queue = list<item>::pop(m_drawing_queue);
-}
-
-template <class RM>
-void plot<RM>::clear_drawing_queue()
-{
- while (m_drawing_queue)
- {
- item& d = m_drawing_queue->content();
- RM::dispose(d.vs);
- m_drawing_queue = list<item>::pop(m_drawing_queue);
- }
-}
-
-static bool area_is_valid(const agg::trans_affine& b)
-{
- const double thresold = 40.0;
- return (b.sx > thresold && b.sy > thresold);
-}
-template <class RM>
-void plot<RM>::draw_virtual_canvas(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
-{
- before_draw();
- draw_legends(canvas, layout);
-
- if (area_is_valid(layout.plot_area))
- {
- draw_axis(canvas, layout, clip);
- draw_elements(canvas, layout);
- }
-};
-
-template <class RM>
-void plot<RM>::draw_simple(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
-{
- before_draw();
- draw_axis(canvas, layout, clip);
- draw_elements(canvas, layout);
+ ptr_list<factor_labels>* m_xaxis_hol;
};
-template <class RM>
-void plot<RM>::draw_element(item& c, canvas_type& canvas, const agg::trans_affine& m)
-{
- sg_object& vs = c.content();
- vs.apply_transform(m, 1.0);
-
- if (c.outline)
- canvas.draw_outline(vs, c.color);
- else
- canvas.draw(vs, c.color);
-}
-
-template <class RM>
-agg::trans_affine plot<RM>::get_model_matrix(const plot_layout& layout)
-{
- agg::trans_affine m = m_trans;
- trans_affine_compose (m, layout.plot_active_area);
- return m;
-}
-
-template<class RM>
-void plot<RM>::clip_plot_area(canvas_type& canvas, const agg::trans_affine& area_mtx)
-{
- if (this->clip_is_active())
- {
- agg::rect_base<int> clip = rect_of_slot_matrix<int>(area_mtx);
- canvas.clip_box(clip);
- }
-}
-
-template <class RM>
-void plot<RM>::draw_elements(canvas_type& canvas, const plot_layout& layout)
-{
- const agg::trans_affine m = get_model_matrix(layout);
-
- this->clip_plot_area(canvas, layout.plot_active_area);
-
- for (unsigned k = 0; k < m_layers.size(); k++)
- {
- item_list& layer = *(m_layers[k]);
- for (unsigned j = 0; j < layer.size(); j++)
- {
- draw_element(layer[j], canvas, m);
- }
- }
-
- canvas.reset_clipping();
-}
-
-template <class RM>
-template <class Canvas> void plot<RM>::draw_queue(Canvas& _canvas, const agg::trans_affine& canvas_mtx, const plot_render_info& inf, opt_rect<double>& bb)
+template <class Canvas>
+void plot::draw_queue(Canvas& _canvas, const agg::trans_affine& canvas_mtx, const plot_render_info& inf, opt_rect<double>& bb)
{
canvas_adapter<Canvas> canvas(&_canvas);
before_draw();
@@ -633,7 +523,7 @@ template <class Canvas> void plot<RM>::draw_queue(Canvas& _canvas, const agg::tr
this->clip_plot_area(canvas, layout.plot_active_area);
- typedef typename plot<RM>::iterator iter_type;
+ typedef typename plot::iterator iter_type;
iter_type *c0 = m_drawing_queue;
for (iter_type *c = c0; c != 0; c = c->next())
{
@@ -658,483 +548,4 @@ template <class Canvas> void plot<RM>::draw_queue(Canvas& _canvas, const agg::tr
canvas.reset_clipping();
}
-template <class RM>
-void plot<RM>::compute_user_trans()
-{
- agg::rect_base<double> r;
-
- if (m_use_units && m_pad_units)
- {
- int ixi, ixs, iyi, iys;
- double xd, yd;
- m_ux.limits(ixi, ixs, xd);
- r.x1 = ixi * xd;
- r.x2 = ixs * xd;
-
- m_uy.limits(iyi, iys, yd);
- r.y1 = iyi * yd;
- r.y2 = iys * yd;
- }
- else
- {
- r = m_rect.is_defined() ? m_rect.rect() : agg::rect_base<double>(0.0, 0.0, 1.0, 1.0);
- }
-
- double dx = r.x2 - r.x1, dy = r.y2 - r.y1;
- double fx = (dx == 0 ? 1.0 : 1/dx), fy = (dy == 0 ? 1.0 : 1/dy);
- this->m_trans = agg::trans_affine(fx, 0.0, 0.0, fy, -r.x1 * fx, -r.y1 * fy);
-}
-
-template <class RM>
-double plot<RM>::draw_axis_m(axis_e dir, units& u,
- const agg::trans_affine& user_mtx,
- ptr_list<draw::text>& labels, double scale,
- agg::path_storage& mark, agg::path_storage& ln)
-{
- const double ppad = double(axis_label_prop_space) / 1000.0;
- const double text_label_size = get_default_font_size(text_axis_labels, scale);
- const double eps = 1.0e-3;
-
- opt_rect<double> bb;
- agg::rect_base<double> r;
-
- bool isx = (dir == x_axis);
-
- const axis& ax = get_axis(dir);
- double hj = ax.labels_hjustif(), vj = ax.labels_vjustif();
- double langle = ax.labels_angle();
-
- category_map::iterator clabels(ax.categories);
- units_iterator ulabels(u, ax.format_tag, ax.label_format());
-
- label_iterator* ilabels = (ax.use_categories ? (label_iterator*) &clabels : (label_iterator*) &ulabels);
-
- double uq;
- const char* text;
- while (ilabels->next(uq, text))
- {
- double x = (isx ? uq : 0.0), y = (isx ? 0.0 : uq);
- user_mtx.transform(&x, &y);
-
- double q = (isx ? x : y);
-
- if (q < -eps || q > 1.0 + eps)
- continue;
-
- draw::text* label = new draw::text(text, text_label_size, hj, vj);
-
- label->set_point(isx ? q : -ppad, isx ? -ppad : q);
- label->angle(langle);
-
- agg::bounding_rect_single(*label, 0, &r.x1, &r.y1, &r.x2, &r.y2);
- bb.add<rect_union>(r);
-
- labels.add(label);
-
- mark.move_to(isx ? q : 0.0 , isx ? 0.0 : q);
- mark.line_to(isx ? q : -0.01, isx ? -0.01 : q);
- }
-
- int jinf = u.begin(), jsup = u.end();
- for (int j = jinf+1; j < jsup; j++)
- {
- double uq = u.mark_value(j);
- double x = (isx ? uq : 0), y = (isx ? 0.0 : uq);
- user_mtx.transform(&x, &y);
- double q = (isx ? x : y);
-
- if (q >= -eps && q <= 1.0 + eps)
- {
- ln.move_to(isx ? q : 0.0, isx ? 0.0 : q);
- ln.line_to(isx ? q : 1.0, isx ? 1.0 : q);
- }
- }
-
- double label_size;
- if (bb.is_defined())
- {
- const agg::rect_base<double>& br = bb.rect();
- label_size = (isx ? br.y2 - br.y1 : br.x2 - br.x1);
- }
- else
- {
- label_size = 0.0;
- }
-
- return label_size;
-}
-
-static inline double approx_text_height(double text_size)
-{
- return text_size * 1.5;
-}
-
-template <class RM>
-plot_layout plot<RM>::compute_plot_layout(const agg::trans_affine& canvas_mtx, bool do_legends)
-{
- plot_layout layout;
-
- const double sx = canvas_mtx.sx, sy = canvas_mtx.sy;
- const double ppad = double(canvas_margin_prop_space) / 1000.0;
- const double fpad = double(canvas_margin_fixed_space);
- const double size_frac_x = 0.125, size_frac_y = 0.05;
-
- double dxl, dxr, dyb, dyt;
-
- dxl = dxr = fpad + ppad * sx;
- dyb = dyt = fpad + ppad * sy;
-
- if (!str_is_null(&m_title))
- {
- const double scale = compute_scale(canvas_mtx);
- const double ptpad = double(axis_title_prop_space) / 1000.0;
- const double title_text_size = get_default_font_size(text_plot_title, scale);
- const double th = approx_text_height(title_text_size);
-
- double x = 0.5, y = 1.0;
- canvas_mtx.transform(&x, &y);
- y -= ptpad + dyt + title_text_size;
-
- layout.title_pos = plot_layout::point(x, y);
- layout.title_font_size = title_text_size;
-
- dyt += 2 * ptpad + th;
- }
-
- for (int k = 0; k < 4 && do_legends; k++)
- {
- plot* mp = m_legend[k];
-
- if (mp)
- {
- agg::rect_base<double> bb;
- mp->get_bounding_rect(bb);
-
- double bb_dx = bb.x2 - bb.x1, bb_dy = bb.y2 - bb.y1;
- double dx, dy;
- double px, py;
- switch (k)
- {
- case right:
- dx = max(sx * size_frac_x, bb_dx);
- dy = dx * bb_dy / bb_dx;
- px = sx - dx - ppad * sx - dxr;
- py = (sy - dy) / 2;
- dxr += dx + 2 * ppad * sx;
- break;
- case left:
- dx = max(sx * size_frac_x, bb_dx);
- dy = dx * bb_dy / bb_dx;
- px = ppad * sx + dxr;
- py = (sy - dy) / 2;
- dxl += dx + 2 * ppad * sx;
- break;
- case bottom:
- dy = sy * size_frac_y;
- dx = dy * bb_dx / bb_dy;
- py = ppad * sy + dyb;
- px = (sx - dx) / 2;
- dyb += dy + 2 * ppad * sy;
- break;
- case top:
- dy = sy * size_frac_y;
- dx = dy * bb_dx / bb_dy;
- py = sy - dy - ppad * sy - dyt;
- px = (sx - dx) / 2;
- dyt += dy + 2 * ppad * sy;
- break;
- default:
- /* */
- ;
- }
-
- if (px >= 0 && py >= 0 && px + dx < sx && py + dy < sy)
- {
- const double x0 = canvas_mtx.tx + px, y0 = canvas_mtx.ty + py;
- layout.legend_area[k] = agg::trans_affine(dx, 0.0, 0.0, dy, x0, y0);
- }
- else
- {
- plot_layout::set_area_undefined(layout.legend_area[k]);
- }
- }
- }
-
- double x0 = canvas_mtx.tx + dxl, y0 = canvas_mtx.ty + dyb;
- double ssx = sx - (dxl + dxr), ssy = sy - (dyb + dyt);
- layout.plot_area = agg::trans_affine(ssx, 0.0, 0.0, ssy, x0, y0);
-
- return layout;
-}
-
-template <class RM>
-void plot<RM>::draw_legends(canvas_type& canvas, const plot_layout& layout)
-{
- if (!str_is_null(&m_title))
- {
- const plot_layout::point& pos = layout.title_pos;
- draw::text title(m_title.cstr(), layout.title_font_size, 0.5, 0.0);
- title.set_point(pos.x, pos.y);
- title.apply_transform(identity_matrix, 1.0);
- canvas.draw(title, colors::black);
- }
-
- for (int k = 0; k < 4; k++)
- {
- plot* mp = m_legend[k];
- const agg::trans_affine& mtx = layout.legend_area[k];
-
- if (mp && plot_layout::is_area_defined(mtx))
- {
- agg::rect_i clip = rect_of_slot_matrix<int>(mtx);
- plot_layout mp_layout = mp->compute_plot_layout(mtx, false);
- mp->draw_simple(canvas, mp_layout, &clip);
- }
- }
-}
-
-// Draw the axis elements and labels and set layout.plot_active_area
-// to the actual plotting are matrix.
-template <class RM>
-void plot<RM>::draw_axis(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
-{
- if (!m_use_units)
- {
- layout.plot_active_area = layout.plot_area;
- return;
- }
-
- double scale = compute_scale(layout.plot_area);
-
- if (clip)
- canvas.clip_box(*clip);
-
- const agg::trans_affine& m = layout.plot_active_area;
-
- agg::path_storage box;
- sg_object_gen<agg::conv_transform<agg::path_storage> > boxtr(box, m);
- trans::stroke_a boxvs(&boxtr);
-
- box.move_to(0.0, 0.0);
- box.line_to(0.0, 1.0);
- box.line_to(1.0, 1.0);
- box.line_to(1.0, 0.0);
- box.close_polygon();
-
- agg::path_storage mark;
- sg_object_gen<agg::conv_transform<agg::path_storage> > mark_tr(mark, m);
- trans::stroke_a mark_stroke(&mark_tr);
-
- agg::path_storage ln;
- sg_object_gen<agg::conv_transform<agg::path_storage> > ln_tr(ln, m);
- trans::dash_a lndash(&ln_tr);
- trans::stroke_a lns(&lndash);
-
- const double label_text_size = get_default_font_size(text_axis_title, scale);
- const double plpad = double(axis_label_prop_space) / 1000.0;
- const double ptpad = double(axis_title_prop_space) / 1000.0;
-
- ptr_list<draw::text> labels;
-
- double 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 dx_left = dx_label, dx_right = 0.0;
- double dy_bottom = dy_label, dy_top = 0.0;
-
- if (!str_is_null(&m_y_axis.title))
- {
- dx_left += approx_text_height(label_text_size);
- ppad_left += ptpad;
- }
-
- if (!str_is_null(&m_x_axis.title))
- {
- dy_bottom += approx_text_height(label_text_size);
- ppad_bottom += ptpad;
- }
-
- const double sx = layout.plot_area.sx, sy = layout.plot_area.sy;
- const double x0 = layout.plot_area.tx, y0 = layout.plot_area.ty;
-
- const double xppad = (ppad_left + ppad_right);
- const double lsx = (dx_left + dx_right + xppad * sx) / (1 + xppad);
-
- const double yppad = (ppad_bottom + ppad_top);
- const double lsy = (dy_bottom + dy_top + yppad * sy) / (1 + yppad);
-
- const double sxr = sx - lsx;
- const double syr = sy - lsy;
-
- const double aax = x0 + dx_left + ppad_left * sxr;
- const double aay = y0 + dy_bottom + ppad_bottom * syr;
- layout.set_plot_active_area(sxr, syr, aax, aay);
-
- for (unsigned j = 0; j < labels.size(); j++)
- {
- draw::text* label = labels[j];
- label->apply_transform(m, 1.0);
- canvas.draw(*label, colors::black);
- }
-
- lndash.add_dash(7.0, 3.0);
-
- lns.width(std_line_width(scale, 0.15));
- canvas.draw(lns, colors::black);
-
- mark_stroke.width(std_line_width(scale, 0.75));
- canvas.draw(mark_stroke, colors::black);
-
- boxvs.width(std_line_width(scale, 0.75));
- canvas.draw(boxvs, colors::black);
-
- if (!str_is_null(&m_x_axis.title))
- {
- double labx = m.sx * 0.5 + m.tx;
- double laby = y0;
-
- const char* text = m_x_axis.title.cstr();
- draw::text xlabel(text, label_text_size, 0.5, 0.0);
- xlabel.set_point(labx, laby);
- xlabel.apply_transform(identity_matrix, 1.0);
-
- canvas.draw(xlabel, colors::black);
- }
-
- if (!str_is_null(&m_y_axis.title))
- {
- double labx = x0;
- double laby = m.sy * 0.5 + m.ty;
-
- const char* text = m_y_axis.title.cstr();
- draw::text ylabel(text, label_text_size, 0.5, 1.0);
- ylabel.set_point(labx, laby);
- ylabel.angle(M_PI/2.0);
- ylabel.apply_transform(identity_matrix, 1.0);
-
- canvas.draw(ylabel, colors::black);
- }
-
- if (clip)
- canvas.reset_clipping();
-}
-
-template<class RM>
-void plot<RM>::set_axis_labels_angle(axis_e axis_dir, double angle)
-{
- get_axis(axis_dir).set_labels_angle(angle);
- m_need_redraw = true;
- compute_user_trans();
-}
-
-template<class RM>
-void plot<RM>::set_units(bool use_units)
-{
- if (m_use_units != use_units)
- {
- m_use_units = use_units;
- m_need_redraw = true;
- compute_user_trans();
- }
-}
-
-template<class RM>
-void plot<RM>::update_units()
-{
- if (m_rect.is_defined())
- {
- const rect_base<double>& r = m_rect.rect();
- m_ux = units(r.x1, r.x2);
- m_uy = units(r.y1, r.y2);
- }
- else
- {
- m_ux = units();
- m_uy = units();
- }
-
- compute_user_trans();
-}
-
-template<class RM>
-void plot<RM>::set_limits(const agg::rect_base<double>& r)
-{
- m_rect.set(r);
- update_units();
- m_need_redraw = true;
-}
-
-template<class RM>
-void plot<RM>::unset_limits()
-{
- m_rect.clear();
- update_units();
- m_need_redraw = true;
-}
-
-template<class RM>
-void plot<RM>::layer_dispose_elements(plot<RM>::item_list* layer)
-{
- unsigned n = layer->size();
- for (unsigned k = 0; k < n; k++)
- {
- RM::dispose(layer->at(k).vs);
- }
-}
-
-template<class RM>
-bool plot<RM>::push_layer()
-{
- if (m_layers.size() >= max_layers)
- return false;
-
- item_list *new_layer = new(std::nothrow) item_list();
- if (new_layer)
- {
- before_draw();
- push_drawing_queue();
- m_layers.add(new_layer);
- return true;
- }
-
- return false;
-}
-
-template<class RM>
-bool plot<RM>::pop_layer()
-{
- if (m_layers.size() <= 1)
- return false;
-
- unsigned n = m_layers.size();
- item_list* layer = m_layers[n-1];
- m_layers.inc_size(-1);
- layer_dispose_elements(layer);
- delete layer;
-
- clear_drawing_queue();
- m_need_redraw = true;
-
- return true;
-}
-
-template <class RM>
-void plot<RM>::clear_current_layer()
-{
- item_list* current = current_layer();
- clear_drawing_queue();
- layer_dispose_elements(current);
- current->clear();
- m_changes_pending = m_changes_accu;
- m_changes_accu.clear();
-}
-
-template <class RM>
-int plot<RM>::current_layer_index()
-{
- return m_layers.size();
-}
-
#endif
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();
}
diff --git a/fox-gui/lua_plot_window.cpp b/fox-gui/lua_plot_window.cpp
index 15a3107e..f327aef7 100644
--- a/fox-gui/lua_plot_window.cpp
+++ b/fox-gui/lua_plot_window.cpp
@@ -40,7 +40,7 @@ static const struct luaL_Reg fox_window_methods[] =
__END_DECLS
-typedef plot<manage_owner> sg_plot;
+typedef plot sg_plot;
class window_mutex {
public:
diff --git a/iter.lua b/iter.lua
index 06d4618a..4d2b6ffa 100644
--- a/iter.lua
+++ b/iter.lua
@@ -20,6 +20,7 @@
local cat = table.concat
local fmt = string.format
+local tostring = tostring
do
local ffi = require('ffi')
@@ -61,6 +62,13 @@ end
local max_depth = 3
+local function cdata_tos(t, deep)
+ local tp = gsl_type and gsl_type(t) or 'cdata'
+ if tp ~= 'cdata' and t.show then
+ return (deep and t:show() or fmt("<%s: %p>", tp, t))
+ end
+end
+
tos = function (t, depth)
local tp = type(t)
if tp == 'table' then
@@ -92,9 +100,9 @@ tos = function (t, depth)
end
end
elseif tp == 'cdata' then
- local tpext = gsl_type and gsl_type(t) or tp
- if tpext ~= 'cdata' and t.show then
- return (depth == 0 and t:show() or fmt("<%s: %p>", tpext, t))
+ local ok, s = pcall(cdata_tos, t, depth == 0)
+ if ok and type(s) == 'string' then
+ return s
end
end
return tostring(t)
diff --git a/matrix.lua b/matrix.lua
index 87df4581..d7c5e75b 100644
--- a/matrix.lua
+++ b/matrix.lua
@@ -3,7 +3,7 @@
local ffi = require 'ffi'
local gsl = require 'gsl'
-local sqrt, abs = math.sqrt, math.abs
+local sqrt, abs, floor = math.sqrt, math.abs, math.floor
local format = string.format
local check = require 'check'
@@ -208,21 +208,34 @@ local function itostr(im, eps, fmt, signed)
end
end
+local function is_small_integer(x)
+ local ax = abs(x)
+ return (ax < 2^31 and floor(ax) == ax)
+end
+
local function recttostr(x, y, eps)
local x_sub, y_sub = abs(x) < eps, abs(y) < eps
- local fmt = '%.8g'
+ local fmt_x, fmt_y = '%.8g', '%.8g'
+ if is_small_integer(x) then
+ fmt_x = '%.0f'
+ x_sub = false
+ end
+ if is_small_integer(y) then
+ fmt_y = '%.0f'
+ y_sub = false
+ end
if not x_sub then
local sign = x+eps < 0 and '-' or ''
local ax = abs(x)
if y_sub then
- return format('%s'..fmt, sign, ax)
+ return format('%s'..fmt_x, sign, ax)
else
- return format('%s'..fmt..'%s', sign, ax, itostr(y, eps, fmt, true))
+ return format('%s'..fmt_x..'%s', sign, ax, itostr(y, eps, fmt_y, true))
end
else
- return (y_sub and '0' or itostr(y, eps, fmt, false))
+ return (y_sub and '0' or itostr(y, eps, fmt_y, false))
end
end
diff --git a/scripts/dos2unix.py b/scripts/dos2unix.py
new file mode 100755
index 00000000..5c2e6266
--- /dev/null
+++ b/scripts/dos2unix.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+import os
+import re
+import sys
+
+def dos2unix(filename):
+ tmp_filename = filename + '.tmp'
+
+ try:
+ fsrc = open(filename, "rb")
+ fdst = open(tmp_filename, "wb")
+ for ln in fsrc:
+ lnu = re.sub(r'015円\n', '\n', ln)
+ fdst.write(lnu)
+ fsrc.close()
+ fdst.close()
+ except OSError as err:
+ print 'Error', err.strerror
+ else:
+ try:
+ os.unlink(filename)
+ os.rename(tmp_filename, filename)
+ except OSError as err:
+ print 'Error', err.strerror
+
+for filename in sys.argv[1:]:
+ inf = os.popen("file " + filename, "r")
+ for ln in inf:
+ if re.search(r'with CRLF line terminators', ln):
+ dos2unix(filename)
+ break
+ else:
+ print "File ", filename, "not in DOS format"
+
diff --git a/scripts/enum2lua.py b/scripts/enum2lua.py
new file mode 100644
index 00000000..0e574ae7
--- /dev/null
+++ b/scripts/enum2lua.py
@@ -0,0 +1,12 @@
+import re
+import sys
+
+f = open(sys.argv[1], 'r')
+count = 0
+for line in f:
+ m = re.match(r'\s*SEL_([A-Z_]+),(.*)', line)
+ if m:
+ print('SEL.%s = %i' % (m.group(1), count) + m.group(2))
+ count += 1
+f.close()
+
generated by cgit v1.2.3 (git 2.39.1) at 2025年09月21日 06:37:58 +0000

AltStyle によって変換されたページ (->オリジナル) /