QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsalgorithmrasterminmax.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmrasterminmax.cpp
3 ---------------------
4 begin : October 2024
5 copyright : (C) 2024 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
19
20#include <QString>
21
22using namespace Qt::StringLiterals;
23
25
26QString QgsRasterMinMaxAlgorithm::name() const
27{
28 return u"rasterminmax"_s;
29}
30
31QString QgsRasterMinMaxAlgorithm::displayName() const
32{
33 return QObject::tr( "Raster minimum/maximum" );
34}
35
36QStringList QgsRasterMinMaxAlgorithm::tags() const
37{
38 return QObject::tr( "dem,statistics,value,extrema,extremes,largest,smallest" ).split( ',' );
39}
40
41QString QgsRasterMinMaxAlgorithm::group() const
42{
43 return QObject::tr( "Raster analysis" );
44}
45
46QString QgsRasterMinMaxAlgorithm::groupId() const
47{
48 return u"rasteranalysis"_s;
49}
50
51void QgsRasterMinMaxAlgorithm::initAlgorithm( const QVariantMap & )
52{
53 addParameter( new QgsProcessingParameterRasterLayer( u"INPUT"_s, QObject::tr( "Input layer" ) ) );
54 addParameter( new QgsProcessingParameterBand( u"BAND"_s, QObject::tr( "Band number" ), 1, u"INPUT"_s ) );
55 addParameter(
56 new QgsProcessingParameterEnum( u"EXTRACT"_s, QObject::tr( "Extract extrema" ), QStringList() << QObject::tr( "Minimum and Maximum" ) << QObject::tr( "Minimum" ) << QObject::tr( "Maximum" ), false, 0 )
57 );
58
59 addParameter( new QgsProcessingParameterFeatureSink( u"OUTPUT"_s, QObject::tr( "Output" ), Qgis::ProcessingSourceType::VectorPoint, QVariant(), true, true ) );
60
61 addOutput( new QgsProcessingOutputNumber( u"MINIMUM"_s, QObject::tr( "Minimum" ) ) );
62 addOutput( new QgsProcessingOutputNumber( u"MAXIMUM"_s, QObject::tr( "Maximum" ) ) );
63}
64
65QString QgsRasterMinMaxAlgorithm::shortHelpString() const
66{
67 return QObject::tr(
68 "This algorithm extracts extrema (minimum and maximum) values from a given band of the raster layer.\n\n"
69 "The output is a vector layer containing point features for the selected extrema, at the center of the associated pixel.\n\n"
70 "If multiple pixels in the raster share the minimum or maximum value, then only one of these pixels will be included in the output."
71 );
72}
73
74QString QgsRasterMinMaxAlgorithm::shortDescription() const
75{
76 return QObject::tr( "Calculates the minimum and maximum pixel in a raster layer." );
77}
78
79QgsRasterMinMaxAlgorithm *QgsRasterMinMaxAlgorithm::createInstance() const
80{
81 return new QgsRasterMinMaxAlgorithm();
82}
83
84bool QgsRasterMinMaxAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
85{
86 QgsRasterLayer *layer = parameterAsRasterLayer( parameters, u"INPUT"_s, context );
87
88 if ( !layer )
89 throw QgsProcessingException( invalidRasterError( parameters, u"INPUT"_s ) );
90
91 mBand = parameterAsInt( parameters, u"BAND"_s, context );
92 if ( mBand < 1 || mBand > layer->bandCount() )
93 throw QgsProcessingException( QObject::tr( "Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand ).arg( layer->bandCount() ) );
94
95 mInterface.reset( layer->dataProvider()->clone() );
96 mHasNoDataValue = layer->dataProvider()->sourceHasNoDataValue( mBand );
97 mLayerWidth = layer->width();
98 mLayerHeight = layer->height();
99 mExtent = layer->extent();
100 mCrs = layer->crs();
101 mRasterUnitsPerPixelX = std::abs( layer->rasterUnitsPerPixelX() );
102 mRasterUnitsPerPixelY = std::abs( layer->rasterUnitsPerPixelY() );
103 return true;
104}
105
106QVariantMap QgsRasterMinMaxAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
107{
108 QString dest;
109 std::unique_ptr<QgsFeatureSink> sink;
110 if ( parameters.value( u"OUTPUT"_s ).isValid() )
111 {
112 QgsFields outFields;
113 outFields.append( QgsField( u"value"_s, QMetaType::Type::Double, QString(), 20, 8 ) );
114 outFields.append( QgsField( u"extremum_type"_s, QMetaType::Type::QString ) );
115 sink.reset( parameterAsSink( parameters, u"OUTPUT"_s, context, dest, outFields, Qgis::WkbType::Point, mCrs ) );
116 if ( !sink )
117 throw QgsProcessingException( invalidSinkError( parameters, u"OUTPUT"_s ) );
118 }
119
120 const int extractType = parameterAsInt( parameters, u"EXTRACT"_s, context );
121
122 QgsRasterIterator iter( mInterface.get() );
123 iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent );
124
125 int iterLeft = 0;
126 int iterTop = 0;
127 int iterCols = 0;
128 int iterRows = 0;
129 std::unique_ptr<QgsRasterBlock> rasterBlock;
130
131 double rasterMinimum = std::numeric_limits<double>::quiet_NaN();
132 double rasterMaximum = std::numeric_limits<double>::quiet_NaN();
133 QgsPointXY rasterMinPoint;
134 QgsPointXY rasterMaxPoint;
135
136 auto blockRowColToXY = [this]( const QgsRectangle &blockExtent, int row, int col ) -> QgsPointXY {
137 return QgsPointXY( blockExtent.xMinimum() + mRasterUnitsPerPixelX * ( col + 0.5 ), blockExtent.yMaximum() - mRasterUnitsPerPixelY * ( row + 0.5 ) );
138 };
139
140 QgsRectangle blockExtent;
141 while ( iter.readNextRasterPart( mBand, iterCols, iterRows, rasterBlock, iterLeft, iterTop, &blockExtent ) )
142 {
143 if ( feedback->isCanceled() )
144 break;
145
146 double blockMinimum = std::numeric_limits<double>::quiet_NaN();
147 double blockMaximum = std::numeric_limits<double>::quiet_NaN();
148 int blockMinRow = 0;
149 int blockMinCol = 0;
150 int blockMaxRow = 0;
151 int blockMaxCol = 0;
152 switch ( extractType )
153 {
154 case 0:
155 {
156 if ( rasterBlock->minimumMaximum( blockMinimum, blockMinRow, blockMinCol, blockMaximum, blockMaxRow, blockMaxCol ) )
157 {
158 if ( std::isnan( rasterMinimum ) || blockMinimum < rasterMinimum )
159 {
160 rasterMinimum = blockMinimum;
161 rasterMinPoint = blockRowColToXY( blockExtent, blockMinRow, blockMinCol );
162 }
163 if ( std::isnan( rasterMaximum ) || blockMaximum > rasterMaximum )
164 {
165 rasterMaximum = blockMaximum;
166 rasterMaxPoint = blockRowColToXY( blockExtent, blockMaxRow, blockMaxCol );
167 }
168 }
169 break;
170 }
171
172 case 1:
173 {
174 if ( rasterBlock->minimum( blockMinimum, blockMinRow, blockMinCol ) )
175 {
176 if ( std::isnan( rasterMinimum ) || blockMinimum < rasterMinimum )
177 {
178 rasterMinimum = blockMinimum;
179 rasterMinPoint = blockRowColToXY( blockExtent, blockMinRow, blockMinCol );
180 }
181 }
182 break;
183 }
184
185 case 2:
186 {
187 if ( rasterBlock->maximum( blockMaximum, blockMaxRow, blockMaxCol ) )
188 {
189 if ( std::isnan( rasterMaximum ) || blockMaximum > rasterMaximum )
190 {
191 rasterMaximum = blockMaximum;
192 rasterMaxPoint = blockRowColToXY( blockExtent, blockMaxRow, blockMaxCol );
193 }
194 }
195 break;
196 }
197 default:
198 break;
199 }
200 feedback->setProgress( 100 * iter.progress( mBand ) );
201 }
202
203 QVariantMap outputs;
204 if ( sink )
205 {
206 QgsFeature f;
207 if ( !std::isnan( rasterMinimum ) )
208 {
209 f.setAttributes( QgsAttributes() << rasterMinimum << u"minimum"_s );
210 f.setGeometry( QgsGeometry::fromPointXY( rasterMinPoint ) );
211 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
212 throw QgsProcessingException( writeFeatureError( sink.get(), parameters, u"OUTPUT"_s ) );
213 }
214 if ( !std::isnan( rasterMaximum ) )
215 {
216 f.setAttributes( QgsAttributes() << rasterMaximum << u"maximum"_s );
217 f.setGeometry( QgsGeometry::fromPointXY( rasterMaxPoint ) );
218 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
219 throw QgsProcessingException( writeFeatureError( sink.get(), parameters, u"OUTPUT"_s ) );
220 }
221 outputs.insert( u"OUTPUT"_s, dest );
222 }
223 outputs.insert( u"MINIMUM"_s, !std::isnan( rasterMinimum ) ? QVariant::fromValue( rasterMinimum ) : QVariant() );
224 outputs.insert( u"MAXIMUM"_s, !std::isnan( rasterMaximum ) ? QVariant::fromValue( rasterMaximum ) : QVariant() );
225 return outputs;
226}
227
228
@ VectorPoint
Vector point layers.
Definition qgis.h:3648
@ Point
Point.
Definition qgis.h:296
A vector of attributes.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
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
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:75
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:90
Represents a 2D point.
Definition qgspointxy.h:62
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A numeric output for processing algorithms.
A raster band parameter for Processing algorithms.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A feature sink output for processing algorithms.
A raster layer parameter for processing algorithms.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
Iterator for sequentially processing raster cells.
Represents a raster layer.
int height() const
Returns the height of the (unclipped) raster.
int bandCount() const
Returns the number of bands in this layer.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
int width() const
Returns the width of the (unclipped) raster.
A rectangle specified with double values.
double xMinimum
double yMaximum