1、为图层添加渲染器和读取器,分离图层基础信息、渲染和读写;
2、LayerTreeLayerNode持有MapLayer图层引用,为右键菜单做准备; 3、改名:imageviewer → mapcavas,mapcavas持有MapLayer图层引用,为刷新图像做准备;
This commit is contained in:
251
HPPA/HPPA.cpp
251
HPPA/HPPA.cpp
@ -265,29 +265,29 @@ sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidt
|
||||
//dock_layers->setMaximumHeight(498);
|
||||
|
||||
|
||||
//高光谱查看
|
||||
QDockWidget* dock_hyperimgViewer = new CustomDockWidgetBase(QString::fromLocal8Bit("hyimgViewer"), this);
|
||||
dock_hyperimgViewer->setObjectName("hyimgViewer");
|
||||
//高光谱查看
|
||||
QDockWidget* dock_hyperimgViewer = new CustomDockWidgetBase(QString::fromLocal8Bit("hyimgViewer"), this);
|
||||
dock_hyperimgViewer->setObjectName("hyimgViewer");
|
||||
|
||||
QWidget* dock_hyperimgViewerWidgetContents = new QWidget();
|
||||
dock_hyperimgViewerWidgetContents->setObjectName(QString::fromUtf8("dock_hyperimgViewerWidgetContents"));
|
||||
QGridLayout* gridLayout_hyperimgViewer = new QGridLayout(dock_hyperimgViewerWidgetContents);
|
||||
gridLayout_hyperimgViewer->setSpacing(6);
|
||||
gridLayout_hyperimgViewer->setObjectName(QString::fromUtf8("gridLayout_hyperimgViewer"));
|
||||
gridLayout_hyperimgViewer->setVerticalSpacing(6);
|
||||
gridLayout_hyperimgViewer->setContentsMargins(1, 2, 1, 2);
|
||||
QWidget* dock_hyperimgViewerWidgetContents = new QWidget();
|
||||
dock_hyperimgViewerWidgetContents->setObjectName(QString::fromUtf8("dock_hyperimgViewerWidgetContents"));
|
||||
QGridLayout* gridLayout_hyperimgViewer = new QGridLayout(dock_hyperimgViewerWidgetContents);
|
||||
gridLayout_hyperimgViewer->setSpacing(6);
|
||||
gridLayout_hyperimgViewer->setObjectName(QString::fromUtf8("gridLayout_hyperimgViewer"));
|
||||
gridLayout_hyperimgViewer->setVerticalSpacing(6);
|
||||
gridLayout_hyperimgViewer->setContentsMargins(1, 2, 1, 2);
|
||||
|
||||
m_imageViewerTabWidget = new QTabWidget();
|
||||
m_imageViewerTabWidget = new QTabWidget();
|
||||
//m_imageViewerTabWidget->tabBar()->setFixedHeight(40);//没有效果,在qss中设置高度才有效果,为啥????
|
||||
m_imageViewerTabWidget->clear();//必须放在最前面,首先删除所有的tab
|
||||
QToolButton* maxButton = new QToolButton();
|
||||
maxButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
|
||||
connect(maxButton, SIGNAL(clicked()), dock_hyperimgViewer, SLOT(toggleMaximize()));
|
||||
m_imageViewerTabWidget->setCornerWidget(maxButton, Qt::TopRightCorner);
|
||||
QToolButton* maxButton = new QToolButton();
|
||||
maxButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
|
||||
connect(maxButton, SIGNAL(clicked()), dock_hyperimgViewer, SLOT(toggleMaximize()));
|
||||
m_imageViewerTabWidget->setCornerWidget(maxButton, Qt::TopRightCorner);
|
||||
//onCreateTab(0);
|
||||
//m_imageViewerTabWidget->setTabsClosable(true);//这样每页都会有关闭按钮
|
||||
connect(m_imageViewerTabWidget, SIGNAL(currentChanged(int)), this, SLOT(onTabWidgetCurrentChanged(int)));
|
||||
m_imageViewerTabWidget->setStyleSheet(R"(
|
||||
connect(m_imageViewerTabWidget, SIGNAL(currentChanged(int)), this, SLOT(onTabWidgetCurrentChanged(int)));
|
||||
m_imageViewerTabWidget->setStyleSheet(R"(
|
||||
QTabBar::tab {
|
||||
background: #0E1C4C;
|
||||
color: white;
|
||||
@ -676,7 +676,6 @@ void HPPA::initMenubarToolbar()
|
||||
}
|
||||
)");
|
||||
|
||||
|
||||
QWidget* topWidget = new QWidget();
|
||||
topWidget->setStyleSheet("background-color: #040125;");
|
||||
QVBoxLayout* verticalLayout_topWidget = new QVBoxLayout(topWidget);
|
||||
@ -934,8 +933,6 @@ void HPPA::createOneMotorScenario()
|
||||
|
||||
m_tabManager->showTab(m_omc);
|
||||
|
||||
|
||||
|
||||
m_view3DModelManager->switchScenario(View3DModelManager::ScenarioType::OneMotor);
|
||||
|
||||
//右上角轮播
|
||||
@ -964,8 +961,6 @@ void HPPA::createPlantPhenotypeScenario()
|
||||
m_tabManager->showTab(m_pc);
|
||||
m_tabManager->showTab(m_tmc);
|
||||
|
||||
|
||||
|
||||
m_view3DModelManager->switchScenario(View3DModelManager::ScenarioType::PlantPhenotype);
|
||||
|
||||
//右上角轮播
|
||||
@ -1078,7 +1073,7 @@ void HPPA::onStartRecordStep1()
|
||||
m_RecordState -= 1;
|
||||
|
||||
ui.action_start_recording->setText(QString::fromLocal8Bit("采集"));
|
||||
ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}");
|
||||
ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1124,42 +1119,41 @@ void HPPA::onStartRecordStep1()
|
||||
|
||||
void HPPA::onCreateTab(int trackNumber)
|
||||
{
|
||||
if (trackNumber >= 0)
|
||||
{
|
||||
m_numberOfRecording = trackNumber;
|
||||
if (trackNumber >= 0)
|
||||
{
|
||||
m_numberOfRecording = trackNumber;
|
||||
|
||||
QWidget* tabTmp = new QWidget();
|
||||
QWidget* tabTmp = new QWidget();
|
||||
|
||||
QGridLayout* GridLayout = new QGridLayout();
|
||||
GridLayout->addWidget(new ImageViewer(tabTmp));
|
||||
QGridLayout* GridLayout = new QGridLayout();
|
||||
GridLayout->addWidget(new mapcavas(tabTmp));
|
||||
|
||||
tabTmp->setLayout(GridLayout);
|
||||
tabTmp->setLayout(GridLayout);
|
||||
|
||||
m_imageViewerTabWidget->addTab(tabTmp, QString::number(trackNumber + 1));
|
||||
m_imageViewerTabWidget->addTab(tabTmp, QString::number(trackNumber + 1));
|
||||
|
||||
m_imageViewerTabWidget->setCurrentIndex(trackNumber);
|
||||
}
|
||||
m_imageViewerTabWidget->setCurrentIndex(trackNumber);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HPPA::onTabWidgetCurrentChanged(int index)//代码新建一个tab,会调用onTabWidgetCurrentChanged函数!
|
||||
{
|
||||
if (index < 0)//当删除所有tab时,index=-1
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (index < 0)//当删除所有tab时,index=-1
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//记录当前
|
||||
m_TabWidgetCurrentIndex = index;
|
||||
|
||||
//记录当前
|
||||
m_TabWidgetCurrentIndex = index;
|
||||
//获取绘图控件
|
||||
QWidget* currentWidget = m_imageViewerTabWidget->widget(index);
|
||||
QList<mapcavas*> currentImageViewer = currentWidget->findChildren<mapcavas*>();
|
||||
|
||||
//获取绘图控件
|
||||
QWidget* currentWidget = m_imageViewerTabWidget->widget(index);
|
||||
QList<ImageViewer*> currentImageViewer = currentWidget->findChildren<ImageViewer*>();
|
||||
|
||||
//先disconnect然后再connect,否则每次切换一次都会connect一次,会累积connect很多次!
|
||||
disconnect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int)));
|
||||
connect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int)));
|
||||
//先disconnect然后再connect,否则每次切换一次都会connect一次,会累积connect很多次!
|
||||
disconnect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int)));
|
||||
connect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int)));
|
||||
}
|
||||
|
||||
void HPPA::onActionOpenDirectory()
|
||||
@ -1169,34 +1163,6 @@ void HPPA::onActionOpenDirectory()
|
||||
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(directory)));
|
||||
|
||||
//QDesktopServices::openUrl(QUrl("file:C:\ASD", QUrl::TolerantMode));
|
||||
|
||||
|
||||
////std::cout << "保存影像文件!" << std::endl;
|
||||
//
|
||||
//FileOperation * fileOperation = new FileOperation();
|
||||
//string directory = fileOperation->getDirectoryFromString();
|
||||
|
||||
//string sourceImg = directory + "\\tmp_image";
|
||||
//string sourceHdr = sourceImg + ".hdr";
|
||||
//
|
||||
|
||||
//QString FileName2Save = QFileDialog::getSaveFileName(this,tr("save image"));
|
||||
|
||||
//if (FileName2Save.length()>0)
|
||||
//{
|
||||
// string targetImg = FileName2Save.toStdString();
|
||||
// string targetHdr = targetImg + ".hdr";
|
||||
|
||||
// emit CopyFileThreadSignal(QString::fromStdString(sourceHdr), QString::fromStdString(targetHdr));
|
||||
// emit CopyFileThreadSignal(QString::fromStdString(sourceImg), QString::fromStdString(targetImg));
|
||||
|
||||
// this->setEnabled(false);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// std::cout << "文件名长度:" << FileName2Save.length() << std::endl;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
@ -1274,6 +1240,7 @@ void HPPA::onLeftMouseButtonPressed(int x, int y)
|
||||
QLineSeries* series = new QLineSeries();
|
||||
//series->clear();//////////////////////////////
|
||||
|
||||
|
||||
QString imagerSelected = mImagerGroup->checkedAction()->objectName();
|
||||
if (imagerSelected == "mActionPica_L" || imagerSelected == "mActionCorning_410" || imagerSelected == "mActionPika_XC2")
|
||||
{
|
||||
@ -1385,7 +1352,6 @@ void HPPA::onPlotRgbImage()
|
||||
int height = m_cam_label->height();
|
||||
QPixmap fitpixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); //按比例缩放
|
||||
|
||||
|
||||
m_cam_label->setPixmap(fitpixmap);
|
||||
}
|
||||
|
||||
@ -1444,6 +1410,53 @@ void HPPA::onExit()
|
||||
|
||||
void HPPA::onOpenImg()
|
||||
{
|
||||
// 1) 弹出文件对话框获取uri
|
||||
QString uri = QFileDialog::getOpenFileName(this, tr("Open Image"), QString(), tr("Raster Files (*.bil *.hdr *.tif *.tiff *.img *.raw);;All Files (*)"));
|
||||
if (uri.isEmpty())
|
||||
return;
|
||||
|
||||
// 2) 创建 RasterLayer,然后添加到图层管理器
|
||||
if (!m_LayerTreeModel || !m_RasterGroup)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Layer model is not initialized."));
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo fi(uri);
|
||||
QString baseName = fi.completeBaseName();
|
||||
|
||||
// Create RasterLayer and wrap in LayerTreeLayerNode
|
||||
RasterLayer* rl = new RasterLayer(baseName, uri);
|
||||
auto* layerNode = new LayerTreeLayerNode(rl);
|
||||
m_LayerTreeModel->addLayer(m_RasterGroup, layerNode);
|
||||
|
||||
// 3) 渲染一副图像并保存到 C:\2
|
||||
RasterLayer::RenderParams params; // use defaults
|
||||
QImage img = rl->render(params);
|
||||
if (img.isNull())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Render failed"), tr("Failed to render image from %1").arg(uri));
|
||||
return;
|
||||
}
|
||||
|
||||
QDir outDir("C:/2");
|
||||
if (!outDir.exists())
|
||||
{
|
||||
if (!outDir.mkpath("."))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Save failed"), tr("Failed to create output directory C:/2"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString outPath = outDir.filePath(baseName + "_render.png");
|
||||
if (!img.save(outPath))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Save failed"), tr("Failed to save rendered image to %1").arg(outPath));
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("Saved"), tr("Rendered image saved to %1").arg(outPath));
|
||||
}
|
||||
|
||||
void HPPA::onconnect()
|
||||
@ -1638,7 +1651,7 @@ void HPPA::onFocus2(int command)
|
||||
QWidget* tabTmp = new QWidget();
|
||||
|
||||
QGridLayout* GridLayout = new QGridLayout();
|
||||
GridLayout->addWidget(new ImageViewer(tabTmp));
|
||||
GridLayout->addWidget(new mapcavas(tabTmp));
|
||||
|
||||
tabTmp->setLayout(GridLayout);
|
||||
|
||||
@ -1726,28 +1739,28 @@ void HPPA::recordWhiteFinish()
|
||||
|
||||
void HPPA::onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber)
|
||||
{
|
||||
//使用机械臂采集时,会在停止采集后的瞬间又开始采集,会导致上次采集最后发射的信号调用此槽函数报错
|
||||
QAction* checked = moveplatformActionGroup->checkedAction();
|
||||
QString checkedName = checked->objectName();
|
||||
if (frameNumber == -1 && checkedName == "mAction_RobotArm")
|
||||
{
|
||||
return;
|
||||
}
|
||||
//使用机械臂采集时,会在停止采集后的瞬间又开始采集,会导致上次采集最后发射的信号调用此槽函数报错
|
||||
QAction* checked = moveplatformActionGroup->checkedAction();
|
||||
QString checkedName = checked->objectName();
|
||||
if (frameNumber == -1 && checkedName == "mAction_RobotArm")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//return;
|
||||
//获取绘图控件
|
||||
QWidget* currentWidget = m_imageViewerTabWidget->widget(fileNumber);
|
||||
QList<ImageViewer*> currentImageViewer = currentWidget->findChildren<ImageViewer*>();
|
||||
currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFrameCounter());//界面中显示已经采集的帧数
|
||||
//return;
|
||||
//获取绘图控件
|
||||
QWidget* currentWidget = m_imageViewerTabWidget->widget(fileNumber);
|
||||
QList<mapcavas*> currentImageViewer = currentWidget->findChildren<mapcavas*>();
|
||||
currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFrameCounter());//界面中显示已经采集的帧数
|
||||
|
||||
//创建需要显示的图像--opencv版本
|
||||
ImageProcessor imageProcessor;
|
||||
//cv::Mat rgbImage(*m_Imager->getRgbImage()->m_matRgbImage, cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all());//2022.3.18重构的
|
||||
cv::Mat rgbImage(*m_Imager->getMatRgbImage(), cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all());
|
||||
cv::Mat rgbImageStretched = imageProcessor.CStretch(rgbImage, 0.02);
|
||||
//创建需要显示的图像--opencv版本
|
||||
ImageProcessor imageProcessor;
|
||||
//cv::Mat rgbImage(*m_Imager->getRgbImage()->m_matRgbImage, cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all());//2022.3.18重构的
|
||||
cv::Mat rgbImage(*m_Imager->getMatRgbImage(), cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all());
|
||||
cv::Mat rgbImageStretched = imageProcessor.CStretch(rgbImage, 0.02);
|
||||
|
||||
//在界面中显示图像
|
||||
currentImageViewer[0]->SetImage(&QPixmap::fromImage(imageProcessor.Mat2QImage(rgbImageStretched)));//绘制图像
|
||||
//在界面中显示图像
|
||||
currentImageViewer[0]->SetImage(&QPixmap::fromImage(imageProcessor.Mat2QImage(rgbImageStretched)));//绘制图像
|
||||
|
||||
//20241225
|
||||
//保存拉伸后的rgb
|
||||
@ -1768,12 +1781,12 @@ void HPPA::onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber)
|
||||
|
||||
void HPPA::PlotSpectral(int state)
|
||||
{
|
||||
if (state == 1)
|
||||
{
|
||||
//显示影像
|
||||
QWidget* currentWidget = m_imageViewerTabWidget->currentWidget();
|
||||
QList<ImageViewer*> currentImageViewer = currentWidget->findChildren<ImageViewer*>();
|
||||
currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFocusFrameCounter());//界面中显示已经采集的帧数
|
||||
if (state == 1)
|
||||
{
|
||||
//显示影像
|
||||
QWidget* currentWidget = m_imageViewerTabWidget->currentWidget();
|
||||
QList<mapcavas*> currentImageViewer = currentWidget->findChildren<mapcavas*>();
|
||||
currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFocusFrameCounter());//界面中显示已经采集的帧数
|
||||
|
||||
ImageProcessor imageProcessor;
|
||||
//cv::Mat grayImage(*m_Imager->getRgbImage()->m_matFocusGrayImage, cv::Range::all(), cv::Range::all());//2022.3.18重构的
|
||||
@ -1782,26 +1795,26 @@ void HPPA::PlotSpectral(int state)
|
||||
|
||||
currentImageViewer[0]->SetImage(&QPixmap::fromImage(m_Imager->getQImageFocusGrayImage()));//绘制图像
|
||||
|
||||
//绘制光谱
|
||||
QLineSeries* series = new QLineSeries();
|
||||
//series->clear();//////////////////////////////
|
||||
int sampleCount = m_Imager->getSampleCount();
|
||||
for (size_t i = 0; i < sampleCount; i++)
|
||||
{
|
||||
//malloc申请的内存用法1:可以当做数组用
|
||||
//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]);
|
||||
}
|
||||
//绘制光谱
|
||||
QLineSeries* series = new QLineSeries();
|
||||
//series->clear();//////////////////////////////
|
||||
int sampleCount = m_Imager->getSampleCount();
|
||||
for (size_t i = 0; i < sampleCount; i++)
|
||||
{
|
||||
//malloc申请的内存用法1:可以当做数组用
|
||||
//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();
|
||||
chart->addSeries(series);
|
||||
chart->createDefaultAxes();
|
||||
//chart->setTitle("Simple line chart example");
|
||||
QChart* chart = new QChart();
|
||||
chart->legend()->hide();
|
||||
chart->addSeries(series);
|
||||
chart->createDefaultAxes();
|
||||
//chart->setTitle("Simple line chart example");
|
||||
|
||||
m_chartView->setChart(chart);
|
||||
}
|
||||
m_chartView->setChart(chart);
|
||||
}
|
||||
else
|
||||
{
|
||||
//改变界面上的按钮文字
|
||||
|
||||
@ -125,7 +125,9 @@
|
||||
<ClCompile Include="PowerControl.cpp" />
|
||||
<ClCompile Include="QDoubleSlider.cpp" />
|
||||
<ClCompile Include="QMotorDoubleSlider.cpp" />
|
||||
<ClCompile Include="RasterDataProvider.cpp" />
|
||||
<ClCompile Include="RasterLayer.cpp" />
|
||||
<ClCompile Include="RasterRenderer.cpp" />
|
||||
<ClCompile Include="resononImager.cpp" />
|
||||
<ClCompile Include="ResononNirImager.cpp" />
|
||||
<ClCompile Include="RgbCameraOperation.cpp" />
|
||||
@ -194,6 +196,8 @@
|
||||
<QtMoc Include="LayerTreeLayerNode.h" />
|
||||
<QtMoc Include="MapLayer.h" />
|
||||
<QtMoc Include="RasterLayer.h" />
|
||||
<ClInclude Include="RasterDataProvider.h" />
|
||||
<ClInclude Include="RasterRenderer.h" />
|
||||
<ClInclude Include="utility_tc.h" />
|
||||
<QtMoc Include="aboutWindow.h" />
|
||||
<ClInclude Include="hppaConfigFile.h" />
|
||||
|
||||
@ -160,6 +160,12 @@
|
||||
<ClCompile Include="RasterLayer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RasterDataProvider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RasterRenderer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="fileOperation.h">
|
||||
@ -287,6 +293,12 @@
|
||||
<ClInclude Include="irisximeaimager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RasterDataProvider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RasterRenderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="FocusDialog.ui">
|
||||
|
||||
@ -5,240 +5,217 @@
|
||||
#include <QPoint>
|
||||
|
||||
#include "ImageViewer.h"
|
||||
#include "RasterLayer.h"
|
||||
|
||||
|
||||
#define VIEW_CENTER viewport()->rect().center()
|
||||
#define VIEW_WIDTH viewport()->rect().width()
|
||||
#define VIEW_HEIGHT viewport()->rect().height()
|
||||
|
||||
|
||||
ImageViewer::ImageViewer(QWidget* pParent) :QGraphicsView(pParent)
|
||||
mapcavas::mapcavas(QWidget* pParent) :QGraphicsView(pParent)
|
||||
{
|
||||
setRenderHint(QPainter::Antialiasing);
|
||||
setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
setDragMode(QGraphicsView::ScrollHandDrag);
|
||||
setRenderHint(QPainter::Antialiasing);
|
||||
setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
setDragMode(QGraphicsView::ScrollHandDrag);
|
||||
|
||||
// <20>ؼ<EFBFBD><D8BC>㣺<EFBFBD><E3A3BA>ʹ<EFBFBD><EFBFBD> Qt Ĭ<>ϵ<EFBFBD> anchor<6F><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
setTransformationAnchor(QGraphicsView::NoAnchor);
|
||||
setResizeAnchor(QGraphicsView::NoAnchor);
|
||||
// ʹ<EFBFBD><EFBFBD> Qt Ĭ<><C4AC> anchor <EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
setTransformationAnchor(QGraphicsView::NoAnchor);
|
||||
setResizeAnchor(QGraphicsView::NoAnchor);
|
||||
|
||||
m_qtGraphicsScene = new QGraphicsScene(this);
|
||||
this->setScene(m_qtGraphicsScene);
|
||||
m_qtGraphicsScene->setSceneRect(-1e6, -1e6, 2e6, 2e6);
|
||||
m_qtGraphicsScene = new QGraphicsScene(this);
|
||||
this->setScene(m_qtGraphicsScene);
|
||||
m_qtGraphicsScene->setSceneRect(-1e6, -1e6, 2e6, 2e6);
|
||||
|
||||
m_framNumberLabel = new QLabel(this);
|
||||
m_framNumberLabel->setAlignment(Qt::AlignHCenter);
|
||||
m_framNumberLabel->setAlignment(Qt::AlignVCenter);
|
||||
m_framNumberLabel = new QLabel(this);
|
||||
m_framNumberLabel->setAlignment(Qt::AlignHCenter);
|
||||
m_framNumberLabel->setAlignment(Qt::AlignVCenter);
|
||||
|
||||
QFont ft;
|
||||
ft.setPointSize(14);
|
||||
m_framNumberLabel->setFont(ft);
|
||||
QFont ft;
|
||||
ft.setPointSize(14);
|
||||
m_framNumberLabel->setFont(ft);
|
||||
m_framNumberLabel->setText("0");
|
||||
|
||||
|
||||
m_GraphicsPixmapItemHandle = nullptr;
|
||||
m_GraphicsPixmapItemHandle = nullptr;
|
||||
|
||||
m_scale = 1.0;
|
||||
m_zoomDelta = 0.1;
|
||||
m_translateSpeed = 1.0;
|
||||
m_bMouseTranslate = false;
|
||||
m_scale = 1.0;
|
||||
m_zoomDelta = 0.1;
|
||||
m_translateSpeed = 1.0;
|
||||
m_bMouseTranslate = false;
|
||||
|
||||
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setFrameShape(QFrame::NoFrame);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setFrameShape(QFrame::NoFrame);
|
||||
}
|
||||
|
||||
ImageViewer::~ImageViewer()
|
||||
mapcavas::~mapcavas()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ImageViewer::DisplayFrameNumber(int frameNumber)
|
||||
void mapcavas::DisplayFrameNumber(int frameNumber)
|
||||
{
|
||||
m_framNumberLabel->setText(QString::number(frameNumber));
|
||||
m_framNumberLabel->adjustSize();
|
||||
m_framNumberLabel->setText(QString::number(frameNumber));
|
||||
m_framNumberLabel->adjustSize();
|
||||
}
|
||||
|
||||
void ImageViewer::SetImage(QPixmap *image)
|
||||
void mapcavas::SetImage(QPixmap *image)
|
||||
{
|
||||
if (!HasImage())
|
||||
{
|
||||
m_GraphicsPixmapItemHandle = m_qtGraphicsScene->addPixmap(*image);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GraphicsPixmapItemHandle->setPixmap(*image);
|
||||
}
|
||||
ensureSceneVisible();
|
||||
if (!HasImage())
|
||||
{
|
||||
m_GraphicsPixmapItemHandle = m_qtGraphicsScene->addPixmap(*image);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GraphicsPixmapItemHandle->setPixmap(*image);
|
||||
}
|
||||
ensureSceneVisible();
|
||||
}
|
||||
|
||||
void ImageViewer::ensureSceneVisible()
|
||||
void mapcavas::ensureSceneVisible()
|
||||
{
|
||||
resetTransform();
|
||||
resetTransform();
|
||||
|
||||
auto view_rect = viewport()->rect();
|
||||
auto scene_rect = this->scene()->itemsBoundingRect();
|
||||
auto view_rect = viewport()->rect();
|
||||
auto scene_rect = this->scene()->itemsBoundingRect();
|
||||
|
||||
double x_ratio = view_rect.width() / scene_rect.width();
|
||||
double y_ratio = view_rect.height() / scene_rect.height();
|
||||
double scale_factor = std::min(x_ratio, y_ratio) * 0.9;
|
||||
double x_ratio = view_rect.width() / scene_rect.width();
|
||||
double y_ratio = view_rect.height() / scene_rect.height();
|
||||
double scale_factor = std::min(x_ratio, y_ratio) * 0.9;
|
||||
|
||||
scale(scale_factor, scale_factor);
|
||||
m_scale *= scale_factor;
|
||||
scale(scale_factor, scale_factor);
|
||||
m_scale *= scale_factor;
|
||||
|
||||
centerOn(scene_rect.center());
|
||||
centerOn(scene_rect.center());
|
||||
}
|
||||
|
||||
bool ImageViewer::HasImage()
|
||||
bool mapcavas::HasImage()
|
||||
{
|
||||
if (m_GraphicsPixmapItemHandle == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (m_GraphicsPixmapItemHandle == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewer::wheelEvent(QWheelEvent *event)
|
||||
void mapcavas::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
//qDebug() << "---------------+++++++++++++++++++++++++++++++++++++++++++++++++++ ";
|
||||
//if (true)//HasImage()
|
||||
//{
|
||||
// //Χ<><CEA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŵ<EFBFBD><C5B4><EFBFBD>https://blog.csdn.net/GoForwardToStep/article/details/77035287?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param
|
||||
// // <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>view<65><77>λ<EFBFBD><CEBB>;
|
||||
// QPointF cursorPoint = event->pos();
|
||||
// // <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>scene<6E><65>λ<EFBFBD><CEBB>;
|
||||
// QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y()));
|
||||
if (HasImage())
|
||||
{
|
||||
QPointF oldPos = mapToScene(event->pos());
|
||||
|
||||
// // <20><>ȡview<65>Ŀ<EFBFBD><C4BF><EFBFBD>;
|
||||
// qreal viewWidth = this->viewport()->width();
|
||||
// qreal viewHeight = this->viewport()->height();
|
||||
QPoint scrollAmount = event->angleDelta();
|
||||
scrollAmount.y() > 0 ? zoomIn() : zoomOut();
|
||||
|
||||
// // <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD>൱<EFBFBD><E0B5B1>view<65><77>С<EFBFBD>ĺ<EFBFBD><C4BA>ݱ<EFBFBD><DDB1><EFBFBD>;
|
||||
// qreal hScale = cursorPoint.x() / viewWidth;
|
||||
// qreal vScale = cursorPoint.y() / viewHeight;
|
||||
QPointF newPos = mapToScene(event->pos());
|
||||
|
||||
|
||||
// // <20><><EFBFBD>ֵĹ<D6B5><C4B9><EFBFBD><EFBFBD><EFBFBD>
|
||||
// QPoint scrollAmount = event->angleDelta();
|
||||
// // <20><>ֵ<EFBFBD><D6B5>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6>ʹ<EFBFBD><CAB9><EFBFBD>߷Ŵ<DFB7><C5B4><EFBFBD>ֵ<EFBFBD><D6B5>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
|
||||
// scrollAmount.y() > 0 ? zoomIn() : zoomOut();
|
||||
|
||||
|
||||
// // <20><>scene<6E><65><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD>Ŵ<EFBFBD><C5B4><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
|
||||
// QPointF viewPoint = this->matrix().map(scenePos);
|
||||
// // ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>view<65>Ŵ<EFBFBD><C5B4><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>չʾscene<6E><65>λ<EFBFBD><CEBB>;
|
||||
// horizontalScrollBar()->setValue(int(viewPoint.x() - viewWidth * hScale));
|
||||
// verticalScrollBar()->setValue(int(viewPoint.y() - viewHeight * vScale));
|
||||
//}
|
||||
|
||||
if (HasImage())
|
||||
{
|
||||
QPointF oldPos = mapToScene(event->pos());
|
||||
|
||||
QPoint scrollAmount = event->angleDelta();
|
||||
scrollAmount.y() > 0 ? zoomIn() : zoomOut();
|
||||
|
||||
QPointF newPos = mapToScene(event->pos());
|
||||
|
||||
QPointF delta = newPos - oldPos;
|
||||
translate(delta.x(), delta.y());
|
||||
}
|
||||
|
||||
//QGraphicsView::wheelEvent(event);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
QPointF delta = newPos - oldPos;
|
||||
translate(delta.x(), delta.y());
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewer::scaling(qreal scaleFactor)
|
||||
void mapcavas::scaling(qreal scaleFactor)
|
||||
{
|
||||
//qDebug() << this->sceneRect();
|
||||
scale(scaleFactor, scaleFactor);
|
||||
scale(scaleFactor, scaleFactor);
|
||||
}
|
||||
|
||||
void ImageViewer::mousePressEvent(QMouseEvent *event)
|
||||
void mapcavas::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button()==Qt::LeftButton)
|
||||
{
|
||||
m_bMouseTranslate = true;
|
||||
m_lastMousePos = event->pos();
|
||||
if (event->button()==Qt::LeftButton)
|
||||
{
|
||||
m_bMouseTranslate = true;
|
||||
m_lastMousePos = event->pos();
|
||||
|
||||
//qDebug() << mapToScene(m_lastMousePos);
|
||||
|
||||
emit leftMouseButtonPressed(mapToScene(m_lastMousePos).x(), mapToScene(m_lastMousePos).y());
|
||||
}
|
||||
|
||||
|
||||
//If you do not perform all the necessary work in your implementation of the virtual function, you may need to call the base class's implementation.
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
emit leftMouseButtonPressed(mapToScene(m_lastMousePos).x(), mapToScene(m_lastMousePos).y());
|
||||
}
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void ImageViewer::mouseMoveEvent(QMouseEvent *event)
|
||||
void mapcavas::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (m_bMouseTranslate){
|
||||
QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos);
|
||||
translate(mouseDelta.x(),mouseDelta.y());
|
||||
}
|
||||
if (m_bMouseTranslate){
|
||||
QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos);
|
||||
translate(mouseDelta.x(),mouseDelta.y());
|
||||
}
|
||||
|
||||
m_lastMousePos = event->pos();
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
m_lastMousePos = event->pos();
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void ImageViewer::mouseReleaseEvent(QMouseEvent *event)
|
||||
void mapcavas::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
m_bMouseTranslate = false;
|
||||
QGraphicsView::mouseReleaseEvent(event);
|
||||
m_bMouseTranslate = false;
|
||||
QGraphicsView::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void ImageViewer::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
void mapcavas::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
QGraphicsView::mouseDoubleClickEvent(event);
|
||||
QGraphicsView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
void ImageViewer::zoomIn()
|
||||
void mapcavas::zoomIn()
|
||||
{
|
||||
zoom(1 + m_zoomDelta);
|
||||
zoom(1 + m_zoomDelta);
|
||||
}
|
||||
|
||||
void ImageViewer::zoomOut()
|
||||
void mapcavas::zoomOut()
|
||||
{
|
||||
zoom(1 - m_zoomDelta);
|
||||
zoom(1 - m_zoomDelta);
|
||||
}
|
||||
|
||||
void ImageViewer::zoom(float scaleFactor)
|
||||
void mapcavas::zoom(float scaleFactor)
|
||||
{
|
||||
// <20><>ֹ<EFBFBD><D6B9>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
|
||||
if (factor < 0.07 || factor > 100)
|
||||
return;
|
||||
qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
|
||||
if (factor < 0.07 || factor > 100)
|
||||
return;
|
||||
|
||||
scale(scaleFactor, scaleFactor);
|
||||
m_scale *= scaleFactor;
|
||||
scale(scaleFactor, scaleFactor);
|
||||
m_scale *= scaleFactor;
|
||||
}
|
||||
|
||||
void ImageViewer::setTranslateSpeed(qreal speed)
|
||||
void mapcavas::setTranslateSpeed(qreal speed)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ٶȷ<D9B6>Χ
|
||||
Q_ASSERT_X(speed >= 0.0 && speed <= 2.0,
|
||||
"InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0].");
|
||||
m_translateSpeed = speed;
|
||||
Q_ASSERT_X(speed >= 0.0 && speed <= 2.0,
|
||||
"InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0].");
|
||||
m_translateSpeed = speed;
|
||||
}
|
||||
|
||||
qreal ImageViewer::translateSpeed() const
|
||||
qreal mapcavas::translateSpeed() const
|
||||
{
|
||||
return m_translateSpeed;
|
||||
return m_translateSpeed;
|
||||
}
|
||||
|
||||
void ImageViewer::setZoomDelta(qreal delta)
|
||||
void mapcavas::setZoomDelta(qreal delta)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ
|
||||
Q_ASSERT_X(delta >= 0.0 && delta <= 1.0,
|
||||
"InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0].");
|
||||
m_zoomDelta = delta;
|
||||
Q_ASSERT_X(delta >= 0.0 && delta <= 1.0,
|
||||
"InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0].");
|
||||
m_zoomDelta = delta;
|
||||
}
|
||||
|
||||
qreal ImageViewer::zoomDelta() const
|
||||
qreal mapcavas::zoomDelta() const
|
||||
{
|
||||
return m_zoomDelta;
|
||||
return m_zoomDelta;
|
||||
}
|
||||
|
||||
// new: set associated raster layer
|
||||
void mapcavas::setLayers(RasterLayer* layer)
|
||||
{
|
||||
m_rasterLayer = layer;
|
||||
}
|
||||
|
||||
// new: refresh the map by rendering using the RasterLayer's render method
|
||||
void mapcavas::freshmap()
|
||||
{
|
||||
if (!m_rasterLayer) return;
|
||||
|
||||
RasterLayer::RenderParams params; // default params; could be extended
|
||||
QImage img = m_rasterLayer->render(params);
|
||||
if (img.isNull()) return;
|
||||
|
||||
QPixmap pm = QPixmap::fromImage(img);
|
||||
SetImage(&pm);
|
||||
}
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
#ifndef IMAGE_VIEWER
|
||||
#define IMAGE_VIEWER
|
||||
#ifndef MAPCAVAS_H
|
||||
#define MAPCAVAS_H
|
||||
|
||||
#include "QGraphicsView"
|
||||
#include "qlabel.h"
|
||||
class ImageViewer :public QGraphicsView
|
||||
|
||||
class RasterLayer; // forward
|
||||
|
||||
class mapcavas : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ImageViewer(QWidget* pParent = NULL);
|
||||
~ImageViewer();
|
||||
mapcavas(QWidget* pParent = NULL);
|
||||
~mapcavas();
|
||||
|
||||
|
||||
void DisplayFrameNumber(int frameNumber);
|
||||
@ -38,12 +41,18 @@ public:
|
||||
// <20><><EFBFBD>ŵ<EFBFBD><C5B5><EFBFBD><EFBFBD><EFBFBD>
|
||||
void setZoomDelta(qreal delta);
|
||||
qreal zoomDelta() const;
|
||||
|
||||
// new: set raster layer and refresh map
|
||||
void setLayers(RasterLayer* layer);
|
||||
void freshmap();
|
||||
|
||||
protected:
|
||||
QGraphicsScene *m_qtGraphicsScene;
|
||||
private:
|
||||
QGraphicsPixmapItem *m_GraphicsPixmapItemHandle;
|
||||
QLabel *m_framNumberLabel;//<2F><>ʾʵʱ<CAB5>ɼ<EFBFBD><C9BC><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>
|
||||
|
||||
|
||||
RasterLayer* m_rasterLayer = nullptr; // associated raster layer
|
||||
|
||||
qreal m_translateSpeed; // ƽ<><C6BD><EFBFBD>ٶ<EFBFBD>
|
||||
qreal m_zoomDelta; // <20><><EFBFBD>ŵ<EFBFBD><C5B5><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
@ -4,3 +4,19 @@ LayerTreeLayerNode::LayerTreeLayerNode(MapLayer* layer, QObject* parent)
|
||||
: LayerTreeNode(layer ? layer->name() : QString(), parent), m_layer(layer)
|
||||
{
|
||||
}
|
||||
|
||||
LayerTreeNode::Type LayerTreeLayerNode::type() const
|
||||
{
|
||||
return Type::Layer;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<>루<EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
|
||||
void LayerTreeLayerNode::setMapLayer(MapLayer* layer)
|
||||
{
|
||||
m_layer = layer;
|
||||
}
|
||||
|
||||
MapLayer* LayerTreeLayerNode::mapLayer() const
|
||||
{
|
||||
return m_layer;
|
||||
}
|
||||
|
||||
@ -7,14 +7,13 @@ class LayerTreeLayerNode : public LayerTreeNode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LayerTreeLayerNode(MapLayer* layer,
|
||||
QObject* parent = nullptr);
|
||||
explicit LayerTreeLayerNode(MapLayer* layer, QObject* parent = nullptr);
|
||||
|
||||
Type type() const override { return Type::Layer; }
|
||||
Type type() const override;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<>루<EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
|
||||
void setMapLayer(MapLayer* layer) { m_layer = layer; }
|
||||
MapLayer* mapLayer() const { return m_layer; }
|
||||
void setMapLayer(MapLayer* layer);
|
||||
MapLayer* mapLayer() const;
|
||||
|
||||
private:
|
||||
MapLayer* m_layer = nullptr;
|
||||
|
||||
123
HPPA/RasterDataProvider.cpp
Normal file
123
HPPA/RasterDataProvider.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include "RasterDataProvider.h"
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
#if HPPA_HAVE_GDAL
|
||||
#include <gdal_priv.h>
|
||||
#include <cpl_conv.h>
|
||||
#endif
|
||||
|
||||
RasterDataProvider::RasterDataProvider(const QString& uri)
|
||||
: m_uri(uri), m_dataset(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
RasterDataProvider::~RasterDataProvider()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
bool RasterDataProvider::open()
|
||||
{
|
||||
#if HPPA_HAVE_GDAL
|
||||
GDALAllRegister();
|
||||
m_dataset = (GDALDataset*)GDALOpen((const char*)m_uri.toLocal8Bit().constData(), GA_ReadOnly);
|
||||
if (!m_dataset) {
|
||||
qWarning() << "RasterDataProvider: failed to open dataset:" << m_uri;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
Q_UNUSED(m_uri);
|
||||
qWarning() << "RasterDataProvider: GDAL not available, open will fail.";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void RasterDataProvider::close()
|
||||
{
|
||||
#if HPPA_HAVE_GDAL
|
||||
if (m_dataset) {
|
||||
GDALClose((GDALDatasetH)m_dataset);
|
||||
m_dataset = nullptr;
|
||||
}
|
||||
#else
|
||||
m_dataset = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
int RasterDataProvider::bandCount() const
|
||||
{
|
||||
#if HPPA_HAVE_GDAL
|
||||
if (!m_dataset) return 0;
|
||||
return m_dataset->GetRasterCount();
|
||||
#else
|
||||
Q_UNUSED(this);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int RasterDataProvider::width() const
|
||||
{
|
||||
#if HPPA_HAVE_GDAL
|
||||
if (!m_dataset) return 0;
|
||||
return m_dataset->GetRasterXSize();
|
||||
#else
|
||||
Q_UNUSED(this);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int RasterDataProvider::height() const
|
||||
{
|
||||
#if HPPA_HAVE_GDAL
|
||||
if (!m_dataset) return 0;
|
||||
return m_dataset->GetRasterYSize();
|
||||
#else
|
||||
Q_UNUSED(this);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<double> RasterDataProvider::bandWavelengths() const
|
||||
{
|
||||
std::vector<double> res;
|
||||
#if HPPA_HAVE_GDAL
|
||||
if (!m_dataset) return res;
|
||||
for (int i = 1; i <= m_dataset->GetRasterCount(); ++i) {
|
||||
GDALRasterBand* band = m_dataset->GetRasterBand(i);
|
||||
if (!band) continue;
|
||||
// Attempt to read wavelength from metadata (commonly "Wavelength" or "wavelength")
|
||||
const char* val = band->GetMetadataItem("Wavelength");
|
||||
if (!val) val = band->GetMetadataItem("wavelength");
|
||||
if (val) {
|
||||
double v = atof(val);
|
||||
res.push_back(v);
|
||||
} else {
|
||||
// push a negative to indicate unknown
|
||||
res.push_back(-1.0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
bool RasterDataProvider::readBandAsFloat(int bandIndex, std::vector<float>& outBuffer) const
|
||||
{
|
||||
#if HPPA_HAVE_GDAL
|
||||
if (!m_dataset) return false;
|
||||
int bands = m_dataset->GetRasterCount();
|
||||
if (bandIndex < 0 || bandIndex >= bands) return false;
|
||||
GDALRasterBand* band = m_dataset->GetRasterBand(bandIndex + 1);
|
||||
if (!band) return false;
|
||||
int w = m_dataset->GetRasterXSize();
|
||||
int h = m_dataset->GetRasterYSize();
|
||||
outBuffer.assign(w * h, 0.0f);
|
||||
CPLErr err = band->RasterIO(GF_Read, 0, 0, w, h, outBuffer.data(), w, h, GDT_Float32, 0, 0);
|
||||
return err == CE_None;
|
||||
#else
|
||||
Q_UNUSED(bandIndex);
|
||||
Q_UNUSED(outBuffer);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
44
HPPA/RasterDataProvider.h
Normal file
44
HPPA/RasterDataProvider.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
#if __has_include(<gdal_priv.h>)
|
||||
#define HPPA_HAVE_GDAL 1
|
||||
#include <gdal_priv.h>
|
||||
#include <cpl_conv.h>
|
||||
#else
|
||||
#define HPPA_HAVE_GDAL 0
|
||||
#endif
|
||||
|
||||
class RasterDataProvider
|
||||
{
|
||||
public:
|
||||
explicit RasterDataProvider(const QString& uri);
|
||||
~RasterDataProvider();
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
|
||||
int bandCount() const;
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
||||
// Returns per-band wavelength metadata if available. If not available, returns empty vector.
|
||||
std::vector<double> bandWavelengths() const;
|
||||
|
||||
// Read a single band (0-based index) into a float buffer of size width()*height().
|
||||
// Returns true on success.
|
||||
bool readBandAsFloat(int bandIndex, std::vector<float>& outBuffer) const;
|
||||
|
||||
QString uri() const { return m_uri; }
|
||||
|
||||
private:
|
||||
QString m_uri;
|
||||
#if HPPA_HAVE_GDAL
|
||||
GDALDataset* m_dataset = nullptr;
|
||||
#else
|
||||
// no-op when GDAL not available
|
||||
void* m_dataset = nullptr;
|
||||
#endif
|
||||
};
|
||||
@ -1,12 +1,48 @@
|
||||
#include "RasterLayer.h"
|
||||
#include "RasterDataProvider.h"
|
||||
#include "RasterRenderer.h"
|
||||
|
||||
RasterLayer::RasterLayer(const QString& name, const QString& uri)
|
||||
: MapLayer(name, uri)
|
||||
{
|
||||
|
||||
// lazy creation
|
||||
}
|
||||
|
||||
MapLayer::LayerType RasterLayer::layerType() const
|
||||
{
|
||||
return MapLayer::LayerType::Raster;
|
||||
}
|
||||
|
||||
RasterDataProvider* RasterLayer::dataProvider() const
|
||||
{
|
||||
return m_provider ? m_provider.get() : nullptr;
|
||||
}
|
||||
|
||||
RasterRenderer* RasterLayer::renderer() const
|
||||
{
|
||||
return m_renderer ? m_renderer.get() : nullptr;
|
||||
}
|
||||
|
||||
bool RasterLayer::openDataProvider()
|
||||
{
|
||||
if (!m_provider) m_provider = std::make_unique<RasterDataProvider>(dataPath());
|
||||
if (!m_provider) return false;
|
||||
bool ok = m_provider->open();
|
||||
if (ok && !m_renderer) m_renderer = std::make_unique<RasterRenderer>(m_provider.get());
|
||||
return ok;
|
||||
}
|
||||
|
||||
QImage RasterLayer::render(const RenderParams& params)
|
||||
{
|
||||
if (!m_provider) {
|
||||
if (!openDataProvider()) return QImage();
|
||||
}
|
||||
if (!m_renderer) m_renderer = std::make_unique<RasterRenderer>(m_provider.get());
|
||||
RasterRenderer::Params p;
|
||||
p.rWave = params.rWave;
|
||||
p.gWave = params.gWave;
|
||||
p.bWave = params.bWave;
|
||||
p.minValue = params.minValue;
|
||||
p.maxValue = params.maxValue;
|
||||
return m_renderer->render(p);
|
||||
}
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include <memory>
|
||||
#include <QImage>
|
||||
|
||||
class RasterDataProvider;
|
||||
class RasterRenderer;
|
||||
|
||||
class RasterLayer : public MapLayer
|
||||
{
|
||||
@ -10,5 +15,25 @@ public:
|
||||
|
||||
LayerType layerType() const override;
|
||||
|
||||
// future: renderer, data provider, etc.
|
||||
// Access provider/renderer
|
||||
RasterDataProvider* dataProvider() const;
|
||||
RasterRenderer* renderer() const;
|
||||
|
||||
// Create or open provider based on this layer's uri
|
||||
bool openDataProvider();
|
||||
|
||||
struct RenderParams {
|
||||
double rWave = 665.0; // default wavelengths (nm)
|
||||
double gWave = 560.0;
|
||||
double bWave = 490.0;
|
||||
double minValue = 0.0; // optional stretch
|
||||
double maxValue = 255.0;
|
||||
};
|
||||
|
||||
// Render the raster using current provider and renderer. Returns an empty QImage on failure.
|
||||
QImage render(const RenderParams& params);
|
||||
|
||||
private:
|
||||
std::unique_ptr<RasterDataProvider> m_provider;
|
||||
std::unique_ptr<RasterRenderer> m_renderer;
|
||||
};
|
||||
|
||||
86
HPPA/RasterRenderer.cpp
Normal file
86
HPPA/RasterRenderer.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "RasterRenderer.h"
|
||||
#include "RasterDataProvider.h"
|
||||
#include <QDebug>
|
||||
#include <algorithm>
|
||||
|
||||
RasterRenderer::RasterRenderer(RasterDataProvider* provider)
|
||||
: m_provider(provider)
|
||||
{
|
||||
}
|
||||
|
||||
void RasterRenderer::stretchTo8bit(const std::vector<float>& in, std::vector<unsigned char>& out, float minVal, float maxVal)
|
||||
{
|
||||
size_t n = in.size();
|
||||
out.resize(n);
|
||||
if (maxVal <= minVal) {
|
||||
std::fill(out.begin(), out.end(), 0);
|
||||
return;
|
||||
}
|
||||
float denom = 1.0f / (maxVal - minVal);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
float v = (in[i] - minVal) * denom;
|
||||
v = std::min(std::max(v, 0.0f), 1.0f);
|
||||
out[i] = static_cast<unsigned char>(v * 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
QImage RasterRenderer::render(const Params& params)
|
||||
{
|
||||
if (!m_provider) return QImage();
|
||||
int bands = m_provider->bandCount();
|
||||
int w = m_provider->width();
|
||||
int h = m_provider->height();
|
||||
if (w <= 0 || h <= 0) return QImage();
|
||||
|
||||
// Find nearest bands for requested wavelengths if wavelengths available
|
||||
std::vector<double> wavelengths = m_provider->bandWavelengths();
|
||||
|
||||
auto chooseBandIndexForWave = [&](double wave)->int {
|
||||
if (wavelengths.empty()) {
|
||||
// fallback: select R,G,B as first three bands
|
||||
if (bands >= 3) return (wave==params.rWave?0:(wave==params.gWave?1:2));
|
||||
if (bands >= 1) return 0;
|
||||
return -1;
|
||||
}
|
||||
int best = -1; double bestDiff = 1e12;
|
||||
for (int i = 0; i < (int)wavelengths.size(); ++i) {
|
||||
if (wavelengths[i] < 0) continue;
|
||||
double d = std::abs(wavelengths[i] - wave);
|
||||
if (d < bestDiff) { bestDiff = d; best = i; }
|
||||
}
|
||||
if (best >= 0) return best;
|
||||
// fallback
|
||||
return std::min(2, bands-1);
|
||||
};
|
||||
|
||||
int rIdx = chooseBandIndexForWave(params.rWave);
|
||||
int gIdx = chooseBandIndexForWave(params.gWave);
|
||||
int bIdx = chooseBandIndexForWave(params.bWave);
|
||||
|
||||
std::vector<float> rbuf, gbuf, bbuf;
|
||||
if (rIdx >= 0) m_provider->readBandAsFloat(rIdx, rbuf);
|
||||
if (gIdx >= 0) m_provider->readBandAsFloat(gIdx, gbuf);
|
||||
if (bIdx >= 0) m_provider->readBandAsFloat(bIdx, bbuf);
|
||||
|
||||
std::vector<unsigned char> r8, g8, b8;
|
||||
float minV = static_cast<float>(params.minValue);
|
||||
float maxV = static_cast<float>(params.maxValue);
|
||||
if (!rbuf.empty()) stretchTo8bit(rbuf, r8, minV, maxV);
|
||||
if (!gbuf.empty()) stretchTo8bit(gbuf, g8, minV, maxV);
|
||||
if (!bbuf.empty()) stretchTo8bit(bbuf, b8, minV, maxV);
|
||||
|
||||
QImage out(w, h, QImage::Format_RGB888);
|
||||
for (int y = 0; y < h; ++y) {
|
||||
unsigned char* scan = out.scanLine(y);
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int idx = y * w + x;
|
||||
unsigned char rc = (r8.size() > (size_t)idx) ? r8[idx] : 0;
|
||||
unsigned char gc = (g8.size() > (size_t)idx) ? g8[idx] : 0;
|
||||
unsigned char bc = (b8.size() > (size_t)idx) ? b8[idx] : 0;
|
||||
scan[x*3 + 0] = rc;
|
||||
scan[x*3 + 1] = gc;
|
||||
scan[x*3 + 2] = bc;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
29
HPPA/RasterRenderer.h
Normal file
29
HPPA/RasterRenderer.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QImage>
|
||||
#include <vector>
|
||||
|
||||
class RasterDataProvider;
|
||||
|
||||
class RasterRenderer
|
||||
{
|
||||
public:
|
||||
struct Params {
|
||||
double rWave = 665.0;
|
||||
double gWave = 560.0;
|
||||
double bWave = 490.0;
|
||||
double minValue = 0.0;
|
||||
double maxValue = 255.0;
|
||||
};
|
||||
|
||||
explicit RasterRenderer(RasterDataProvider* provider);
|
||||
|
||||
// Render to an 8-bit RGB image. Returns empty image on failure.
|
||||
QImage render(const Params& params);
|
||||
|
||||
private:
|
||||
RasterDataProvider* m_provider;
|
||||
|
||||
// helper to map float buffer to 8-bit with min/max stretch
|
||||
static void stretchTo8bit(const std::vector<float>& in, std::vector<unsigned char>& out, float minVal, float maxVal);
|
||||
};
|
||||
Reference in New Issue
Block a user