QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgsrasteranalysisutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasteranalysisutils.cpp
3 ---------------------
4 Date : June 2018
5 Copyright : (C) 2018 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include <cmath>
19#include <map>
20#include <unordered_map>
21#include <unordered_set>
22
23#include "qgsfeedback.h"
24#include "qgsgeos.h"
26#include "qgsrasterblock.h"
27#include "qgsrasteriterator.h"
28
29#include <QString>
30
31using namespace Qt::StringLiterals;
32
34
35void QgsRasterAnalysisUtils::cellInfoForBBox( const QgsRectangle &rasterBBox, const QgsRectangle &featureBBox, double cellSizeX, double cellSizeY, int &nCellsX, int &nCellsY, int rasterWidth, int rasterHeight, QgsRectangle &rasterBlockExtent )
36{
37 //get intersecting bbox
38 const QgsRectangle intersectBox = rasterBBox.intersect( featureBBox );
39 if ( intersectBox.isEmpty() )
40 {
41 nCellsX = 0;
42 nCellsY = 0;
43 rasterBlockExtent = QgsRectangle();
44 return;
45 }
46
47 //get offset in pixels in x- and y- direction
48 const int offsetX = static_cast<int>( std::floor( ( intersectBox.xMinimum() - rasterBBox.xMinimum() ) / cellSizeX ) );
49 const int offsetY = static_cast<int>( std::floor( ( rasterBBox.yMaximum() - intersectBox.yMaximum() ) / cellSizeY ) );
50
51 const int maxColumn = static_cast<int>( std::floor( ( intersectBox.xMaximum() - rasterBBox.xMinimum() ) / cellSizeX ) ) + 1;
52 const int maxRow = static_cast<int>( std::floor( ( rasterBBox.yMaximum() - intersectBox.yMinimum() ) / cellSizeY ) ) + 1;
53
54 nCellsX = maxColumn - offsetX;
55 nCellsY = maxRow - offsetY;
56
57 //avoid access to cells outside of the raster (may occur because of rounding)
58 nCellsX = std::min( offsetX + nCellsX, rasterWidth ) - offsetX;
59 nCellsY = std::min( offsetY + nCellsY, rasterHeight ) - offsetY;
60
61 rasterBlockExtent = QgsRectangle( rasterBBox.xMinimum() + offsetX * cellSizeX, rasterBBox.yMaximum() - offsetY * cellSizeY, rasterBBox.xMinimum() + ( nCellsX + offsetX ) * cellSizeX, rasterBBox.yMaximum() - ( nCellsY + offsetY ) * cellSizeY );
62}
63
64void 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, const QgsPointXY & )> &addValue, bool skipNodata )
65{
66 if ( !poly.constGet() )
67 return;
68
69 auto polyEngine = std::make_unique<QgsGeos>( poly.constGet() );
70 polyEngine->prepareGeometry();
71
72 QgsRasterIterator iter( rasterInterface );
73 iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
74
75 std::unique_ptr<QgsRasterBlock> block;
76 int iterLeft = 0;
77 int iterTop = 0;
78 int iterCols = 0;
79 int iterRows = 0;
80 QgsRectangle blockExtent;
81 bool isNoData = false;
82 while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
83 {
84 double cellCenterY = blockExtent.yMaximum() - 0.5 * cellSizeY;
85
86 for ( int row = 0; row < iterRows; ++row )
87 {
88 double cellCenterX = blockExtent.xMinimum() + 0.5 * cellSizeX;
89 for ( int col = 0; col < iterCols; ++col )
90 {
91 const double pixelValue = block->valueAndNoData( row, col, isNoData );
92 if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
93 {
94 if ( polyEngine->contains( cellCenterX, cellCenterY ) )
95 {
96 addValue( pixelValue, QgsPointXY( cellCenterX, cellCenterY ) );
97 }
98 }
99 cellCenterX += cellSizeX;
100 }
101 cellCenterY -= cellSizeY;
102 }
103 }
104}
105
106void 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, const QgsPointXY & )> &addValue, bool skipNodata )
107{
108 QgsGeometry pixelRectGeometry;
109
110 const double hCellSizeX = cellSizeX / 2.0;
111 const double hCellSizeY = cellSizeY / 2.0;
112 const double pixelArea = cellSizeX * cellSizeY;
113 double weight = 0;
114
115 std::unique_ptr<QgsGeometryEngine> polyEngine( QgsGeometry::createGeometryEngine( poly.constGet() ) );
116 if ( !polyEngine )
117 {
118 return;
119 }
120 polyEngine->prepareGeometry();
121
122 QgsRasterIterator iter( rasterInterface );
123 iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
124
125 std::unique_ptr<QgsRasterBlock> block;
126 int iterLeft = 0;
127 int iterTop = 0;
128 int iterCols = 0;
129 int iterRows = 0;
130 QgsRectangle blockExtent;
131 bool isNoData = false;
132 while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
133 {
134 double currentY = blockExtent.yMaximum() - 0.5 * cellSizeY;
135 for ( int row = 0; row < iterRows; ++row )
136 {
137 double currentX = blockExtent.xMinimum() + 0.5 * cellSizeX;
138 for ( int col = 0; col < iterCols; ++col )
139 {
140 const double pixelValue = block->valueAndNoData( row, col, isNoData );
141 if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
142 {
143 pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
144 // GEOS intersects tests on prepared geometry is MAGNITUDES faster than calculating the intersection itself,
145 // so we first test to see if there IS an intersection before doing the actual calculation
146 if ( !pixelRectGeometry.isNull() && polyEngine->intersects( pixelRectGeometry.constGet() ) )
147 {
148 //intersection
149 const QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly );
150 if ( !intersectGeometry.isEmpty() )
151 {
152 const double intersectionArea = intersectGeometry.area();
153 if ( intersectionArea > 0.0 )
154 {
155 weight = intersectionArea / pixelArea;
156 addValue( pixelValue, weight, QgsPointXY( currentX, currentY ) );
157 }
158 }
159 }
160 }
161 currentX += cellSizeX;
162 }
163 currentY -= cellSizeY;
164 }
165 }
166}
167
168bool QgsRasterAnalysisUtils::validPixel( double value )
169{
170 return !std::isnan( value );
171}
172
173void QgsRasterAnalysisUtils::mapToPixel( const double x, const double y, const QgsRectangle bounds, const double unitsPerPixelX, const double unitsPerPixelY, int &px, int &py )
174{
175 px = trunc( ( x - bounds.xMinimum() ) / unitsPerPixelX );
176 py = trunc( ( y - bounds.yMaximum() ) / -unitsPerPixelY );
177}
178
179void QgsRasterAnalysisUtils::pixelToMap( const int px, const int py, const QgsRectangle bounds, const double unitsPerPixelX, const double unitsPerPixelY, double &x, double &y )
180{
181 x = bounds.xMinimum() + ( px + 0.5 ) * unitsPerPixelX;
182 y = bounds.yMaximum() - ( py + 0.5 ) * unitsPerPixelY;
183}
184
185static QVector<QPair<QString, Qgis::DataType>> sDataTypes;
186
187void populateDataTypes()
188{
189 if ( sDataTypes.empty() )
190 {
191 sDataTypes.append( qMakePair( u"Byte"_s, Qgis::DataType::Byte ) );
192 sDataTypes.append( qMakePair( u"Int16"_s, Qgis::DataType::Int16 ) );
193 sDataTypes.append( qMakePair( u"UInt16"_s, Qgis::DataType::UInt16 ) );
194 sDataTypes.append( qMakePair( u"Int32"_s, Qgis::DataType::Int32 ) );
195 sDataTypes.append( qMakePair( u"UInt32"_s, Qgis::DataType::UInt32 ) );
196 sDataTypes.append( qMakePair( u"Float32"_s, Qgis::DataType::Float32 ) );
197 sDataTypes.append( qMakePair( u"Float64"_s, Qgis::DataType::Float64 ) );
198 sDataTypes.append( qMakePair( u"CInt16"_s, Qgis::DataType::CInt16 ) );
199 sDataTypes.append( qMakePair( u"CInt32"_s, Qgis::DataType::CInt32 ) );
200 sDataTypes.append( qMakePair( u"CFloat32"_s, Qgis::DataType::CFloat32 ) );
201 sDataTypes.append( qMakePair( u"CFloat64"_s, Qgis::DataType::CFloat64 ) );
202 sDataTypes.append( qMakePair( u"Int8"_s, Qgis::DataType::Int8 ) );
203 }
204}
205
206std::unique_ptr<QgsProcessingParameterDefinition> QgsRasterAnalysisUtils::createRasterTypeParameter( const QString &name, const QString &description, Qgis::DataType defaultType )
207{
208 populateDataTypes();
209
210 QStringList names;
211 int defaultChoice = 0;
212 int i = 0;
213 for ( auto it = sDataTypes.constBegin(); it != sDataTypes.constEnd(); ++it )
214 {
215 names.append( it->first );
216 if ( it->second == defaultType )
217 defaultChoice = i;
218 i++;
219 }
220
221 return std::make_unique<QgsProcessingParameterEnum>( name, description, names, false, defaultChoice );
222}
223
224Qgis::DataType QgsRasterAnalysisUtils::rasterTypeChoiceToDataType( int choice )
225{
226 if ( choice < 0 || choice >= sDataTypes.count() )
228
229 return sDataTypes.value( choice ).second;
230}
231
232void QgsRasterAnalysisUtils::applyRasterLogicOperator( const std::vector<QgsRasterAnalysisUtils::RasterLogicInput> &inputs, std::unique_ptr<QgsRasterDataProvider> destinationRaster, double outputNoDataValue, const bool treatNoDataAsFalse, int width, int height, const QgsRectangle &extent, QgsFeedback *feedback, std::function<void( const std::vector<std::unique_ptr<QgsRasterBlock>> &, bool &, bool &, int, int, bool )> &applyLogicFunc, qgssize &noDataCount, qgssize &trueCount, qgssize &falseCount )
233{
234 destinationRaster->setEditable( true );
235 QgsRasterIterator outputIter( destinationRaster.get() );
236 outputIter.startRasterRead( 1, width, height, extent );
237
238 const bool hasReportsDuringClose = destinationRaster->hasReportsDuringClose();
239 const double maxProgressDuringBlockWriting = hasReportsDuringClose ? 50.0 : 100.0;
240
241 int iterLeft = 0;
242 int iterTop = 0;
243 int iterCols = 0;
244 int iterRows = 0;
245 QgsRectangle blockExtent;
246 std::unique_ptr<QgsRasterBlock> outputBlock;
247 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
248 {
249 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
250 for ( const QgsRasterAnalysisUtils::RasterLogicInput &i : inputs )
251 {
252 for ( const int band : i.bands )
253 {
254 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
255 inputBlocks.emplace_back( std::move( b ) );
256 }
257 }
258
259 feedback->setProgress( maxProgressDuringBlockWriting * outputIter.progress( 1 ) );
260 for ( int row = 0; row < iterRows; row++ )
261 {
262 if ( feedback->isCanceled() )
263 break;
264
265 for ( int column = 0; column < iterCols; column++ )
266 {
267 bool res = false;
268 bool resIsNoData = false;
269 applyLogicFunc( inputBlocks, res, resIsNoData, row, column, treatNoDataAsFalse );
270 if ( resIsNoData )
271 noDataCount++;
272 else if ( res )
273 trueCount++;
274 else
275 falseCount++;
276
277 outputBlock->setValue( row, column, resIsNoData ? outputNoDataValue : ( res ? 1 : 0 ) );
278 }
279 }
280 if ( !destinationRaster->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
281 {
282 throw QgsProcessingException( QObject::tr( "Could not write raster block: %1" ).arg( destinationRaster->error().summary() ) );
283 }
284 }
285 destinationRaster->setEditable( false );
286
287 if ( hasReportsDuringClose )
288 {
289 std::unique_ptr<QgsFeedback> scaledFeedback( QgsFeedback::createScaledFeedback( feedback, maxProgressDuringBlockWriting, 100.0 ) );
290 if ( !destinationRaster->closeWithProgress( scaledFeedback.get() ) )
291 {
292 if ( feedback->isCanceled() )
293 return;
294 throw QgsProcessingException( QObject::tr( "Could not write raster dataset" ) );
295 }
296 }
297}
298
299std::vector<double> QgsRasterAnalysisUtils::getCellValuesFromBlockStack( const std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks, int &row, int &col, bool &noDataInStack )
300{
301 //get all values from inputBlocks
302 std::vector<double> cellValues;
303 bool hasNoData = false;
304 cellValues.reserve( inputBlocks.size() );
305
306 for ( auto &block : inputBlocks )
307 {
308 double value = 0;
309 if ( !block || !block->isValid() )
310 {
311 noDataInStack = true;
312 break;
313 }
314 else
315 {
316 value = block->valueAndNoData( row, col, hasNoData );
317 if ( hasNoData )
318 {
319 noDataInStack = true;
320 continue; //NoData is not included in the cell value vector
321 }
322 else
323 {
324 cellValues.push_back( value );
325 }
326 }
327 }
328 return cellValues;
329}
330
331double QgsRasterAnalysisUtils::meanFromCellValues( std::vector<double> &cellValues, int stackSize )
332{
333 const double sum = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
334 const double mean = sum / static_cast<double>( stackSize );
335 return mean;
336}
337
338double QgsRasterAnalysisUtils::medianFromCellValues( std::vector<double> &cellValues, int stackSize )
339{
340 std::sort( cellValues.begin(), cellValues.end() );
341 const bool even = ( stackSize % 2 ) < 1;
342 if ( even )
343 {
344 return ( cellValues[stackSize / 2 - 1] + cellValues[stackSize / 2] ) / 2.0;
345 }
346 else //odd
347 {
348 return cellValues[( stackSize + 1 ) / 2 - 1];
349 }
350}
351
352
353double QgsRasterAnalysisUtils::stddevFromCellValues( std::vector<double> &cellValues, int stackSize )
354{
355 const double variance = varianceFromCellValues( cellValues, stackSize );
356 const double stddev = std::sqrt( variance );
357 return stddev;
358}
359
360double QgsRasterAnalysisUtils::varianceFromCellValues( std::vector<double> &cellValues, int stackSize )
361{
362 const double mean = meanFromCellValues( cellValues, stackSize );
363 double accum = 0.0;
364 for ( int i = 0; i < stackSize; i++ )
365 {
366 accum += std::pow( ( cellValues.at( i ) - mean ), 2.0 );
367 }
368 const double variance = accum / static_cast<double>( stackSize );
369 return variance;
370}
371
372double QgsRasterAnalysisUtils::maximumFromCellValues( std::vector<double> &cellValues )
373{
374 return *std::max_element( cellValues.begin(), cellValues.end() );
375}
376
377double QgsRasterAnalysisUtils::minimumFromCellValues( std::vector<double> &cellValues )
378{
379 return *std::min_element( cellValues.begin(), cellValues.end() );
380}
381
382double QgsRasterAnalysisUtils::majorityFromCellValues( std::vector<double> &cellValues, const double noDataValue, int stackSize )
383{
384 if ( stackSize == 1 )
385 {
386 //output will be same as input if only one layer is entered
387 return cellValues[0];
388 }
389 else if ( stackSize == 2 )
390 {
391 //if only two layers are input, return NoData if values are not the same (eg. no Majority could be found)
392 return ( qgsDoubleNear( cellValues[0], cellValues[1] ) ) ? cellValues[0] : noDataValue;
393 }
394 else if ( std::adjacent_find( cellValues.begin(), cellValues.end(), std::not_equal_to<double>() ) == cellValues.end() )
395 {
396 //check if all values in cellValues are equal
397 //output will be same as input if all cellValues of the stack are the same
398 return cellValues[0];
399 }
400 else
401 {
402 //search for majority using hash map [O(n)]
403 std::unordered_map<double, int> map;
404
405 for ( int i = 0; i < stackSize; i++ )
406 {
407 map[cellValues[i]]++;
408 }
409
410 int maxCount = 0;
411 bool multipleMajorities = false;
412 double result = noDataValue;
413 for ( const auto &pair : std::as_const( map ) )
414 {
415 if ( maxCount < pair.second )
416 {
417 result = pair.first;
418 maxCount = pair.second;
419 multipleMajorities = false;
420 }
421 else if ( maxCount == pair.second )
422 {
423 multipleMajorities = true;
424 }
425 }
426 return multipleMajorities ? noDataValue : result;
427 }
428}
429
430double QgsRasterAnalysisUtils::minorityFromCellValues( std::vector<double> &cellValues, const double noDataValue, int stackSize )
431{
432 if ( stackSize == 1 )
433 {
434 //output will be same as input if only one layer is entered
435 return cellValues[0];
436 }
437 else if ( stackSize == 2 )
438 {
439 //if only two layers are input, return NoData if values are not the same (eg. no minority could be found)
440 return ( qgsDoubleNear( cellValues[0], cellValues[1] ) ) ? cellValues[0] : noDataValue;
441 }
442 else if ( std::adjacent_find( cellValues.begin(), cellValues.end(), std::not_equal_to<double>() ) == cellValues.end() )
443 {
444 //check if all values in cellValues are equal
445 //output will be same as input if all cellValues of the stack are the same
446 return cellValues[0];
447 }
448 else
449 {
450 //search for minority using hash map [O(n)]
451 std::unordered_map<double, int> map;
452
453 for ( int i = 0; i < stackSize; i++ )
454 {
455 map[cellValues[i]]++;
456 }
457
458 int minCount = stackSize;
459 bool multipleMinorities = false;
460 double result = noDataValue; //result will stay NoData if no minority value exists
461 for ( const auto &pair : std::as_const( map ) )
462 {
463 if ( minCount > pair.second )
464 {
465 result = pair.first;
466 minCount = pair.second;
467 multipleMinorities = false;
468 }
469 else if ( minCount == pair.second )
470 {
471 multipleMinorities = true;
472 }
473 }
474 return multipleMinorities ? noDataValue : result;
475 }
476}
477
478double QgsRasterAnalysisUtils::rangeFromCellValues( std::vector<double> &cellValues )
479{
480 const double max = *std::max_element( cellValues.begin(), cellValues.end() );
481 const double min = *std::min_element( cellValues.begin(), cellValues.end() );
482 return max - min;
483}
484
485double QgsRasterAnalysisUtils::varietyFromCellValues( std::vector<double> &cellValues )
486{
487 const std::unordered_set<double> uniqueValues( cellValues.begin(), cellValues.end() );
488 return uniqueValues.size();
489}
490
491double QgsRasterAnalysisUtils::nearestRankPercentile( std::vector<double> &cellValues, int stackSize, double percentile )
492{
493 //if percentile equals 0 -> pick the first element of the ordered list
494 std::sort( cellValues.begin(), cellValues.end() );
495
496 int i = 0;
497 if ( percentile > 0 )
498 {
499 i = std::ceil( percentile * static_cast<double>( stackSize ) ) - 1;
500 }
501
502 return cellValues[i];
503}
504
505double QgsRasterAnalysisUtils::interpolatedPercentileInc( std::vector<double> &cellValues, int stackSize, double percentile )
506{
507 std::sort( cellValues.begin(), cellValues.end() );
508
509 if ( qgsDoubleNear( percentile, 1.0 ) )
510 {
511 return cellValues[stackSize - 1];
512 }
513 else if ( qgsDoubleNear( percentile, 0.0 ) )
514 {
515 return cellValues[0];
516 }
517
518 const double x = ( percentile * ( stackSize - 1 ) );
519
520 const int i = static_cast<int>( std::floor( x ) );
521 const double xFraction = std::fmod( x, 1 );
522
523 if ( stackSize == 1 )
524 {
525 return cellValues[0];
526 }
527 else if ( stackSize == 2 )
528 {
529 return cellValues[0] + ( cellValues[1] - cellValues[0] ) * percentile;
530 }
531 else
532 {
533 return cellValues[i] + ( cellValues[i + 1] - cellValues[i] ) * xFraction;
534 }
535}
536
537double QgsRasterAnalysisUtils::interpolatedPercentileExc( std::vector<double> &cellValues, int stackSize, double percentile, double noDataValue )
538{
539 std::sort( cellValues.begin(), cellValues.end() );
540 const double x = ( percentile * ( stackSize + 1 ) );
541
542 const int i = static_cast<int>( std::floor( x ) ) - 1;
543 const double xFraction = std::fmod( x, 1 );
544 const double lowerExcValue = 1.0 / ( static_cast<double>( stackSize ) + 1.0 );
545 const double upperExcValue = static_cast<double>( stackSize ) / ( static_cast<double>( stackSize ) + 1.0 );
546
547 if ( stackSize < 2 || ( ( percentile < lowerExcValue || percentile > upperExcValue ) ) )
548 {
549 return noDataValue;
550 }
551 else
552 {
553 return cellValues[i] + ( cellValues[i + 1] - cellValues[i] ) * xFraction;
554 }
555}
556
557double QgsRasterAnalysisUtils::interpolatedPercentRankInc( std::vector<double> &cellValues, int stackSize, double value, double noDataValue )
558{
559 std::sort( cellValues.begin(), cellValues.end() );
560
561 if ( value < cellValues[0] || value > cellValues[stackSize - 1] )
562 {
563 return noDataValue;
564 }
565 else
566 {
567 for ( int i = 0; i < stackSize - 1; i++ )
568 {
569 if ( cellValues[i] <= value && cellValues[i + 1] >= value )
570 {
571 double fraction = 0.0;
572
573 //make sure that next number in the distribution is not the same to prevent NaN fractions
574 if ( !qgsDoubleNear( cellValues[i], cellValues[i + 1] ) )
575 fraction = ( value - cellValues[i] ) / ( cellValues[i + 1] - cellValues[i] );
576
577 return ( fraction + i ) / ( stackSize - 1 );
578 }
579 }
580 return noDataValue;
581 }
582}
583
584double QgsRasterAnalysisUtils::interpolatedPercentRankExc( std::vector<double> &cellValues, int stackSize, double value, double noDataValue )
585{
586 std::sort( cellValues.begin(), cellValues.end() );
587
588 if ( value < cellValues[0] || value > cellValues[stackSize - 1] )
589 {
590 return noDataValue;
591 }
592 else
593 {
594 for ( int i = 0; i < stackSize - 1; i++ )
595 {
596 if ( cellValues[i] <= value && cellValues[i + 1] >= value )
597 {
598 double fraction = 0.0;
599
600 //make sure that next number in the distribution is not the same to prevent NaN fractions
601 if ( !qgsDoubleNear( cellValues[i], cellValues[i + 1] ) )
602 fraction = ( value - cellValues[i] ) / ( cellValues[i + 1] - cellValues[i] );
603
604 return ( ( i + 1 ) + fraction ) / ( stackSize + 1 );
605 }
606 }
607 return noDataValue;
608 }
609}
610
611
DataType
Raster data types.
Definition qgis.h:379
@ CInt32
Complex Int32.
Definition qgis.h:390
@ Float32
Thirty two bit floating point (float).
Definition qgis.h:387
@ CFloat64
Complex Float64.
Definition qgis.h:392
@ Int16
Sixteen bit signed integer (qint16).
Definition qgis.h:384
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
Definition qgis.h:382
@ UInt16
Sixteen bit unsigned integer (quint16).
Definition qgis.h:383
@ Byte
Eight bit unsigned integer (quint8).
Definition qgis.h:381
@ Int32
Thirty two bit signed integer (qint32).
Definition qgis.h:386
@ Float64
Sixty four bit floating point (double).
Definition qgis.h:388
@ CFloat32
Complex Float32.
Definition qgis.h:391
@ CInt16
Complex Int16.
Definition qgis.h:389
@ UInt32
Thirty two bit unsigned integer (quint32).
Definition qgis.h:385
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:55
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:63
static std::unique_ptr< QgsFeedback > createScaledFeedback(QgsFeedback *parentFeedback, double startPercentage, double endPercentage)
Returns a feedback object whose [0, 100] progression range will be mapped to parentFeedback [startPer...
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
double area() const
Returns the planar, 2-dimensional area of the geometry.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters &parameters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Represents a 2D point.
Definition qgspointxy.h:62
Custom exception class for processing related exceptions.
Base class for processing filters like renderers, reprojector, resampler etc.
Iterator for sequentially processing raster cells.
A rectangle specified with double values.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition qgis.h:7458
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6935