Skip to content

Commit f0f5211

Browse files
committedJun 13, 2018
Add reclassify by table algorithm
1 parent 3c8f80d commit f0f5211

File tree

5 files changed

+251
-138
lines changed

5 files changed

+251
-138
lines changed
 

‎src/analysis/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ SET(QGIS_ANALYSIS_SRCS
8888
processing/qgsnativealgorithms.cpp
8989
processing/qgsoverlayutils.cpp
9090
processing/qgsrasteranalysisutils.cpp
91+
processing/qgsreclassifyutils.cpp
9192

9293
raster/qgsalignraster.cpp
9394
raster/qgsninecellfilter.cpp
@@ -217,6 +218,7 @@ QT5_WRAP_CPP(QGIS_ANALYSIS_MOC_SRCS ${QGIS_ANALYSIS_MOC_HDRS})
217218

218219
SET(QGIS_ANALYSIS_HDRS
219220
processing/qgsalgorithmimportphotos.h
221+
processing/qgsreclassifyutils.h
220222

221223
raster/qgsalignraster.h
222224
raster/qgsaspectfilter.h

‎src/analysis/processing/qgsalgorithmreclassifybylayer.cpp

Lines changed: 135 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -16,53 +16,35 @@
1616
***************************************************************************/
1717

1818
#include "qgsalgorithmreclassifybylayer.h"
19-
#include "qgsgeos.h"
20-
#include "qgslogger.h"
2119
#include "qgsrasterfilewriter.h"
20+
#include "qgsreclassifyutils.h"
2221
#include "qgis.h"
2322

2423
///@cond PRIVATE
2524

26-
QString QgsReclassifyByLayerAlgorithm::name() const
27-
{
28-
return QStringLiteral( "reclassifybylayer" );
29-
}
25+
//
26+
// QgsReclassifyAlgorithmBase
27+
//
3028

31-
QString QgsReclassifyByLayerAlgorithm::displayName() const
32-
{
33-
return QObject::tr( "Reclassify by layer" );
34-
}
3529

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
4231
{
4332
return QObject::tr( "Raster analysis" );
4433
}
4534

46-
QString QgsReclassifyByLayerAlgorithm::groupId() const
35+
QString QgsReclassifyAlgorithmBase::groupId() const
4736
{
4837
return QStringLiteral( "rasteranalysis" );
4938
}
5039

51-
void QgsReclassifyByLayerAlgorithm::initAlgorithm( const QVariantMap & )
40+
void QgsReclassifyAlgorithmBase::initAlgorithm( const QVariantMap &configuration )
5241
{
5342
addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT_RASTER" ),
5443
QObject::tr( "Raster layer" ) ) );
5544
addParameter( new QgsProcessingParameterBand( QStringLiteral( "RASTER_BAND" ),
5645
QObject::tr( "Band number" ), 1, QStringLiteral( "INPUT_RASTER" ) ) );
5746

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();
6648

6749
std::unique_ptr< QgsProcessingParameterNumber > noDataValueParam = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "NO_DATA" ),
6850
QObject::tr( "Output no data value" ), QgsProcessingParameterNumber::Double, -9999 );
@@ -71,17 +53,7 @@ void QgsReclassifyByLayerAlgorithm::initAlgorithm( const QVariantMap & )
7153
addParameter( new QgsProcessingParameterRasterDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Reclassified raster" ) ) );
7254
}
7355

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 &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
56+
bool QgsReclassifyAlgorithmBase::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
8557
{
8658
QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT_RASTER" ), context );
8759
mBand = parameterAsInt( parameters, QStringLiteral( "RASTER_BAND" ), context );
@@ -99,6 +71,77 @@ bool QgsReclassifyByLayerAlgorithm::prepareAlgorithm( const QVariantMap &paramet
9971

10072
mNoDataValue = parameterAsDouble( parameters, QStringLiteral( "NO_DATA" ), context );
10173

74+
return _prepareAlgorithm( parameters, context, feedback );
75+
}
76+
77+
QVariantMap QgsReclassifyAlgorithmBase::processAlgorithm( const QVariantMap &parameters, 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 &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
144+
{
102145
std::unique_ptr< QgsFeatureSource >tableSource( parameterAsSource( parameters, QStringLiteral( "INPUT_TABLE" ), context ) );
103146
if ( !tableSource )
104147
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT_TABLE" ) ) );
@@ -124,10 +167,9 @@ bool QgsReclassifyByLayerAlgorithm::prepareAlgorithm( const QVariantMap &paramet
124167
return true;
125168
}
126169

127-
QVariantMap QgsReclassifyByLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
170+
QVector<QgsReclassifyUtils::RasterClass> QgsReclassifyByLayerAlgorithm::createClasses( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
128171
{
129-
// step 1 - build up the table of reclassification values
130-
QVector< Class > classes;
172+
QVector< QgsReclassifyUtils::RasterClass > classes;
131173
QgsFeature f;
132174
while ( mTableIterator.nextFeature( f ) )
133175
{
@@ -142,89 +184,78 @@ QVariantMap QgsReclassifyByLayerAlgorithm::processAlgorithm( const QVariantMap &
142184
if ( !ok )
143185
throw QgsProcessingException( QObject::tr( "Invalid output value: %1" ).arg( f.attribute( mValueFieldIdx ).toString() ) );
144186

145-
classes << Class( minValue, maxValue, value );
187+
classes << QgsReclassifyUtils::RasterClass( minValue, maxValue, QgsRasterRange::IncludeMax, value );
146188
}
189+
return classes;
190+
}
147191

148-
const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral( "OUTPUT" ), context );
149-
QFileInfo fi( outputFile );
150-
const QString outputFormat = QgsRasterFileWriter::driverForExtension( fi.suffix() );
151192

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+
//
158196

159-
provider->setNoDataValue( 1, mNoDataValue );
197+
QString QgsReclassifyByTableAlgorithm::name() const
198+
{
199+
return QStringLiteral( "reclassifybytable" );
200+
}
160201

161-
reclassify( classes, provider.get(), feedback );
202+
QString QgsReclassifyByTableAlgorithm::displayName() const
203+
{
204+
return QObject::tr( "Reclassify by table" );
205+
}
162206

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( ',' );
166210
}
167211

168-
void QgsReclassifyByLayerAlgorithm::reclassify( const QVector<QgsReclassifyByLayerAlgorithm::Class> &classes, QgsRasterDataProvider *destinationRaster, QgsProcessingFeedback *feedback )
212+
QString QgsReclassifyByTableAlgorithm::shortHelpString() const
169213
{
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+
}
172216

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+
}
177221

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+
}
181230

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;
214234
}
215235

