新增能峰拟合分析框选
This commit is contained in:
parent
ceb970319e
commit
db797522e8
|
|
@ -15,6 +15,7 @@
|
|||
#include <QCheckBox>
|
||||
#include <QwtScaleDiv>
|
||||
#include <QFileInfo>
|
||||
#include "PlotRectItem.h"
|
||||
|
||||
|
||||
EnergyCountPeakFitView::EnergyCountPeakFitView(QWidget *parent)
|
||||
|
|
@ -33,6 +34,8 @@ EnergyCountPeakFitView::EnergyCountPeakFitView(QWidget *parent)
|
|||
EnergyCountPeakFitView::~EnergyCountPeakFitView()
|
||||
{
|
||||
LOG_DEBUG(QStringLiteral(u"%1析构.").arg(this->GetViewName()));
|
||||
delete _rubberBand;
|
||||
clearAllSelectionRects();
|
||||
}
|
||||
|
||||
void EnergyCountPeakFitView::InitViewWorkspace(const QString &project_name)
|
||||
|
|
@ -79,8 +82,14 @@ void EnergyCountPeakFitView::setupPlot()
|
|||
// _plot->insertLegend(legend, QwtPlot::RightLegend);
|
||||
|
||||
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
|
||||
|
||||
|
||||
_data_selector = new CustomQwtPlotXaxisSelector(_plot->canvas());
|
||||
_data_selector->setEnabled(false);
|
||||
|
||||
// 启用鼠标追踪,并安装事件过滤器
|
||||
_plot->canvas()->setMouseTracking(true);
|
||||
_plot->canvas()->installEventFilter(this);
|
||||
}
|
||||
|
||||
void EnergyCountPeakFitView::setupMenu()
|
||||
|
|
@ -101,6 +110,13 @@ void EnergyCountPeakFitView::setupMenu()
|
|||
QAction* action_plot_config = this->_menu->addAction(QStringLiteral(u"图表配置"));
|
||||
action_plot_config->setObjectName("plot_config");
|
||||
connect(action_plot_config, &QAction::triggered, this, &EnergyCountPeakFitView::onActionPlotConfigure);
|
||||
|
||||
this->_menu->addSeparator();
|
||||
QAction* action_clear_rect = this->_menu->addAction(QStringLiteral(u"清除框选标记"));
|
||||
connect(action_clear_rect, &QAction::triggered, this, &EnergyCountPeakFitView::clearAllSelectionRects);
|
||||
|
||||
QAction* action_hint = this->_menu->addAction(QStringLiteral(u"框选提示:按住 Ctrl 键并拖动左键"));
|
||||
action_hint->setEnabled(false);
|
||||
}
|
||||
|
||||
void EnergyCountPeakFitView::loadDataFromFile(const QString &data_name, const QString &filename)
|
||||
|
|
@ -209,4 +225,130 @@ void EnergyCountPeakFitView::onActionCurveShowSetting()
|
|||
void EnergyCountPeakFitView::onActionPlotConfigure()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EnergyCountPeakFitView::clearAllSelectionRects()
|
||||
{
|
||||
for (PlotRectItem* item : _selectionRectItems) {
|
||||
if (item) {
|
||||
item->detach();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
_selectionRectItems.clear();
|
||||
_plot->replot();
|
||||
}
|
||||
|
||||
bool EnergyCountPeakFitView::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (watched == _plot->canvas()) {
|
||||
QMouseEvent* me = static_cast<QMouseEvent*>(event);
|
||||
|
||||
// 按下 Ctrl+左键 开始框选
|
||||
if (event->type() == QEvent::MouseButtonPress &&
|
||||
me->button() == Qt::LeftButton &&
|
||||
(me->modifiers() & Qt::ControlModifier)) {
|
||||
startSelection(me->pos());
|
||||
return true;
|
||||
}
|
||||
// 移动时更新橡皮筋
|
||||
else if (event->type() == QEvent::MouseMove && _isSelecting) {
|
||||
updateSelection(me->pos());
|
||||
return true;
|
||||
}
|
||||
// 释放左键完成框选
|
||||
else if (event->type() == QEvent::MouseButtonRelease &&
|
||||
me->button() == Qt::LeftButton && _isSelecting) {
|
||||
finishSelection();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return MeasureAnalysisView::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void EnergyCountPeakFitView::startSelection(const QPoint& pos)
|
||||
{
|
||||
_isSelecting = true;
|
||||
_selectionStart = pos;
|
||||
|
||||
if (!_rubberBand) {
|
||||
_rubberBand = new QRubberBand(QRubberBand::Rectangle, _plot->canvas());
|
||||
}
|
||||
_rubberBand->setGeometry(QRect(pos, QSize()));
|
||||
_rubberBand->show();
|
||||
}
|
||||
|
||||
void EnergyCountPeakFitView::updateSelection(const QPoint& pos)
|
||||
{
|
||||
if (!_rubberBand) return;
|
||||
// 计算矩形(归一化)
|
||||
QRect rect = QRect(_selectionStart, pos).normalized();
|
||||
_rubberBand->setGeometry(rect);
|
||||
}
|
||||
|
||||
void EnergyCountPeakFitView::finishSelection()
|
||||
{
|
||||
if (_rubberBand) {
|
||||
QRect finalRect = _rubberBand->geometry();
|
||||
_rubberBand->hide();
|
||||
if (finalRect.width() > 2 && finalRect.height() > 2) {
|
||||
QRectF plotRect = pixelRectToPlotRect(finalRect);
|
||||
addSelectionRect(plotRect); // 直接添加,不清除旧的
|
||||
// TODO: 在此处添加峰拟合逻辑
|
||||
// ========== 新增拟合逻辑 ==========
|
||||
QList<QwtPlotCurve*> curves = _plot->GetCurveList();
|
||||
if (curves.isEmpty()) return;
|
||||
QwtPlotCurve* originalCurve = curves.first();
|
||||
|
||||
// 获取原始数据
|
||||
QVector<double> origX, origY;
|
||||
for (size_t i = 0; i < originalCurve->dataSize(); ++i) {
|
||||
origX.push_back(originalCurve->sample(i).x());
|
||||
origY.push_back(originalCurve->sample(i).y());
|
||||
}
|
||||
|
||||
// 提取框内的点
|
||||
QVector<double> roiX, roiY;
|
||||
for (int i = 0; i < origX.size(); ++i) {
|
||||
if (origX[i] >= plotRect.left() && origX[i] <= plotRect.right() &&
|
||||
origY[i] >= plotRect.bottom() && origY[i] <= plotRect.top()) {
|
||||
roiX.push_back(origX[i]);
|
||||
roiY.push_back(origY[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (roiX.size() >= 3)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isSelecting = false;
|
||||
}
|
||||
|
||||
QRectF EnergyCountPeakFitView::pixelRectToPlotRect(const QRect& pixelRect) const
|
||||
{
|
||||
const QwtScaleMap xMap = _plot->canvasMap(QwtPlot::xBottom);
|
||||
const QwtScaleMap yMap = _plot->canvasMap(QwtPlot::yLeft);
|
||||
|
||||
double x1 = xMap.invTransform(pixelRect.left());
|
||||
double x2 = xMap.invTransform(pixelRect.right());
|
||||
double y1 = yMap.invTransform(pixelRect.top());
|
||||
double y2 = yMap.invTransform(pixelRect.bottom());
|
||||
|
||||
return QRectF(QPointF(x1, y1), QPointF(x2, y2)).normalized();
|
||||
}
|
||||
|
||||
void EnergyCountPeakFitView::addSelectionRect(const QRectF &plotRect)
|
||||
{
|
||||
PlotRectItem* rectItem = new PlotRectItem("Selection");
|
||||
rectItem->setAxes(QwtPlot::xBottom, QwtPlot::yLeft);
|
||||
rectItem->setRect(plotRect);
|
||||
rectItem->attach(_plot);
|
||||
_selectionRectItems.append(rectItem);
|
||||
_plot->replot();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,17 @@
|
|||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <MeasureAnalysisView.h>
|
||||
#include <QwtPlotPicker>
|
||||
#include <QwtPickerDragRectMachine>
|
||||
#include <QRubberBand> // 新增
|
||||
#include <qwt_plot_shapeitem.h> // 新增
|
||||
|
||||
class PlotRectItem; // 前向声明
|
||||
class QMenu;
|
||||
class CustomQwtPlot;
|
||||
class CustomQwtPlotXaxisSelector;
|
||||
|
||||
class QwtPlotPicker;
|
||||
class QwtPlotCurve;
|
||||
class EnergyCountPeakFitView : public MeasureAnalysisView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -27,12 +33,32 @@ private:
|
|||
private slots:
|
||||
void onActionCurveShowSetting();
|
||||
void onActionPlotConfigure();
|
||||
void clearAllSelectionRects();
|
||||
protected:
|
||||
bool eventFilter(QObject* watched, QEvent* event) override; // 事件过滤器
|
||||
|
||||
private:
|
||||
void startSelection(const QPoint& pos);
|
||||
void updateSelection(const QPoint& pos);
|
||||
void finishSelection();
|
||||
QRectF pixelRectToPlotRect(const QRect& pixelRect) const;
|
||||
void addSelectionRect(const QRectF& plotRect);
|
||||
|
||||
|
||||
private:
|
||||
CustomQwtPlot* _plot = nullptr;
|
||||
QMenu* _menu = nullptr;
|
||||
QDialog* _curve_show_setting_dlg = nullptr;
|
||||
CustomQwtPlotXaxisSelector* _data_selector = nullptr;
|
||||
// 手动框选状态
|
||||
bool _isSelecting = false;
|
||||
QPoint _selectionStart;
|
||||
QRubberBand* _rubberBand = nullptr; // 原生橡皮筋
|
||||
QList<PlotRectItem*> _selectionRectItems;
|
||||
|
||||
QwtPlotCurve* _fittedCurve = nullptr; // 显示拟合结果的曲线
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // ENERGYCOUNTPEAKFITVIEW_H
|
||||
|
|
|
|||
42
src/EnergyCountPeakFitView/PlotRectItem.cpp
Normal file
42
src/EnergyCountPeakFitView/PlotRectItem.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#include "PlotRectItem.h"
|
||||
#include <QPainter>
|
||||
#include <QwtScaleMap>
|
||||
PlotRectItem::PlotRectItem(const QString &title)
|
||||
: QwtPlotItem() {
|
||||
setTitle(title);
|
||||
setZ(1000);
|
||||
m_pen = QPen(Qt::red, 2, Qt::SolidLine);
|
||||
m_brush = QBrush(QColor(255, 0, 0, 30));
|
||||
}
|
||||
|
||||
void PlotRectItem::setRect(const QRectF &rect) {
|
||||
m_rect = rect;
|
||||
}
|
||||
|
||||
void PlotRectItem::setPen(const QPen &pen) {
|
||||
m_pen = pen;
|
||||
}
|
||||
|
||||
void PlotRectItem::setBrush(const QBrush &brush) {
|
||||
m_brush = brush;
|
||||
}
|
||||
|
||||
void PlotRectItem::draw(QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &) const {
|
||||
const int x1 = xMap.transform(m_rect.left());
|
||||
const int x2 = xMap.transform(m_rect.right());
|
||||
const int y1 = yMap.transform(m_rect.top());
|
||||
const int y2 = yMap.transform(m_rect.bottom());
|
||||
const QRect rect(QPoint(x1, y1), QPoint(x2, y2));
|
||||
|
||||
painter->save();
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(m_brush);
|
||||
painter->drawRect(rect);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QRectF PlotRectItem::boundingRect() const {
|
||||
return m_rect;
|
||||
}
|
||||
28
src/EnergyCountPeakFitView/PlotRectItem.h
Normal file
28
src/EnergyCountPeakFitView/PlotRectItem.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef PLOTRECTITEM_H
|
||||
#define PLOTRECTITEM_H
|
||||
|
||||
#include <qwt_plot_item.h>
|
||||
#include <QRectF>
|
||||
#include <QString>
|
||||
#include <QPen>
|
||||
class PlotRectItem : public QwtPlotItem {
|
||||
public:
|
||||
PlotRectItem(const QString &title = QString());
|
||||
|
||||
void setRect(const QRectF &rect);
|
||||
void setPen(const QPen &pen);
|
||||
void setBrush(const QBrush &brush);
|
||||
|
||||
virtual void draw(QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &canvasRect) const override;
|
||||
|
||||
virtual QRectF boundingRect() const override;
|
||||
|
||||
private:
|
||||
QRectF m_rect;
|
||||
QPen m_pen;
|
||||
QBrush m_brush;
|
||||
};
|
||||
|
||||
#endif // PLOTRECTITEM_H
|
||||
|
|
@ -74,6 +74,7 @@ SOURCES += \
|
|||
DeviceParameterConfig/DeviceParameterConfig.cpp \
|
||||
DeviceParameterConfig/DeviceParameterConfigList.cpp \
|
||||
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
||||
EnergyCountPeakFitView/PlotRectItem.cpp \
|
||||
EnergyCountPlotView/EnergyCountPlotView.cpp \
|
||||
EnergyScaleDataModel.cpp \
|
||||
EnergyScaleForm.cpp \
|
||||
|
|
@ -119,6 +120,7 @@ HEADERS += \
|
|||
DeviceParameterConfig/DeviceParameterConfig.h \
|
||||
DeviceParameterConfig/DeviceParameterConfigList.h \
|
||||
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
||||
EnergyCountPeakFitView/PlotRectItem.h \
|
||||
EnergyCountPlotView/EnergyCountPlotView.h \
|
||||
EnergyScaleDataModel.h \
|
||||
EnergyScaleForm.h \
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user