QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
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
20#include "qgis.h"
22#include "qgsrasterblock.h"
24#include "qgsrasterinterface.h"
25#include "qgsrasteriterator.h"
26
27#include <QString>
28
29using namespace Qt::StringLiterals;
30
32
33void QgsReclassifyUtils::reportClasses( const QVector<QgsReclassifyUtils::RasterClass> &classes, QgsProcessingFeedback *feedback )
34{
35 int i = 1;
36 feedback->pushInfo( QObject::tr( "Using classes:" ) );
37 for ( const RasterClass &c : classes )
38 {
39 feedback->pushInfo( u" %1) %2 %3 %4"_s.arg( i ).arg( c.asText() ).arg( QChar( 0x2192 ) ).arg( c.value ) );
40 i++;
41 }
42}
43
44void QgsReclassifyUtils::checkForOverlaps( const QVector<QgsReclassifyUtils::RasterClass> &classes, QgsProcessingFeedback *feedback )
45{
46 // test each class against each other class
47 for ( int i = 0; i < classes.count() - 1; i++ )
48 {
49 for ( int j = i + 1; j < classes.count(); j++ )
50 {
51 const QgsReclassifyUtils::RasterClass &class1 = classes.at( i );
52 const QgsReclassifyUtils::RasterClass &class2 = classes.at( j );
53 if ( class1.overlaps( class2 ) )
54 {
55 feedback->reportError( QObject::tr( "Warning: Class %1 (%2) overlaps with class %3 (%4)" ).arg( i + 1 ).arg( class1.asText() ).arg( j + 1 ).arg( class2.asText() ) );
56 }
57 }
58 }
59}
60
61void QgsReclassifyUtils::reclassify(
62 const QVector<QgsReclassifyUtils::RasterClass> &classes,
63 QgsRasterInterface *sourceRaster,
64 int band,
65 const QgsRectangle &extent,
66 int sourceWidthPixels,
67 int sourceHeightPixels,
68 std::unique_ptr<QgsRasterDataProvider> destinationRaster,
69 double destNoDataValue,
70 bool useNoDataForMissingValues,
71 QgsProcessingFeedback *feedback
72)
73{
74 QgsRasterIterator iter( sourceRaster );
75 iter.startRasterRead( band, sourceWidthPixels, sourceHeightPixels, extent );
76
77 const bool hasReportsDuringClose = destinationRaster->hasReportsDuringClose();
78 const double maxProgressDuringBlockWriting = hasReportsDuringClose ? 50.0 : 100.0;
79
80 int iterLeft = 0;
81 int iterTop = 0;
82 int iterCols = 0;
83 int iterRows = 0;
84 destinationRaster->setEditable( true );
85 std::unique_ptr<QgsRasterBlock> rasterBlock;
86 bool reclassed = false;
87 bool isNoData = false;
88 while ( iter.readNextRasterPart( band, iterCols, iterRows, rasterBlock, iterLeft, iterTop ) )
89 {
90 if ( feedback )
91 feedback->setProgress( maxProgressDuringBlockWriting * iter.progress( band ) );
92 if ( feedback && feedback->isCanceled() )
93 break;
94 auto reclassifiedBlock = std::make_unique<QgsRasterBlock>( destinationRaster->dataType( 1 ), iterCols, iterRows );
95
96 for ( int row = 0; row < iterRows; row++ )
97 {
98 if ( feedback && feedback->isCanceled() )
99 break;
100 for ( int column = 0; column < iterCols; column++ )
101 {
102 const double value = rasterBlock->valueAndNoData( row, column, isNoData );
103 if ( isNoData )
104 reclassifiedBlock->setValue( row, column, destNoDataValue );
105 else
106 {
107 const double newValue = reclassifyValue( classes, value, reclassed );
108 if ( reclassed )
109 reclassifiedBlock->setValue( row, column, newValue );
110 else
111 reclassifiedBlock->setValue( row, column, useNoDataForMissingValues ? destNoDataValue : value );
112 }
113 }
114 }
115 if ( !destinationRaster->writeBlock( reclassifiedBlock.get(), 1, iterLeft, iterTop ) )
116 {
117 throw QgsProcessingException( QObject::tr( "Could not write raster block: %1" ).arg( destinationRaster->error().summary() ) );
118 }
119 }
120 destinationRaster->setEditable( false );
121
122 if ( feedback && hasReportsDuringClose )
123 {
124 std::unique_ptr<QgsFeedback> scaledFeedback( QgsFeedback::createScaledFeedback( feedback, maxProgressDuringBlockWriting, 100.0 ) );
125 if ( !destinationRaster->closeWithProgress( scaledFeedback.get() ) )
126 {
127 if ( feedback->isCanceled() )
128 return;
129 throw QgsProcessingException( QObject::tr( "Could not write raster dataset" ) );
130 }
131 }
132}
133
134
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:65
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...
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Base class for processing filters like renderers, reprojector, resampler etc.
Iterator for sequentially processing raster cells.
A rectangle specified with double values.
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