216-
double QgsReclassifyByLayerAlgorithm::reclassifyValue( const QVector<QgsReclassifyByLayerAlgorithm::Class> &classes, double input ) const
236+
QVector<QgsReclassifyUtils::RasterClass> QgsReclassifyByTableAlgorithm::createClasses( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
217237
{
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 )
219242
{
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() ) );
224253

254+
classes << QgsReclassifyUtils::RasterClass( minValue, maxValue, QgsRasterRange::IncludeMax, value );
255+
}
256+
return classes;
225257
}
226258

227259
///@endcond
228260

229261

230-

‎src/analysis/processing/qgsalgorithmreclassifybylayer.h

Lines changed: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,66 +22,104 @@
2222

2323
#include "qgis.h"
2424
#include "qgsprocessingalgorithm.h"
25+
#include "qgsreclassifyutils.h"
2526

2627
///@cond PRIVATE
2728

2829
/**
29-
* Native zonal histogram algorithm.
30+
* Base class for reclassify algorithms.
3031
*/
31-
class QgsReclassifyByLayerAlgorithm : public QgsProcessingAlgorithm
32+
class QgsReclassifyAlgorithmBase : public QgsProcessingAlgorithm
3233
{
33-
3434
public:
3535

36-
QgsReclassifyByLayerAlgorithm() = default;
37-
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
38-
QString name() const override;
39-
QString displayName() const override;
40-
QStringList tags() const override;
41-
QString group() const override;
42-
QString groupId() const override;
43-
QString shortHelpString() const override;
44-
QgsReclassifyByLayerAlgorithm *createInstance() const override SIP_FACTORY;
36+
QString group() const override final;
37+
QString groupId() const override final;
38+
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override final;
4539

4640
protected:
4741

48-
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
49-
QVariantMap processAlgorithm( const QVariantMap &parameters,
50-
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
51-
42+
/**
43+
* Adds specific subclass algorithm parameters. The common parameters, such as raster destination, are automatically
44+
* added by the base class.
45+
*/
46+
virtual void addAlgorithmParams() = 0;
5247

53-
struct Class
54-
{
55-
Class() = default;
56-
Class( double minValue, double maxValue, double value )
57-
: range( minValue, maxValue )
58-
, value( value )
59-
{}
60-
QgsRasterRange range;
61-
double value = 0;
62-
};
48+
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override final;
6349

50+
/**
51+
* Prepares the reclassify algorithm subclass for execution.
52+
*/
53+
virtual bool _prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0;
6454

65-
void reclassify( const QVector< Class > &classes, QgsRasterDataProvider *destinationRaster, QgsProcessingFeedback *feedback );
66-
double reclassifyValue( const QVector< Class > &classes, double input ) const;
55+
/**
56+
* Returns a list of classes to use during the reclassification.
57+
*/
58+
virtual QVector< QgsReclassifyUtils::RasterClass > createClasses( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0;
6759

68-
private:
60+
QVariantMap processAlgorithm( const QVariantMap &parameters,
61+
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override final;
6962

7063
std::unique_ptr< QgsRasterInterface > mInterface;
7164

72-
int mMinFieldIdx = -1;
73-
int mMaxFieldIdx = -1;
74-
int mValueFieldIdx = -1;
7565
double mNoDataValue = -9999;
76-
77-
QgsFeatureIterator mTableIterator;
7866
int mBand = 1;
7967
QgsRectangle mExtent;
8068
QgsCoordinateReferenceSystem mCrs;
8169
double mRasterUnitsPerPixelX = 0;
8270
double mRasterUnitsPerPixelY = 0;
8371
int mNbCellsXProvider = 0;
8472
int mNbCellsYProvider = 0;
73+
};
74+
75+
/**
76+
* Native reclassify by layer algorithm.
77+
*/
78+
class QgsReclassifyByLayerAlgorithm : public QgsReclassifyAlgorithmBase
79+
{
80+
81+
public:
82+
83+
QgsReclassifyByLayerAlgorithm() = default;
84+
QString name() const override;
85+
QString displayName() const override;
86+
QStringList tags() const override;
87+
QString shortHelpString() const override;
88+
QgsReclassifyByLayerAlgorithm *createInstance() const override SIP_FACTORY;
89+
90+
protected:
91+
void addAlgorithmParams() override;
92+
bool _prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
93+
QVector< QgsReclassifyUtils::RasterClass > createClasses( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
94+
95+
private:
96+
int mMinFieldIdx = -1;
97+
int mMaxFieldIdx = -1;
98+
int mValueFieldIdx = -1;
99+
QgsFeatureIterator mTableIterator;
100+
101+
};
102+
103+
/**
104+
* Native reclassify by table algorithm.
105+
*/
106+
class QgsReclassifyByTableAlgorithm : public QgsReclassifyAlgorithmBase
107+
{
108+
109+
public:
110+
111+
QgsReclassifyByTableAlgorithm() = default;
112+
QString name() const override;
113+
QString displayName() const override;
114+
QStringList tags() const override;
115+
QString shortHelpString() const override;
116+
QgsReclassifyByTableAlgorithm *createInstance() const override SIP_FACTORY;
117+
118+
protected:
119+
120+
void addAlgorithmParams() override;
121+
bool _prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
122+
QVector< QgsReclassifyUtils::RasterClass > createClasses( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
85123

86124
};
87125

‎src/analysis/processing/qgsnativealgorithms.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
166166
addAlgorithm( new QgsRasterLayerUniqueValuesReportAlgorithm() );
167167
addAlgorithm( new QgsAlgorithmRemoveDuplicateVertices() );
168168
addAlgorithm( new QgsReclassifyByLayerAlgorithm() );
169+
addAlgorithm( new QgsReclassifyByTableAlgorithm() );
169170
addAlgorithm( new QgsRemoveHolesAlgorithm() );
170171
addAlgorithm( new QgsRemoveNullGeometryAlgorithm() );
171172
addAlgorithm( new QgsRenameLayerAlgorithm() );

‎tests/src/analysis/testqgsprocessingalgs.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "qgsnativealgorithms.h"
2626
#include "qgsalgorithmimportphotos.h"
2727
#include "qgsalgorithmtransform.h"
28+
#include "qgsreclassifyutils.h"
2829

2930
class TestQgsProcessingAlgs: public QObject
3031
{
@@ -41,6 +42,7 @@ class TestQgsProcessingAlgs: public QObject
4142
void parseGeoTags();
4243
void featureFilterAlg();
4344
void transformAlg();
45+
void reclassifyValue();
4446

4547
private:
4648

@@ -435,6 +437,45 @@ void TestQgsProcessingAlgs::transformAlg()
435437
QVERIFY( ok );
436438
}
437439

440+
void TestQgsProcessingAlgs::reclassifyValue()
441+
{
442+
// no classes
443+
bool ok = false;
444+
QVector< QgsReclassifyUtils::RasterClass > classes;
445+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 5.9, ok ), 5.9 );
446+
QVERIFY( !ok );
447+
448+
// one class
449+
classes << QgsReclassifyUtils::RasterClass( 5, 11, QgsRasterRange::IncludeMin, -99.5 );
450+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 5.9, ok ), -99.5 );
451+
QVERIFY( ok );
452+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 15.9, ok ), 15.9 );
453+
QVERIFY( !ok );
454+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, -15.9, ok ), -15.9 );
455+
QVERIFY( !ok );
456+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 5, ok ), -99.5 );
457+
QVERIFY( ok );
458+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 11, ok ), 11.0 );
459+
QVERIFY( !ok );
460+
461+
// second class
462+
classes << QgsReclassifyUtils::RasterClass( 11, 15, QgsRasterRange::IncludeMin, -59.5 );
463+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 5.9, ok ), -99.5 );
464+
QVERIFY( ok );
465+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 11.9, ok ), -59.5 );
466+
QVERIFY( ok );
467+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 15.9, ok ), 15.9 );
468+
QVERIFY( !ok );
469+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, -15.9, ok ), -15.9 );
470+
QVERIFY( !ok );
471+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 5, ok ), -99.5 );
472+
QVERIFY( ok );
473+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 11, ok ), -59.5 );
474+
QVERIFY( ok );
475+
QCOMPARE( QgsReclassifyUtils::reclassifyValue( classes, 15, ok ), 15.0 );
476+
QVERIFY( !ok );
477+
}
478+
438479

439480
QGSTEST_MAIN( TestQgsProcessingAlgs )
440481
#include "testqgsprocessingalgs.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.