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