24#include <unordered_map> 
   25#include <unordered_set> 
   29void QgsRasterAnalysisUtils::cellInfoForBBox( 
const QgsRectangle &rasterBBox, 
const QgsRectangle &featureBBox, 
double cellSizeX, 
double cellSizeY, 
int &nCellsX, 
int &nCellsY, 
int rasterWidth, 
int rasterHeight, 
QgsRectangle &rasterBlockExtent )
 
   42  const int offsetX = 
static_cast<int>( std::floor( ( intersectBox.
xMinimum() - rasterBBox.
xMinimum() ) / cellSizeX ) );
 
   43  const int offsetY = 
static_cast<int>( std::floor( ( rasterBBox.
yMaximum() - intersectBox.
yMaximum() ) / cellSizeY ) );
 
   45  const int maxColumn = 
static_cast<int>( std::floor( ( intersectBox.
xMaximum() - rasterBBox.
xMinimum() ) / cellSizeX ) ) + 1;
 
   46  const int maxRow = 
static_cast<int>( std::floor( ( rasterBBox.
yMaximum() - intersectBox.
yMinimum() ) / cellSizeY ) ) + 1;
 
   48  nCellsX = maxColumn - offsetX;
 
   49  nCellsY = maxRow - offsetY;
 
   52  nCellsX = std::min( offsetX + nCellsX, rasterWidth ) - offsetX;
 
   53  nCellsY = std::min( offsetY + nCellsY, rasterHeight ) - offsetY;
 
   55  rasterBlockExtent = 
QgsRectangle( rasterBBox.
xMinimum() + offsetX * cellSizeX, rasterBBox.
yMaximum() - offsetY * cellSizeY, rasterBBox.
xMinimum() + ( nCellsX + offsetX ) * cellSizeX, rasterBBox.
yMaximum() - ( nCellsY + offsetY ) * cellSizeY );
 
   58void 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 )
 
   60  auto polyEngine = std::make_unique<QgsGeos>( poly.
constGet() );
 
   65  polyEngine->prepareGeometry();
 
   68  iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
 
   70  std::unique_ptr<QgsRasterBlock> block;
 
   76  bool isNoData = 
false;
 
   77  while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
 
   79    double cellCenterY = blockExtent.
yMaximum() - 0.5 * cellSizeY;
 
   81    for ( 
int row = 0; row < iterRows; ++row )
 
   83      double cellCenterX = blockExtent.
xMinimum() + 0.5 * cellSizeX;
 
   84      for ( 
int col = 0; col < iterCols; ++col )
 
   86        const double pixelValue = block->valueAndNoData( row, col, isNoData );
 
   87        if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
 
   89          if ( polyEngine->contains( cellCenterX, cellCenterY ) )
 
   91            addValue( pixelValue, 
QgsPointXY( cellCenterX, cellCenterY ) );
 
   94        cellCenterX += cellSizeX;
 
   96      cellCenterY -= cellSizeY;
 
  101void 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 )
 
  105  const double hCellSizeX = cellSizeX / 2.0;
 
  106  const double hCellSizeY = cellSizeY / 2.0;
 
  107  const double pixelArea = cellSizeX * cellSizeY;
 
  115  polyEngine->prepareGeometry();
 
  118  iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
 
  120  std::unique_ptr<QgsRasterBlock> block;
 
  126  bool isNoData = 
false;
 
  127  while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
 
  129    double currentY = blockExtent.
yMaximum() - 0.5 * cellSizeY;
 
  130    for ( 
int row = 0; row < iterRows; ++row )
 
  132      double currentX = blockExtent.
xMinimum() + 0.5 * cellSizeX;
 
  133      for ( 
int col = 0; col < iterCols; ++col )
 
  135        const double pixelValue = block->valueAndNoData( row, col, isNoData );
 
  136        if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
 
  141          if ( !pixelRectGeometry.
isNull() && polyEngine->intersects( pixelRectGeometry.
constGet() ) )
 
  145            if ( !intersectGeometry.
isEmpty() )
 
  147              const double intersectionArea = intersectGeometry.
