QGIS API Documentation  2.99.0-Master (6a61179)
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 "qgswkbptr.h"
24 
25 QgsInterpolator::QgsInterpolator( const QList<LayerData>& layerData )
26  : mDataIsCached( false )
27  , mLayerData( layerData )
28 {
29 
30 }
31 
33  : mDataIsCached( false )
34 {
35 
36 }
37 
39 {
40 
41 }
42 
44 {
45  if ( mLayerData.size() < 1 )
46  {
47  return 0;
48  }
49 
50  //reserve initial memory for 100000 vertices
51  mCachedBaseData.clear();
52  mCachedBaseData.reserve( 100000 );
53 
54  Q_FOREACH ( const LayerData& layer, mLayerData )
55  {
56  if ( !layer.vectorLayer )
57  {
58  continue;
59  }
60 
61  QgsVectorLayer* vlayer = layer.vectorLayer;
62  if ( !vlayer )
63  {
64  return 2;
65  }
66 
67  QgsAttributeList attList;
68  if ( !layer.zCoordInterpolation )
69  {
70  attList.push_back( layer.interpolationAttribute );
71  }
72 
73 
74  double attributeValue = 0.0;
75  bool attributeConversionOk = false;
76 
77  QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );
78 
79  QgsFeature theFeature;
80  while ( fit.nextFeature( theFeature ) )
81  {
82  if ( !layer.zCoordInterpolation )
83  {
84  QVariant attributeVariant = theFeature.attribute( layer.interpolationAttribute );
85  if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
86  {
87  continue;
88  }
89  attributeValue = attributeVariant.toDouble( &attributeConversionOk );
90  if ( !attributeConversionOk || qIsNaN( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
91  {
92  continue;
93  }
94  }
95 
96  if ( addVerticesToCache( theFeature.geometry(), layer.zCoordInterpolation, attributeValue ) != 0 )
97  {
98  return 3;
99  }
100  }
101  }
102 
103  return 0;
104 }
105 
106 int QgsInterpolator::addVerticesToCache( const QgsGeometry& geom, bool zCoord, double attributeValue )
107 {
108  if ( geom.isEmpty() )
109  return 1;
110 
111  bool hasZValue = false;
112  QByteArray wkb( geom.exportToWkb() );
113  QgsConstWkbPtr currentWkbPtr( wkb );
114  currentWkbPtr.readHeader();
115  vertexData theVertex; //the current vertex
116 
117  QgsWkbTypes::Type wkbType = geom.wkbType();
118  switch ( wkbType )
119  {
121  hasZValue = true;
122  //intentional fall-through
123  FALLTHROUGH;
124  case QgsWkbTypes::Point:
125  {
126  currentWkbPtr >> theVertex.x >> theVertex.y;
127  if ( zCoord && hasZValue )
128  {
129  currentWkbPtr >> theVertex.z;
130  }
131  else
132  {
133  theVertex.z = attributeValue;
134  }
135  mCachedBaseData.push_back( theVertex );
136  break;
137  }
139  hasZValue = true;
140  //intentional fall-through
141  FALLTHROUGH;
143  {
144  int nPoints;
145  currentWkbPtr >> nPoints;
146  for ( int index = 0; index < nPoints; ++index )
147  {
148  currentWkbPtr >> theVertex.x >> theVertex.y;
149  if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
150  {
151  currentWkbPtr >> theVertex.z;
152  }
153  else
154  {
155  theVertex.z = attributeValue;
156  }
157  mCachedBaseData.push_back( theVertex );
158  }
159  break;
160  }
161 #if 0
163  hasZValue = true;
164  //intentional fall-through
166  {
167  int nRings;
168  wkbPtr >> nRings;
169  for ( int index = 0; index < nRings; ++index )
170  {
171  int nPoints;
172  wkbPtr >> nPoints;
173  for ( int index2 = 0; index2 < *npoints; ++index2 )
174  {
175  double x, y;
176  wkbPtr >> x >> y;
177  if ( point.sqrDist( x, y ) < actdist )
178  {
179  actdist = point.sqrDist( x, y );
180  vertexnr = vertexcounter;
181  //assign the rubber band indices
182  if ( index2 == 0 )
183  {
184  beforeVertex = vertexcounter + ( *npoints - 2 );
185  afterVertex = vertexcounter + 1;
186  }
187  else if ( index2 == ( *npoints - 1 ) )
188  {
189  beforeVertex = vertexcounter - 1;
190  afterVertex = vertexcounter - ( *npoints - 2 );
191  }
192  else
193  {
194  beforeVertex = vertexcounter - 1;
195  afterVertex = vertexcounter + 1;
196  }
197  }
198  if ( hasZValue ) //skip z-coordinate for 25D geometries
199  {
200  wkbPtr += sizeof( double );
201  }
202  ++vertexcounter;
203  }
204  }
205  break;
206  }
208  hasZValue = true;
209  //intentional fall-through
211  {
212  int nPoints;
213  wkbPtr >> nPoints;
214  for ( int index = 0; index < nPoints; ++index )
215  {
216  wkbPtr += 1 + sizeof( int ); //skip endian and point type
217 
218  double x, y;
219  wkbPtr >> x >> y;
220  if ( point.sqrDist( x, y ) < actdist )
221  {
222  actdist = point.sqrDist( x, y );
223  vertexnr = index;
224  }
225  if ( hasZValue ) //skip z-coordinate for 25D geometries
226  {
227  wkbPtr += sizeof( double );
228  }
229  }
230  break;
231  }
233  hasZValue = true;
234  //intentional fall-through
236  {
237  int nLines;
238  wkbPtr >> nLines;
239  for ( int index = 0; index < nLines; ++index )
240  {
241  int nPoints;
242  wkbPtr >> nPoints;
243  for ( int index2 = 0; index2 < nPoints; ++index2 )
244  {
245  double x, y;
246  wkbPtr >> x >> y;
247  if ( point.sqrDist( x, y ) < actdist )
248  {
249  actdist = point.sqrDist( x, y );
250  vertexnr = vertexcounter;
251 
252  if ( index2 == 0 )//assign the rubber band indices
253  {
254  beforeVertex = -1;
255  }
256  else
257  {
258  beforeVertex = vertexnr - 1;
259  }
260  if ( index2 == nPoints - 1 )
261  {
262  afterVertex = -1;
263  }
264  else
265  {
266  afterVertex = vertexnr + 1;
267  }
268  }
269  if ( hasZValue ) //skip z-coordinate for 25D geometries
270  {
271  wkbPtr += sizeof( double );
272  }
273  ++vertexcounter;
274  }
275  }
276  break;
277  }
279  hasZValue = true;
280  //intentional fall-through
282  {
283  int nPolys;
284  wkbPtr >> nPolys;
285  for ( int index = 0; index < nPolys; ++index )
286  {
287  wkbPtr += 1 + sizeof( int ); //skip endian and polygon type
288  int nRings;
289  wkbPtr >> nRings;
290  for ( int index2 = 0; index2 < nRings; ++index2 )
291  {
292  int nPoints;
293  wkbPtr >> nPoints;
294  for ( int index3 = 0; index3 < nPoints; ++index3 )
295  {
296  double x, y;
297  wkbPtr >> x >> y;
298  if ( point.sqrDist( x, y ) < actdist )
299  {
300  actdist = point.sqrDist( x, y );
301  vertexnr = vertexcounter;
302 
303  //assign the rubber band indices
304  if ( index3 == 0 )
305  {
306  beforeVertex = vertexcounter + ( nPoints - 2 );
307  afterVertex = vertexcounter + 1;
308  }
309  else if ( index3 == ( *npoints - 1 ) )
310  {
311  beforeVertex = vertexcounter - 1;
312  afterVertex = vertexcounter - ( nPoints - 2 );
313  }
314  else
315  {
316  beforeVertex = vertexcounter - 1;
317  afterVertex = vertexcounter + 1;
318  }
319  }
320  if ( hasZValue ) //skip z-coordinate for 25D geometries
321  {
322  wkbPtr += sizeof( double );
323  }
324  ++vertexcounter;
325  }
326  }
327  }
328  break;
329  }
330 #endif //0
331  default:
332  break;
333  }
334  mDataIsCached = true;
335  return 0;
336 }
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
QList< LayerData > mLayerData
QVector< vertexData > mCachedBaseData
QgsVectorLayer * vectorLayer
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:78
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:135
virtual ~QgsInterpolator()
#define FALLTHROUGH
Definition: qgis.h:375
QByteArray exportToWkb() const
Export the geometry to WKB.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const
Query the layer for features specified in request.
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)...
QList< int > QgsAttributeList
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:113
A layer together with the information about interpolation attribute / z-coordinate interpolation and ...
QgsInterpolator(const QList< LayerData > &layerData)
bool nextFeature(QgsFeature &f)
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:277
int cacheBaseData()
Caches the vertex and value data from the provider.