24#include <unordered_map> 
   25#include <unordered_set> 
   29void QgsRasterAnalysisUtils::cellInfoForBBox( 
const QgsRectangle &rasterBBox, 
const QgsRectangle &featureBBox, 
double cellSizeX, 
double cellSizeY,
 
   30    int &nCellsX, 
int &nCellsY, 
int rasterWidth, 
int rasterHeight, 
QgsRectangle &rasterBlockExtent )
 
   43  const int offsetX = 
static_cast< int >( std::floor( ( intersectBox.
xMinimum() - rasterBBox.
xMinimum() ) / cellSizeX ) );
 
   44  const int offsetY = 
static_cast< int >( std::floor( ( rasterBBox.
yMaximum() - intersectBox.
yMaximum() ) / cellSizeY ) );
 
   46  const int maxColumn = 
static_cast< int >( std::floor( ( intersectBox.
xMaximum() - rasterBBox.
xMinimum() ) / cellSizeX ) ) + 1;
 
   47  const int maxRow = 
static_cast< int >( std::floor( ( rasterBBox.
yMaximum() - intersectBox.
yMinimum() ) / cellSizeY ) ) + 1;
 
   49  nCellsX = maxColumn - offsetX;
 
   50  nCellsY = maxRow - offsetY;
 
   53  nCellsX = std::min( offsetX + nCellsX, rasterWidth ) - offsetX;
 
   54  nCellsY = std::min( offsetY + nCellsY, rasterHeight ) - offsetY;
 
   57                                    rasterBBox.
yMaximum() - offsetY * cellSizeY,
 
   58                                    rasterBBox.
xMinimum() + ( nCellsX + offsetX ) * cellSizeX,
 
   59                                    rasterBBox.
yMaximum() - ( nCellsY + offsetY ) * cellSizeY );
 
   62void 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 )
 
   69  polyEngine->prepareGeometry();
 
   72  iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
 
   74  std::unique_ptr< QgsRasterBlock > block;
 
   80  bool isNoData = 
false;
 
   81  while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
 
   83    double cellCenterY = blockExtent.
yMaximum() - 0.5 * cellSizeY;
 
   85    for ( 
int row = 0; row < iterRows; ++row )
 
   87      double cellCenterX = blockExtent.
xMinimum() + 0.5 * cellSizeX;
 
   88      for ( 
int col = 0; col < iterCols; ++col )
 
   90        const double pixelValue = block->valueAndNoData( row, col, isNoData );
 
   91        if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
 
   93          QgsPoint cellCenter( cellCenterX, cellCenterY );
 
   94          if ( polyEngine->contains( &cellCenter ) )
 
   96            addValue( pixelValue );
 
   99        cellCenterX += cellSizeX;
 
  101      cellCenterY -= cellSizeY;
 
  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 )> &addValue, 
bool skipNodata )
 
  110  const double hCellSizeX = cellSizeX / 2.0;
 
  111  const double hCellSizeY = cellSizeY / 2.0;
 
  112  const double pixelArea = cellSizeX * cellSizeY;
 
  120  polyEngine->prepareGeometry();
 
  123  iter.startRasterRead( rasterBand, nCellsX, nCellsY, rasterBBox );
 
  125  std::unique_ptr< QgsRasterBlock > block;
 
  131  bool isNoData = 
false;
 
  132  while ( iter.readNextRasterPart( rasterBand, iterCols, iterRows, block, iterLeft, iterTop, &blockExtent ) )
 
  134    double currentY = blockExtent.
yMaximum() - 0.5 * cellSizeY;
 
  135    for ( 
int row = 0; row < iterRows; ++row )
 
  137      double currentX = blockExtent.
xMinimum() + 0.5 * cellSizeX;
 
  138      for ( 
int col = 0; col < iterCols; ++col )
 
  140        const double pixelValue = block->valueAndNoData( row, col, isNoData );
 
  141        if ( validPixel( pixelValue ) && ( !skipNodata || !isNoData ) )
 
  146          if ( !pixelRectGeometry.
isNull() && polyEngine->intersects( pixelRectGeometry.
constGet() ) )
 
  150            if ( !intersectGeometry.
isEmpty() )
 
  152              const double intersectionArea = intersectGeometry.
