// // Created by Lenn on 2025/10/17. // #ifndef TOUCHSENSOR_HEATMAP_IMPL_HH #define TOUCHSENSOR_HEATMAP_IMPL_HH #include "heatmap.hh" #include "modern-qt/utility/theme/theme.hh" #include "modern-qt/widget/sliders.hh" #include #include #include using namespace creeper::plot_widget::internal; struct BasicPlot::Impl { explicit Impl(BasicPlot& self) noexcept : self{self}, initialized(false), matrix_size(QSize{3, 4}) {} public: auto set_xlabel_text(const QString& text) -> void { xlabel = text; if (initialized) { self.xAxis->setLabel(text); self.replot(); } } auto set_ylabel_text(const QString& text) -> void { ylabel = text; if (initialized) { self.yAxis->setLabel(text); self.replot(); } } auto set_matrix_size(const QSize& size) -> void { matrix_size = size; if (initialized) { reset_plot(); if (!data_points.isEmpty()) { set_data(data_points); } } } auto load_theme_manager(ThemeManager& mgr) -> void { mgr.append_handler(&self, [this](const ThemeManager& mgr) { if (initialized) { self.replot(); } }); } auto set_color_gradient_range(const double& min, const double& max) -> void { if (initialized && self.plottableCount() > 0) { auto* cpmp = static_cast(self.plottable(0)); cpmp->setDataRange(QCPRange(min, max)); self.replot(); } color_min = min; color_max = max; } auto set_data(const QVector& data) -> void { data_points = data; if (initialized) { update_plot_data(); } } auto initialize_plot() -> void { if (initialized) return; QCPColorMap* cpmp = new QCPColorMap(self.xAxis, self.yAxis); cpmp->data()->setSize(matrix_size.width(), matrix_size.height()); cpmp->data()->setRange(QCPRange(0.5, matrix_size.width() - 0.5), QCPRange(0.5, matrix_size.height() - 0.5)); QSharedPointer xticker(new QCPAxisTickerText); QSharedPointer yticker(new QCPAxisTickerText); xticker->setSubTickCount(1); yticker->setSubTickCount(1); self.xAxis->setVisible(false); self.yAxis->setVisible(false); self.xAxis->setTicker(xticker); self.yAxis->setTicker(yticker); self.xAxis->grid()->setPen(Qt::NoPen); self.yAxis->grid()->setPen(Qt::NoPen); self.xAxis->grid()->setSubGridVisible(true); self.yAxis->grid()->setSubGridVisible(true); self.xAxis->setSubTicks(true); self.yAxis->setSubTicks(true); self.xAxis->setTickLength(0); self.yAxis->setTickLength(0); self.xAxis->setSubTickLength(6); self.yAxis->setSubTickLength(6); self.xAxis->setRange(0, matrix_size.width()); self.yAxis->setRange(0, matrix_size.height()); if (!xlabel.isEmpty()) self.xAxis->setLabel(xlabel); if (!ylabel.isEmpty()) self.yAxis->setLabel(ylabel); QCPColorScale* color_scale = new QCPColorScale(&self); color_scale->setType(QCPAxis::atBottom); self.plotLayout()->addElement(1, 0, color_scale); cpmp->setColorScale(color_scale); QCPColorGradient gradient; gradient.setColorStopAt(0.0, QColor(246, 239, 166)); // F6EFA6 gradient.setColorStopAt(1.0, QColor(191, 68, 76)); // BF444C cpmp->setGradient(gradient); cpmp->setDataRange(QCPRange(color_min, color_max)); cpmp->setInterpolate(false); QCPMarginGroup *margin_group = new QCPMarginGroup(&self); self.axisRect()->setMarginGroup(QCP::msLeft | QCP::msRight, margin_group); color_scale->setMarginGroup(QCP::msLeft | QCP::msRight, margin_group); initialized = true; if (!data_points.isEmpty()) { update_plot_data(); } } auto reset_plot() -> void { // 清除所有绘图元素 self.clearPlottables(); self.clearGraphs(); self.clearItems(); self.clearFocus(); // 重新初始化 initialized = false; initialize_plot(); } auto update_plot_data() -> void { if (!initialized || self.plottableCount() == 0) return; auto* cpmp = static_cast(self.plottable(0)); // 设置新数据 for (const auto& item : data_points) { if (item.x >= 0 && item.x < matrix_size.width() && item.y >= 0 && item.y < matrix_size.height()) { cpmp->data()->setCell(item.x, item.y, item.z); } } // 重绘 self.replot(); } auto is_plot_initialized() const -> bool { return initialized; } auto get_matrix_size() const -> QSize { return matrix_size; } private: QString xlabel; QString ylabel; QSize matrix_size; QVector data_points; double color_min = 0.0; double color_max = 800.0; bool initialized; BasicPlot& self; }; #endif // TOUCHSENSOR_HEATMAP_IMPL_HH