QGIS API Documentation  3.20.0-Odense (decaadbb31)
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"
20 #include "qgsvectordataprovider.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsgeometry.h"
23 #include "qgsfeedback.h"
24 
25 QgsInterpolator::QgsInterpolator( const QList<LayerData> &layerData )
26  : mLayerData( layerData )
27 {
28 
29 }
30 
32 {
33  if ( mLayerData.empty() )
34  {
35  return Success;
36  }
37 
38  //reserve initial memory for 100000 vertices
39  mCachedBaseData.clear();
40  mCachedBaseData.reserve( 100000 );
41 
42  const QgsCoordinateReferenceSystem crs = !mLayerData.empty() ? mLayerData.at( 0 ).source->sourceCrs() : QgsCoordinateReferenceSystem();
43 
44  double layerStep = !mLayerData.empty() ? 100.0 / mLayerData.count() : 1;
45  int layerCount = 0;
46  for ( const LayerData &layer : std::as_const( mLayerData ) )
47  {
48  if ( feedback && feedback->isCanceled() )
49  return Canceled;
50 
51  QgsFeatureSource *source = layer.source;
52  if ( !source )
53  {
54  return InvalidSource;
55  }
56 
57  QgsAttributeList attList;
58  switch ( layer.valueSource )
59  {
60  case ValueAttribute:
61  attList.push_back( layer.interpolationAttribute );
62  break;
63 
64  case ValueZ:
65  case ValueM:
66  break;
67  }
68 
69  double attributeValue = 0.0;
70  bool attributeConversionOk = false;
71  double progress = layerCount * layerStep;
72 
73  QgsFeatureIterator fit = source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ).setDestinationCrs( crs, layer.transformContext ) );
74  double featureStep = source->featureCount() > 0 ? layerStep / source->featureCount() : layerStep;
75 
76  QgsFeature feature;
77  while ( fit.nextFeature( feature ) )
78  {
79  if ( feedback && feedback->isCanceled() )
80  return Canceled;
81 
82  progress += featureStep;
83  if ( feedback )
84  feedback->setProgress( progress );
85 
86  switch ( layer.valueSource )
87  {
88  case ValueAttribute:
89  {
90  QVariant attributeVariant = feature.attribute( layer.interpolationAttribute );
91  if ( !attributeVariant.isValid() || attributeVariant.isNull() ) //attribute not found, something must be wrong (e.g. NULL value)
92  {
93  continue;
94  }
95  attributeValue = attributeVariant.toDouble( &attributeConversionOk );
96  if ( !attributeConversionOk || std::isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
97  {
98  continue;
99  }
100  break;
101  }
102 
103  case ValueZ:
104  case ValueM:
105  break;
106  }
107 
108  if ( !addVerticesToCache( feature.geometry(), layer.valueSource, attributeValue ) )
109  return FeatureGeometryError;
110  }
111  layerCount++;
112  }
113 
114  return Success;
115 }
116 
117 bool QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, ValueSource source, double attributeValue )
118 {
119  if ( geom.isNull() || geom.isEmpty() )
120  return true; // nothing to do
121 
122  //validate source
123  switch ( source )
124  {
125  case ValueAttribute:
126  break;
127 
128  case ValueM:
129  if ( !geom.constGet()->isMeasure() )
130  return false;
131  else
132  break;
133 
134  case ValueZ:
135  if ( !geom.constGet()->is3D() )
136  return false;
137  else
138  break;
139  }
140 
141  for ( auto point = geom.vertices_begin(); point != geom.vertices_end(); ++point )
142  {
143  switch ( source )
144  {
145  case ValueM:
146  mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).m() ) );
147  break;
148 
149  case ValueZ:
150  mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).z() ) );
151  break;
152 
153  case ValueAttribute:
154  mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), attributeValue ) );
155  break;
156  }
157  }
158  mDataIsCached = true;
159  return true;
160 }
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:302
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:124
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:126
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.
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...