area();
 
  153              if ( intersectionArea > 0.0 )
 
  155                weight = intersectionArea / pixelArea;
 
  156                addValue( pixelValue, weight );
 
  161        currentX += cellSizeX;
 
  163      currentY -= cellSizeY;
 
  168bool QgsRasterAnalysisUtils::validPixel( 
double value )
 
  170  return !std::isnan( value );
 
  173void QgsRasterAnalysisUtils::mapToPixel( 
const double x, 
const double y, 
const QgsRectangle bounds, 
const double unitsPerPixelX, 
const double unitsPerPixelY, 
int &px, 
int &py )
 
  175  px = trunc( ( x - bounds.
xMinimum() ) / unitsPerPixelX );
 
  176  py = trunc( ( y - bounds.
yMaximum() ) / -unitsPerPixelY );
 
  179void QgsRasterAnalysisUtils::pixelToMap( 
const int px, 
const int py, 
const QgsRectangle bounds, 
const double unitsPerPixelX, 
const double unitsPerPixelY, 
double &x, 
double &y )
 
  181  x = bounds.
xMinimum() + ( px + 0.5 ) * unitsPerPixelX;
 
  182  y = bounds.
yMaximum() - ( py + 0.5 ) * unitsPerPixelY;
 
  185static QVector< QPair< QString, Qgis::DataType > > sDataTypes;
 
  187void populateDataTypes()
 
  189  if ( sDataTypes.empty() )
 
  206std::unique_ptr<QgsProcessingParameterDefinition> QgsRasterAnalysisUtils::createRasterTypeParameter( 
const QString &name, 
const QString &description, 
Qgis::DataType defaultType )
 
  211  int defaultChoice = 0;
 
  213  for ( 
auto it = sDataTypes.constBegin(); it != sDataTypes.constEnd(); ++it )
 
  215    names.append( it->first );
 
  216    if ( it->second == defaultType )
 
  221  return std::make_unique< QgsProcessingParameterEnum >( name, description, names, 
false, defaultChoice );
 
  224Qgis::DataType QgsRasterAnalysisUtils::rasterTypeChoiceToDataType( 
int choice )
 
  226  if ( choice < 0 || choice >= sDataTypes.count() )
 
  229  return sDataTypes.value( choice ).second;
 
  232void QgsRasterAnalysisUtils::applyRasterLogicOperator( 
const std::vector< QgsRasterAnalysisUtils::RasterLogicInput > &inputs, 
QgsRasterDataProvider *destinationRaster, 
double outputNoDataValue, 
const bool treatNoDataAsFalse,
 
  234    std::function<
void( 
const std::vector< std::unique_ptr< QgsRasterBlock > > &, 
bool &, 
bool &, 
int, 
int, 
bool )> &applyLogicFunc,
 
  239  const int nbBlocksWidth = 
static_cast< int>( std::ceil( 1.0 * width / maxWidth ) );
 
  240  const int nbBlocksHeight = 
static_cast< int >( std::ceil( 1.0 * height / maxHeight ) );
 
  241  const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
 
  245  outputIter.startRasterRead( 1, width, height, extent );
 
  252  std::unique_ptr< QgsRasterBlock > outputBlock;
 
  253  while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
 
  255    std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
 
  256    for ( 
const QgsRasterAnalysisUtils::RasterLogicInput &i : inputs )
 
  258      for ( 
const int band : i.bands )
 
  260        std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
 
  261        inputBlocks.emplace_back( std::move( b ) );
 
  265    feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
 
  266    for ( 
int row = 0; row < iterRows; row++ )
 
  271      for ( 
int column = 0; column < iterCols; column++ )
 
  274        bool resIsNoData = 
false;
 
  275        applyLogicFunc( inputBlocks, res, resIsNoData, row, column, treatNoDataAsFalse );
 
  283        outputBlock->setValue( row, column, resIsNoData ? outputNoDataValue : ( res ? 1 : 0 ) );
 
  286    destinationRaster->
writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
 
  291std::vector<double> QgsRasterAnalysisUtils::getCellValuesFromBlockStack( 
const std::vector< std::unique_ptr< QgsRasterBlock > > &inputBlocks, 
int &row, 
int &col, 
bool &noDataInStack )
 
  294  std::vector<double> cellValues;
 
  295  bool hasNoData = 
false;
 
  296  cellValues.reserve( inputBlocks.size() );
 
  298  for ( 
auto &block : inputBlocks )
 
  301    if ( !block || !block->isValid() )
 
  303      noDataInStack = 
true;
 
  308      value = block->valueAndNoData( row, col, hasNoData );
 
  311        noDataInStack = 
true;
 
  316        cellValues.push_back( value );
 
  323double QgsRasterAnalysisUtils::meanFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  325  const double sum = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
 
  326  const double mean = sum / 
static_cast<double>( stackSize );
 
  330double QgsRasterAnalysisUtils::medianFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  332  std::sort( cellValues.begin(), cellValues.end() );
 
  333  const bool even = ( stackSize % 2 ) < 1;
 
  336    return ( cellValues[stackSize / 2 - 1] + cellValues[stackSize / 2] ) / 2.0;
 
  340    return cellValues[( stackSize + 1 ) / 2 - 1];
 
  345double QgsRasterAnalysisUtils::stddevFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  347  const double variance = varianceFromCellValues( cellValues, stackSize );
 
  348  const double stddev = std::sqrt( variance );
 
  352double QgsRasterAnalysisUtils::varianceFromCellValues( std::vector<double> &cellValues, 
int stackSize )
 
  354  const double mean = meanFromCellValues( cellValues, stackSize );
 
  356  for ( 
int i = 0; i < stackSize; i++ )
 
  358    accum += std::pow( ( cellValues.at( i ) - mean ), 2.0 );
 
  360  const double variance = accum / 
static_cast<double>( stackSize );
 
  364double QgsRasterAnalysisUtils::maximumFromCellValues( std::vector<double> &cellValues )
 
  366  return *std::max_element( cellValues.begin(), cellValues.end() );
 
  369double QgsRasterAnalysisUtils::minimumFromCellValues( std::vector<double> &cellValues )
 
  371  return *std::min_element( cellValues.begin(), cellValues.end() );
 
  374double QgsRasterAnalysisUtils::majorityFromCellValues( std::vector<double> &cellValues, 
const double noDataValue, 
int stackSize )
 
  376  if ( stackSize == 1 )
 
  379    return cellValues[0];
 
  381  else if ( stackSize == 2 )
 
  384    return ( 
qgsDoubleNear( cellValues[0], cellValues[1] ) ) ?  cellValues[0] : noDataValue;
 
  386  else if ( std::adjacent_find( cellValues.begin(), cellValues.end(), std::not_equal_to<double>() ) == cellValues.end() )
 
  390    return cellValues[0];
 
  395    std::unordered_map<double, int> map;
 
  397    for ( 
int i = 0; i < stackSize; i++ )
 
  399      map[cellValues[i]]++;
 
  403    bool multipleMajorities = 
false;
 
  404    double result = noDataValue;
 
  405    for ( 
const auto &pair : std::as_const( map ) )
 
  407      if ( maxCount < pair.second )
 
  410        maxCount = pair.second;
 
  411        multipleMajorities = 
false;
 
  413      else if ( maxCount == pair.second )
 
  415        multipleMajorities = 
true;
 
  418    return multipleMajorities ? noDataValue : result;
 
  422double QgsRasterAnalysisUtils::minorityFromCellValues( std::vector<double> &cellValues, 
const double noDataValue, 
int stackSize )
 
  424  if ( stackSize == 1 )
 
  427    return cellValues[0];
 
  429  else if ( stackSize == 2 )
 
  432    return ( 
qgsDoubleNear( cellValues[0], cellValues[1] ) ) ?  cellValues[0] : noDataValue;
 
  434  else if ( std::adjacent_find( cellValues.begin(), cellValues.end(), std::not_equal_to<double>() ) == cellValues.end() )
 
  438    return cellValues[0];
 
  443    std::unordered_map<double, int> map;
 
  445    for ( 
int i = 0; i < stackSize; i++ )
 
  447      map[cellValues[i]]++;
 
  450    int minCount = stackSize;
 
  451    bool multipleMinorities = 
false;
 
  452    double result = noDataValue; 
 
  453    for ( 
const auto &pair : std::as_const( map ) )
 
  455      if ( minCount > pair.second )
 
  458        minCount = pair.second;
 
  459        multipleMinorities = 
false;
 
  461      else if ( minCount == pair.second )
 
  463        multipleMinorities = 
true;
 
  466    return multipleMinorities ? noDataValue : result;
 
  470double QgsRasterAnalysisUtils::rangeFromCellValues( std::vector<double> &cellValues )
 
  472  const double max = *std::max_element( cellValues.begin(), cellValues.end() );
 
  473  const double min = *std::min_element( cellValues.begin(), cellValues.end() );
 
  477double QgsRasterAnalysisUtils::varietyFromCellValues( std::vector<double> &cellValues )
 
  479  const std::unordered_set<double> uniqueValues( cellValues.begin(), cellValues.end() );
 
  480  return uniqueValues.size();
 
  483double QgsRasterAnalysisUtils::nearestRankPercentile( std::vector<double> &cellValues, 
int stackSize, 
double percentile )
 
  486  std::sort( cellValues.begin(), cellValues.end() );
 
  489  if ( percentile > 0 )
 
  491    i = std::ceil( percentile * 
static_cast<double>( stackSize ) ) - 1;
 
  494  return cellValues[i];
 
  497double QgsRasterAnalysisUtils::interpolatedPercentileInc( std::vector<double> &cellValues, 
int stackSize, 
double percentile )
 
  499  std::sort( cellValues.begin(), cellValues.end() );
 
  503    return cellValues[stackSize - 1 ];
 
  507    return cellValues[0];
 
  510  const double x = ( percentile * ( stackSize - 1 ) );
 
  512  const int i = 
static_cast<int>( std::floor( x ) );
 
  513  const double xFraction = std::fmod( x, 1 );
 
  515  if ( stackSize == 1 )
 
  517    return cellValues[0];
 
  519  else if ( stackSize == 2 )
 
  521    return cellValues[0] + ( cellValues[1] - cellValues[0] ) * percentile;
 
  525    return cellValues[i] + ( cellValues[i + 1] - cellValues[i] ) * xFraction;
 
  529double QgsRasterAnalysisUtils::interpolatedPercentileExc( std::vector<double> &cellValues, 
int stackSize, 
double percentile, 
double noDataValue )
 
  531  std::sort( cellValues.begin(), cellValues.end() );
 
  532  const double x = ( percentile * ( stackSize + 1 ) );
 
  534  const int i = 
static_cast<int>( std::floor( x ) ) - 1;
 
  535  const double xFraction = std::fmod( x, 1 );
 
  536  const double lowerExcValue =  1.0 / ( 
static_cast<double>( stackSize ) + 1.0 );
 
  537  const double upperExcValue = 
static_cast<double>( stackSize ) / ( 
static_cast<double>( stackSize ) + 1.0 );
 
  539  if ( stackSize < 2 || ( ( percentile < lowerExcValue || percentile > upperExcValue ) ) )
 
  545    return cellValues[i] + ( cellValues[i + 1] - cellValues[i] ) * xFraction;
 
  549double QgsRasterAnalysisUtils::interpolatedPercentRankInc( std::vector<double> &cellValues, 
int stackSize, 
double value, 
double noDataValue )
 
  551  std::sort( cellValues.begin(), cellValues.end() );
 
  553  if ( value < cellValues[0] || value > cellValues[stackSize - 1] )
 
  559    for ( 
int i = 0; i < stackSize - 1; i++ )
 
  561      if ( cellValues[i] <= value && cellValues[i + 1] >= value )
 
  563        double fraction = 0.0;
 
  567          fraction = ( value - cellValues[i] ) / ( cellValues[i + 1] - cellValues[i] );
 
  569        return ( fraction + i ) / ( stackSize - 1 );
 
  576double QgsRasterAnalysisUtils::interpolatedPercentRankExc( std::vector<double> &cellValues, 
int stackSize, 
double value, 
double noDataValue )
 
  578  std::sort( cellValues.begin(), cellValues.end() );
 
  580  if ( value < cellValues[0] || value > cellValues[stackSize - 1] )
 
  586    for ( 
int i = 0; i < stackSize - 1; i++ )
 
  588      if ( cellValues[i] <= value && cellValues[i + 1] >= value )
 
  590        double fraction = 0.0;
 
  594          fraction = ( value - cellValues[i] ) / ( cellValues[i + 1] - cellValues[i] );
 
  596        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)
 
Base class for feedback objects to be used for cancellation of something running in a worker thread.
 
bool isCanceled() const SIP_HOLDGIL
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.
 
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
 
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
 
double area() const
Returns the planar, 2-dimensional area of the geometry.
 
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified 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...
 
Point geometry type, with support for z-dimension and m-values.
 
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.
 
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
 
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
 
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
 
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
 
bool isEmpty() const
Returns true if the rectangle is empty.
 
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)