Empirical
axis.h
Go to the documentation of this file.
1 
10 #ifndef EMP_D3_AXIS_H
11 #define EMP_D3_AXIS_H
12 
13 #include "../js_utils.h"
14 #include "../../tools/string_utils.h"
15 
16 #include "d3_init.h"
17 #include "selection.h"
18 #include "scales.h"
19 
20 namespace D3 {
21 
24  template <typename SCALE_TYPE = LinearScale>
25  class Axis : public D3_Base {
26  private:
27  SCALE_TYPE scale;
28  std::string label;
29  std::string dom_id = "";
30  std::string label_offset = "";
31  std::string orientation;
32 
33  public:
34 
39 
48  Axis(std::string type, std::string label = "") {
49  //The scale got added to th the list of objects before this one
50  this->label = label;
51  this->orientation = type;
52  if (type == "left") {
53  EM_ASM_ARGS({
54  js.objects[$0] = d3.axisLeft(js.objects[$1]);
55  }, this->id, scale.GetID());
56  } else if (type == "right") {
57  EM_ASM_ARGS({
58  js.objects[$0] = d3.axisRight(js.objects[$1]);
59  }, this->id, scale.GetID());
60  } else if (type == "bottom") {
61  EM_ASM_ARGS({
62  js.objects[$0] = d3.axisBottom(js.objects[$1]);
63  }, this->id, scale.GetID());
64  } else if (type == "top") {
65  EM_ASM_ARGS({
66  js.objects[$0] = d3.axisTop(js.objects[$1]);
67  }, this->id, scale.GetID());
68  } else {
69  std::cout << "WARNING: Invalid type given to axis constructor" << std::endl;
70  EM_ASM_ARGS({
71  js.objects[$0] = d3.axisBottom(js.objects[$1]);
72  }, this->id, scale.GetID());
73  }
74 
75  }
76 
79  Axis& Draw(Selection & selection){
80  //this->SetTickFormat("g");
81 
82  //Dom ids can't contain whitespace
83  dom_id = label;
84  emp::remove_whitespace(dom_id);
85  dom_id += "_axis";
86 
87  EM_ASM_ARGS({
88  var axis_range = js.objects[$0].scale().range();
89  js.objects[$3] = js.objects[$1].append("g");
90 
91  js.objects[$3].append("g").attr("id", Pointer_stringify($2))
92  .call(js.objects[$0]);
93 
94  var canvas_width = js.objects[$1].attr("width");
95  var canvas_height = js.objects[$1].attr("height");
96 
97  var orient = Pointer_stringify($6);
98  var dy = "2.5em";
99  var x_divisor = 2.0;
100  var text_orient = 0;
101  js.objects[$3].attr("transform", "translate(0,"+(canvas_height-60)+")");
102  if (orient == "top") {
103  dy = "-2.5em";
104  x_divisor = 2.0;
105  js.objects[$3].attr("transform", "translate(0,60)");
106  } else if (orient == "left") {
107  dy = "-2.5em";
108  x_divisor = -2.0;
109  text_orient = -90;
110  js.objects[$3].attr("transform", "translate(60,0)");
111  } else if(orient == "right") {
112  dy = "2.5em";
113  text_orient = -90;
114  js.objects[$3].attr("transform", "translate("+(canvas_width-60)+",0)");
115  }
116 
117  if (Pointer_stringify($5) != "") {
118  dy = Pointer_stringify($5);
119  }
120 
121  var label_x = axis_range[0]+(axis_range[1]-axis_range[0])/x_divisor;
122  if (axis_range[0] > axis_range[1]) {
123  label_x = axis_range[1]+(axis_range[0]-axis_range[1])/x_divisor;
124  }
125 
126  js.objects[$3].append("text")
127  .attr("id", Pointer_stringify($2)+"_label")
128  .attr("transform", "rotate("+text_orient+")")
129  .attr("x", label_x)
130  .attr("dy", dy).style("text-anchor", "middle")
131  .text(Pointer_stringify($4));
132  }, this->id, selection.GetID(), dom_id.c_str(), group.GetID(), label.c_str(),
133  label_offset.c_str(), orientation.c_str());
134  return *this;
135  }
136 
137  // selection needs to be const for this to compile, but it feels wrong since
138  // technically the contents of the selection are changed
139  template <typename T>
141  EM_ASM_ARGS({
142  js.objects[$1].call(js.objects[$0]);
143  }, this->id, selection.GetID());
144  return *this;
145  }
146 
150  Axis& SetScale(SCALE_TYPE & scale) {
151  this->scale = scale;
152 
153  EM_ASM_ARGS({
154  js.objects[$0].scale(js.objects[$1]);
155  }, this->id, scale.GetID());
156  return *this;
157  }
158 
160  SCALE_TYPE& GetScale(){
161  return this->scale;
162  }
163 
167  Axis& AdjustLabelOffset(std::string offset) {
168  label_offset = offset;
169  if (dom_id != "") { //We've already drawn stuff
170  group.Select("#"+dom_id+"_label").SetAttr("dy", label_offset);
171  }
172  return *this;
173  }
174 
177  Axis& Move(int x, int y) {
178  group.Move(x,y);
179  return *this;
180  }
181 
182  template <typename T, std::size_t SIZE>
185 
186  EM_ASM_ARGS({
187  js.objects[$0].tickValues(emp_i.__incoming_array);
188  }, this->id);
189  return *this;
190  }
191 
192  Axis& SetTickSize(float size) {
193  EM_ASM_ARGS({
194  js.objects[$0].tickSize($1);
195  }, this->id, size);
196  return *this;
197  }
198 
199  Axis& SetTickSizeInner(float size) {
200  EM_ASM_ARGS({
201  js.objects[$0].tickSizeInner($1);
202  }, this->id, size);
203  return *this;
204  }
205 
206  Axis& SetTickSizeOuter(float size) {
207  EM_ASM_ARGS({
208  js.objects[$0].tickSizeOuter($1);
209  }, this->id, size);
210  return *this;
211  }
212 
213  Axis& SetTickPadding(int padding) {
214  EM_ASM_ARGS({
215  js.objects[$0].tickPadding($1);
216  }, this->id, padding);
217  return *this;
218  }
219 
221  Axis& SetTicks(int count){
222  EM_ASM_ARGS({
223  js.objects[$0].ticks($1);
224  }, this->id, count);
225  return *this;
226  }
227 
231  Axis& SetTickFormat(std::string format) {
232  EM_ASM_ARGS({
233  js.objects[$0].tickFormat(d3.format(Pointer_stringify($1)));
234  }, this->id, format.c_str());
235  return *this;
236  }
237 
241  template <typename T>
242  Axis& Rescale(double new_min, double new_max, const D3::SelectionOrTransition<T> & svg){
243  this->scale.SetDomain(emp::array<double, 2>{{new_min, new_max}});
244  ApplyAxis(svg.Select("#"+dom_id));
245  return *this;
246  }
247 
248  //TODO: ticks
249 
250  };
251 
254  template <typename SCALE_X_TYPE = D3::LinearScale, typename SCALE_Y_TYPE = D3::LinearScale>
255  void DrawAxes(Axis<SCALE_X_TYPE> & x_axis, Axis<SCALE_Y_TYPE> & y_axis, Selection & selection){
256  x_axis.Draw(selection);
257  y_axis.Draw(selection);
258 
259  EM_ASM_ARGS({
260  x_range = js.objects[$0].scale().range();
261  y_range = js.objects[$1].scale().range();
262 
263  js.objects[$2].attr("transform", "translate(0,"+d3.max(y_range)+")");
264  js.objects[$3].attr("transform", "translate("+x_range[0]+",0)");
265  }, x_axis.GetID(), y_axis.GetID(), x_axis.group.GetID(), y_axis.group.GetID());
266  }
267 
268 }
269 
270 #endif
Axis & SetTickFormat(std::string format)
Definition: axis.h:231
Definition: array.h:42
Axis(std::string type, std::string label="")
Definition: axis.h:48
Axis & SetTicks(int count)
Set the number of ticks along the axis.
Definition: axis.h:221
static void remove_whitespace(std::string &in_string)
Remove all whitespace from anywhere within a string.
Definition: string_utils.h:392
Definition: d3_init.h:43
Axis & SetTickSizeOuter(float size)
Definition: axis.h:206
DERIVED & SetAttr(std::string name, std::string value)
Definition: selection.h:208
Selection group
Definition: axis.h:38
int id
Definition: d3_init.h:45
Axis & SetScale(SCALE_TYPE &scale)
Definition: axis.h:150
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
Tools for scaling graph axes in D3.
Definition: selection.h:39
void DrawAxes(Axis< SCALE_X_TYPE > &x_axis, Axis< SCALE_Y_TYPE > &y_axis, Selection &selection)
Definition: axis.h:255
Definition: selection.h:936
Axis & SetTickSizeInner(float size)
Definition: axis.h:199
Axis & Draw(Selection &selection)
Definition: axis.h:79
Axis & SetTickPadding(int padding)
Definition: axis.h:213
Axis & Rescale(double new_min, double new_max, const D3::SelectionOrTransition< T > &svg)
Definition: axis.h:242
Axis & Move(int x, int y)
Definition: axis.h:177
Definition: axis.h:20
Selection & Move(int x, int y)
Definition: selection.h:1486
Axis & ApplyAxis(const SelectionOrTransition< T > &selection)
Definition: axis.h:140
Axis & SetTickValues(emp::array< T, SIZE > values)
Definition: axis.h:183
DERIVED Select(std::string selector) const
Definition: selection.h:47
Definition: axis.h:25
Axis & AdjustLabelOffset(std::string offset)
Definition: axis.h:167
int GetID() const
Definition: d3_init.h:96
void pass_array_to_javascript(C values)
Definition: js_utils.h:212
SCALE_TYPE & GetScale()
Get a reference to this object&#39;s scale.
Definition: axis.h:160
Axis & SetTickSize(float size)
Definition: axis.h:192