QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgsalgorithmvirtualrastercalculator.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmvirtualrastercalculator.cpp
3 ---------------------
4 begin : August 2023
5 copyright : (C) 2023 by Alexander Bruy
6 email : alexander dot bruy 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
20
22
23QgsProcessingAlgorithm::Flags QgsVirtualRasterCalculatorAlgorithm::flags() const
24{
26}
27
28QString QgsVirtualRasterCalculatorAlgorithm::name() const
29{
30 return QStringLiteral( "virtualrastercalc" );
31}
32
33QString QgsVirtualRasterCalculatorAlgorithm::displayName() const
34{
35 return QObject::tr( "Raster calculator (virtual)" );
36}
37
38QStringList QgsVirtualRasterCalculatorAlgorithm::tags() const
39{
40 return QObject::tr( "raster,calculator,virtual" ).split( ',' );
41}
42
43QString QgsVirtualRasterCalculatorAlgorithm::group() const
44{
45 return QObject::tr( "Raster analysis" );
46}
47
48QString QgsVirtualRasterCalculatorAlgorithm::groupId() const
49{
50 return QStringLiteral( "rasteranalysis" );
51}
52
53QString QgsVirtualRasterCalculatorAlgorithm::shortHelpString() const
54{
55 return QObject::tr( "Performs algebraic operations using raster layers and generates in-memory result." );
56}
57
58QgsVirtualRasterCalculatorAlgorithm *QgsVirtualRasterCalculatorAlgorithm::createInstance() const
59{
60 return new QgsVirtualRasterCalculatorAlgorithm();
61}
62
63void QgsVirtualRasterCalculatorAlgorithm::initAlgorithm( const QVariantMap & )
64{
65 addParameter( new QgsProcessingParameterMultipleLayers( QStringLiteral( "LAYERS" ), QObject::tr( "Input layers" ), QgsProcessing::SourceType::TypeRaster ) );
66 addParameter( new QgsProcessingParameterExpression( QStringLiteral( "EXPRESSION" ), QObject::tr( "Expression" ), QVariant(), QStringLiteral( "LAYERS" ), false, Qgis::ExpressionType::RasterCalculator ) );
67 std::unique_ptr<QgsProcessingParameterExtent> extentParam = std::make_unique<QgsProcessingParameterExtent>( QStringLiteral( "EXTENT" ), QObject::tr( "Output extent" ), QVariant(), true );
68 extentParam->setHelp( QObject::tr( "Extent of the output layer. If not specified, the extent will be the overall extent of all input layers" ) );
69 addParameter( extentParam.release() );
70 std::unique_ptr<QgsProcessingParameterNumber> cellSizeParam = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "CELL_SIZE" ), QObject::tr( "Output cell size (leave empty to set automatically)" ), QgsProcessingParameterNumber::Double, QVariant(), true, 0.0 );
71 cellSizeParam->setHelp( QObject::tr( "Cell size of the output layer. If not specified, the smallest cell size from the input layers will be used" ) );
72 addParameter( cellSizeParam.release() );
73 std::unique_ptr<QgsProcessingParameterCrs> crsParam = std::make_unique<QgsProcessingParameterCrs>( QStringLiteral( "CRS" ), QObject::tr( "Output CRS" ), QVariant(), true );
74 crsParam->setHelp( QObject::tr( "CRS of the output layer. If not specified, the CRS of the first input layer will be used" ) );
75 addParameter( crsParam.release() );
76 addParameter( new QgsProcessingParameterString( QStringLiteral( "LAYER_NAME" ), QObject::tr( "Output layer name" ), QVariant(), false, true ) );
77 addOutput( new QgsProcessingOutputRasterLayer( QStringLiteral( "OUTPUT" ), QObject::tr( "Calculated" ) ) );
78}
79
80QVariantMap QgsVirtualRasterCalculatorAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
81{
82 Q_UNUSED( feedback );
83
84 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
85 if ( layers.isEmpty() )
86 {
87 throw QgsProcessingException( QObject::tr( "No input layers selected" ) );
88 }
89
91 if ( parameters.value( QStringLiteral( "CRS" ) ).isValid() )
92 {
93 crs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
94 }
95 else
96 {
97 crs = layers.at( 0 )->crs();
98 }
99
100 QgsRectangle bbox;
101 if ( parameters.value( QStringLiteral( "EXTENT" ) ).isValid() )
102 {
103 bbox = parameterAsExtent( parameters, QStringLiteral( "EXTENT" ), context, crs );
104 }
105 else
106 {
107 bbox = QgsProcessingUtils::combineLayerExtents( layers, crs, context );
108 }
109
110 double minCellSize = 1e9;
112
113 for ( const QgsMapLayer *layer : layers )
114 {
115 const QgsRasterLayer *rLayer = qobject_cast<const QgsRasterLayer *>( layer );
116 if ( !rLayer )
117 {
118 continue;
119 }
120
122 rasterLayer.name = rLayer->name();
123 rasterLayer.provider = rLayer->dataProvider()->name();
124 rasterLayer.uri = rLayer->source();
125 rasterParameters.rInputLayers.append( rasterLayer );
126
127 QgsRectangle ext = rLayer->extent();
128 if ( rLayer->crs() != crs )
129 {
130 QgsCoordinateTransform ct( rLayer->crs(), crs, context.transformContext() );
131 ext = ct.transformBoundingBox( ext );
132 }
133
134 double cellSize = ( ext.xMaximum() - ext.xMinimum() ) / rLayer->width();
135 if ( cellSize < minCellSize )
136 {
137 minCellSize = cellSize;
138 }
139 }
140
141 double cellSize = parameterAsDouble( parameters, QStringLiteral( "CELL_SIZE" ), context );
142 if ( cellSize == 0 )
143 {
144 cellSize = minCellSize;
145 }
146
147 const QString expression = parameterAsExpression( parameters, QStringLiteral( "EXPRESSION" ), context );
148 QString layerName = parameterAsString( parameters, QStringLiteral( "LAYER_NAME" ), context );
149 if ( layerName.isEmpty() )
150 {
151 layerName = expression;
152 }
153
154 double width = std::round( ( bbox.xMaximum() - bbox.xMinimum() ) / cellSize );
155 double height = std::round( ( bbox.yMaximum() - bbox.yMinimum() ) / cellSize );
156
157 rasterParameters.crs = crs;
158 rasterParameters.extent = bbox;
159 rasterParameters.width = width;
160 rasterParameters.height = height;
161 rasterParameters.formula = expression;
162
163 std::unique_ptr< QgsRasterLayer > layer;
164 layer = std::make_unique< QgsRasterLayer >( QgsRasterDataProvider::encodeVirtualRasterProviderUri( rasterParameters ),
165 layerName, QStringLiteral( "virtualraster" ) );
166 if ( !layer->isValid() )
167 {
168 feedback->reportError( QObject::tr( "Failed to create virtual raster layer" ) );
169 }
170 else
171 {
172 }
173 const QString layerId = layer->id();
174 const QgsProcessingContext::LayerDetails details( layer->name(), context.project(), QStringLiteral( "OUTPUT" ), QgsProcessingUtils::LayerHint::Raster );
175 context.addLayerToLoadOnCompletion( layerId, details );
176 context.temporaryLayerStore()->addMapLayer( layer.release() );
177
178 QVariantMap outputs;
179 outputs.insert( QStringLiteral( "OUTPUT" ), layerId );
180 return outputs;
181}
182
183QgsProcessingAlgorithm::Flags QgsVirtualRasterCalculatorModelerAlgorithm::flags() const
184{
186}
187
188QString QgsVirtualRasterCalculatorModelerAlgorithm::name() const
189{
190 return QStringLiteral( "modelervirtualrastercalc" );
191}
192
193QString QgsVirtualRasterCalculatorModelerAlgorithm::displayName() const
194{
195 return QObject::tr( "Raster calculator (virtual)" );
196}
197
198QStringList QgsVirtualRasterCalculatorModelerAlgorithm::tags() const
199{
200 return QObject::tr( "raster,calculator,virtual" ).split( ',' );
201}
202
203QString QgsVirtualRasterCalculatorModelerAlgorithm::group() const
204{
205 return QObject::tr( "Raster analysis" );
206}
207
208QString QgsVirtualRasterCalculatorModelerAlgorithm::groupId() const
209{
210 return QStringLiteral( "rasteranalysis" );
211}
212
213QgsVirtualRasterCalculatorModelerAlgorithm *QgsVirtualRasterCalculatorModelerAlgorithm::createInstance() const
214{
215 return new QgsVirtualRasterCalculatorModelerAlgorithm();
216}
217
218QVariantMap QgsVirtualRasterCalculatorModelerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
219{
220 Q_UNUSED( feedback );
221
222 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "INPUT" ), context );
223 if ( layers.isEmpty() )
224 {
225 throw QgsProcessingException( QObject::tr( "No input layers selected" ) );
226 }
227
229 if ( parameters.value( QStringLiteral( "CRS" ) ).isValid() )
230 {
231 crs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
232 }
233 else
234 {
235 crs = layers.at( 0 )->crs();
236 }
237
238 QgsRectangle bbox;
239 if ( parameters.value( QStringLiteral( "EXTENT" ) ).isValid() )
240 {
241 bbox = parameterAsExtent( parameters, QStringLiteral( "EXTENT" ), context, crs );
242 }
243 else
244 {
245 bbox = QgsProcessingUtils::combineLayerExtents( layers, crs, context );
246 }
247
248 double minCellSize = 1e9;
250
251 int n = 0;
252 for ( const QgsMapLayer *layer : layers )
253 {
254 const QgsRasterLayer *rLayer = qobject_cast<const QgsRasterLayer *>( layer );
255 if ( !rLayer )
256 {
257 continue;
258 }
259
260 n++;
262 rasterLayer.name = indexToName( n );
263 rasterLayer.provider = rLayer->dataProvider()->name();
264 rasterLayer.uri = rLayer->source();
265 rasterParameters.rInputLayers.append( rasterLayer );
266
267 QgsRectangle ext = rLayer->extent();
268 if ( rLayer->crs() != crs )
269 {
270 QgsCoordinateTransform ct( rLayer->crs(), crs, context.transformContext() );
271 ext = ct.transformBoundingBox( ext );
272 }
273
274 double cellSize = ( ext.xMaximum() - ext.xMinimum() ) / rLayer->width();
275 if ( cellSize < minCellSize )
276 {
277 minCellSize = cellSize;
278 }
279 }
280
281 double cellSize = parameterAsDouble( parameters, QStringLiteral( "CELL_SIZE" ), context );
282 if ( cellSize == 0 )
283 {
284 cellSize = minCellSize;
285 }
286
287 const QString expression = parameterAsExpression( parameters, QStringLiteral( "EXPRESSION" ), context );
288 QString layerName = parameterAsString( parameters, QStringLiteral( "LAYER_NAME" ), context );
289 if ( layerName.isEmpty() )
290 {
291 layerName = expression;
292 }
293
294 double width = std::round( ( bbox.xMaximum() - bbox.xMinimum() ) / cellSize );
295 double height = std::round( ( bbox.yMaximum() - bbox.yMinimum() ) / cellSize );
296
297 rasterParameters.crs = crs;
298 rasterParameters.extent = bbox;
299 rasterParameters.width = width;
300 rasterParameters.height = height;
301 rasterParameters.formula = expression;
302
303 std::unique_ptr< QgsRasterLayer > layer;
304 layer = std::make_unique< QgsRasterLayer >( QgsRasterDataProvider::encodeVirtualRasterProviderUri( rasterParameters ),
305 layerName, QStringLiteral( "virtualraster" ) );
306 if ( !layer->isValid() )
307 {
308 feedback->reportError( QObject::tr( "Failed to create virtual raster layer" ) );
309 }
310 else
311 {
312 }
313 const QString layerId = layer->id();
314 const QgsProcessingContext::LayerDetails details( layer->name(), context.project(), QStringLiteral( "OUTPUT" ), QgsProcessingUtils::LayerHint::Raster );
315 context.addLayerToLoadOnCompletion( layerId, details );
316 context.temporaryLayerStore()->addMapLayer( layer.release() );
317
318 QVariantMap outputs;
319 outputs.insert( QStringLiteral( "OUTPUT" ), layerId );
320 return outputs;
321}
322
323QString QgsVirtualRasterCalculatorModelerAlgorithm::indexToName( int index ) const
324{
325 QString name;
326 int div = index;
327 int mod = 0;
328
329 while ( div > 0 )
330 {
331 mod = ( div - 1 ) % 26;
332 name = static_cast<char>( 65 + mod ) + name;
333 div = ( int )( ( div - mod ) / 26 );
334 }
335 return name;
336}
337
@ RasterCalculator
Raster calculator expression (since QGIS 3.34)
This class represents a coordinate reference system (CRS).
Class for doing transforms between two map coordinate systems.
virtual QString name() const =0
Returns a provider name.
QgsMapLayer * addMapLayer(QgsMapLayer *layer, bool takeOwnership=true)
Add a layer to the store.
Base class for all map layer types.
Definition qgsmaplayer.h:74
QString name
Definition qgsmaplayer.h:77
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:80
virtual Flags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
@ FlagNoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
Details for layers to load into projects.
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
void addLayerToLoadOnCompletion(const QString &layer, const QgsProcessingContext::LayerDetails &details)
Adds a layer to load (by ID or datasource) into the canvas upon completion of the algorithm or model.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
QgsMapLayerStore * temporaryLayerStore()
Returns a reference to the layer store used for storing temporary layers during algorithm execution.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A raster layer output for processing algorithms.
An expression parameter for processing algorithms.
A parameter for processing algorithms which accepts multiple map layers.
A string parameter for processing algorithms.
@ Raster
Raster layer type.
static QgsRectangle combineLayerExtents(const QList< QgsMapLayer * > &layers, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context)
Combines the extent of several map layers.
@ TypeRaster
Raster layers.
static QString encodeVirtualRasterProviderUri(const VirtualRasterParameters &parts)
Encodes the URI starting from the struct .
Represents a raster layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
int width() const
Returns the width of the (unclipped) raster.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
const QgsCoordinateReferenceSystem & crs
Struct that stores information of the raster used in QgsVirtualRasterProvider for the calculations,...
Struct that stores the information about the parameters that should be given to the QgsVirtualRasterP...
QList< QgsRasterDataProvider::VirtualRasterInputLayers > rInputLayers