From e3b2d136d3c3eb1986ac3122bf56c3c908354b49 Mon Sep 17 00:00:00 2001 From: tangchao0503 <735056338@qq.com> Date: Thu, 12 Feb 2026 16:10:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=E9=87=87?= =?UTF-8?q?=E9=9B=86=E3=80=81=E5=9B=BE=E5=B1=82=E5=92=8CTOC=E8=81=94?= =?UTF-8?q?=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HPPA/HPPA.cpp | 370 ++++++++++++++++++++--------------- HPPA/HPPA.h | 55 +++--- HPPA/HPPA.ui | 5 +- HPPA/HPPA.vcxproj | 10 +- HPPA/HPPA.vcxproj.filters | 12 ++ HPPA/ImagerOperationBase.cpp | 21 +- HPPA/ImagerOperationBase.h | 8 + HPPA/LayerTreeLayerNode.cpp | 4 +- HPPA/LayerTreeLayerNode.h | 12 +- HPPA/LayerTreeModel.cpp | 5 +- HPPA/LayerTreeModel.h | 4 +- HPPA/MapLayer.cpp | 26 +++ HPPA/MapLayer.h | 28 +++ HPPA/RasterLayer.cpp | 12 ++ HPPA/RasterLayer.h | 14 ++ 15 files changed, 387 insertions(+), 199 deletions(-) create mode 100644 HPPA/MapLayer.cpp create mode 100644 HPPA/MapLayer.h create mode 100644 HPPA/RasterLayer.cpp create mode 100644 HPPA/RasterLayer.h diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index 23e71d9..e3b6054 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -3,113 +3,119 @@ #include #include +#include // 新增,用于解析路径 #include "HPPA.h" #include "ImageReaderWriter.h" - +#include "RasterLayer.h" +#include "LayerTreeLayerNode.h" HPPA::HPPA(QWidget* parent) - : QMainWindow(parent) + : QMainWindow(parent) { - ui.setupUi(this); + ui.setupUi(this); - QCoreApplication::setOrganizationName("IRIS"); - QCoreApplication::setOrganizationDomain("iris.com"); - QCoreApplication::setApplicationName("HPPA"); + // register MapLayer* metatype for queued signal/slot across threads + qRegisterMetaType("MapLayer*"); - //配置文件:如果没有,就创建配置文件 - string HPPACfgFile = getPathofEXE() + "\\HPPA.cfg"; - mConfigfile.setConfigfilePath(HPPACfgFile); - if (!mConfigfile.isConfigfileExist()) - { - mConfigfile.createConfigFile(); - qDebug() << "create: " << QString::fromStdString(HPPACfgFile); - } - mConfigfile.parseConfigfile(); - qDebug() << "exist: " << QString::fromStdString(HPPACfgFile); + QCoreApplication::setOrganizationName("IRIS"); + QCoreApplication::setOrganizationDomain("iris.com"); + QCoreApplication::setApplicationName("HPPA"); - /*int max, min; - mConfigfile.getPositionRestriction(max, min); + //配置文件:如果没有,就创建配置文件 + string HPPACfgFile = getPathofEXE() + "\\HPPA.cfg"; + mConfigfile.setConfigfilePath(HPPACfgFile); + if (!mConfigfile.isConfigfileExist()) + { + mConfigfile.createConfigFile(); + qDebug() << "create: " << QString::fromStdString(HPPACfgFile); + } + mConfigfile.parseConfigfile(); + qDebug() << "exist: " << QString::fromStdString(HPPACfgFile); - string sn; - mConfigfile.getSN(sn); + /*int max, min; + mConfigfile.getPositionRestriction(max, min); - int coarse, fine; - mConfigfile.getTuningStepSize(coarse, fine); - float fa, fb; - mConfigfile.getFitParams(fa, fb); - int max_FocusRange, min_FocusRange; - mConfigfile.getAutoFocusRange(max_FocusRange, min_FocusRange); + string sn; + mConfigfile.getSN(sn); - float StepAnglemar_x, Lead_x, ScaleFactor_x; - int SubdivisionMultiples_x; - mConfigfile.getXMotorParm(StepAnglemar_x, Lead_x, SubdivisionMultiples_x, ScaleFactor_x); - float StepAnglemar_y, Lead_y, ScaleFactor_y; - int SubdivisionMultiples_y; - mConfigfile.getYMotorParm(StepAnglemar_y, Lead_y, SubdivisionMultiples_y, ScaleFactor_y);*/ + int coarse, fine; + mConfigfile.getTuningStepSize(coarse, fine); + float fa, fb; + mConfigfile.getFitParams(fa, fb); + int max_FocusRange, min_FocusRange; + mConfigfile.getAutoFocusRange(max_FocusRange, min_FocusRange); - //状态栏 - //xmotor_state_label1 = new QLabel(); - //ymotor_state_label1 = new QLabel(); - //xmotor_state_label1->setText("xMotor"); - //ymotor_state_label1->setText("yMotor"); - //ui.statusBar->addPermanentWidget(xmotor_state_label1); - //ui.statusBar->addPermanentWidget(ymotor_state_label1); + float StepAnglemar_x, Lead_x, ScaleFactor_x; + int SubdivisionMultiples_x; + mConfigfile.getXMotorParm(StepAnglemar_x, Lead_x, SubdivisionMultiples_x, ScaleFactor_x); + float StepAnglemar_y, Lead_y, ScaleFactor_y; + int SubdivisionMultiples_y; + mConfigfile.getYMotorParm(StepAnglemar_y, Lead_y, SubdivisionMultiples_y, ScaleFactor_y);*/ + + //状态栏 + //xmotor_state_label1 = new QLabel(); + //ymotor_state_label1 = new QLabel(); + //xmotor_state_label1->setText("xMotor"); + //ymotor_state_label1->setText("yMotor"); + //ui.statusBar->addPermanentWidget(xmotor_state_label1); + //ui.statusBar->addPermanentWidget(ymotor_state_label1); - connect(this->ui.action_exit, SIGNAL(triggered()), this, SLOT(onExit())); + connect(this->ui.action_exit, SIGNAL(triggered()), this, SLOT(onExit())); + connect(this->ui.mActionOpenImg, SIGNAL(triggered()), this, SLOT(onOpenImg())); - //ui.cam_label->setScaledContents(true); + //ui.cam_label->setScaledContents(true); - /*ui.splitter->setStretchFactor(0, 1); - ui.splitter->setStretchFactor(1, 1); - ui.splitter->setStretchFactor(2, 3);*/ - - - - - initMenubarToolbar(); + /*ui.splitter->setStretchFactor(0, 1); + ui.splitter->setStretchFactor(1, 1); + ui.splitter->setStretchFactor(2, 3);*/ - //光谱仪操作 - m_Imager = nullptr; - m_RecordState = 0; - connect(this->ui.action_connect_imager, SIGNAL(triggered()), this, SLOT(onconnect()));//信号与槽:连接相机,相机操作相关信号与槽绑定放在函数onconnect中 - //设置相机可用帧率范围:这些设置必须在slider的信号和槽连接connect前,否则setMinimum会改变slider的值 - ui.FramerateSlider->setMinimum(1); - ui.FramerateSlider->setMaximum(250); - ui.GainSlider->setMinimum(0); - ui.GainSlider->setMaximum(24); - //相机参数控件设置为不可用 - frame_number->setEnabled(false); + initMenubarToolbar(); - ui.framerate_lineEdit->setEnabled(false); - ui.integratioin_time_lineEdit->setEnabled(false); - ui.gain_lineEdit->setEnabled(false); - ui.FramerateSlider->setEnabled(false); - ui.IntegratioinTimeSlider->setEnabled(false); - ui.GainSlider->setEnabled(false); - startTimer(1000); + //光谱仪操作 + m_Imager = nullptr; + m_RecordState = 0; + connect(this->ui.action_connect_imager, SIGNAL(triggered()), this, SLOT(onconnect()));//信号与槽:连接相机,相机操作相关信号与槽绑定放在函数onconnect中 - widthScale = 1; - heightScale = 1; + //设置相机可用帧率范围:这些设置必须在slider的信号和槽连接connect前,否则setMinimum会改变slider的值 + ui.FramerateSlider->setMinimum(1); + ui.FramerateSlider->setMaximum(250); + ui.GainSlider->setMinimum(0); + ui.GainSlider->setMaximum(24); + //相机参数控件设置为不可用 + frame_number->setEnabled(false); - //马达位置模拟 - //connect(ui.graphicsView->imager, SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onimagerSimulatorMove(int, int))); + ui.framerate_lineEdit->setEnabled(false); + ui.integratioin_time_lineEdit->setEnabled(false); + ui.gain_lineEdit->setEnabled(false); - initPanelToolbar(); - setDockNestingEnabled(true); - connect(this->ui.action_about, SIGNAL(triggered()), this, SLOT(onAbout())); - connect(this->ui.mActionOneMotorScenario, SIGNAL(triggered()), this, SLOT(createOneMotorScenario())); - connect(this->ui.mActionPlantPhenotypeScenario, SIGNAL(triggered()), this, SLOT(createPlantPhenotypeScenario())); + ui.FramerateSlider->setEnabled(false); + ui.IntegratioinTimeSlider->setEnabled(false); + ui.GainSlider->setEnabled(false); - delete ui.centralWidget; + startTimer(1000); - QString qss_DockWidget_contentWidget = R"( + widthScale = 1; + heightScale = 1; + + //马达位置模拟 + //connect(ui.graphicsView->imager, SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onimagerSimulatorMove(int, int))); + + initPanelToolbar(); + setDockNestingEnabled(true); + connect(this->ui.action_about, SIGNAL(triggered()), this, SLOT(onAbout())); + connect(this->ui.mActionOneMotorScenario, SIGNAL(triggered()), this, SLOT(createOneMotorScenario())); + connect(this->ui.mActionPlantPhenotypeScenario, SIGNAL(triggered()), this, SLOT(createPlantPhenotypeScenario())); + + delete ui.centralWidget; + + QString qss_DockWidget_contentWidget = R"( background: #0D1233; /*border: 1px solid #2c586b;*/ @@ -123,42 +129,42 @@ HPPA::HPPA(QWidget* parent) )"; - //TOC - CustomDockWidgetBase* dock_layers = new CustomDockWidgetBase(QString::fromLocal8Bit("layers"), this); - dock_layers->setObjectName("mDockLayers"); - dock_layers->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - mPanelMenu->addAction(dock_layers->toggleViewAction()); - addDockWidget(Qt::LeftDockWidgetArea, dock_layers); - dock_layers->hideMaxButton(); + //TOC + CustomDockWidgetBase* dock_layers = new CustomDockWidgetBase(QString::fromLocal8Bit("layers"), this); + dock_layers->setObjectName("mDockLayers"); + dock_layers->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + mPanelMenu->addAction(dock_layers->toggleViewAction()); + addDockWidget(Qt::LeftDockWidgetArea, dock_layers); + dock_layers->hideMaxButton(); - //1、没用 - QWidget* dock_layersWidgetContents = new QWidget(); - dock_layersWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents_2")); - QGridLayout* gridLayout_toc = new QGridLayout(dock_layersWidgetContents); - gridLayout_toc->setSpacing(6); - gridLayout_toc->setContentsMargins(11, 11, 11, 11); - gridLayout_toc->setObjectName(QString::fromUtf8("gridLayout_toc")); - gridLayout_toc->setVerticalSpacing(0); - gridLayout_toc->setContentsMargins(0, 0, 0, 0); + //1、没用 + QWidget* dock_layersWidgetContents = new QWidget(); + dock_layersWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents_2")); + QGridLayout* gridLayout_toc = new QGridLayout(dock_layersWidgetContents); + gridLayout_toc->setSpacing(6); + gridLayout_toc->setContentsMargins(11, 11, 11, 11); + gridLayout_toc->setObjectName(QString::fromUtf8("gridLayout_toc")); + gridLayout_toc->setVerticalSpacing(0); + gridLayout_toc->setContentsMargins(0, 0, 0, 0); - ImagerPositionSimulation* graphicsView_delete = new ImagerPositionSimulation(dock_layersWidgetContents); - graphicsView_delete->setObjectName(QString::fromUtf8("graphicsView_delete")); - QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Preferred); - sizePolicy1.setHorizontalStretch(0); - sizePolicy1.setVerticalStretch(0); - sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidth()); - graphicsView_delete->setSizePolicy(sizePolicy1); - graphicsView_delete->setFrameShape(QFrame::NoFrame); - graphicsView_delete->setFrameShadow(QFrame::Raised); - //gridLayout_toc->addWidget(graphicsView_delete, 0, 0, 1, 1); + ImagerPositionSimulation* graphicsView_delete = new ImagerPositionSimulation(dock_layersWidgetContents); + graphicsView_delete->setObjectName(QString::fromUtf8("graphicsView_delete")); + QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); +sizePolicy1.setVerticalStretch(0); +sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidth()); + graphicsView_delete->setSizePolicy(sizePolicy1); + graphicsView_delete->setFrameShape(QFrame::NoFrame); + graphicsView_delete->setFrameShadow(QFrame::Raised); + //gridLayout_toc->addWidget(graphicsView_delete, 0, 0, 1, 1); - //2、没用,仅仅使用QTreeWidget实现的简略ui - QTreeWidget* treeWidget = new QTreeWidget(); - treeWidget->setColumnCount(1); - treeWidget->setIndentation(18); - treeWidget->setRootIsDecorated(true); - treeWidget->header()->hide(); - treeWidget->setStyleSheet(R"( + //2、没用,仅仅使用QTreeWidget实现的简略ui + QTreeWidget* treeWidget = new QTreeWidget(); + treeWidget->setColumnCount(1); + treeWidget->setIndentation(18); + treeWidget->setRootIsDecorated(true); + treeWidget->header()->hide(); + treeWidget->setStyleSheet(R"( QTreeWidget { color: #ACCDFF; @@ -181,47 +187,51 @@ HPPA::HPPA(QWidget* parent) } )"); - //QList items; - //for (int i = 0; i < 3; ++i) - // items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("tmp_image_%1").arg(i)))); - //treeWidget->insertTopLevelItems(0, items); + //QList items; + //for (int i = 0; i < 3; ++i) + // items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("tmp_image_%1").arg(i)))); + //treeWidget->insertTopLevelItems(0, items); - QTreeWidgetItem* group1 = new QTreeWidgetItem(treeWidget); - group1->setText(0, "Raster"); - group1->setExpanded(true); // 默认展开 + QTreeWidgetItem* group1 = new QTreeWidgetItem(treeWidget); + group1->setText(0, "Raster"); + group1->setExpanded(true); // 默认展开 - QTreeWidgetItem* group2 = new QTreeWidgetItem(treeWidget); - group2->setText(0, "Vector"); - group2->setExpanded(true); + QTreeWidgetItem* group2 = new QTreeWidgetItem(treeWidget); + group2->setText(0, "Vector"); + group2->setExpanded(true); - QTreeWidgetItem* layerA = new QTreeWidgetItem(group1); - layerA->setText(0, "tmp_image_1"); + QTreeWidgetItem* layerA = new QTreeWidgetItem(group1); + layerA->setText(0, "tmp_image_1"); - QTreeWidgetItem* layerB = new QTreeWidgetItem(group1); - layerB->setText(0, "tmp_image_2"); + QTreeWidgetItem* layerB = new QTreeWidgetItem(group1); + layerB->setText(0, "tmp_image_2"); - //gridLayout_toc->addWidget(treeWidget, 0, 0, 1, 1); + //gridLayout_toc->addWidget(treeWidget, 0, 0, 1, 1); - //3、正经TOC - LayerTree* tree = new LayerTree(); - auto* model = new LayerTreeModel(tree, this, true); + //3、正经TOC + m_LayerTree = new LayerTree(); + m_LayerTreeModel = new LayerTreeModel(m_LayerTree, this, true); - //auto* g1 = model->addGroup(model->root(), "Group A"); - //model->addLayer(g1, "Roads"); - //model->addLayer(g1, "Buildings"); + // 创建并保留 Raster 分组指针,后续添加 layer 使用它 + m_RasterGroup = m_LayerTreeModel->addGroup(m_LayerTreeModel->root(), "Raster"); + { + auto* ln1 = new LayerTreeLayerNode(nullptr); + ln1->setName("tmp_image_1"); + m_LayerTreeModel->addLayer(m_RasterGroup, ln1); + } + { + auto* ln2 = new LayerTreeLayerNode(nullptr); + ln2->setName("tmp_image_2"); + m_LayerTreeModel->addLayer(m_RasterGroup, ln2); + } + auto* g2 = m_LayerTreeModel->addGroup(m_LayerTreeModel->root(), "Vector"); + //model->addLayer(g2, "Rivers"); - auto* g1 = model->addGroup(model->root(), "Raster"); - model->addLayer(g1, "tmp_image_1"); - model->addLayer(g1, "tmp_image_2"); - - auto* g2 = model->addGroup(model->root(), "Vector"); - //model->addLayer(g2, "Rivers"); - - QTreeView* LayerTreeView = new QTreeView(); - LayerTreeView->setModel(model); - LayerTreeView->setHeaderHidden(true); - LayerTreeView->setStyleSheet(R"( + QTreeView* LayerTreeView = new QTreeView(); + LayerTreeView->setModel(m_LayerTreeModel); + LayerTreeView->setHeaderHidden(true); + LayerTreeView->setStyleSheet(R"( QTreeView { color: #ACCDFF; @@ -244,15 +254,15 @@ HPPA::HPPA(QWidget* parent) } )"); - gridLayout_toc->addWidget(LayerTreeView, 0, 0, 1, 1); + gridLayout_toc->addWidget(LayerTreeView, 0, 0, 1, 1); - dock_layers->setWidget(dock_layersWidgetContents); - dock_layersWidgetContents->setStyleSheet(qss_DockWidget_contentWidget); + dock_layers->setWidget(dock_layersWidgetContents); + dock_layersWidgetContents->setStyleSheet(qss_DockWidget_contentWidget); - //dock_layers->setMinimumWidth(449); - //dock_layers->setMaximumWidth(450); - //dock_layers->setMinimumHeight(497); - //dock_layers->setMaximumHeight(498); + //dock_layers->setMinimumWidth(449); + //dock_layers->setMaximumWidth(450); + //dock_layers->setMinimumHeight(497); + //dock_layers->setMaximumHeight(498); //高光谱查看 @@ -864,6 +874,7 @@ void HPPA::initPanelToolbar() mToolbarMenu->addAction(ui.mainToolBar->toggleViewAction()); } +//---------------------------------------------------- void HPPA::createScenarioActionGroup() { m_ScenarioActionGroup = new QActionGroup(this); @@ -1053,7 +1064,7 @@ void HPPA::onStartRecordStep1() onCreateTab(0); ui.action_start_recording->setText(QString::fromLocal8Bit("停止采集")); - ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(255,0,0);}"); + ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(255,0,0);}"); //应该先控制马达运动,当马达运动后,再开始光谱仪采集(发射开始采集信号) m_Imager->setFileName2Save(imgPath); @@ -1090,12 +1101,12 @@ void HPPA::onStartRecordStep1() } else { - m_tmc->stop(); + m_tmc->stop(); - m_RecordState--; + m_RecordState--; - ui.action_start_recording->setText(QString::fromLocal8Bit("采集")); - ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}"); + ui.action_start_recording->setText(QString::fromLocal8Bit("采集")); + ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}"); } return; @@ -1431,6 +1442,10 @@ void HPPA::onExit() this->close(); } +void HPPA::onOpenImg() +{ +} + void HPPA::onconnect() { if (m_Imager != nullptr) @@ -1494,7 +1509,6 @@ void HPPA::onconnect() m_TestImagerStausThread = new WorkerThread(m_Imager); - connect(this->ui.action_auto_exposure, SIGNAL(triggered()), this, SLOT(onAutoExposure())); connect(this->ui.action_focus, SIGNAL(triggered()), this, SLOT(onFocus1())); connect(this, SIGNAL(StartFocusSignal()), m_Imager, SLOT(focus())); @@ -1508,11 +1522,12 @@ void HPPA::onconnect() connect(m_Imager, SIGNAL(RecordWhiteFinishSignal()), this, SLOT(recordWhiteFinish())); connect(m_Imager, SIGNAL(RecordDarlFinishSignal()), this, SLOT(recordDarkFinish())); + // Connect LayerFileCreated from imager to HPPA slot + connect(m_Imager, SIGNAL(LayerFileCreated(QString,QString,int)), this, SLOT(onLayerCreatedFromFile(QString,QString,int))); + connect(this->ui.actionOpenDirectory, SIGNAL(triggered()), this, SLOT(onActionOpenDirectory())); - - connect(this->ui.framerate_lineEdit, SIGNAL(editingFinished()), this, SLOT(OnFramerateLineeditEditingFinished())); connect(this->ui.FramerateSlider, SIGNAL(valueChanged(double)), this, SLOT(OnFramerateSliderChanged(double))); connect(this->ui.integratioin_time_lineEdit, SIGNAL(editingFinished()), this, SLOT(OnIntegratioinTimeEditingFinished())); @@ -1571,6 +1586,26 @@ void HPPA::testImagerStatus() m_TestImagerStausThread->start(); } +void HPPA::onImageFileSaved(QString path, int fileIndex) +{ + // 该槽在 UI 线程中执行(Qt 会使用 queued connection),可以安全操作 model + QFileInfo fi(path); + QString base = fi.completeBaseName(); // 去掉路径与扩展名(例如 tmp_image_0) + + // 将新的 layer 添加到 Raster 分组 + if (!m_LayerTreeModel || !m_RasterGroup) return; + + // layer 名称可根据需要调整,这里用文件名作为图层名 + { + auto* ln = new LayerTreeLayerNode(nullptr); + ln->setName(base); + m_LayerTreeModel->addLayer(m_RasterGroup, ln); + } + + // 可选:展开 TOC 或者做其他 UI 更新(目前不做动画,仅打印日志) + qDebug() << "ImageFileSaved -> add layer:" << base << " index:" << fileIndex; +} + void HPPA::onAutoExposure() { double ReturnedExposureTime = m_Imager->auto_exposure(); @@ -1757,7 +1792,7 @@ void HPPA::PlotSpectral(int state) //series->append(i, m_Imager->buffer[i + 5 * 900]); //series->append(i, m_Imager->buffer[900 * 150 + i]); series->append(i, m_Imager->buffer[1368 * 150 + i]); - } + } QChart* chart = new QChart(); chart->legend()->hide(); @@ -1868,3 +1903,20 @@ void WorkerThread3::run() emit AutoFocusFinishedSignal(); } + +void HPPA::onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex) +{ + if (!m_LayerTreeModel || !m_RasterGroup) return; + + // Create MapLayer first and attach it to a LayerTreeLayerNode + MapLayer* ml = new RasterLayer(baseName, filePath); + auto* layerNode = new LayerTreeLayerNode(ml); + + LayerTreeNode* node = m_LayerTreeModel->addLayer(m_RasterGroup, layerNode); + LayerTreeLayerNode* lnode = dynamic_cast(node); + if (!lnode) return; + + // layerNode already holds the MapLayer pointer from constructor + + qDebug() << "LayerFileCreated -> created layer:" << baseName << "path:" << filePath << "index:" << fileIndex; +} diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index 28fe91b..e4cac03 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -53,10 +53,11 @@ #include "LayerTreeModel.h" #include "LayerTree.h" +#include "MapLayer.h" #define PI 3.1415926 -QT_CHARTS_USE_NAMESPACE//QChartView ʹ ҪӺ꣬ ޷ʹ +QT_CHARTS_USE_NAMESPACE//QChartView 使用 需要加宏, 否则无法使用 class WorkerThread : public QThread { @@ -83,11 +84,11 @@ public: // //double x = m_Imager->m_ResononImager.get_framerate(); // int x = m_Imager->m_ResononImager.get_band_count(); - // std::cout << "slopeΪ" << x << std::endl; + // std::cout << "相机连接正常!slope为:" << x << std::endl; // } // catch (std::runtime_error *e)//CException *e // { - // std::cout << "Ͽӣ" << e->what() << std::endl; + // std::cout << "相机断开连接!" << e->what() << std::endl; // } // Sleep(1000); // } @@ -142,9 +143,9 @@ class WidgetWithBackgroundPicture : public QWidget public: explicit WidgetWithBackgroundPicture(QWidget* parent = nullptr) : QWidget(parent), - m_pixmap(".//icon//titile_bar_bgp.png") // ʹԴ· + m_pixmap(".//icon//titile_bar_bgp.png") // 使用资源或绝对路径 { - // ѡóʼС + // 可选:设置初始大小 resize(800, 600); } @@ -168,9 +169,9 @@ public: HPPA(QWidget *parent = Q_NULLPTR); ~HPPA(); - void CalculateIntegratioinTimeRange();//ͨ֡ʼʱ䷶Χsliderֵ + void CalculateIntegratioinTimeRange();//通过帧率计算积分时间范围,设置slider最大值 - WorkerThread * m_TestImagerStausThread;//״̬߳ + WorkerThread * m_TestImagerStausThread;//检测相机连接状态的线程 private: Ui::HPPAClass ui; @@ -192,11 +193,11 @@ private: ImagerOperationBase* m_Imager;// - int m_RecordState;//ɼ̣ȡ21 ڲɼ0 ֹͣɼ + int m_RecordState;//用来控制相机采集流程,取2的余数,1 → 正在采集,0 → 停止采集 - QThread * m_RecordThread;//Ӱɼ߳ - QThread * m_RgbCameraThread;//rgbȡͼ߳ - QThread * m_CopyFileThread;//Ӱļ߳ + QThread * m_RecordThread;//影像采集线程 + QThread * m_RgbCameraThread;//rgb相机获取图像线程 + QThread * m_CopyFileThread;//影像文件复制线程 FileOperation * m_FileOperation; QChartView * m_chartView; @@ -205,18 +206,18 @@ private: //QLineSeries *series; //QChart *chart; - QString operateWidget;//ǰĿؼ + QString operateWidget;//当前操作的控件名 - //ģλ - double widthScale;//QGraphicsViewviewportʵwidthScale = rect.width() / maxDistance; - double heightScale;//QGraphicsViewviewportߺʵheightScale = rect.height() / maxDistance; + //模拟相机位置 + double widthScale;//QGraphicsView的viewport宽和真实距离比例:widthScale = rect.width() / maxDistance; + double heightScale;//QGraphicsView的viewport高和真实距离比例:heightScale = rect.height() / maxDistance; void setImagerSimulationPos(double x, double y);//ui.graphicsView->imager->setPos(x, y); - //ɼ߹滮 - int m_numberOfRecording;//ʾui.recordLine_tableWidgetеĵڼ ڲɼڼ + //采集线规划 + int m_numberOfRecording;//表示ui.recordLine_tableWidget中的第几行 → 正在采集第几条线 // - int m_TabWidgetCurrentIndex;//ֶѡTabWidgetıǩʱ¼仯tab index + int m_TabWidgetCurrentIndex;//当手动选择TabWidget的标签时,记录变化后的tab index RgbCameraOperation *m_RgbCamera; void getRequest(QString str); @@ -254,6 +255,9 @@ private: View3DModelManager* m_view3DModelManager; + LayerTree* m_LayerTree = nullptr; + LayerTreeModel* m_LayerTreeModel = nullptr; + LayerTreeNode* m_RasterGroup = nullptr; // 指向 "Raster" 分组,便于后续添加 layer public Q_SLOTS: void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber); @@ -263,8 +267,9 @@ public Q_SLOTS: void onsequenceComplete(); void onExit(); - void onconnect();// - void testImagerStatus();//ȡ״̬Ƿ + void onOpenImg(); + void onconnect();//连接相机 + void testImagerStatus();//获取相机状态:连接是否正常 void onAutoExposure(); void onFocus1(); void onFocus2(int command); @@ -286,7 +291,7 @@ public Q_SLOTS: void OnGainEditingFinished();// void OnGainSliderChanged(double Gain);// - void onLeftMouseButtonPressed(int x, int y);//ӰԪʾ + void onLeftMouseButtonPressed(int x, int y);//点击影像像元显示光谱 void setAxis(QValueAxis* axisX, QValueAxis* axisY); @@ -309,6 +314,11 @@ public Q_SLOTS: void createPlantPhenotypeScenario(); void onCreated3DModelPlantPhenotype(); void onCreated3DModelOneMotor(); + + void onImageFileSaved(QString path, int fileIndex); + + void onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex); + signals: void StartFocusSignal(); void StartRecordSignal(); @@ -317,4 +327,3 @@ signals: void RecordWhiteSignal(); void RecordDarlSignal(); }; - diff --git a/HPPA/HPPA.ui b/HPPA/HPPA.ui index 08deffb..c42fe34 100644 --- a/HPPA/HPPA.ui +++ b/HPPA/HPPA.ui @@ -70,8 +70,7 @@ color:white; 文件 - - + @@ -1024,7 +1023,7 @@ QPushButton:pressed 三脚架(旋转平台) - + 打开影像 diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj index 434052c..6ec8f21 100644 --- a/HPPA/HPPA.vcxproj +++ b/HPPA/HPPA.vcxproj @@ -14,16 +14,16 @@ {E7886664-B69E-4781-BCBE-804574FB4033} QtVS_v304 $(MSBuildProjectDirectory)\QtMsBuild - 10.0.22000.0 + 10.0 Application - v141 + v143 Application - v141 + v143 false @@ -119,11 +119,13 @@ + + @@ -190,6 +192,8 @@ + + diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters index fd08928..fa1daaa 100644 --- a/HPPA/HPPA.vcxproj.filters +++ b/HPPA/HPPA.vcxproj.filters @@ -154,6 +154,12 @@ Source Files + + Source Files + + + Source Files + @@ -243,6 +249,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/HPPA/ImagerOperationBase.cpp b/HPPA/ImagerOperationBase.cpp index f179220..9738708 100644 --- a/HPPA/ImagerOperationBase.cpp +++ b/HPPA/ImagerOperationBase.cpp @@ -218,9 +218,9 @@ void ImagerOperationBase::record_white() void ImagerOperationBase::start_record() { - using namespace std; + using namespace std; - //std::cout << "------------------------------------------------------" << std::endl; + //std::cout << "------------------------------------------------------" << std::endl; m_iFrameCounter = 0; m_RgbImage->m_iFrameCounter = 0;//rgbͼĵ0 @@ -233,7 +233,15 @@ void ImagerOperationBase::start_record() exit(EXIT_FAILURE); } - m_FileName2Save2 = m_FileName2Save + "_" + std::to_string(m_FileSavedCounter) + ".bil"; + // ڿʼɼʱļϢUI д MapLayer + { + // prepare file name that will be used for saving + m_FileName2Save2 = m_FileName2Save + "_" + std::to_string(m_FileSavedCounter) + ".bil"; + QString baseName = QString::fromStdString(removeFileExtension(m_FileName2Save2)); + QString filePath = QString::fromStdString(m_FileName2Save2); + emit LayerFileCreated(baseName, filePath, m_FileSavedCounter); + } + FILE* m_fImage = fopen(m_FileName2Save2.c_str(), "w+b"); size_t x; @@ -312,10 +320,15 @@ void ImagerOperationBase::start_record() //һλͼǰҪһ //m_RgbImage - emit PlotSignal(m_FileSavedCounter, -1);//1ɼɺһλͼԷɼ֡֡ʵıʱͼȫ2ʹûе۲ɼʱֹͣɼ˲俪ʼɼᵼϴβɼĴźŵõIJۺΪ˼ݣע͵ + emit PlotSignal(m_FileSavedCounter, -1); m_bRecordControlState = false; WriteHdr(); + + // ImageFileSaved źţ֪ͨ UI Ѹļͼ + // m_FileName2Save2 ˱д .bil ļ "tmp_image_0.bil" + emit ImageFileSaved(QString::fromStdString(m_FileName2Save2), m_FileSavedCounter); + m_FileSavedCounter++; if (m_iFrameCounter >= m_iFrameNumber) diff --git a/HPPA/ImagerOperationBase.h b/HPPA/ImagerOperationBase.h index fdc3480..5b04ece 100644 --- a/HPPA/ImagerOperationBase.h +++ b/HPPA/ImagerOperationBase.h @@ -9,6 +9,8 @@ #include "ImagerOperationBase.h" #include "utility_tc.h" +class MapLayer; // forward declaration + class ImagerOperationBase :public QObject { Q_OBJECT @@ -112,4 +114,10 @@ signals: void testImagerStatus();//ʾԲ״̬Ƿӣӳ + + // һӰļ.bil/.hdrдɺ󷢳Ӳɼ̷߳Qt queued connection + void ImageFileSaved(const QString& path, int fileIndex); + + // ޸ģֱӷ MapLayer*Ƿļļ·UI 㸺𴴽 MapLayer 󲢹 + void LayerFileCreated(const QString& baseName, const QString& filePath, int fileIndex); }; diff --git a/HPPA/LayerTreeLayerNode.cpp b/HPPA/LayerTreeLayerNode.cpp index a2ba524..aa81f67 100644 --- a/HPPA/LayerTreeLayerNode.cpp +++ b/HPPA/LayerTreeLayerNode.cpp @@ -1,6 +1,6 @@ #include "LayerTreeLayerNode.h" -LayerTreeLayerNode::LayerTreeLayerNode(const QString& name, QObject* parent) - : LayerTreeNode(name, parent) +LayerTreeLayerNode::LayerTreeLayerNode(MapLayer* layer, QObject* parent) + : LayerTreeNode(layer ? layer->name() : QString(), parent), m_layer(layer) { } diff --git a/HPPA/LayerTreeLayerNode.h b/HPPA/LayerTreeLayerNode.h index e12b971..6c3e3bd 100644 --- a/HPPA/LayerTreeLayerNode.h +++ b/HPPA/LayerTreeLayerNode.h @@ -1,15 +1,23 @@ #pragma once #include "LayerTreeNode.h" +#include "MapLayer.h" /** Layer ڵ */ class LayerTreeLayerNode : public LayerTreeNode { Q_OBJECT public: - explicit LayerTreeLayerNode(const QString& name, + explicit LayerTreeLayerNode(MapLayer* layer, QObject* parent = nullptr); Type type() const override { return Type::Layer; } - // ԺչlayerId / pointer / legendItems + // һ MapLayer ָ루ӵУ + void setMapLayer(MapLayer* layer) { m_layer = layer; } + MapLayer* mapLayer() const { return m_layer; } + +private: + MapLayer* m_layer = nullptr; + + // չlayerId / pointer / legendItems }; diff --git a/HPPA/LayerTreeModel.cpp b/HPPA/LayerTreeModel.cpp index a888bb7..d2096ba 100644 --- a/HPPA/LayerTreeModel.cpp +++ b/HPPA/LayerTreeModel.cpp @@ -133,13 +133,14 @@ LayerTreeNode* LayerTreeModel::addGroup(LayerTreeNode* parent, const QString& na return g; } -LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, const QString& name, const QIcon& icon) +LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, LayerTreeLayerNode* layerNode, const QIcon& icon) { if (!parent) parent = m_tree->root(); + if (!layerNode) return nullptr; const int row = parent->childCount(); beginInsertRows(indexFromNode(parent), row, row); - LayerTreeNode* l = m_tree->insertNode(parent, row, new LayerTreeLayerNode(name)); + LayerTreeNode* l = m_tree->insertNode(parent, row, layerNode); endInsertRows(); return l; diff --git a/HPPA/LayerTreeModel.h b/HPPA/LayerTreeModel.h index 2473bfe..17a64bb 100644 --- a/HPPA/LayerTreeModel.h +++ b/HPPA/LayerTreeModel.h @@ -3,6 +3,8 @@ #include #include "LayerTree.h" +class LayerTreeLayerNode; // forward declare + /** * LayerTreeModelQt 㣨ٹ * - 1 Уƣͼ꣩+ checkbox @@ -32,7 +34,7 @@ public: LayerTreeNode* root() const; LayerTreeNode* addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon = QIcon()); - LayerTreeNode* addLayer(LayerTreeNode* parent, const QString& name, const QIcon& icon = QIcon()); + LayerTreeNode* addLayer(LayerTreeNode* parent, LayerTreeLayerNode* layerNode, const QIcon& icon = QIcon()); void setCascadeCheckEnabled(bool enabled); bool cascadeCheckEnabled() const; diff --git a/HPPA/MapLayer.cpp b/HPPA/MapLayer.cpp new file mode 100644 index 0000000..e4122ca --- /dev/null +++ b/HPPA/MapLayer.cpp @@ -0,0 +1,26 @@ +#include "MapLayer.h" + +MapLayer::MapLayer(const QString& name, const QString& uri) + : QObject(nullptr), m_name(name), m_uri(uri) +{ +} + +QString MapLayer::name() const +{ + return m_name; +} + +void MapLayer::setName(const QString& n) +{ + m_name = n; +} + +QString MapLayer::dataPath() const +{ + return m_uri; +} + +void MapLayer::setDataPath(const QString& p) +{ + m_uri = p; +} diff --git a/HPPA/MapLayer.h b/HPPA/MapLayer.h new file mode 100644 index 0000000..23ff393 --- /dev/null +++ b/HPPA/MapLayer.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +class MapLayer : public QObject +{ + Q_OBJECT +public: + enum class LayerType { Raster, Vector }; + + explicit MapLayer(const QString& name, const QString& uri); + + virtual ~MapLayer() override = default; + + QString name() const; + void setName(const QString& n); + + QString dataPath() const; + void setDataPath(const QString& p); + + virtual LayerType layerType() const = 0; + +private: + QString m_name; + QString m_uri; +}; diff --git a/HPPA/RasterLayer.cpp b/HPPA/RasterLayer.cpp new file mode 100644 index 0000000..44db3e6 --- /dev/null +++ b/HPPA/RasterLayer.cpp @@ -0,0 +1,12 @@ +#include "RasterLayer.h" + +RasterLayer::RasterLayer(const QString& name, const QString& uri) + : MapLayer(name, uri) +{ + +} + +MapLayer::LayerType RasterLayer::layerType() const +{ + return MapLayer::LayerType::Raster; +} diff --git a/HPPA/RasterLayer.h b/HPPA/RasterLayer.h new file mode 100644 index 0000000..8674a8a --- /dev/null +++ b/HPPA/RasterLayer.h @@ -0,0 +1,14 @@ +#pragma once + +#include "MapLayer.h" + +class RasterLayer : public MapLayer +{ + Q_OBJECT +public: + explicit RasterLayer(const QString& name, const QString& uri); + + LayerType layerType() const override; + + // future: renderer, data provider, etc. +};