QGIS API Documentation  3.6.0-Noosa (5873452)
qgsreclassifyutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsreclassifyutils.cpp
3  ---------------------
4  begin : June, 2018
5  copyright : (C) 2018 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsreclassifyutils.h"
19 #include "qgsrasterinterface.h"
20 #include "qgsrasteriterator.h"
21 #include "qgsrasterblock.h"
22 #include "qgsprocessingfeedback.h"
23 #include "qgsrasterdataprovider.h"
24 
25 #include "qgis.h"
26 
28 
29 void QgsReclassifyUtils::reportClasses( const QVector<QgsReclassifyUtils::RasterClass> &classes, QgsProcessingFeedback *feedback )
30 {
31  int i = 1;
32  feedback->pushInfo( QObject::tr( "Using classes:" ) );
33  for ( const RasterClass &c : classes )
34  {
35  feedback->pushInfo( QStringLiteral( " %1) %2 %3 %4" ).arg( i )
36  .arg( c.asText() )
37  .arg( QChar( 0x2192 ) )
38  .arg( c.value ) );
39  i++;
40  }
41 }
42 
43 void QgsReclassifyUtils::checkForOverlaps( const QVector<QgsReclassifyUtils::RasterClass> &classes, QgsProcessingFeedback *feedback )
44 {
45  // test each class against each other class
46  for ( int i = 0; i < classes.count() - 1; i++ )
47  {
48  for ( int j = i + 1; j < classes.count(); j++ )
49  {
50  const QgsReclassifyUtils::RasterClass &class1 = classes.at( i );
51  const QgsReclassifyUtils::RasterClass &class2 = classes.at( j );
52  if ( class1.overlaps( class2 ) )
53  {
54  feedback->reportError( QObject::tr( "Warning: Class %1 (%2) overlaps with class %3 (%4)" ).arg( i + 1 )
55  .arg( class1.asText() )
56  .arg( j + 1 )
57  .arg( class2.asText() ) );
58  }
59  }
60  }
61 }
62 
63 void QgsReclassifyUtils::reclassify( const QVector<QgsReclassifyUtils::RasterClass> &classes, QgsRasterInterface *sourceRaster, int band,
64  const QgsRectangle &extent, int sourceWidthPixels, int sourceHeightPixels,
65  QgsRasterDataProvider *destinationRaster, double destNoDataValue, bool useNoDataForMissingValues,
66  QgsProcessingFeedback *feedback )
67 {
70 
71  QgsRasterIterator iter( sourceRaster );
72  iter.startRasterRead( band, sourceWidthPixels, sourceHeightPixels, extent );
73 
74  int nbBlocksWidth = static_cast< int >( std::ceil( 1.0 * sourceWidthPixels / maxWidth ) );
75  int nbBlocksHeight = static_cast< int >( std::ceil( 1.0 * sourceHeightPixels / maxHeight ) );
76  int nbBlocks = nbBlocksWidth * nbBlocksHeight;
77 
78  int iterLeft = 0;
79  int iterTop = 0;
80  int iterCols = 0;
81  int iterRows = 0;
82  destinationRaster->setEditable( true );
83  std::unique_ptr< QgsRasterBlock > rasterBlock;
84  bool reclassed = false;
85  bool isNoData = false;
86  while ( iter.readNextRasterPart( band, iterCols, iterRows, rasterBlock, iterLeft, iterTop ) )
87  {
88  if ( feedback )
89  feedback->setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
90  if ( feedback && feedback->isCanceled() )
91  break;
92  std::unique_ptr< QgsRasterBlock > reclassifiedBlock = qgis::make_unique< QgsRasterBlock >( destinationRaster->dataType( 1 ), iterCols, iterRows );
93 
94  for ( int row = 0; row < iterRows; row++ )
95  {
96  if ( feedback && feedback->isCanceled() )
97  break;
98  for ( int column = 0; column < iterCols; column++ )
99  {
100  const double value = rasterBlock->valueAndNoData( row, column, isNoData );
101  if ( isNoData )
102  reclassifiedBlock->setValue( row, column, destNoDataValue );
103  else
104  {
105  double newValue = reclassifyValue( classes, value, reclassed );
106  if ( reclassed )
107  reclassifiedBlock->setValue( row, column, newValue );
108  else
109  reclassifiedBlock->setValue( row, column, useNoDataForMissingValues ? destNoDataValue : value );
110  }
111  }
112  }
113  destinationRaster->writeBlock( reclassifiedBlock.get(), 1, iterLeft, iterTop );
114  }
115  destinationRaster->setEditable( false );
116 }
117 
118 
119 
121 
122 
123 
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for providing feedback from a processing algorithm.
Iterator for sequentially processing raster cells.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
virtual bool setEditable(bool enabled)
Turns on/off editing mode of the provider.
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
Base class for processing filters like renderers, reprojector, resampler etc.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
bool writeBlock(QgsRasterBlock *block, int band, int xOffset=0, int yOffset=0)
Writes pixel data from a raster block into the provider data source.
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Base class for raster data providers.