/
Stormbery
/
CEX
Обзор
Документация
Войти
/
Stormbery
/
CEX
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/plot2d.cpp
291 строка
11 KB
Stormbery
HTTP запросы через корутины
23 май 2024, 13:30
23 май 2024, 13:30
7a69853
Код
Авторство
О чём код?
/** * \file Файл описания членов класса Plot2D * * Файл содержит определение членов класса для отрисовкиб масштабирования сдвига графиков на холсте */ #include "plot2d.h" using namespace boost; Plot2D::Plot2D () { m_maxSize = 0; m_delta = 0; auto GestureClick = Gtk::GestureClick::create(); auto MotionController = Gtk::EventControllerMotion::create(); auto ScrollController = Gtk::EventControllerScroll::create(); GestureClick->signal_pressed().connect(sigc::mem_fun(*this, &Plot2D::MouseButtonPressed)); GestureClick->signal_released().connect(sigc::mem_fun(*this, &Plot2D::MouseButtonReleased)); MotionController->signal_motion ().connect(sigc::mem_fun(*this, &Plot2D::Motioning)); ScrollController->signal_scroll().connect(sigc::mem_fun(*this, &Plot2D::Scrolling), false); ScrollController->set_flags(Gtk::EventControllerScroll::Flags::VERTICAL); set_draw_func(sigc::mem_fun(*this, &Plot2D::OnDraw)); add_controller(GestureClick); add_controller(MotionController); add_controller(ScrollController); } bool Plot2D::Scrolling(double dx, double dy) { double xMin; double xMax; double deltaX; xMin = m_interval_begin; xMax = m_interval_end; if (xMax == 0) xMax = m_maxSize; deltaX = (xMax-xMin) * XY_SCROLL_COEF; if (dy == 1) { xMin = xMin-deltaX; xMax = xMax+deltaX; if ((xMax - xMin) > m_maxSize * 0.95) return true; //если очень большая дельта то ничего не увеличиваем if ((xMax >= m_maxSize) | (xMax <= 5)) xMax = 0; if (xMin <= 20) xMin = 20; m_delta = m_delta + XY_SCROLL_COEF; // PlotDraw(m_current_axes_name, xMin, xMax, m_Y_offset_min - m_delta, m_Y_offset_max + m_delta); PlotDraw(m_current_axes_name, xMin, xMax, 0, m_Y_offset_max + m_delta); } else if (dy == -1) { xMin=xMin + deltaX; xMax=xMax - deltaX; if ((xMax - xMin) < 30) return true; //если очень маленькая дельта то ничего не уменьшаем if ((xMax >= m_maxSize) | (xMax <= 5)) xMax = 0; if (xMin <= 20) xMin = 20; m_delta = m_delta - XY_SCROLL_COEF; // PlotDraw(m_current_axes_name, xMin, xMax, m_Y_offset_min + m_delta, m_Y_offset_max - m_delta); PlotDraw(m_current_axes_name, xMin, xMax, 0, m_Y_offset_max - m_delta); } return true; } void Plot2D::MouseButtonPressed(int n_press, double x, double y) { m_StartPosX = x; m_StartPosY = y; int width = get_allocated_width (); if ((n_press == 2) && (x < width * X_OFFSET_LEFT)) { //изменение имени плота для отображения значений осей на графике auto i = m_plot_data.begin(); while (i != m_plot_data.end()) { m_PlotData2D_temp = *i; if (m_current_axes_name == m_PlotData2D_temp->GetName()) { ++i; if (i==m_plot_data.end()) { i = m_plot_data.begin(); m_PlotData2D_temp = *i; } else { m_PlotData2D_temp = *i; } m_current_axes_name = m_PlotData2D_temp->GetName(); m_Y_offset_min = m_PlotData2D_temp->GetMinOffsetY(); m_Y_offset_max = m_PlotData2D_temp->GetMaxOffsetY(); break; } ++i; } queue_draw();//полная перерисовка области } if ((n_press == 2) && (x > width * X_OFFSET_LEFT)) { // возвращение графика к исходному масштабированию m_Y_offset_min = 999; m_Y_offset_max = 999; m_interval_begin = 300; // количество интервалов для отображения по умолчанию от конца массива данных(изменить !!!!!!) m_interval_end = 0; queue_draw();//полная перерисовка области m_Y_offset_min = 0.001; m_Y_offset_max = 0.001; } m_MotionOn = true; } void Plot2D::MouseButtonReleased(int n_press, double x, double y) { m_MotionOn = false; } void Plot2D::Motioning(double x, double y) { double deltaX = 0.0; double deltaY = 0.0; int width, height; width = get_allocated_width (); height = get_allocated_height (); if ((m_MotionOn == true) && (m_StartPosX > X_OFFSET_LEFT*width)) { //сдвиг графиков по оси Х deltaX = X_SHIFT_COEF * (x - m_StartPosX) / (static_cast<double> (width) * (1 - X_OFFSET_LEFT - X_OFFSET_RIGHT)); m_StartPosX = x; m_interval_end_temp = m_interval_end - deltaX; m_interval_begin_temp = m_interval_begin - deltaX; if ((m_interval_end == 0) | (m_interval_end_temp >= m_maxSize)) { m_interval_begin_temp = m_interval_begin; m_interval_end_temp = m_maxSize; } else if (m_interval_end_temp <= 10) { //ограничение от выход за пределы значений массива данных m_interval_begin_temp = m_interval_begin; m_interval_end_temp = 9; } else if (m_interval_begin_temp <= 1) { //ограничение от выход за пределы значений массива данных m_interval_begin_temp = 0; m_interval_end_temp = m_interval_end; } PlotDraw(m_current_axes_name,m_interval_begin_temp, m_interval_end_temp, m_Y_offset_min, m_Y_offset_max); } if ((m_MotionOn == true) && (m_StartPosX < X_OFFSET_LEFT*width)) { //сдвиг оси Y текущего графика deltaY = (y - m_StartPosY); m_StartPosY = y; if (deltaY > 0) deltaY = Y_SCROLL_COEF; else deltaY = -Y_SCROLL_COEF; m_Y_offset_max = m_Y_offset_max + deltaY; m_Y_offset_min = m_Y_offset_min - deltaY; PlotDraw(m_current_axes_name,m_interval_begin, m_interval_end, m_Y_offset_min, m_Y_offset_max); } } void Plot2D::AddDataToPlot(PlotData2D *data) { container::vector<PlotData2D*> ::iterator iter = find(m_plot_data, data); if (iter == m_plot_data.end()) { m_plot_data.push_back(data); } for (auto i = m_plot_data.begin(); i != m_plot_data.end(); i++) { m_PlotData2D_temp = *i; auto temp = m_PlotData2D_temp->GetSize(); if (temp > m_maxSize) { m_maxSize = temp; } } } void Plot2D::OnDraw(const Cairo::RefPtr<Cairo::Context> &cr, uint16_t width, uint16_t height) { switch (OnDrawState) { case OnDrawSignals::DrawPlot: { PlotsDrawing(cr, width, height); AxesDrawing(cr, width, height); break; } case OnDrawSignals::DrawAxes: { break; } case OnDrawSignals::MovePLot: { break; } case OnDrawSignals::IdlePLot: { break; } } } void Plot2D::PlotsDrawing(const ::Cairo::RefPtr<::Cairo::Context> &cr,uint16_t width,uint16_t height) { for (auto i = m_plot_data.begin(); i != m_plot_data.end(); i++) { m_PlotData2D_temp = *i; if (m_PlotData2D_temp->GetName() == m_current_axes_name) { m_PlotData2D_temp->DataDraw(cr, width, height, m_interval_begin, m_interval_end,m_Y_offset_min, m_Y_offset_max); } else { m_PlotData2D_temp->DataDraw(cr, width, height, m_interval_begin, m_interval_end, 0.0, 0.0); } } } void Plot2D::PlotDraw(ustring axes_name,double interval_begin,double interval_end, double y_offset_min,double y_offset_max) //шкала Y берется от плота с именем axes_name { OnDrawState = OnDrawSignals::DrawPlot; // выбирается функция перерисовки cairo графики+оси m_current_axes_name = axes_name; m_interval_begin = interval_begin; m_interval_end = interval_end; m_Y_offset_min = y_offset_min; m_Y_offset_max = y_offset_max; queue_draw();//полная перерисовка области } void Plot2D::AxesDrawing(const ::Cairo::RefPtr<::Cairo::Context> &cr,uint16_t width,uint16_t height) //отрисовка осей и шкал { unsigned long long x_min; unsigned long long x_max; double y_min; double y_max; double stepX; double stepY; double stepX_data; double stepY_data; double step_temp; ustring str; ustring strY; Gdk::RGBA color; for (auto i = m_plot_data.begin(); i != m_plot_data.end(); i++) { m_PlotData2D_temp = *i; if (m_PlotData2D_temp->GetName() == m_current_axes_name) { y_min = m_PlotData2D_temp->GetMinY(); y_max = m_PlotData2D_temp->GetMaxY(); x_min = m_PlotData2D_temp->GetMinX(); x_max = m_PlotData2D_temp->GetMaxX(); color = m_PlotData2D_temp->GetColor(); } } stepX = (width - width * (X_OFFSET_LEFT + X_OFFSET_RIGHT)) / GRID_X; stepY = (height - height * (Y_OFFSET_UP + Y_OFFSET_DOWN)) / GRID_Y; stepY_data = (y_max - y_min) / GRID_Y; stepX_data = (x_max - x_min) / GRID_X; cr -> save(); cr -> move_to(0, height); cr -> line_to(width, height); // рисуем ось Х(внизу холста) cr -> move_to(0, 0); cr -> line_to(0, height);// рисуем ось Y(слева холста) cr -> stroke(); cr -> restore(); cr -> save(); cr -> set_source_rgba( color.get_red(), color.get_green(), color.get_blue(), color.get_alpha()); step_temp = x_min; for (uint16_t i = 1 ; i <= GRID_X; i++) { cr -> move_to(X_OFFSET_LEFT * width + stepX * i, height - X_OFFSET_TEXT); step_temp = static_cast<unsigned long long>(step_temp + stepX_data); str = lexical_cast<std::string>(step_temp); cr -> show_text(str); } step_temp = y_min; for (uint16_t i = 1;i <= GRID_Y; i++) { cr -> move_to(Y_OFFSET_TEXT, height - (Y_OFFSET_UP * height + stepY * i)); step_temp = step_temp + stepY_data; str = lexical_cast<std::string>(step_temp); uint16_t count{}; for(const char c: str) { count++; if(c == ',') break; } std::string strY=str.substr(0,count+2); // обрезаем все, что после 2х знаков после запятой cr->show_text(strY); } cr -> stroke(); cr -> restore(); }