fix
1、基于新框架实现点击显示光谱; 2、影像拉伸显示优化; 3、右键菜单新增:移除所有栅格图层;
This commit is contained in:
142
HPPA/HPPA.cpp
142
HPPA/HPPA.cpp
@ -6,7 +6,6 @@
|
||||
#include <QFileInfo> // 新增,用于解析路径
|
||||
|
||||
#include "HPPA.h"
|
||||
#include "ImageReaderWriter.h"
|
||||
#include "RasterLayer.h"
|
||||
#include "LayerTreeLayerNode.h"
|
||||
|
||||
@ -17,6 +16,11 @@ HPPA* HPPA::instance()
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
LayerTreeNode* HPPA::rasterGroupNode() const
|
||||
{
|
||||
return m_RasterGroup;
|
||||
}
|
||||
|
||||
HPPA::HPPA(QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
@ -720,7 +724,7 @@ void HPPA::initControlTabwidget()
|
||||
//电源控制
|
||||
m_pc = new PowerControl();
|
||||
m_pc->setWindowFlags(Qt::Widget);
|
||||
ui.controlTabWidget->addTab(m_pc, QString::fromLocal8Bit("电源控制"));
|
||||
ui.controlTabWidget->addTab(m_pc, QString::fromLocal8Bit("电源控制"));
|
||||
|
||||
//机械臂控制
|
||||
m_rac = new RobotArmControl();
|
||||
@ -912,6 +916,61 @@ void HPPA::removeLayerByTreeIndex()
|
||||
}
|
||||
}
|
||||
|
||||
void HPPA::removeAllLayersInRasterGroup()
|
||||
{
|
||||
if (!m_LayerTreeModel || !m_RasterGroup) return;
|
||||
|
||||
QVector<LayerTreeNode*> pending;
|
||||
for (int i = 0; i < m_RasterGroup->childCount(); ++i)
|
||||
{
|
||||
pending.push_back(m_RasterGroup->childAt(i));
|
||||
}
|
||||
|
||||
while (!pending.isEmpty())
|
||||
{
|
||||
LayerTreeNode* node = pending.back();
|
||||
pending.pop_back();
|
||||
if (!node) continue;
|
||||
|
||||
for (int i = 0; i < node->childCount(); ++i)
|
||||
{
|
||||
pending.push_back(node->childAt(i));
|
||||
}
|
||||
|
||||
if (node->type() != LayerTreeNode::Type::Layer) continue;
|
||||
|
||||
auto* layerNode = static_cast<LayerTreeLayerNode*>(node);
|
||||
MapLayer* mapLayer = layerNode->mapLayer();
|
||||
QWidget* layerWidget = nullptr;
|
||||
|
||||
if (mapLayer && m_MapLayerStore)
|
||||
{
|
||||
layerWidget = m_MapLayerStore->widgetForLayer(mapLayer);
|
||||
m_MapLayerStore->removeLayer(mapLayer);
|
||||
}
|
||||
|
||||
if (layerWidget && m_imageViewerTabWidget)
|
||||
{
|
||||
const int tabIndex = m_imageViewerTabWidget->indexOf(layerWidget);
|
||||
if (tabIndex >= 0)
|
||||
{
|
||||
m_imageViewerTabWidget->removeTab(tabIndex);
|
||||
}
|
||||
layerWidget->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
while (m_RasterGroup->childCount() > 0)
|
||||
{
|
||||
const int row = m_RasterGroup->childCount() - 1;
|
||||
LayerTreeNode* removed = m_LayerTreeModel->removeNode(m_RasterGroup, row);
|
||||
if (removed)
|
||||
{
|
||||
delete removed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HPPA::initPanelToolbar()
|
||||
{
|
||||
mPanelMenu = new QMenu(QString::fromLocal8Bit("面板"), this);//create panel menu
|
||||
@ -1084,7 +1143,7 @@ void HPPA::onStartRecordStep1()
|
||||
|
||||
if (m_RecordState % 2 == 1)
|
||||
{
|
||||
m_imageViewerTabWidget->clear();
|
||||
//m_imageViewerTabWidget->clear();
|
||||
|
||||
m_Imager->setFileName2Save(imgPath);
|
||||
m_Imager->setFrameNumber(this->frame_number->text().toInt());
|
||||
@ -1099,7 +1158,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;
|
||||
}
|
||||
@ -1109,10 +1168,10 @@ void HPPA::onStartRecordStep1()
|
||||
|
||||
if (m_RecordState % 2 == 1)
|
||||
{
|
||||
m_imageViewerTabWidget->clear();
|
||||
//m_imageViewerTabWidget->clear();
|
||||
|
||||
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);
|
||||
@ -1136,7 +1195,7 @@ void HPPA::onStartRecordStep1()
|
||||
|
||||
if (m_RecordState % 2 == 1)
|
||||
{
|
||||
m_imageViewerTabWidget->clear();
|
||||
//m_imageViewerTabWidget->clear();
|
||||
|
||||
m_Imager->setFileName2Save(imgPath);
|
||||
m_Imager->setFrameNumber(this->frame_number->text().toInt());
|
||||
@ -1145,7 +1204,7 @@ void HPPA::onStartRecordStep1()
|
||||
m_tmc->run();
|
||||
|
||||
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);}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1201,8 +1260,8 @@ void HPPA::onTabWidgetCurrentChanged(int index)//代码新建一个tab,会调
|
||||
QList<Mapcavas*> currentImageViewer = currentWidget->findChildren<Mapcavas*>();
|
||||
|
||||
//先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(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int,int,QVector<double>,QVector<double>)), this, SLOT(onLeftMouseButtonPressed(int,int,QVector<double>,QVector<double>)));
|
||||
connect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int,int,QVector<double>,QVector<double>)), this, SLOT(onLeftMouseButtonPressed(int,int,QVector<double>,QVector<double>)));
|
||||
}
|
||||
|
||||
void HPPA::onActionOpenDirectory()
|
||||
@ -1259,8 +1318,11 @@ void HPPA::OnGainSliderChanged(double Gain)
|
||||
ui.gain_lineEdit->setText(QString::number(Gain));
|
||||
}
|
||||
|
||||
void HPPA::onLeftMouseButtonPressed(int x, int y)
|
||||
void HPPA::onLeftMouseButtonPressed(int x, int y, QVector<double> wavelengths, QVector<double> spectrum)
|
||||
{
|
||||
Q_UNUSED(x);
|
||||
Q_UNUSED(y);
|
||||
|
||||
try
|
||||
{
|
||||
//正在采集时,不能显示光谱曲线
|
||||
@ -1269,62 +1331,29 @@ void HPPA::onLeftMouseButtonPressed(int x, int y)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FileOperation* fileOperation = new FileOperation();
|
||||
string directory = fileOperation->getDirectoryFromString();
|
||||
string imgPath = directory + "\\" + m_FilenameLineEdit->text().toStdString() + "_" + std::to_string(m_TabWidgetCurrentIndex) + ".bil";
|
||||
|
||||
ImageReaderWriter* ImageReader = new ImageReaderWriter(imgPath.c_str());
|
||||
|
||||
|
||||
if (x < 0 || x>ImageReader->getXCount() || y<0 || y>ImageReader->getyCount() - 1)
|
||||
if (spectrum.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
float* data = ImageReader->ReadImage(x, y, 1, 1);
|
||||
|
||||
|
||||
QLineSeries* series = new QLineSeries();
|
||||
//series->clear();//////////////////////////////
|
||||
|
||||
|
||||
QString imagerSelected = mImagerGroup->checkedAction()->objectName();
|
||||
if (imagerSelected == "mActionPica_L" || imagerSelected == "mActionCorning_410" || imagerSelected == "mActionPika_XC2")
|
||||
const int count = qMin(wavelengths.size(), spectrum.size());
|
||||
if (count > 0)
|
||||
{
|
||||
int start = m_Imager->getStartBand();
|
||||
for (size_t i = 0; i < m_Imager->getBandCount() - 1; i++)
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
//malloc申请的内存用法1:可以当做数组用
|
||||
series->append(m_Imager->getWavelengthAtBand(i + start), data[i]);
|
||||
|
||||
////malloc申请的内存用法2:指针存取
|
||||
//series->append(m_Imager->getWavelengthAtBand(i), *data);
|
||||
//data++;
|
||||
}
|
||||
}
|
||||
else if (imagerSelected == "mActionPica_NIR")
|
||||
{
|
||||
int start = 0;
|
||||
for (size_t i = 0; i < m_Imager->getBandCount() - 1; i++)
|
||||
{
|
||||
//malloc申请的内存用法1:可以当做数组用
|
||||
series->append(m_Imager->getWavelengthAtBand(i + start), data[i]);
|
||||
|
||||
////malloc申请的内存用法2:指针存取
|
||||
//series->append(m_Imager->getWavelengthAtBand(i), *data);
|
||||
//data++;
|
||||
series->append(wavelengths[i], spectrum[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(QString::fromLocal8Bit("请选择相机!"));
|
||||
msgBox.exec();
|
||||
|
||||
return;
|
||||
for (int i = 0; i < spectrum.size(); ++i)
|
||||
{
|
||||
series->append(i, spectrum[i]);
|
||||
}
|
||||
}
|
||||
|
||||
series->setPen(QPen(QColor("#FF928A"), 2));
|
||||
|
||||
m_chart->removeAllSeries();
|
||||
@ -1335,11 +1364,6 @@ void HPPA::onLeftMouseButtonPressed(int x, int y)
|
||||
QValueAxis* axisY = qobject_cast<QValueAxis*>(m_chart->axisY());
|
||||
|
||||
setAxis(axisX, axisY);
|
||||
|
||||
/*std::cout << "x坐标:" << x << std::endl;
|
||||
std::cout << "y坐标:" << y << std::endl;
|
||||
std::cout << "文件名:" << imgPath << std::endl;*/
|
||||
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
|
||||
51
HPPA/HPPA.h
51
HPPA/HPPA.h
@ -18,6 +18,7 @@
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QVector>
|
||||
|
||||
#include "ui_HPPA.h"
|
||||
#include "resononImager.h"
|
||||
@ -174,6 +175,7 @@ public:
|
||||
~HPPA();
|
||||
|
||||
static HPPA* instance();
|
||||
LayerTreeNode* rasterGroupNode() const;
|
||||
|
||||
void CalculateIntegratioinTimeRange();//通过帧率计算积分时间范围,设置slider最大值
|
||||
|
||||
@ -294,41 +296,42 @@ public Q_SLOTS:
|
||||
void onActionOpenDirectory();
|
||||
|
||||
void OnFramerateLineeditEditingFinished();//
|
||||
void OnFramerateSliderChanged(double framerate);//
|
||||
void OnFramerateSliderChanged(double framerate);//
|
||||
|
||||
void OnIntegratioinTimeEditingFinished();//
|
||||
void OnIntegratioinTimeSliderChanged(double IntegratioinTime);//
|
||||
void OnGainEditingFinished();//
|
||||
void OnGainSliderChanged(double Gain);//
|
||||
void OnIntegratioinTimeEditingFinished();//
|
||||
void OnIntegratioinTimeSliderChanged(double IntegratioinTime);//
|
||||
void OnGainEditingFinished();//
|
||||
void OnGainSliderChanged(double Gain);//
|
||||
|
||||
void onLeftMouseButtonPressed(int x, int y);//点击影像像元显示光谱
|
||||
void setAxis(QValueAxis* axisX, QValueAxis* axisY);
|
||||
void onLeftMouseButtonPressed(int x, int y, QVector<double> wavelengths, QVector<double> spectrum);//点击影像像元显示光谱
|
||||
void setAxis(QValueAxis* axisX, QValueAxis* axisY);
|
||||
|
||||
|
||||
void timerEvent(QTimerEvent *event);
|
||||
//
|
||||
void onimagerSimulatorMove(int x, int y);
|
||||
void OnSendLogToCallClass(QString str);
|
||||
void timerEvent(QTimerEvent *event);
|
||||
//
|
||||
void onimagerSimulatorMove(int x, int y);
|
||||
void OnSendLogToCallClass(QString str);
|
||||
|
||||
void onPlotRgbImage();
|
||||
void onCloseRgbCamera();
|
||||
void onClearLabel();
|
||||
void onPlotRgbImage();
|
||||
void onCloseRgbCamera();
|
||||
void onClearLabel();
|
||||
|
||||
void onCopyFinished();
|
||||
void onCopyFinished();
|
||||
|
||||
void requestFinished(QNetworkReply* reply);
|
||||
void requestFinished(QNetworkReply* reply);
|
||||
|
||||
void recordFromRobotArm(int fileCounter);
|
||||
void recordFromRobotArm(int fileCounter);
|
||||
|
||||
void createOneMotorScenario();
|
||||
void createPlantPhenotypeScenario();
|
||||
void onCreated3DModelPlantPhenotype();
|
||||
void onCreated3DModelOneMotor();
|
||||
void createOneMotorScenario();
|
||||
void createPlantPhenotypeScenario();
|
||||
void onCreated3DModelPlantPhenotype();
|
||||
void onCreated3DModelOneMotor();
|
||||
|
||||
void onImageFileSaved(QString path, int fileIndex);
|
||||
void onImageFileSaved(QString path, int fileIndex);
|
||||
|
||||
void onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex);
|
||||
void removeLayerByTreeIndex();
|
||||
void onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex);
|
||||
void removeLayerByTreeIndex();
|
||||
void removeAllLayersInRasterGroup();
|
||||
|
||||
signals:
|
||||
void StartFocusSignal();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
#include <QWheelEvent>
|
||||
#include <QPoint>
|
||||
@ -130,7 +131,19 @@ void Mapcavas::mousePressEvent(QMouseEvent *event)
|
||||
m_bMouseTranslate = true;
|
||||
m_lastMousePos = event->pos();
|
||||
|
||||
emit leftMouseButtonPressed(mapToScene(m_lastMousePos).x(), mapToScene(m_lastMousePos).y());
|
||||
const QPointF scenePt = mapToScene(m_lastMousePos);
|
||||
const int x = static_cast<int>(std::floor(scenePt.x()));
|
||||
const int y = static_cast<int>(std::floor(scenePt.y()));
|
||||
|
||||
if (m_rasterLayer && m_rasterLayer->isValidPixel(x, y))
|
||||
{
|
||||
QVector<double> wavelengths;
|
||||
QVector<double> spectrum;
|
||||
if (m_rasterLayer->readPixelSpectrum(x, y, wavelengths, spectrum))
|
||||
{
|
||||
emit leftMouseButtonPressed(x, y, wavelengths, spectrum);
|
||||
}
|
||||
}
|
||||
}
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "QGraphicsView"
|
||||
#include "qlabel.h"
|
||||
#include <QVector>
|
||||
|
||||
class RasterLayer; // forward
|
||||
|
||||
@ -62,6 +63,6 @@ private:
|
||||
|
||||
|
||||
signals:
|
||||
void leftMouseButtonPressed(int, int);
|
||||
void leftMouseButtonPressed(int, int, QVector<double>, QVector<double>);
|
||||
};
|
||||
#endif
|
||||
@ -24,7 +24,9 @@ void LayerTreeView::contextMenuEvent(QContextMenuEvent* event)
|
||||
return;
|
||||
|
||||
const QModelIndex idx = indexAt(event->pos());
|
||||
if (!idx.isValid())
|
||||
if (idx.isValid())
|
||||
setCurrentIndex(idx);
|
||||
else
|
||||
setCurrentIndex(QModelIndex());
|
||||
|
||||
QMenu* menu = m_menuProvider->createContextMenu();
|
||||
|
||||
@ -17,20 +17,37 @@ QMenu* LayerTreeViewMenuProvider::createContextMenu()
|
||||
|
||||
QMenu* menu = new QMenu();
|
||||
|
||||
// Always allow remove when index is valid and points to a Layer
|
||||
if (m_contextIndex.isValid())
|
||||
if (!m_contextIndex.isValid())
|
||||
{
|
||||
// determine node type by looking at model's node
|
||||
const LayerTreeModel* model = static_cast<const LayerTreeModel*>(m_contextIndex.model());
|
||||
if (model)
|
||||
return menu;
|
||||
}
|
||||
|
||||
const LayerTreeModel* model = static_cast<const LayerTreeModel*>(m_contextIndex.model());
|
||||
if (!model)
|
||||
{
|
||||
return menu;
|
||||
}
|
||||
|
||||
LayerTreeNode* node = static_cast<LayerTreeNode*>(m_contextIndex.internalPointer());
|
||||
if (!node)
|
||||
{
|
||||
return menu;
|
||||
}
|
||||
|
||||
if (node->type() == LayerTreeNode::Type::Layer)
|
||||
{
|
||||
QAction* removeAction = new QAction(QStringLiteral("<EFBFBD>Ƴ<EFBFBD>ͼ<EFBFBD><EFBFBD>"), menu);
|
||||
connect(removeAction, &QAction::triggered, HPPA::instance(), &HPPA::removeLayerByTreeIndex);
|
||||
menu->addAction(removeAction);
|
||||
}
|
||||
else if (node->type() == LayerTreeNode::Type::Group)
|
||||
{
|
||||
HPPA* app = HPPA::instance();
|
||||
if (app && node == app->rasterGroupNode())
|
||||
{
|
||||
LayerTreeNode* node = static_cast<LayerTreeNode*>(m_contextIndex.internalPointer());
|
||||
if (node && node->type() == LayerTreeNode::Type::Layer)
|
||||
{
|
||||
QAction* removeAction = new QAction(QStringLiteral("<EFBFBD>Ƴ<EFBFBD>ͼ<EFBFBD><EFBFBD>"), menu);
|
||||
connect(removeAction, &QAction::triggered, HPPA::instance(), &HPPA::removeLayerByTreeIndex);
|
||||
menu->addAction(removeAction);
|
||||
}
|
||||
QAction* removeAllAction = new QAction(QStringLiteral("<EFBFBD>Ƴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>"), menu);
|
||||
connect(removeAllAction, &QAction::triggered, app, &HPPA::removeAllLayersInRasterGroup);
|
||||
menu->addAction(removeAllAction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
#include "RasterDataProvider.h"
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#if HPPA_HAVE_GDAL
|
||||
#include <gdal_priv.h>
|
||||
@ -79,27 +82,126 @@ int RasterDataProvider::height() const
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RasterDataProvider::isValidPixel(int x, int y) const
|
||||
{
|
||||
const int w = width();
|
||||
const int h = height();
|
||||
return x >= 0 && y >= 0 && x < w && y < h;
|
||||
}
|
||||
|
||||
std::vector<double> RasterDataProvider::parseEnviHdrWavelengths() const
|
||||
{
|
||||
std::vector<double> res;
|
||||
|
||||
QFileInfo fi(m_uri);
|
||||
QString hdrPath = fi.path() + "/" + fi.completeBaseName() + ".hdr";
|
||||
QFile hdr(hdrPath);
|
||||
if (!hdr.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
QString text = QString::fromLocal8Bit(hdr.readAll());
|
||||
hdr.close();
|
||||
|
||||
QRegularExpression rx("wavelength\\s*=\\s*\\{([^}]*)\\}", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
|
||||
QRegularExpressionMatch m = rx.match(text);
|
||||
if (!m.hasMatch()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
const QString body = m.captured(1);
|
||||
const QStringList parts = body.split(',', QString::SkipEmptyParts);
|
||||
res.reserve(parts.size());
|
||||
for (const QString& p : parts) {
|
||||
bool ok = false;
|
||||
double v = p.trimmed().toDouble(&ok);
|
||||
if (ok) {
|
||||
res.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<double> RasterDataProvider::bandWavelengths() const
|
||||
{
|
||||
std::vector<double> res;
|
||||
#if HPPA_HAVE_GDAL
|
||||
if (!m_dataset) return res;
|
||||
|
||||
// 1) Try ENVI dataset-level metadata first: wavelength = { ... }
|
||||
const char* dsWave = m_dataset->GetMetadataItem("wavelength", "ENVI");
|
||||
if (!dsWave) dsWave = m_dataset->GetMetadataItem("Wavelength", "ENVI");
|
||||
if (dsWave) {
|
||||
QString dsWaveStr = QString::fromLocal8Bit(dsWave);
|
||||
dsWaveStr.remove('{').remove('}');
|
||||
const QStringList parts = dsWaveStr.split(',', QString::SkipEmptyParts);
|
||||
res.reserve(parts.size());
|
||||
for (const QString& p : parts) {
|
||||
bool ok = false;
|
||||
double v = p.trimmed().toDouble(&ok);
|
||||
if (ok) res.push_back(v);
|
||||
}
|
||||
if (!res.empty()) return res;
|
||||
}
|
||||
|
||||
// 2) Try per-band metadata
|
||||
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);
|
||||
bool ok = false;
|
||||
double v = QString::fromLocal8Bit(val).trimmed().toDouble(&ok);
|
||||
res.push_back(ok ? v : -1.0);
|
||||
} else {
|
||||
// push a negative to indicate unknown
|
||||
res.push_back(-1.0);
|
||||
}
|
||||
}
|
||||
if (!res.empty()) return res;
|
||||
#endif
|
||||
|
||||
// 3) Fallback: parse ENVI .hdr directly
|
||||
return parseEnviHdrWavelengths();
|
||||
}
|
||||
|
||||
bool RasterDataProvider::readPixelSpectrum(int x, int y, std::vector<double>& outSpectrum) const
|
||||
{
|
||||
#if HPPA_HAVE_GDAL
|
||||
outSpectrum.clear();
|
||||
if (!m_dataset) return false;
|
||||
if (!isValidPixel(x, y)) return false;
|
||||
|
||||
const int bands = m_dataset->GetRasterCount();
|
||||
if (bands <= 0) return false;
|
||||
|
||||
outSpectrum.resize(bands);
|
||||
for (int i = 0; i < bands; ++i) {
|
||||
GDALRasterBand* band = m_dataset->GetRasterBand(i + 1);
|
||||
if (!band) return false;
|
||||
|
||||
float value = 0.0f;
|
||||
CPLErr err = band->RasterIO(
|
||||
GF_Read,
|
||||
x, y,
|
||||
1, 1,
|
||||
&value,
|
||||
1, 1,
|
||||
GDT_Float32,
|
||||
0, 0);
|
||||
|
||||
if (err != CE_None) return false;
|
||||
outSpectrum[i] = static_cast<double>(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
Q_UNUSED(x);
|
||||
Q_UNUSED(y);
|
||||
Q_UNUSED(outSpectrum);
|
||||
return false;
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
bool RasterDataProvider::readBandAsFloat(int bandIndex, std::vector<float>& outBuffer) const
|
||||
|
||||
@ -24,9 +24,14 @@ public:
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
||||
bool isValidPixel(int x, int y) const;
|
||||
|
||||
// Returns per-band wavelength metadata if available. If not available, returns empty vector.
|
||||
std::vector<double> bandWavelengths() const;
|
||||
|
||||
// Read spectrum of one pixel (x,y) across all bands.
|
||||
bool readPixelSpectrum(int x, int y, std::vector<double>& outSpectrum) 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;
|
||||
@ -35,6 +40,7 @@ public:
|
||||
|
||||
private:
|
||||
QString m_uri;
|
||||
std::vector<double> parseEnviHdrWavelengths() const;
|
||||
#if HPPA_HAVE_GDAL
|
||||
GDALDataset* m_dataset = nullptr;
|
||||
#else
|
||||
|
||||
@ -36,6 +36,40 @@ bool RasterLayer::openDataProvider()
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool RasterLayer::isValidPixel(int x, int y)
|
||||
{
|
||||
if (!m_provider) {
|
||||
if (!openDataProvider()) return false;
|
||||
}
|
||||
return m_provider->isValidPixel(x, y);
|
||||
}
|
||||
|
||||
bool RasterLayer::readPixelSpectrum(int x, int y, QVector<double>& wavelengths, QVector<double>& spectrum)
|
||||
{
|
||||
if (!m_provider) {
|
||||
if (!openDataProvider()) return false;
|
||||
}
|
||||
|
||||
std::vector<double> wl;
|
||||
std::vector<double> sp;
|
||||
|
||||
if (!m_provider->readPixelSpectrum(x, y, sp)) return false;
|
||||
|
||||
wl = m_provider->bandWavelengths();
|
||||
|
||||
wavelengths = QVector<double>::fromStdVector(wl);
|
||||
spectrum = QVector<double>::fromStdVector(sp);
|
||||
|
||||
if (wavelengths.size() != spectrum.size()) {
|
||||
wavelengths.resize(spectrum.size());
|
||||
for (int i = 0; i < wavelengths.size(); ++i) {
|
||||
wavelengths[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QImage RasterLayer::render(const RenderParams& params)
|
||||
{
|
||||
if (!m_provider) {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "MapLayer.h"
|
||||
#include <memory>
|
||||
#include <QImage>
|
||||
#include <QVector>
|
||||
|
||||
class RasterDataProvider;
|
||||
class RasterRenderer;
|
||||
@ -23,12 +24,15 @@ public:
|
||||
// Create or open provider based on this layer's uri
|
||||
bool openDataProvider();
|
||||
|
||||
bool isValidPixel(int x, int y);
|
||||
bool readPixelSpectrum(int x, int y, QVector<double>& wavelengths, QVector<double>& spectrum);
|
||||
|
||||
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;
|
||||
double maxValue = 4095.0;
|
||||
};
|
||||
|
||||
// Render the raster using current provider and renderer. Returns an empty QImage on failure.
|
||||
|
||||
Reference in New Issue
Block a user