area();
 
  148              if ( intersectionArea > 0.0 )
 
  150                weight = intersectionArea / pixelArea;
 
  151                addValue( pixelValue, weight, 
QgsPointXY( currentX, currentY ) );
 
  156        currentX += cellSizeX;
 
  158      currentY -= cellSizeY;
 
  163bool QgsRasterAnalysisUtils::validPixel( 
double value )
 
  165  return !std::isnan( value );
 
  168void QgsRasterAnalysisUtils::mapToPixel( 
const double x, 
const double y, 
const QgsRectangle bounds, 
const double unitsPerPixelX, 
const double unitsPerPixelY, 
int &px, 
int &py )
 
  170  px = trunc( ( x - bounds.
xMinimum() ) / unitsPerPixelX );
 
  171  py = trunc( ( y - bounds.
yMaximum() ) / -unitsPerPixelY );
 
  174void QgsRasterAnalysisUtils::pixelToMap( 
const int px, 
const int py, 
const QgsRectangle bounds, 
const double unitsPerPixelX, 
const double unitsPerPixelY, 
double &x, 
double &y )
 
  176  x = bounds.
xMinimum() + ( px + 0.5 ) * unitsPerPixelX;
 
  177  y = bounds.
yMaximum() - ( py + 0.5 ) * unitsPerPixelY;
 
  180static QVector<QPair<QString, Qgis::DataType>> sDataTypes;
 
  182void populateDataTypes()
 
  184  if ( sDataTypes.empty() )
 
  201std::unique_ptr<QgsProcessingParameterDefinition> QgsRasterAnalysisUtils::createRasterTypeParameter( 
const QString &name, 
const QString &description, 
Qgis::DataType defaultType )
 
  206  int defaultChoice = 0;
 
  208  for ( 
auto it = sDataTypes.constBegin(); it != sDataTypes.constEnd(); ++it )
 
  210    names.append( it->first );
 
  211    if ( it->second == defaultType )
 
  216  return std::make_unique<QgsProcessingParameterEnum>( name, description, names, 
false, defaultChoice );
 
  219Qgis::DataType QgsRasterAnalysisUtils::rasterTypeChoiceToDataType( 
int choice )
 
  221  if ( choice < 0 || choice >= sDataTypes.count() )
 
  224  return sDataTypes.value( choice ).second;
 
  227void QgsRasterAnalysisUtils::applyRasterLogicOperator( 
const std::vector<QgsRasterAnalysisUtils::RasterLogicInput> &inputs, 
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 )
 
  231  const int nbBlocksWidth = 
static_cast<int>( std::ceil( 1.0 * width / maxWidth ) );
 
  232  const int nbBlocksHeight = 
static_cast<int>( std::ceil( 1.0 * height / maxHeight ) );
 
  233  const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
 
  237  outputIter.startRasterRead( 1, width, height, extent );
 
  244  std::unique_ptr<QgsRasterBlock> outputBlock;
 
  245  while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
 
  247    std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
 
  248    for ( 
const QgsRasterAnalysisUtils::RasterLogicInput &i : inputs )
 
  250      for ( 
const int band : i.bands )
 
  252        std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
 
  253        inputBlocks.emplace_back( std::move( b ) );
 
  257    feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
 
  258    for ( 
int row = 0; row < iterRows; row++ )
 
  263      for ( 
int column = 0; column < iterCols; column++ )
 
  266        bool resIsNoData = 
