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