QGIS API Documentation 4.3.0-Master (ffcfc20b9b4)
Loading...
Searching...
No Matches
qgsalgorithmidwinterpolation.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmidwinterpolation.cpp
3 -----------------------------------
4 begin : August 2026
5 copyright : (C) 2026 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 "qgsgridfilewriter.h"
21#include "qgsidwinterpolator.h"
24#include "qgsprocessingutils.h"
25
26#include <QString>
27
28using namespace Qt::StringLiterals;
29
31QgsIdwInterpolationAlgorithm::QgsIdwInterpolationAlgorithm() = default;
32
33QString QgsIdwInterpolationAlgorithm::name() const
34{
35 return u"idwinterpolation"_s;
36}
37
38QString QgsIdwInterpolationAlgorithm::displayName() const
39{
40 return QObject::tr( "IDW interpolation" );
41}
42
43QStringList QgsIdwInterpolationAlgorithm::tags() const
44{
45 return QObject::tr( "idw,inverse,distance,weighted,interpolation,surface,grid,breaklines,breaks,structures" ).split( ',' );
46}
47
48QString QgsIdwInterpolationAlgorithm::group() const
49{
50 return QObject::tr( "Interpolation" );
51}
52
53QString QgsIdwInterpolationAlgorithm::groupId() const
54{
55 return u"interpolation"_s;
56}
57
58QString QgsIdwInterpolationAlgorithm::shortDescription() const
59{
60 return QObject::tr( "Generates an Inverse Distance Weighted (IDW) interpolation from vector layers." );
61}
62
63QString QgsIdwInterpolationAlgorithm::shortHelpString() const
64{
65 return QObject::tr(
66 "This algorithm generates an Inverse Distance Weighted (IDW) interpolation surface raster from one or more vector layers.\n\n"
67 "IDW calculates cell values using a linearly weighted combination of sample points. The weighting is an inverse function of "
68 "distance, meaning closer sample points exert greater influence on the target cell value than more distant points.\n\n"
69 "Input layers can supply sample values from feature attributes or feature Z coordinates. Features can be specified "
70 "as discrete points, structure lines, or breaklines."
71 );
72}
73
74QgsIdwInterpolationAlgorithm *QgsIdwInterpolationAlgorithm::createInstance() const
75{
76 return new QgsIdwInterpolationAlgorithm();
77}
78
79void QgsIdwInterpolationAlgorithm::initAlgorithm( const QVariantMap & )
80{
81 auto dataParam = std::make_unique<QgsProcessingParameterInterpolationSource>( u"INTERPOLATION_DATA"_s, QObject::tr( "Input layer(s)" ) );
82 dataParam->setHelp( QObject::tr( "Vector layers to use for interpolation along with their attributes and source types." ) );
83 addParameter( dataParam.release() );
84
85 auto distanceParam
86 = std::make_unique<QgsProcessingParameterNumber>( u"DISTANCE_COEFFICIENT"_s, QObject::tr( "Distance coefficient P" ), Qgis::ProcessingNumberParameterType::Double, 2.0, false, 0.0, 99.99 );
87 distanceParam->setHelp( QObject::tr( "Distance coefficient determines how influence decreases with distance." ) );
88 addParameter( distanceParam.release() );
89
90 auto extentParam = std::make_unique<QgsProcessingParameterExtent>( u"EXTENT"_s, QObject::tr( "Extent" ), QVariant(), false );
91 extentParam->setHelp( QObject::tr( "Bounding box defining the extent of the output raster grid." ) );
92 addParameter( extentParam.release() );
93
94 auto pixelSizeParam = std::make_unique<QgsProcessingParameterInterpolationPixelSize>( u"PIXEL_SIZE"_s, QObject::tr( "Output raster size" ), u"INTERPOLATION_DATA"_s, u"EXTENT"_s, 0.1 );
95 pixelSizeParam->setHelp( QObject::tr( "Pixel size in layer units used to calculate output grid dimensions." ) );
96 addParameter( pixelSizeParam.release() );
97
98 auto colsParam = std::make_unique<QgsProcessingParameterNumber>( u"COLUMNS"_s, QObject::tr( "Number of columns" ), Qgis::ProcessingNumberParameterType::Integer, QVariant(), true, 0, 10000000 );
99 colsParam->setFlags( colsParam->flags() | Qgis::ProcessingParameterFlag::Hidden );
100 addParameter( colsParam.release() );
101
102 auto rowsParam = std::make_unique<QgsProcessingParameterNumber>( u"ROWS"_s, QObject::tr( "Number of rows" ), Qgis::ProcessingNumberParameterType::Integer, QVariant(), true, 0, 10000000 );
103 rowsParam->setFlags( rowsParam->flags() | Qgis::ProcessingParameterFlag::Hidden );
104 addParameter( rowsParam.release() );
105
106 auto outputNodataParam = std::make_unique<QgsProcessingParameterNumber>( u"NODATA"_s, QObject::tr( "Output NoData value" ), Qgis::ProcessingNumberParameterType::Double, -9999.0 );
107 outputNodataParam->setHelp( QObject::tr( "The NODATA value to use in the output raster." ) );
108 outputNodataParam->setFlags( outputNodataParam->flags() | Qgis::ProcessingParameterFlag::Advanced );
109 addParameter( outputNodataParam.release() );
110
111 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( u"CREATION_OPTIONS"_s, QObject::tr( "Creation options" ), QVariant(), false, true );
112 creationOptsParam->setHelp( QObject::tr( "The raster creation options for the output raster. These options control things like colorimetry, compression, etc." ) );
113 creationOptsParam->setMetadata( QVariantMap( { { u"widget_wrapper"_s, QVariantMap( { { u"widget_type"_s, u"rasteroptions"_s } } ) } } ) );
114 creationOptsParam->setFlags( creationOptsParam->flags() | Qgis::ProcessingParameterFlag::Advanced );
115 addParameter( creationOptsParam.release() );
116
117 auto outputParam = std::make_unique<QgsProcessingParameterRasterDestination>( u"OUTPUT"_s, QObject::tr( "Interpolated" ) );
118 addParameter( outputParam.release() );
119}
120
121QVariantMap QgsIdwInterpolationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
122{
123 QGS_MARK_ALGORITHM_SOURCE
124
125 const QString interpolationData = parameterAsString( parameters, u"INTERPOLATION_DATA"_s, context );
126
127 const double coefficient = parameterAsDouble( parameters, u"DISTANCE_COEFFICIENT"_s, context );
128 const QgsRectangle boundingBox = parameterAsExtent( parameters, u"EXTENT"_s, context );
129 const double pixelSize = parameterAsDouble( parameters, u"PIXEL_SIZE"_s, context );
130 const QString creationOptions = parameterAsString( parameters, u"CREATION_OPTIONS"_s, context ).trimmed();
131 const double outputNodata = parameterAsDouble( parameters, u"NODATA"_s, context );
132 const QString output = parameterAsOutputLayer( parameters, u"OUTPUT"_s, context );
133
134 int columns = parameterAsInt( parameters, u"COLUMNS"_s, context );
135 int rows = parameterAsInt( parameters, u"ROWS"_s, context );
136 if ( columns == 0 )
137 {
138 columns = std::max( static_cast<int>( std::ceil( boundingBox.width() / pixelSize ) ), 1 );
139 }
140 if ( rows == 0 )
141 {
142 rows = std::max( static_cast<int>( std::ceil( boundingBox.height() / pixelSize ) ), 1 );
143 }
144
145 if ( interpolationData.isEmpty() )
146 {
147 throw QgsProcessingException( QObject::tr( "At least one input layer must be specified." ) );
148 }
149
150 QList<QgsInterpolator::LayerData> layerDataList;
151 std::vector<std::unique_ptr<QgsFeatureSource>> sourceHolders;
152
153 const QStringList layerRows = interpolationData.split( "::|::"_L1, Qt::SkipEmptyParts );
154 for ( const QString &row : std::as_const( layerRows ) )
155 {
156 const QStringList tokens = row.split( "::~::"_L1 );
157 if ( tokens.size() < 4 )
158 {
159 continue;
160 }
161
163 std::unique_ptr<QgsProcessingFeatureSource> source( QgsProcessingUtils::variantToSource( tokens.at( 0 ), context ) );
164
165 if ( !source )
166 {
167 throw QgsProcessingException( QObject::tr( "Could not load source layer for input %1." ).arg( tokens.at( 0 ) ) );
168 }
169
170 data.source = source.get();
171 data.transformContext = context.transformContext();
172
173 data.valueSource = static_cast<Qgis::InterpolationValueSource>( tokens.at( 1 ).toInt() );
174
175 bool intOk = false;
176 data.interpolationAttribute = tokens.at( 2 ).toInt( &intOk );
177
179 {
180 if ( !intOk )
181 {
182 data.interpolationAttribute = source->fields().lookupField( tokens.at( 2 ) );
183 if ( data.interpolationAttribute < 0 )
184 {
185 throw QgsProcessingException( QObject::tr( "Field %1 does not exist in layer %2." ).arg( tokens.at( 2 ), source->sourceName() ) );
186 }
187 }
188 else if ( data.interpolationAttribute < 0 )
189 {
190 throw QgsProcessingException( QObject::tr( "Layer %1 is set to use a value attribute, but no attribute was set." ).arg( source->sourceName() ) );
191 }
192 else if ( data.interpolationAttribute >= source->fields().size() )
193 {
194 throw QgsProcessingException( QObject::tr( "Layer %1 is set to use an invalid attribute." ).arg( source->sourceName() ) );
195 }
196 }
197
198 data.sourceType = static_cast<Qgis::InterpolationSourceType>( tokens.at( 3 ).toInt() );
199
200 layerDataList.append( data );
201 sourceHolders.push_back( std::move( source ) );
202 }
203
204 QgsIDWInterpolator interpolator( layerDataList );
205 interpolator.setDistanceCoefficient( coefficient );
206
207 QgsGridFileWriter writer( &interpolator, output, boundingBox, columns, rows );
208 if ( !creationOptions.isEmpty() )
209 {
210 writer.setCreationOptions( creationOptions.split( '|' ) );
211 }
212 writer.setNoDataValue( outputNodata );
213
214 writer.writeFile( feedback );
215
216 QVariantMap outputs;
217 outputs.insert( u"OUTPUT"_s, output );
218 return outputs;
219}
InterpolationSourceType
Interpolation source types.
Definition qgis.h:6666
InterpolationValueSource
Source for interpolated values from features.
Definition qgis.h:6679
@ Attribute
Take value from feature's attribute.
Definition qgis.h:6680
@ Hidden
Parameter is hidden and should not be shown to users.
Definition qgis.h:3983
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
Definition qgis.h:3982
@ Double
Double/float values.
Definition qgis.h:4023
Handles interpolation to a grid and writes the results to a raster grid file.
Inverse distance weight interpolator.
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
static QgsProcessingFeatureSource * variantToSource(const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue=QVariant())
Converts a variant value to a new feature source.
A rectangle specified with double values.
A source together with the information about interpolation attribute / z-coordinate interpolation and...
QgsFeatureSource * source
Feature source.
Qgis::InterpolationSourceType sourceType
Source type.
QgsCoordinateTransformContext transformContext
Coordinate transform context.
int interpolationAttribute
Index of feature attribute to use for interpolation.
Qgis::InterpolationValueSource valueSource
Source for feature values to interpolate.