Qgs开发-读取栅格数据
2014年10月28日
通过驱动程序将栅格读入内存,并按照像素的实际大小,计算内存位置,读取数据。
驱动程序提供相应的计算接口。
通过驱动(默认GDAL(key=”gdal”)等),读入Raster数据(QgsRasterLayer)。然后读取数据的内存地址(QgsRasterDataProvider::block())(如果数据过大,则需要分块读取)。
可以通过block()加载数据块,但是此块不能太大。对于大数据(实测超过1G大小,bValid=false,bEmpty=true),只能使用分块读取的方法。小数据(实测不超过1G,但并没有找到官方说明)可以直接取得全部范围并根据行列号取得像素值(QgsRasterDataProvider取得QgsRasterBlock)。
QgsRasterBlock提供value(row,col)取影像数据的行、列号数据。但分块时要重新计算范围,实际上就是QgsRasterDataProvider::Identify()的算法。小数据可以直接使用,方便。
对于经纬度,使用QgsRasterDataProvider::Identify(),会先将经纬度转换为行列号,然后计算读取1*1范围(单个像素)大小的像素值。
/**************************************************************************
* @file QgsVectorAnalysis.cpp
* @brief analysis core funtion
*
* analysis core funtion.
* @author [email protected]
* @date 2014-10-20 16:19:16
**************************************************************************/
#include "qgsrasteranalysis.h"
#include <qgsrasterlayer.h>
#include <QDebug>
#include <qgsmapcanvas.h>
#include <qgsmapsettings.h>
#include <QgsRasterIdentifyResult.h>
using namespace gutang::qgsmaplib;
QgsRasterAnalysis::QgsRasterAnalysis()
{
}
/**
* @briefQgsRasterAnalysis::lonLat2ColRow
*
* convertlon/lat to raster column number/row number.
* @param pLayer
* @param dLon
* @param dLat
* @param iCol
* @param iRow
* @return
* @date2014-10-31 10:36:25
*/
int QgsRasterAnalysis::lonLat2ColRow (QgsRasterLayer*pLayer, double dLon, double dLat,
int&iCol, int &iRow)
{
QgsPointptLeftTop;
doubledXResolution, dYResolution;
calculateRasterInfo(pLayer,ptLeftTop, dXResolution, dYResolution);
iCol = qFloor((dLon - ptLeftTop.x ())/dXResolution);
iRow = qFloor((dLat - ptLeftTop.y ())/dYResolution);
return 0;
}
/**
* @briefQgsRasterAnalysis::colRow2LonLat
*
* convert rastercolumn number/row number to lon/lat.
* @param pLayer
* @param iCol
* @param iRow
* @param dLon
* @param dLat
* @param bCentertrue = convert to pixel center lon/lat. false = convert to pixel lefttop cornerlon/lat.
* @return
* @date2014-10-31 10:36:25
*/
int QgsRasterAnalysis::colRow2LonLat (QgsRasterLayer*pLayer, int iCol, int iRow,
double&dLon, double &dLat, bool bCenter)
{
QgsPointptLeftTop;
doubledXResolution, dYResolution;
calculateRasterInfo(pLayer, ptLeftTop, dXResolution, dYResolution);
dLon =ptLeftTop.x () + dXResolution*iCol;
dLat =ptLeftTop.y () + dYResolution*iRow;
if(true ==bCenter)
{
dLon +=dXResolution/2;
dLat +=dYResolution/2;
}
return 0;
}
/**
* @briefQgsRasterAnalysis::calculateRasterInfo
*
* calculateraster layer info.
* @param pLayer
* @paramptLeftTop
* @paramdXResolution
* @paramdYResolution
* @date2014-10-31 10:36:25
*/
void QgsRasterAnalysis::calculateRasterInfo(QgsRasterLayer *pLayer, QgsPoint &ptLeftTop,
double &dXResolution, double &dYResolution)
{
int iRowCount= pLayer->height ();
int iColCount = pLayer->width ();
QgsRectanglerExtent = pLayer->extent ();
QgsPointptLT(rExtent.xMinimum (),rExtent.yMaximum ());
ptLeftTop =ptLT;
dXResolution= rExtent.width ()/iColCount;
dYResolution= rExtent.height ()/iRowCount;
dYResolution*= -1;//reverse direction
}
/**
* @briefQgsRasterAnalysis::getRasterValue
*
* get pixelvalue of raster.
* @param pLayer
* @param vPt
* @paramiBandIndex start from 1
* @parampFinished finished percent
* @return
* @author [email protected]
* @date2014-10-31 10:36:25
*/
QVector<double> QgsRasterAnalysis::getRasterValue(QgsRasterLayer *pLayer,
constQVector<QgsPoint> &vPt,
intiBandIndex,
int*pFinished)
{
QgsRasterDataProvider *pProvider = pLayer->dataProvider ();
if(NULL ==pProvider)
{
qDebug()<<"invalid layer.";
returnQVector<double>();
}
QVector<double> vValue;
for(inti=0;i<vPt.size ();++i)
{
QgsRasterIdentifyResult rst = pProvider->identify(vPt[i],QgsRaster::IdentifyFormatValue);
doubledValue = rst.results ()[iBandIndex].toDouble ();
vValue<<dValue;
if(pFinished != NULL){
*pFinished = i;
}
}
returnvValue;
}