27 void QgsRasterAnalysisUtils::cellInfoForBBox(
const QgsRectangle &rasterBBox,
const QgsRectangle &featureBBox,
double cellSizeX,
double cellSizeY,
28 int &nCellsX,
int &nCellsY,
int rasterWidth,
int rasterHeight,
QgsRectangle &rasterBlockExtent )
41 int offsetX =
static_cast< int >( std::floor( ( intersectBox.
xMinimum() - rasterBBox.
xMinimum() ) / cellSizeX ) );
42 int offsetY =
static_cast< int >( std::floor( ( rasterBBox.
yMaximum() - intersectBox.
yMaximum() ) / cellSizeY ) );
44 int maxColumn =
static_cast< int >( std::floor( ( intersectBox.
xMaximum() - rasterBBox.
xMinimum() ) / cellSizeX ) ) + 1;
45 int maxRow =
static_cast< int >( std::floor( ( rasterBBox.
yMaximum() - intersectBox.
yMinimum() ) / cellSizeY ) ) + 1;
47 nCellsX = maxColumn - offsetX;
48 nCellsY = maxRow - offsetY;
51 nCellsX = std::min( offsetX + nCellsX, rasterWidth ) - offsetX;
52 nCellsY = std::min( offsetY + nCellsY, rasterHeight ) - offsetY;
55 rasterBBox.
yMaximum() - offsetY * cellSizeY,
56 rasterBBox.
xMinimum() + ( nCellsX + offsetX ) * cellSizeX,
57 rasterBBox.
yMaximum() - ( nCellsY + offsetY ) * cellSizeY );
60 void QgsRasterAnalysisUtils::statisticsFromMiddlePointTest(
QgsRasterInterface *rasterInterface,
int rasterBand,
const QgsGeometry &poly,
int nCellsX,
int nCellsY,
double cellSizeX,
double cellSizeY,
const QgsRectangle &rasterBBox,
const std::function<
void(
double )> &addValue,
bool skipNodata )
67 polyEngine->prepareGeometry();
70 iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
72 std::unique_ptr< QgsRasterBlock > block;
78 bool isNoData =
false;
79 while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
81 double cellCenterY = blockExtent.
yMaximum() - 0.5 * cellSizeY;
83 for (
int row = 0; row < iterRows; ++row )
85 double cellCenterX = blockExtent.
xMinimum() + 0.5 * cellSizeX;
86 for (
int col = 0; col < iterCols; ++col )
88 const double pixelValue = block->valueAndNoData( row, col, isNoData );
89 if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
91 QgsPoint cellCenter( cellCenterX, cellCenterY );
92 if ( polyEngine->contains( &cellCenter ) )
94 addValue( pixelValue );
97 cellCenterX += cellSizeX;
99 cellCenterY -= cellSizeY;
104 void QgsRasterAnalysisUtils::statisticsFromPreciseIntersection(
QgsRasterInterface *rasterInterface,
int rasterBand,
const QgsGeometry &poly,
int nCellsX,
int nCellsY,
double cellSizeX,
double cellSizeY,
const QgsRectangle &rasterBBox,
const std::function<
void(
double,
double )> &addValue,
bool skipNodata )
108 double hCellSizeX = cellSizeX / 2.0;
109 double hCellSizeY = cellSizeY / 2.0;
110 double pixelArea = cellSizeX * cellSizeY;
118 polyEngine->prepareGeometry();
121 iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
123 std::unique_ptr< QgsRasterBlock > block;
129 bool isNoData =
false;
130 while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
132 double currentY = blockExtent.
yMaximum() - 0.5 * cellSizeY;
133 for (
int row = 0; row < iterRows; ++row )
135 double currentX = blockExtent.
xMinimum() + 0.5 * cellSizeX;
136 for (
int col = 0; col < iterCols; ++col )
138 const double pixelValue = block->valueAndNoData( row, col, isNoData );
139 if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
144 if ( !pixelRectGeometry.
isNull() && polyEngine->intersects( pixelRectGeometry.
constGet() ) )
148 if ( !intersectGeometry.
isEmpty() )
150 double intersectionArea = intersectGeometry.
area();
151 if ( intersectionArea > 0.0 )
153 weight = intersectionArea / pixelArea;
154 addValue( pixelValue, weight );
159 currentX += cellSizeX;
161 currentY -= cellSizeY;
166 bool QgsRasterAnalysisUtils::validPixel(
double value )
168 return !std::isnan( value );
171 void QgsRasterAnalysisUtils::mapToPixel(
const double x,
const double y,
const QgsRectangle bounds,
const double unitsPerPixelX,
const double unitsPerPixelY,
int &px,
int &py )
173 px = trunc( ( x - bounds.
xMinimum() ) / unitsPerPixelX );
174 py = trunc( ( y - bounds.
yMaximum() ) / -unitsPerPixelY );
177 void QgsRasterAnalysisUtils::pixelToMap(
const int px,
const int py,
const QgsRectangle bounds,
const double unitsPerPixelX,
const double unitsPerPixelY,
double &x,
double &y )
179 x = bounds.
xMinimum() + ( px + 0.5 ) * unitsPerPixelX;
180 y = bounds.
yMaximum() - ( py + 0.5 ) * unitsPerPixelY;
183 static QVector< QPair< QString, Qgis::DataType > > sDataTypes;
185 void populateDataTypes()
187 if ( sDataTypes.empty() )
189 sDataTypes.append( qMakePair( QStringLiteral(
"Byte" ),
Qgis::Byte ) );
190 sDataTypes.append( qMakePair( QStringLiteral(
"Int16" ),
Qgis::Int16 ) );
191 sDataTypes.append( qMakePair( QStringLiteral(
"UInt16" ),
Qgis::UInt16 ) );
192 sDataTypes.append( qMakePair( QStringLiteral(
"Int32" ),
Qgis::Int32 ) );
193 sDataTypes.append( qMakePair( QStringLiteral(
"UInt32" ),
Qgis::UInt32 ) );
194 sDataTypes.append( qMakePair( QStringLiteral(
"Float32" ),
Qgis::Float32 ) );
195 sDataTypes.append( qMakePair( QStringLiteral(
"Float64" ),
Qgis::Float64 ) );
196 sDataTypes.append( qMakePair( QStringLiteral(
"CInt16" ),
Qgis::CInt16 ) );
197 sDataTypes.append( qMakePair( QStringLiteral(
"CInt32" ),
Qgis::CInt32 ) );
198 sDataTypes.append( qMakePair( QStringLiteral(
"CFloat32" ),
Qgis::CFloat32 ) );
199 sDataTypes.append( qMakePair( QStringLiteral(
"CFloat64" ),
Qgis::CFloat64 ) );
203 std::unique_ptr<QgsProcessingParameterDefinition> QgsRasterAnalysisUtils::createRasterTypeParameter(
const QString &name,
const QString &description,
Qgis::DataType defaultType )
208 int defaultChoice = 0;
210 for (
auto it = sDataTypes.constBegin(); it != sDataTypes.constEnd(); ++it )
212 names.append( it->first );
213 if ( it->second == defaultType )
218 return qgis::make_unique< QgsProcessingParameterEnum >( name, description, names,
false, defaultChoice );
221 Qgis::DataType QgsRasterAnalysisUtils::rasterTypeChoiceToDataType(
int choice )
223 if ( choice < 0 || choice >= sDataTypes.count() )
226 return sDataTypes.value( choice ).second;
229 void QgsRasterAnalysisUtils::applyRasterLogicOperator(
const std::vector< QgsRasterAnalysisUtils::RasterLogicInput > &inputs,
QgsRasterDataProvider *destinationRaster,
double outputNoDataValue,
const bool treatNoDataAsFalse,
231 std::function<
void(
const std::vector< std::unique_ptr< QgsRasterBlock > > &,
bool &,
bool &,
int,
int,
bool )> &applyLogicFunc,
236 int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * width / maxWidth ) );
237 int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * height / maxHeight ) );
238 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
242 outputIter.startRasterRead( 1, width, height, extent );
249 std::unique_ptr< QgsRasterBlock > outputBlock;
250 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
252 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
253 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : inputs )
255 for (
int band : i.bands )
257 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
258 inputBlocks.emplace_back( std::move( b ) );
262 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
263 for (
int row = 0; row < iterRows; row++ )
268 for (
int column = 0; column < iterCols; column++ )
271 bool resIsNoData =
false;
272 applyLogicFunc( inputBlocks, res, resIsNoData, row, column, treatNoDataAsFalse );
280 outputBlock->setValue( row, column, resIsNoData ? outputNoDataValue : ( res ? 1 : 0 ) );
283 destinationRaster->
writeBlock( outputBlock.get(), 1, iterLeft, iterTop );