QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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  double layerStep = !mLayerData.empty() ? 100.0 / mLayerData.count() : 1;
43  int layerCount = 0;
44  for ( const LayerData &layer : qgis::as_const( mLayerData ) )
45  {
46  if ( feedback && feedback->isCanceled() )
47  return Canceled;
48 
49  QgsFeatureSource *source = layer.source;
50  if ( !source )
51  {
52  return InvalidSource;
53  }
54 
55  QgsAttributeList attList;
56  switch ( layer.valueSource )
57  {
58  case ValueAttribute:
59  attList.push_back( layer.interpolationAttribute );
60  break;
61 
62  case ValueZ:
63  case ValueM:
64  break;
65  }
66 
67  double attributeValue = 0.0;
68  bool attributeConversionOk = false;
69  double progress = layerCount * layerStep;
70 
71  QgsFeatureIterator fit = source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );
72  double featureStep = source->featureCount() > 0 ? layerStep / source->featureCount() : layerStep;
73 
74  QgsFeature feature;
75  while ( fit.nextFeature( feature ) )
76  {
77  if ( feedback && feedback->isCanceled() )
78  return Canceled;
79 
80  progress += featureStep;
81  if ( feedback )
82  feedback->setProgress( progress );
83 
84  switch ( layer.valueSource )
85  {
86  case ValueAttribute:
87  {
88  QVariant attributeVariant = feature.attribute( layer.interpolationAttribute );
89  if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
90  {
91  continue;
92  }
93  attributeValue = attributeVariant.toDouble( &attributeConversionOk );
94  if ( !attributeConversionOk || std::isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
95  {
96  continue;
97  }
98  break;
99  }
100 
101  case ValueZ:
102  case ValueM:
103  break;
104  }
105 
106  if ( !addVerticesToCache( feature.geometry(), layer.valueSource, attributeValue ) )
107  return FeatureGeometryError;
108  }
109  layerCount++;
110  }
111 
112  return Success;
113 }
114 
115 bool QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, ValueSource source, double attributeValue )
116 {
117  if ( geom.isNull() || geom.isEmpty() )
118  return true; // nothing to do
119 
120  //validate source
121  switch ( source )
122  {
123  case ValueAttribute:
124  break;
125 
126  case ValueM:
127  if ( !geom.constGet()->isMeasure() )
128  return false;
129  else
130  break;
131 
132  case ValueZ:
133  if ( !geom.constGet()->is3D() )
134  return false;
135  else
136  break;
137  }
138 
139  for ( auto point = geom.vertices_begin(); point != geom.vertices_end(); ++point )
140  {
141  switch ( source )
142  {
143  case ValueM:
144  mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).m() ) );
145  break;
146 
147  case ValueZ:
148  mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).z() ) );
149  break;
150 
151  case ValueAttribute:
152  mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), attributeValue ) );
153  break;
154  }
155  }
156  mDataIsCached = true;
157  return true;
158 }
Wrapper for iterator of features from vector data provider or vector layer.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
QList< LayerData > mLayerData
Information about the input vector layers and the attributes (or z-values) that are used for interpol...
Operation was successful.
QgsInterpolator(const QList< QgsInterpolator::LayerData > &layerData)
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry...
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
Operation failed due to invalid source.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
Operation was manually canceled.
Interpolation data for an individual source vertex.
Base class for feedback objects to be used for cancellation of something running in a worker thread...
Definition: qgsfeedback.h:44
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool isMeasure() const
Returns true if the geometry contains m values.
ValueSource
Source for interpolated values from features.
Take value from feature&#39;s attribute.
QVector< QgsInterpolatorVertexData > mCachedBaseData
Cached vertex data for input sources.
bool mDataIsCached
Flag that tells if the cache already has been filled.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Use feature&#39;s geometry Z values for interpolation.
Result
Result of an interpolation operation.
A source together with the information about interpolation attribute / z-coordinate interpolation and...
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
An interface for objects which provide features via a getFeatures method.
Use feature&#39;s geometry M values for interpolation.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
Operation failed due to invalid feature geometry.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
QgsGeometry geometry
Definition: qgsfeature.h:67
QList< int > QgsAttributeList
Definition: qgsfield.h:27
bool nextFeature(QgsFeature &f)
Result cacheBaseData(QgsFeedback *feedback=nullptr)
Caches the vertex and value data from the provider.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
virtual long featureCount() const =0
Returns the number of features contained in the source, or -1 if the feature count is unknown...