1 #ifndef RAMMING_CHART_H_ 2 #define RAMMING_CHART_H_ 3 4 #include <vector> 5 #include <wx/wxprec.h> 6 #ifndef WX_PRECOMP 7 #include <wx/wx.h> 8 #endif 9 10 wxDECLARE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); 11 12 13 class Chart : public wxWindow { 14 15 public: Chart(wxWindow * parent,wxRect rect,const std::vector<std::pair<float,float>> & initial_buttons,int ramming_speed_size,float sampling,int scale_unit=10)16 Chart(wxWindow* parent, wxRect rect,const std::vector<std::pair<float,float>>& initial_buttons,int ramming_speed_size, float sampling, int scale_unit=10) : 17 wxWindow(parent,wxID_ANY,rect.GetTopLeft(),rect.GetSize()), 18 scale_unit(scale_unit), legend_side(5*scale_unit) 19 { 20 SetBackgroundStyle(wxBG_STYLE_PAINT); 21 m_rect = wxRect(wxPoint(legend_side,0),rect.GetSize()-wxSize(legend_side,legend_side)); 22 visible_area = wxRect2DDouble(0.0, 0.0, sampling*ramming_speed_size, 20.); 23 m_buttons.clear(); 24 if (initial_buttons.size()>0) 25 for (const auto& pair : initial_buttons) 26 m_buttons.push_back(wxPoint2DDouble(pair.first,pair.second)); 27 recalculate_line(); 28 } set_xy_range(float x,float y)29 void set_xy_range(float x,float y) { 30 x = int(x/0.5) * 0.5; 31 if (x>=0) visible_area.SetRight(x); 32 if (y>=0) visible_area.SetBottom(y); 33 recalculate_line(); 34 } get_volume() const35 float get_volume() const { return m_total_volume; } get_time() const36 float get_time() const { return visible_area.m_width; } 37 38 std::vector<float> get_ramming_speed(float sampling) const; //returns sampled ramming speed 39 std::vector<std::pair<float,float>> get_buttons() const; // returns buttons position 40 41 void draw(); 42 43 void mouse_clicked(wxMouseEvent& event); 44 void mouse_right_button_clicked(wxMouseEvent& event); 45 void mouse_moved(wxMouseEvent& event); 46 void mouse_double_clicked(wxMouseEvent& event); mouse_left_window(wxMouseEvent &)47 void mouse_left_window(wxMouseEvent&) { m_dragged = nullptr; } mouse_released(wxMouseEvent &)48 void mouse_released(wxMouseEvent&) { m_dragged = nullptr; } paint_event(wxPaintEvent &)49 void paint_event(wxPaintEvent&) { draw(); } 50 DECLARE_EVENT_TABLE() 51 52 53 54 55 private: 56 static const bool fixed_x = true; 57 static const bool splines = true; 58 static const bool manual_points_manipulation = false; 59 static const int side = 10; // side of draggable button 60 61 const int scale_unit; 62 int legend_side; 63 64 class ButtonToDrag { 65 public: operator <(const ButtonToDrag & a) const66 bool operator<(const ButtonToDrag& a) const { return m_pos.m_x < a.m_pos.m_x; } ButtonToDrag(wxPoint2DDouble pos)67 ButtonToDrag(wxPoint2DDouble pos) : m_pos{pos} {}; get_pos() const68 wxPoint2DDouble get_pos() const { return m_pos; } move(double x,double y)69 void move(double x,double y) { m_pos.m_x+=x; m_pos.m_y+=y; } 70 private: 71 wxPoint2DDouble m_pos; // position in math coordinates 72 }; 73 74 75 math_to_screen(const wxPoint2DDouble & math) const76 wxPoint math_to_screen(const wxPoint2DDouble& math) const { 77 wxPoint screen; 78 screen.x = (math.m_x-visible_area.m_x) * (m_rect.GetWidth() / visible_area.m_width ); 79 screen.y = (math.m_y-visible_area.m_y) * (m_rect.GetHeight() / visible_area.m_height ); 80 screen.y *= -1; 81 screen += m_rect.GetLeftBottom(); 82 return screen; 83 } screen_to_math(const wxPoint & screen) const84 wxPoint2DDouble screen_to_math(const wxPoint& screen) const { 85 wxPoint2DDouble math = screen; 86 math -= m_rect.GetLeftBottom(); 87 math.m_y *= -1; 88 math.m_x *= visible_area.m_width / m_rect.GetWidth(); // scales to [0;1]x[0,1] 89 math.m_y *= visible_area.m_height / m_rect.GetHeight(); 90 return (math+visible_area.GetLeftTop()); 91 } 92 which_button_is_clicked(const wxPoint & point) const93 int which_button_is_clicked(const wxPoint& point) const { 94 if (!m_rect.Contains(point)) 95 return -1; 96 for (unsigned int i=0;i<m_buttons.size();++i) { 97 wxRect rect(math_to_screen(m_buttons[i].get_pos())-wxPoint(side/2.,side/2.),wxSize(side,side)); // bounding rectangle of this button 98 if ( rect.Contains(point) ) 99 return i; 100 } 101 return (-1); 102 } 103 104 105 void recalculate_line(); 106 void recalculate_volume(); 107 108 109 wxRect m_rect; // rectangle on screen the chart is mapped into (screen coordinates) 110 wxPoint m_previous_mouse; 111 std::vector<ButtonToDrag> m_buttons; 112 std::vector<int> m_line_to_draw; 113 wxRect2DDouble visible_area; 114 ButtonToDrag* m_dragged = nullptr; 115 float m_total_volume = 0.f; 116 117 }; 118 119 120 #endif // RAMMING_CHART_H_