QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsinterpolator.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsinterpolator.cpp
3 -------------------
4 begin : Marco 10, 2008
5 copyright : (C) 2008 by Marco Hugentobler
6 email : marco dot hugentobler at karto dot baug dot ethz dot ch
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
18#include "qgsinterpolator.h"
19#include "qgsfeatureiterator.h"
21#include "qgsvectorlayer.h"
22#include "qgsgeometry.h"
23#include "qgsfeedback.h"
24#include "qgsvariantutils.h"
25
26QgsInterpolator::QgsInterpolator( const QList<LayerData> &layerData )
27 : mLayerData( layerData )
28{
29
30}
31
33{
34 if ( mLayerData.empty() )
35 {
36 return Success;
37 }
38
39 //reserve initial memory for 100000 vertices
40 mCachedBaseData.clear();
41 mCachedBaseData.reserve( 100000 );
42
43 const QgsCoordinateReferenceSystem crs = !mLayerData.empty() ? mLayerData.at( 0 ).source->sourceCrs() : QgsCoordinateReferenceSystem();
44
45 double layerStep = !mLayerData.empty() ? 100.0 / mLayerData.count() : 1;
46 int layerCount = 0;
47 for ( const LayerData &layer : std::as_const( mLayerData ) )
48 {
49 if ( feedback && feedback->isCanceled() )
50 return Canceled;
51
52 QgsFeatureSource *source = layer.source;
53 if ( !source )
54 {
55 return InvalidSource;
56 }
57
58 QgsAttributeList attList;
59 switch ( layer.valueSource )
60 {
61 case ValueAttribute:
62 attList.push_back( layer.interpolationAttribute );
63 break;
64
65 case ValueZ:
66 case ValueM:
67 break;
68 }
69
70 double attributeValue = 0.0;
71 bool attributeConversionOk = false;
72 double progress = layerCount * layerStep;
73
74 QgsFeatureIterator fit = source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ).setDestinationCrs( crs, layer.transformContext ) );
75 double featureStep = source->featureCount() > 0 ? layerStep / source->featureCount() : layerStep;
76
77 QgsFeature feature;
78 while ( fit.nextFeature( feature ) )
79 {
80 if ( feedback && feedback->isCanceled() )
81 return Canceled;
82
83 progress += featureStep;
84 if ( feedback )
85 feedback->setProgress( progress );
86
87 switch ( layer.valueSource )
88 {
89 case ValueAttribute:
90 {
91 QVariant attributeVariant = feature.attribute( layer.interpolationAttribute );
92 if ( QgsVariantUtils::isNull( attributeVariant ) ) //attribute not found, something must be wrong (e.g. NULL value)
93 {
94 continue;
95 }
96 attributeValue = attributeVariant.toDouble( &attributeConversionOk );
97 if ( !attributeConversionOk || std::isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
98 {
99 continue;
100 }
101 break;
102 }
103
104 case ValueZ:
105 case ValueM:
106 break;
107 }
108
109 if ( !addVerticesToCache( feature.geometry(), layer.valueSource, attributeValue ) )
111 }
112 layerCount++;
113 }
114
115 return Success;
116}
117
118bool QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, ValueSource source, double attributeValue )
119{
120 if ( geom.isNull() || geom.isEmpty() )
121 return true; // nothing to do
122
123 //validate source
124 switch ( source )
125 {
126 case ValueAttribute:
127 break;
128
129 case ValueM:
130 if ( !geom.constGet()->isMeasure() )
131 return false;
132 else
133 break;
134
135 case ValueZ:
136 if ( !geom.constGet()->is3D() )
137 return false;
138 else
139 break;
140 }
141
142 for ( auto point = geom.vertices_begin(); point != geom.vertices_end(); ++point )
143 {
144 switch ( source )
145 {
146 case ValueM:
147 mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).m() ) );
148 break;
149
150 case ValueZ:
151 mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).z() ) );
152 break;
153
154 case ValueAttribute:
155 mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), attributeValue ) );
156 break;
157 }
158 }
159 mDataIsCached = true;
160 return true;
161}
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
This class represents a coordinate reference system (CRS).
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
An interface for objects which provide features via a getFeatures method.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
virtual long long featureCount() const =0
Returns the number of features contained in the source, or -1 if the feature count is unknown.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:338
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Q_GADGET bool isNull
Definition: qgsgeometry.h:166
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
QVector< QgsInterpolatorVertexData > mCachedBaseData
Cached vertex data for input sources.
@ ValueM
Use feature's geometry M values for interpolation.
@ ValueAttribute
Take value from feature's attribute.
@ ValueZ
Use feature's geometry Z values for interpolation.
QgsInterpolator(const QList< QgsInterpolator::LayerData > &layerData)
Result
Result of an interpolation operation.
@ Canceled
Operation was manually canceled.
@ InvalidSource
Operation failed due to invalid source.
@ FeatureGeometryError
Operation failed due to invalid feature geometry.
@ Success
Operation was successful.
bool mDataIsCached
Flag that tells if the cache already has been filled.
QList< LayerData > mLayerData
Information about the input vector layers and the attributes (or z-values) that are used for interpol...
Result cacheBaseData(QgsFeedback *feedback=nullptr)
Caches the vertex and value data from the provider.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsCoordinateReferenceSystem & crs
Interpolation data for an individual source vertex.
A source together with the information about interpolation attribute / z-coordinate interpolation and...