false;
 
  267        applyLogicFunc( inputBlocks, res, resIsNoData, row, column, treatNoDataAsFalse );
 
  275        outputBlock->setValue( row, column, resIsNoData ? outputNoDataValue : ( res ? 1 : 0 ) );
 
  278    if ( !destinationRaster->
writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
 
  286std::vector<double> QgsRasterAnalysisUtils::getCellValuesFromBlockStack( 
const std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks, 
int &row, 
int &col, 
bool &noDataInStack )
 
  289  std::vector<double> cellValues;
 
  290  bool hasNoData = 
false;
 
  291  cellValues.reserve( inputBlocks.size() );
 
  293  for ( 
auto &block : inputBlocks )
 
  296    if ( !block || !block->isValid() )
 
  298      noDataInStack = 
true;
 
  303      value = block->valueAndNoData( row, col, hasNoData );
 
  306        noDataInStack = 
true;
 
  311        cellValues.push_back( value );
 
  318double QgsRasterAnalysisUtils::meanFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  320  const double sum = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
 
  321  const double mean = sum / 
static_cast<double>( stackSize );
 
  325double QgsRasterAnalysisUtils::medianFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  327  std::sort( cellValues.begin(), cellValues.end() );
 
  328  const bool even = ( stackSize % 2 ) < 1;
 
  331    return ( cellValues[stackSize / 2 - 1] + cellValues[stackSize / 2] ) / 2.0;
 
  335    return cellValues[( stackSize + 1 ) / 2 - 1];
 
  340double QgsRasterAnalysisUtils::stddevFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  342  const double variance = varianceFromCellValues( cellValues, stackSize );
 
  343  const double stddev = std::sqrt( variance );
 
  347double QgsRasterAnalysisUtils::varianceFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  349  const double mean = meanFromCellValues( cellValues, stackSize );
 
  351  for ( 
int i = 0; i < stackSize; i++ )
 
  353    accum += std::pow( ( cellValues.at( i ) - mean ), 2.0 );
 
  355  const double variance = accum / 
static_cast<double>( stackSize );
 
  359double QgsRasterAnalysisUtils::maximumFromCellValues( std::vector<double> &cellValues )
 
  361  return *std::max_element( cellValues.begin(), cellValues.end() );
 
  364double QgsRasterAnalysisUtils::minimumFromCellValues( std::vector<double> &cellValues )
 
  366  return *std::min_element( cellValues.begin(), cellValues.end() );
 
  369double QgsRasterAnalysisUtils::majorityFromCellValues( std::vector<double> &cellValues, 
const double noDataValue, 
int stackSize )
 
  371  if ( stackSize == 1 )
 
  374    return cellValues[0];
 
  376  else if ( stackSize == 2 )
 
  379    return ( 
qgsDoubleNear( cellValues[0], cellValues[1] ) ) ? cellValues[0] : noDataValue;
 
  381  else if ( std::adjacent_find( cellValues.begin(), cellValues.end(), std::not_equal_to<double>() ) == cellValues.end() )
 
  385    return cellValues[0];
 
  390    std::unordered_map<double, int> map;
 
  392    for ( 
int i = 0; i < stackSize; i++ )
 
  394      map[cellValues[i]]++;
 
  398    bool multipleMajorities = 
false;
 
  399    double result = noDataValue;
 
  400    for ( 
const auto &pair : std::as_const( map ) )
 
  402      if ( maxCount < pair.second )
 
  405        maxCount = pair.second;
 
  406        multipleMajorities = 
false;
 
  408      else if ( maxCount == pair.second )
 
  410        multipleMajorities = 
true;
 
  413    return multipleMajorities ? noDataValue : result;
 
  417double QgsRasterAnalysisUtils::minorityFromCellValues( std::vector<double> &cellValues, 
const double noDataValue, 
int stackSize )
 
  419  if ( stackSize == 1 )
 
  422    return cellValues[0];
 
  424  else if ( stackSize == 2 )
 
  427    return ( 
qgsDoubleNear( cellValues[0], cellValues[1] ) ) ? cellValues[0] : noDataValue;
 
  429  else if ( std::adjacent_find( cellValues.begin(), cellValues.end(), std::not_equal_to<double>() ) == cellValues.end() )
 
  433    return cellValues[0];
 
  438    std::unordered_map<double, int> map;
 
  440    for ( 
int i = 0; i < stackSize; i++ )
 
  442      map[cellValues[i]]++;
 
  445    int minCount = stackSize;
 
  446    bool multipleMinorities = 
false;
 
  447    double result = noDataValue; 
 
  448    for ( 
const auto &pair : std::as_const( map ) )
 
  450      if ( minCount > pair.second )
 
  453        minCount = pair.second;
 
  454        multipleMinorities = 
false;
 
  456      else if ( minCount == pair.second )
 
  458        multipleMinorities = 
true;
 
  461    return multipleMinorities ? noDataValue : result;
 
  465double QgsRasterAnalysisUtils::rangeFromCellValues( std::vector<double> &cellValues )
 
  467  const double max = *std::max_element( cellValues.begin(), cellValues.end() );
 
  468  const double min = *std::min_element( cellValues.begin(), cellValues.end() );
 
  472double QgsRasterAnalysisUtils::varietyFromCellValues( std::vector<double> &cellValues )
 
  474  const std::unordered_set<double> uniqueValues( cellValues.begin(), cellValues.end() );
 
  475  return uniqueValues.size();
 
  478double QgsRasterAnalysisUtils::nearestRankPercentile( std::vector<double> &cellValues, 
int stackSize, 
double percentile )
 
  481  std::sort( cellValues.begin(), cellValues.end() );
 
  484  if ( percentile > 0 )
 
  486    i = std::ceil( percentile * 
static_cast<double>( stackSize ) ) - 1;
 
  489  return cellValues[i];
 
  492double QgsRasterAnalysisUtils::interpolatedPercentileInc( std::vector<double> &cellValues, 
int stackSize, 
double percentile )
 
  494  std::sort( cellValues.begin(), cellValues.end() );
 
  498    return cellValues[stackSize - 1];
 
  502    return cellValues[0];
 
  505  const double x = ( percentile * ( stackSize - 1 ) );
 
  507  const int i = 
static_cast<int>( std::floor( x ) );
 
  508  const double xFraction = std::fmod( x, 1 );
 
  510  if ( stackSize == 1 )
 
  512    return cellValues[0];
 
  514  else if ( stackSize == 2 )
 
  516    return cellValues[0] + ( cellValues[1] - cellValues[0] ) * percentile;
 
  520    return cellValues[i] + ( cellValues[i + 1] - cellValues[i] ) * xFraction;
 
  524double QgsRasterAnalysisUtils::interpolatedPercentileExc( std::vector<double> &cellValues, 
int stackSize, 
double percentile, 
double noDataValue )
 
  526  std::sort( cellValues.begin(), cellValues.end() );
 
  527  const double x = ( percentile * ( stackSize + 1 ) );
 
  529  const int i = 
static_cast<int>( std::floor( x ) ) - 1;
 
  530  const double xFraction = std::fmod( x, 1 );
 
  531  const double lowerExcValue = 1.0 / ( 
static_cast<double>( stackSize ) + 1.0 );
 
  532  const double upperExcValue = 
static_cast<double>( stackSize ) / ( 
static_cast<double>( stackSize ) + 1.0 );
 
  534  if ( stackSize < 2 || ( ( percentile < lowerExcValue || percentile > upperExcValue ) ) )
 
  540    return cellValues[i] + ( cellValues[i + 1] - cellValues[i] ) * xFraction;
 
  544double QgsRasterAnalysisUtils::interpolatedPercentRankInc( std::vector<double> &cellValues, 
int stackSize, 
double value, 
double noDataValue )
 
  546  std::sort( cellValues.begin(), cellValues.end() );
 
  548  if ( value < cellValues[0] || value > cellValues[stackSize - 1] )
 
  554    for ( 
int i = 0; i < stackSize - 1; i++ )
 
  556      if ( cellValues[i] <= value && cellValues[i + 1] >= value )
 
  558        double fraction = 0.0;
 
  562          fraction = ( value - cellValues[i] ) / ( cellValues[i + 1] - cellValues[i] );
 
  564        return ( fraction + i ) / ( stackSize - 1 );
 
  571double QgsRasterAnalysisUtils::interpolatedPercentRankExc( std::vector<double> &cellValues, 
int stackSize, 
double value, 
double noDataValue )
 
  573  std::sort( cellValues.begin(), cellValues.end() );
 
  575  if ( value < cellValues[0] || value > cellValues[stackSize - 1] )
 
  581    for ( 
int i = 0; i < stackSize - 1; i++ )
 
  583      if ( cellValues[i] <= value && cellValues[i + 1] >= value )
 
  585        double fraction = 0.0;
 
  589          fraction = ( value - cellValues[i] ) / ( cellValues[i + 1] - cellValues[i] );
 
  591        return ( ( i + 1 ) + fraction ) / ( stackSize + 1 );
 
DataType
Raster data types.
 
@ Float32
Thirty two bit floating point (float)
 
@ CFloat64
Complex Float64.
 
@ Int16
Sixteen bit signed integer (qint16)
 
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30)
 
@ UInt16
Sixteen bit unsigned integer (quint16)
 
@ Byte
Eight bit unsigned integer (quint8)
 
@ Int32
Thirty two bit signed integer (qint32)
 
@ Float64
Sixty four bit floating point (double)
 
@ CFloat32
Complex Float32.
 
@ UInt32
Thirty two bit unsigned integer (quint32)
 
virtual QgsError error() const
Gets current status error.
 
QString summary() const
Short error description, usually the first error in chain, the real error.
 
Base class for feedback objects to be used for cancellation of something running in a worker thread.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
void setProgress(double progress)
Sets the current progress for the feedback object.
 
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 ¶meters=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...
 
Custom exception class for processing related exceptions.
 
Base class for raster data providers.
 
bool writeBlock(QgsRasterBlock *block, int band, int xOffset=0, int yOffset=0)
Writes pixel data from a raster block into the provider data source.
 
virtual bool setEditable(bool enabled)
Turns on/off editing mode of the provider.
 
Base class for processing filters like renderers, reprojector, resampler etc.
 
Iterator for sequentially processing raster cells.
 
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
 
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
 
A rectangle specified with double values.
 
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...
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)