feat/dataset-detail-chart #5
|
|
@ -7,9 +7,18 @@
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include <qwt_plot.h>
|
||||||
|
#include <qwt_plot_grid.h>
|
||||||
|
#include <qwt_plot_magnifier.h>
|
||||||
|
#include <qwt_plot_rescaler.h>
|
||||||
|
|
||||||
#include "PanelHeader.hpp"
|
#include "PanelHeader.hpp"
|
||||||
#include "panels/AnomalyTablePanel.hpp"
|
#include "panels/AnomalyTablePanel.hpp"
|
||||||
#include "panels/DescriptionPanel.hpp"
|
#include "panels/DescriptionPanel.hpp"
|
||||||
|
#include "panels/chart/ColorBarWidget.hpp"
|
||||||
|
#include "panels/chart/ColorMapService.hpp"
|
||||||
|
#include "panels/chart/ContourPlotItem.hpp"
|
||||||
|
#include "panels/chart/LivePanner.hpp"
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
|
|
@ -85,16 +94,42 @@ GridDataChartView::GridDataChartView(QWidget* parent) : QWidget(parent) {
|
||||||
|
|
||||||
lay->addWidget(toolbar);
|
lay->addWidget(toolbar);
|
||||||
|
|
||||||
// ---- 图表占位区(stretch) ----
|
// ---- QwtPlot(仿 RawDataChartView,差异:x 轴在底部、不画过原点零线、网格线被填充覆盖故省)----
|
||||||
plotArea_ = new QWidget(this);
|
plot_ = new QwtPlot(this);
|
||||||
plotArea_->setObjectName(QStringLiteral("gridPlotArea"));
|
plot_->setObjectName(QStringLiteral("gridPlotArea"));
|
||||||
lay->addWidget(plotArea_, 1);
|
plot_->enableAxis(QwtPlot::xBottom, true);
|
||||||
|
plot_->enableAxis(QwtPlot::xTop, false);
|
||||||
|
plot_->enableAxis(QwtPlot::yLeft, true);
|
||||||
|
|
||||||
// ---- 色阶占位(固定高 36px) ----
|
// 白底浅色(对齐原版 web 图表)。
|
||||||
auto* colorScaleBar = new QWidget(this);
|
plot_->setCanvasBackground(QBrush(Qt::white));
|
||||||
colorScaleBar->setObjectName(QStringLiteral("gridColorScaleBar"));
|
plot_->setAutoFillBackground(true);
|
||||||
colorScaleBar->setFixedHeight(36);
|
{
|
||||||
lay->addWidget(colorScaleBar);
|
QPalette pal = plot_->palette();
|
||||||
|
pal.setColor(QPalette::Window, Qt::white);
|
||||||
|
pal.setColor(QPalette::WindowText, QColor(90, 90, 90));
|
||||||
|
pal.setColor(QPalette::Text, QColor(90, 90, 90));
|
||||||
|
plot_->setPalette(pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 交互:LivePanner(左键实时平移,x 底轴 + y 左轴)+ Magnifier(滚轮缩放,反向使上滚=放大)。
|
||||||
|
new LivePanner(plot_, QwtPlot::xBottom, QwtPlot::yLeft, this);
|
||||||
|
auto* magnifier = new QwtPlotMagnifier(plot_->canvas());
|
||||||
|
magnifier->setWheelFactor(1.0 / 0.9);
|
||||||
|
|
||||||
|
plot_->setMinimumSize(0, 0);
|
||||||
|
|
||||||
|
// 锁定 x:y 真实比尺(参考轴 xBottom,Expanding)。
|
||||||
|
rescaler_ = new QwtPlotRescaler(plot_->canvas(), QwtPlot::xBottom, QwtPlotRescaler::Expanding);
|
||||||
|
rescaler_->setAspectRatio(1.0);
|
||||||
|
rescaler_->setEnabled(true);
|
||||||
|
|
||||||
|
lay->addWidget(plot_, 1);
|
||||||
|
|
||||||
|
// ---- 独立色阶条(固定高 36px)----
|
||||||
|
colorBar_ = new ColorBarWidget(this);
|
||||||
|
colorBar_->setObjectName(QStringLiteral("gridColorScaleBar"));
|
||||||
|
lay->addWidget(colorBar_);
|
||||||
|
|
||||||
// ---- 底部双页签(异常列表 / 描述),固定高约 200px ----
|
// ---- 底部双页签(异常列表 / 描述),固定高约 200px ----
|
||||||
anomalyTable_ = new AnomalyTablePanel(this);
|
anomalyTable_ = new AnomalyTablePanel(this);
|
||||||
|
|
@ -109,12 +144,67 @@ GridDataChartView::GridDataChartView(QWidget* parent) : QWidget(parent) {
|
||||||
auto* bottomContainer = tabbedBottom.container;
|
auto* bottomContainer = tabbedBottom.container;
|
||||||
bottomContainer->setFixedHeight(200);
|
bottomContainer->setFixedHeight(200);
|
||||||
lay->addWidget(bottomContainer);
|
lay->addWidget(bottomContainer);
|
||||||
|
|
||||||
|
// ---- 工具条开关 → 重建/重绘 ----
|
||||||
|
connect(chkShowAnom, &QCheckBox::toggled, this, [this](bool on) {
|
||||||
|
showAnomalies_ = on;
|
||||||
|
if (contourItem_) { contourItem_->setShowAnomalies(on); plot_->replot(); }
|
||||||
|
});
|
||||||
|
connect(chkShowContourLabel, &QCheckBox::toggled, this, [this](bool on) {
|
||||||
|
showLabels_ = on;
|
||||||
|
if (contourItem_) { contourItem_->setShowLabels(on); plot_->replot(); }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridDataChartView::setData(const geopro::controller::DatasetDetailController::ChartData& d) {
|
void GridDataChartView::setData(const geopro::controller::DatasetDetailController::ChartData& d) {
|
||||||
data_ = d;
|
data_ = d;
|
||||||
// 步骤1:只把 anomalies 喂给底部异常列表;图表区留空。
|
// 开页:仅把 anomalies 喂给底部异常列表;图表区待网格数据懒加载后填充。
|
||||||
anomalyTable_->setAnomalies(d.anomalies, {}, {});
|
anomalyTable_->setAnomalies(d.anomalies, {}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GridDataChartView::setGridData(const geopro::core::Grid& grid,
|
||||||
|
const geopro::core::ColorScale& gridScale,
|
||||||
|
const std::vector<geopro::core::Anomaly>& anoms) {
|
||||||
|
grid_ = grid;
|
||||||
|
gridScale_ = gridScale;
|
||||||
|
anoms_ = anoms;
|
||||||
|
hasGrid_ = true;
|
||||||
|
|
||||||
|
// 重建色彩服务(旧 contourItem 已 detach/delete)。
|
||||||
|
delete colorSvc_;
|
||||||
|
colorSvc_ = new ColorMapService(gridScale_);
|
||||||
|
|
||||||
|
rebuildContour();
|
||||||
|
|
||||||
|
// 色阶条 + 底部异常表(懒加载结果含真实异常)。
|
||||||
|
colorBar_->setColorScale(gridScale_);
|
||||||
|
anomalyTable_->setAnomalies(anoms_, {}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridDataChartView::rebuildContour() {
|
||||||
|
if (!hasGrid_ || !colorSvc_) return;
|
||||||
|
|
||||||
|
// 卸载旧项(QwtPlot 不拥有 item)。
|
||||||
|
if (contourItem_) {
|
||||||
|
contourItem_->detach();
|
||||||
|
delete contourItem_;
|
||||||
|
contourItem_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
contourItem_ = new ContourPlotItem();
|
||||||
|
contourItem_->setData(grid_, colorSvc_, anoms_, /*showLines*/ true, showLabels_);
|
||||||
|
contourItem_->setShowAnomalies(showAnomalies_);
|
||||||
|
contourItem_->attach(plot_);
|
||||||
|
|
||||||
|
// 轴范围 = 数据范围(x=距离、y=深度/高程)。
|
||||||
|
const QRectF bbox = contourItem_->boundingRect();
|
||||||
|
if (!bbox.isNull()) {
|
||||||
|
plot_->setAxisScale(QwtPlot::xBottom, bbox.left(), bbox.right());
|
||||||
|
plot_->setAxisScale(QwtPlot::yLeft, bbox.top(), bbox.bottom());
|
||||||
|
}
|
||||||
|
plot_->updateAxes();
|
||||||
|
if (rescaler_) rescaler_->rescale(); // 应用真实比尺
|
||||||
|
plot_->replot();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,65 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "DatasetDetailController.hpp"
|
#include "DatasetDetailController.hpp"
|
||||||
|
#include "model/Anomaly.hpp"
|
||||||
|
#include "model/ColorScale.hpp"
|
||||||
|
#include "model/Field.hpp"
|
||||||
|
|
||||||
class QSlider;
|
class QSlider;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
class QwtPlot;
|
||||||
|
class QwtPlotRescaler;
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
class AnomalyTablePanel;
|
class AnomalyTablePanel;
|
||||||
class DescriptionPanel;
|
class DescriptionPanel;
|
||||||
|
class ColorBarWidget;
|
||||||
|
class ColorMapService;
|
||||||
|
class ContourPlotItem;
|
||||||
|
|
||||||
// 网格数据图表视图(步骤1骨架):工具条 + 图表占位 + 色阶占位 + 底部双页签(异常列表/描述)。
|
// 网格数据图表视图:工具条 + QwtPlot(白底 + 真实比尺 + 实时平移/滚轮缩放,x 轴在底部)
|
||||||
// 图表渲染由后续步骤填入 plotArea()。
|
// + 独立色阶条 + 底部双页签(异常列表/描述)。
|
||||||
|
// 填充走 ContourPlotItem 栅格热力图 + 矢量等值线 + 标注 + 异常叠加。
|
||||||
class GridDataChartView : public QWidget {
|
class GridDataChartView : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit GridDataChartView(QWidget* parent = nullptr);
|
explicit GridDataChartView(QWidget* parent = nullptr);
|
||||||
|
|
||||||
// 步骤1:把 anomalies 喂给底部异常列表;图表区留空。
|
// 开页时调用:仅喂底部异常列表(网格数据随网格页激活懒加载)。
|
||||||
void setData(const geopro::controller::DatasetDetailController::ChartData& d);
|
void setData(const geopro::controller::DatasetDetailController::ChartData& d);
|
||||||
|
|
||||||
// 供后续步骤填充 Qwt 画布的占位区域。
|
// 网格数据到达(懒加载结果):建色彩服务 + ContourPlotItem,挂到 QwtPlot,更新色阶条/异常表。
|
||||||
QWidget* plotArea() const { return plotArea_; }
|
void setGridData(const geopro::core::Grid& grid, const geopro::core::ColorScale& gridScale,
|
||||||
|
const std::vector<geopro::core::Anomaly>& anoms);
|
||||||
// 供后续步骤联动异常叠加。
|
|
||||||
AnomalyTablePanel* anomalyTable() const { return anomalyTable_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void rebuildContour(); // 按当前显隐开关重建并重绘 ContourPlotItem
|
||||||
|
|
||||||
geopro::controller::DatasetDetailController::ChartData data_;
|
geopro::controller::DatasetDetailController::ChartData data_;
|
||||||
QWidget* plotArea_;
|
|
||||||
AnomalyTablePanel* anomalyTable_;
|
QwtPlot* plot_ = nullptr;
|
||||||
DescriptionPanel* descriptionPanel_;
|
QwtPlotRescaler* rescaler_ = nullptr;
|
||||||
QSlider* simplifySlider_;
|
ColorBarWidget* colorBar_ = nullptr;
|
||||||
QLabel* simplifyValueLabel_;
|
AnomalyTablePanel* anomalyTable_ = nullptr;
|
||||||
|
DescriptionPanel* descriptionPanel_ = nullptr;
|
||||||
|
QSlider* simplifySlider_ = nullptr;
|
||||||
|
QLabel* simplifyValueLabel_ = nullptr;
|
||||||
|
|
||||||
|
// 渲染状态
|
||||||
|
ColorMapService* colorSvc_ = nullptr; // heap,setGridData 重建
|
||||||
|
ContourPlotItem* contourItem_ = nullptr;
|
||||||
|
geopro::core::Grid grid_{1, 1};
|
||||||
|
geopro::core::ColorScale gridScale_;
|
||||||
|
std::vector<geopro::core::Anomaly> anoms_;
|
||||||
|
bool hasGrid_ = false;
|
||||||
|
|
||||||
|
// 工具条显隐开关
|
||||||
|
bool showAnomalies_ = true;
|
||||||
|
bool showLabels_ = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue