16
16
***************************************************************************/
17
17
18
18
#include " qgsalgorithmreclassifybylayer.h"
19
- #include " qgsgeos.h"
20
- #include " qgslogger.h"
21
19
#include " qgsrasterfilewriter.h"
20
+ #include " qgsreclassifyutils.h"
22
21
#include " qgis.h"
23
22
24
23
// /@cond PRIVATE
25
24
26
- QString QgsReclassifyByLayerAlgorithm::name () const
27
- {
28
- return QStringLiteral ( " reclassifybylayer" );
29
- }
25
+ //
26
+ // QgsReclassifyAlgorithmBase
27
+ //
30
28
31
- QString QgsReclassifyByLayerAlgorithm::displayName () const
32
- {
33
- return QObject::tr ( " Reclassify by layer" );
34
- }
35
29
36
- QStringList QgsReclassifyByLayerAlgorithm::tags () const
37
- {
38
- return QObject::tr ( " raster,reclassify,classes,calculator" ).split ( ' ,' );
39
- }
40
-
41
- QString QgsReclassifyByLayerAlgorithm::group () const
30
+ QString QgsReclassifyAlgorithmBase::group () const
42
31
{
43
32
return QObject::tr ( " Raster analysis" );
44
33
}
45
34
46
- QString QgsReclassifyByLayerAlgorithm ::groupId () const
35
+ QString QgsReclassifyAlgorithmBase ::groupId () const
47
36
{
48
37
return QStringLiteral ( " rasteranalysis" );
49
38
}
50
39
51
- void QgsReclassifyByLayerAlgorithm ::initAlgorithm ( const QVariantMap & )
40
+ void QgsReclassifyAlgorithmBase ::initAlgorithm ( const QVariantMap &configuration )
52
41
{
53
42
addParameter ( new QgsProcessingParameterRasterLayer ( QStringLiteral ( " INPUT_RASTER" ),
54
43
QObject::tr ( " Raster layer" ) ) );
55
44
addParameter ( new QgsProcessingParameterBand ( QStringLiteral ( " RASTER_BAND" ),
56
45
QObject::tr ( " Band number" ), 1 , QStringLiteral ( " INPUT_RASTER" ) ) );
57
46
58
- addParameter ( new QgsProcessingParameterFeatureSource ( QStringLiteral ( " INPUT_TABLE" ),
59
- QObject::tr ( " Layer containing class breaks" ), QList< int >() << QgsProcessing::TypeVector ) );
60
- addParameter ( new QgsProcessingParameterField ( QStringLiteral ( " MIN_FIELD" ),
61
- QObject::tr ( " Minimum class value field" ), QVariant (), QStringLiteral ( " INPUT_TABLE" ), QgsProcessingParameterField::Numeric ) );
62
- addParameter ( new QgsProcessingParameterField ( QStringLiteral ( " MAX_FIELD" ),
63
- QObject::tr ( " Maximum class value field" ), QVariant (), QStringLiteral ( " INPUT_TABLE" ), QgsProcessingParameterField::Numeric ) );
64
- addParameter ( new QgsProcessingParameterField ( QStringLiteral ( " VALUE_FIELD" ),
65
- QObject::tr ( " Output value field" ), QVariant (), QStringLiteral ( " INPUT_TABLE" ), QgsProcessingParameterField::Numeric ) );
47
+ addAlgorithmParams ();
66
48
67
49
std::unique_ptr< QgsProcessingParameterNumber > noDataValueParam = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral ( " NO_DATA" ),
68
50
QObject::tr ( " Output no data value" ), QgsProcessingParameterNumber::Double, -9999 );
@@ -71,17 +53,7 @@ void QgsReclassifyByLayerAlgorithm::initAlgorithm( const QVariantMap & )
71
53
addParameter ( new QgsProcessingParameterRasterDestination ( QStringLiteral ( " OUTPUT" ), QObject::tr ( " Reclassified raster" ) ) );
72
54
}
73
55
74
- QString QgsReclassifyByLayerAlgorithm::shortHelpString () const
75
- {
76
- return QObject::tr ( " This algorithm reclassifies a raster band by assigning new class values based on the ranges specified in a vector table." );
77
- }
78
-
79
- QgsReclassifyByLayerAlgorithm *QgsReclassifyByLayerAlgorithm::createInstance () const
80
- {
81
- return new QgsReclassifyByLayerAlgorithm ();
82
- }
83
-
84
- bool QgsReclassifyByLayerAlgorithm::prepareAlgorithm ( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
56
+ bool QgsReclassifyAlgorithmBase::prepareAlgorithm ( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
85
57
{
86
58
QgsRasterLayer *layer = parameterAsRasterLayer ( parameters, QStringLiteral ( " INPUT_RASTER" ), context );
87
59
mBand = parameterAsInt ( parameters, QStringLiteral ( " RASTER_BAND" ), context );
@@ -99,6 +71,77 @@ bool QgsReclassifyByLayerAlgorithm::prepareAlgorithm( const QVariantMap ¶met
99
71
100
72
mNoDataValue = parameterAsDouble ( parameters, QStringLiteral ( " NO_DATA" ), context );
101
73
74
+ return _prepareAlgorithm ( parameters, context, feedback );
75
+ }
76
+
77
+ QVariantMap QgsReclassifyAlgorithmBase::processAlgorithm ( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
78
+ {
79
+ QVector< QgsReclassifyUtils::RasterClass > classes = createClasses ( parameters, context, feedback );
80
+
81
+ const QString outputFile = parameterAsOutputLayer ( parameters, QStringLiteral ( " OUTPUT" ), context );
82
+ QFileInfo fi ( outputFile );
83
+ const QString outputFormat = QgsRasterFileWriter::driverForExtension ( fi.suffix () );
84
+
85
+ std::unique_ptr< QgsRasterFileWriter > writer = qgis::make_unique< QgsRasterFileWriter >( outputFile );
86
+ writer->setOutputProviderKey ( QStringLiteral ( " gdal" ) );
87
+ writer->setOutputFormat ( outputFormat );
88
+ std::unique_ptr<QgsRasterDataProvider > provider ( writer->createOneBandRaster ( Qgis::Float32, mNbCellsXProvider , mNbCellsYProvider , mExtent , mCrs ) );
89
+ if ( !provider )
90
+ throw QgsProcessingException ( QObject::tr ( " Could not create raster output: %1" ).arg ( outputFile ) );
91
+
92
+ provider->setNoDataValue ( 1 , mNoDataValue );
93
+
94
+ QgsReclassifyUtils::reclassify ( classes, mInterface .get (), mBand , mExtent , mNbCellsXProvider , mNbCellsYProvider , provider.get (), mNoDataValue , feedback );
95
+
96
+ QVariantMap outputs;
97
+ outputs.insert ( QStringLiteral ( " OUTPUT" ), outputFile );
98
+ return outputs;
99
+ }
100
+
101
+
102
+ //
103
+ // QgsReclassifyByLayerAlgorithm
104
+ //
105
+
106
+ QString QgsReclassifyByLayerAlgorithm::name () const
107
+ {
108
+ return QStringLiteral ( " reclassifybylayer" );
109
+ }
110
+
111
+ QString QgsReclassifyByLayerAlgorithm::displayName () const
112
+ {
113
+ return QObject::tr ( " Reclassify by layer" );
114
+ }
115
+
116
+ QStringList QgsReclassifyByLayerAlgorithm::tags () const
117
+ {
118
+ return QObject::tr ( " raster,reclassify,classes,calculator" ).split ( ' ,' );
119
+ }
120
+
121
+ QString QgsReclassifyByLayerAlgorithm::shortHelpString () const
122
+ {
123
+ return QObject::tr ( " This algorithm reclassifies a raster band by assigning new class values based on the ranges specified in a vector table." );
124
+ }
125
+
126
+ QgsReclassifyByLayerAlgorithm *QgsReclassifyByLayerAlgorithm::createInstance () const
127
+ {
128
+ return new QgsReclassifyByLayerAlgorithm ();
129
+ }
130
+
131
+ void QgsReclassifyByLayerAlgorithm::addAlgorithmParams ()
132
+ {
133
+ addParameter ( new QgsProcessingParameterFeatureSource ( QStringLiteral ( " INPUT_TABLE" ),
134
+ QObject::tr ( " Layer containing class breaks" ), QList< int >() << QgsProcessing::TypeVector ) );
135
+ addParameter ( new QgsProcessingParameterField ( QStringLiteral ( " MIN_FIELD" ),
136
+ QObject::tr ( " Minimum class value field" ), QVariant (), QStringLiteral ( " INPUT_TABLE" ), QgsProcessingParameterField::Numeric ) );
137
+ addParameter ( new QgsProcessingParameterField ( QStringLiteral ( " MAX_FIELD" ),
138
+ QObject::tr ( " Maximum class value field" ), QVariant (), QStringLiteral ( " INPUT_TABLE" ), QgsProcessingParameterField::Numeric ) );
139
+ addParameter ( new QgsProcessingParameterField ( QStringLiteral ( " VALUE_FIELD" ),
140
+ QObject::tr ( " Output value field" ), QVariant (), QStringLiteral ( " INPUT_TABLE" ), QgsProcessingParameterField::Numeric ) );
141
+ }
142
+
143
+ bool QgsReclassifyByLayerAlgorithm::_prepareAlgorithm ( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
144
+ {
102
145
std::unique_ptr< QgsFeatureSource >tableSource ( parameterAsSource ( parameters, QStringLiteral ( " INPUT_TABLE" ), context ) );
103
146
if ( !tableSource )
104
147
throw QgsProcessingException ( invalidSourceError ( parameters, QStringLiteral ( " INPUT_TABLE" ) ) );
@@ -124,10 +167,9 @@ bool QgsReclassifyByLayerAlgorithm::prepareAlgorithm( const QVariantMap ¶met
124
167
return true ;
125
168
}
126
169
127
- QVariantMap QgsReclassifyByLayerAlgorithm::processAlgorithm ( const QVariantMap ¶meters , QgsProcessingContext &context , QgsProcessingFeedback *feedback )
170
+ QVector<QgsReclassifyUtils::RasterClass> QgsReclassifyByLayerAlgorithm::createClasses ( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
128
171
{
129
- // step 1 - build up the table of reclassification values
130
- QVector< Class > classes;
172
+ QVector< QgsReclassifyUtils::RasterClass > classes;
131
173
QgsFeature f;
132
174
while ( mTableIterator .nextFeature ( f ) )
133
175
{
@@ -142,89 +184,78 @@ QVariantMap QgsReclassifyByLayerAlgorithm::processAlgorithm( const QVariantMap &
142
184
if ( !ok )
143
185
throw QgsProcessingException ( QObject::tr ( " Invalid output value: %1" ).arg ( f.attribute ( mValueFieldIdx ).toString () ) );
144
186
145
- classes << Class ( minValue, maxValue, value );
187
+ classes << QgsReclassifyUtils::RasterClass ( minValue, maxValue, QgsRasterRange::IncludeMax , value );
146
188
}
189
+ return classes;
190
+ }
147
191
148
- const QString outputFile = parameterAsOutputLayer ( parameters, QStringLiteral ( " OUTPUT" ), context );
149
- QFileInfo fi ( outputFile );
150
- const QString outputFormat = QgsRasterFileWriter::driverForExtension ( fi.suffix () );
151
192
152
- std::unique_ptr< QgsRasterFileWriter > writer = qgis::make_unique< QgsRasterFileWriter >( outputFile );
153
- writer->setOutputProviderKey ( QStringLiteral ( " gdal" ) );
154
- writer->setOutputFormat ( outputFormat );
155
- std::unique_ptr<QgsRasterDataProvider > provider ( writer->createOneBandRaster ( Qgis::Float32, mNbCellsXProvider , mNbCellsYProvider , mExtent , mCrs ) );
156
- if ( !provider )
157
- throw QgsProcessingException ( QObject::tr ( " Could not create raster output: %1" ).arg ( outputFile ) );
193
+ //
194
+ // QgsReclassifyByTableAlgorithm
195
+ //
158
196
159
- provider->setNoDataValue ( 1 , mNoDataValue );
197
+ QString QgsReclassifyByTableAlgorithm::name () const
198
+ {
199
+ return QStringLiteral ( " reclassifybytable" );
200
+ }
160
201
161
- reclassify ( classes, provider.get (), feedback );
202
+ QString QgsReclassifyByTableAlgorithm::displayName () const
203
+ {
204
+ return QObject::tr ( " Reclassify by table" );
205
+ }
162
206
163
- QVariantMap outputs;
164
- outputs. insert ( QStringLiteral ( " OUTPUT " ), outputFile );
165
- return outputs ;
207
+ QStringList QgsReclassifyByTableAlgorithm::tags () const
208
+ {
209
+ return QObject::tr ( " raster,reclassify,classes,calculator " ). split ( ' , ' ) ;
166
210
}
167
211
168
- void QgsReclassifyByLayerAlgorithm::reclassify ( const QVector<QgsReclassifyByLayerAlgorithm::Class> &classes, QgsRasterDataProvider *destinationRaster, QgsProcessingFeedback *feedback )
212
+ QString QgsReclassifyByTableAlgorithm::shortHelpString () const
169
213
{
170
- int maxWidth = 4000 ;
171
- int maxHeight = 4000 ;
214
+ return QObject::tr ( " This algorithm reclassifies a raster band by assigning new class values based on the ranges specified in a fixed table. " ) ;
215
+ }
172
216
173
- QgsRasterIterator iter ( mInterface . get () );
174
- iter. setMaximumTileWidth ( maxWidth );
175
- iter. setMaximumTileHeight ( maxHeight );
176
- iter. startRasterRead ( mBand , mNbCellsXProvider , mNbCellsYProvider , mExtent );
217
+ QgsReclassifyByTableAlgorithm * QgsReclassifyByTableAlgorithm::createInstance () const
218
+ {
219
+ return new QgsReclassifyByTableAlgorithm ( );
220
+ }
177
221
178
- int nbBlocksWidth = std::ceil ( 1.0 * mNbCellsXProvider / maxWidth );
179
- int nbBlocksHeight = std::ceil ( 1.0 * mNbCellsYProvider / maxHeight );
180
- int nbBlocks = nbBlocksWidth * nbBlocksHeight;
222
+ void QgsReclassifyByTableAlgorithm::addAlgorithmParams ()
223
+ {
224
+ addParameter ( new QgsProcessingParameterMatrix ( QStringLiteral ( " TABLE" ),
225
+ QObject::tr ( " Reclassification table" ),
226
+ 1 , false , QStringList () << QObject::tr ( " Minimum" )
227
+ << QObject::tr ( " Maximum" )
228
+ << QObject::tr ( " Value" ) ) );
229
+ }
181
230
182
- int iterLeft = 0 ;
183
- int iterTop = 0 ;
184
- int iterCols = 0 ;
185
- int iterRows = 0 ;
186
- destinationRaster->setEditable ( true );
187
- QgsRasterBlock *rasterBlock = nullptr ;
188
- while ( iter.readNextRasterPart ( mBand , iterCols, iterRows, &rasterBlock, iterLeft, iterTop ) )
189
- {
190
- feedback->setProgress ( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
191
- std::unique_ptr< QgsRasterBlock > reclassifiedBlock = qgis::make_unique< QgsRasterBlock >( Qgis::Float32, iterCols, iterRows );
192
-
193
- for ( int row = 0 ; row < iterRows; row++ )
194
- {
195
- if ( feedback->isCanceled () )
196
- break ;
197
- for ( int column = 0 ; column < iterCols; column++ )
198
- {
199
- if ( rasterBlock->isNoData ( row, column ) )
200
- reclassifiedBlock->setValue ( row, column, mNoDataValue );
201
- else
202
- {
203
- double value = rasterBlock->value ( row, column );
204
- double newValue = reclassifyValue ( classes, value );
205
- reclassifiedBlock->setValue ( row, column, newValue );
206
- }
207
- }
208
- }
209
- destinationRaster->writeBlock ( reclassifiedBlock.get (), 1 , iterLeft, iterTop );
210
-
211
- delete rasterBlock;
212
- }
213
- destinationRaster->setEditable ( false );
231
+ bool QgsReclassifyByTableAlgorithm::_prepareAlgorithm ( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
232
+ {
233
+ return true ;
214
234
}
215
235
216
- double QgsReclassifyByLayerAlgorithm::reclassifyValue ( const QVector<QgsReclassifyByLayerAlgorithm::Class> &classes, double input ) const
236
+ QVector<QgsReclassifyUtils::RasterClass> QgsReclassifyByTableAlgorithm::createClasses ( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
217
237
{
218
- for ( const QgsReclassifyByLayerAlgorithm::Class &c : classes )
238
+ const QVariantList table = parameterAsMatrix ( parameters, QStringLiteral ( " TABLE" ), context );
239
+ int rows = table.count () / 3 ;
240
+ QVector< QgsReclassifyUtils::RasterClass > classes;
241
+ for ( int row = 0 ; row < rows; ++row )
219
242
{
220
- if ( input >= c.range .min () && input < c.range .max () )
221
- return c.value ;
222
- }
223
- return mNoDataValue ;
243
+ bool ok = false ;
244
+ const double minValue = table.at ( row * 3 ).toDouble ( &ok );
245
+ if ( !ok )
246
+ throw QgsProcessingException ( QObject::tr ( " Invalid value for minimum: %1" ).arg ( table.at ( row * 3 ).toString () ) );
247
+ const double maxValue = table.at ( row * 3 + 1 ).toDouble ( &ok );
248
+ if ( !ok )
249
+ throw QgsProcessingException ( QObject::tr ( " Invalid value for maximum: %1" ).arg ( table.at ( row * 3 + 1 ).toString () ) );
250
+ const double value = table.at ( row * 3 + 2 ).toDouble ( &ok );
251
+ if ( !ok )
252
+ throw QgsProcessingException ( QObject::tr ( " Invalid output value: %1" ).arg ( table.at ( row * 3 + 2 ).toString () ) );
224
253
254
+ classes << QgsReclassifyUtils::RasterClass ( minValue, maxValue, QgsRasterRange::IncludeMax, value );
255
+ }
256
+ return classes;
225
257
}
226
258
227
259
// /@endcond
228
260
229
261
230
-
0 commit comments