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