QGIS API Documentation  2.2.0-Valmiera
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
23 QgsInterpolator::QgsInterpolator( const QList<LayerData>& layerData ): mDataIsCached( false ), mLayerData( layerData )
24 {
25 
26 }
27 
29 {
30 
31 }
32 
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  QList<LayerData>::iterator v_it = mLayerData.begin();
50 
51  for ( ; v_it != mLayerData.end(); ++v_it )
52  {
53  if ( v_it->vectorLayer == 0 )
54  {
55  continue;
56  }
57 
58  QgsVectorLayer* vlayer = v_it->vectorLayer;
59  if ( !vlayer )
60  {
61  return 2;
62  }
63 
64  QgsAttributeList attList;
65  if ( !v_it->zCoordInterpolation )
66  {
67  attList.push_back( v_it->interpolationAttribute );
68  }
69 
70 
71  double attributeValue = 0.0;
72  bool attributeConversionOk = false;
73 
74  QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );
75 
76  QgsFeature theFeature;
77  while ( fit.nextFeature( theFeature ) )
78  {
79  if ( !v_it->zCoordInterpolation )
80  {
81  QVariant attributeVariant = theFeature.attribute( v_it->interpolationAttribute );
82  if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
83  {
84  continue;
85  }
86  attributeValue = attributeVariant.toDouble( &attributeConversionOk );
87  if ( !attributeConversionOk || qIsNaN( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
88  {
89  continue;
90  }
91  }
92 
93  if ( addVerticesToCache( theFeature.geometry(), v_it->zCoordInterpolation, attributeValue ) != 0 )
94  {
95  return 3;
96  }
97  }
98  }
99 
100  return 0;
101 }
102 
103 int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double attributeValue )
104 {
105  if ( !geom )
106  return 1;
107 
108  bool hasZValue = false;
109  QgsConstWkbPtr currentWkbPtr( geom->asWkb() + 1 + sizeof( int ) );
110  vertexData theVertex; //the current vertex
111 
112  QGis::WkbType wkbType = geom->wkbType();
113  switch ( wkbType )
114  {
115  case QGis::WKBPoint25D:
116  hasZValue = true;
117  case QGis::WKBPoint:
118  {
119  currentWkbPtr >> theVertex.x >> theVertex.y;
120  if ( zCoord && hasZValue )
121  {
122  currentWkbPtr >> theVertex.z;
123  }
124  else
125  {
126  theVertex.z = attributeValue;
127  }
128  mCachedBaseData.push_back( theVertex );
129  break;
130  }
132  hasZValue = true;
133  case QGis::WKBLineString:
134  {
135  int nPoints;
136  currentWkbPtr >> nPoints;
137  for ( int index = 0; index < nPoints; ++index )
138  {
139  currentWkbPtr >> theVertex.x >> theVertex.y;
140  if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
141  {
142  currentWkbPtr >> theVertex.z;
143  }
144  else
145  {
146  theVertex.z = attributeValue;
147  }
148  mCachedBaseData.push_back( theVertex );
149  }
150  break;
151  }
152 #if 0
153  case QGis::WKBPolygon25D:
154  hasZValue = true;
155  case QGis::WKBPolygon:
156  {
157  int nRings;
158  wkbPtr >> nRings;
159  for ( int index = 0; index < nRings; ++index )
160  {
161  int nPoints;
162  wkbPtr >> nPoints;
163  for ( int index2 = 0; index2 < *npoints; ++index2 )
164  {
165  double x, y;
166  wkbPtr >> x >> y;
167  if ( point.sqrDist( x, y ) < actdist )
168  {
169  actdist = point.sqrDist( x, y );
170  vertexnr = vertexcounter;
171  //assign the rubber band indices
172  if ( index2 == 0 )
173  {
174  beforeVertex = vertexcounter + ( *npoints - 2 );
175  afterVertex = vertexcounter + 1;
176  }
177  else if ( index2 == ( *npoints - 1 ) )
178  {
179  beforeVertex = vertexcounter - 1;
180  afterVertex = vertexcounter - ( *npoints - 2 );
181  }
182  else
183  {
184  beforeVertex = vertexcounter - 1;
185  afterVertex = vertexcounter + 1;
186  }
187  }
188  if ( hasZValue ) //skip z-coordinate for 25D geometries
189  {
190  wkbPtr += sizeof( double );
191  }
192  ++vertexcounter;
193  }
194  }
195  break;
196  }
198  hasZValue = true;
199  case QGis::WKBMultiPoint:
200  {
201  int nPoints;
202  wkbPtr >> nPoints;
203  for ( int index = 0; index < nPoints; ++index )
204  {
205  wkbPtr += 1 + sizeof( int ); //skip endian and point type
206 
207  double x, y;
208  wkbPtr >> x >> y;
209  if ( point.sqrDist( x, y ) < actdist )
210  {
211  actdist = point.sqrDist( x, y );
212  vertexnr = index;
213  }
214  if ( hasZValue ) //skip z-coordinate for 25D geometries
215  {
216  wkbPtr += sizeof( double );
217  }
218  }
219  break;
220  }
222  hasZValue = true;
224  {
225  int nLines;
226  wkbPtr >> nLines;
227  for ( int index = 0; index < nLines; ++index )
228  {
229  int nPoints;
230  wkbPtr >> nPoints;
231  for ( int index2 = 0; index2 < nPoints; ++index2 )
232  {
233  double x, y;
234  wkbPtr >> x >> y;
235  if ( point.sqrDist( x, y ) < actdist )
236  {
237  actdist = point.sqrDist( x, y );
238  vertexnr = vertexcounter;
239 
240  if ( index2 == 0 )//assign the rubber band indices
241  {
242  beforeVertex = -1;
243  }
244  else
245  {
246  beforeVertex = vertexnr - 1;
247  }
248  if ( index2 == nPoints - 1 )
249  {
250  afterVertex = -1;
251  }
252  else
253  {
254  afterVertex = vertexnr + 1;
255  }
256  }
257  if ( hasZValue ) //skip z-coordinate for 25D geometries
258  {
259  wkbPtr += sizeof( double );
260  }
261  ++vertexcounter;
262  }
263  }
264  break;
265  }
267  hasZValue = true;
269  {
270  int nPolys;
271  wkbPtr >> nPolys;
272  for ( int index = 0; index < nPolys; ++index )
273  {
274  wkbPtr += 1 + sizeof( int ); //skip endian and polygon type
275  int nRings;
276  wkbPtr >> nRings;
277  for ( int index2 = 0; index2 < nRings; ++index2 )
278  {
279  int nPoints;
280  wkbPtr >> nPoints;
281  for ( int index3 = 0; index3 < nPoints; ++index3 )
282  {
283  double x, y;
284  wkbPtr >> x >> y;
285  if ( point.sqrDist( x, y ) < actdist )
286  {
287  actdist = point.sqrDist( x, y );
288  vertexnr = vertexcounter;
289 
290  //assign the rubber band indices
291  if ( index3 == 0 )
292  {
293  beforeVertex = vertexcounter + ( nPoints - 2 );
294  afterVertex = vertexcounter + 1;
295  }
296  else if ( index3 == ( *npoints - 1 ) )
297  {
298  beforeVertex = vertexcounter - 1;
299  afterVertex = vertexcounter - ( nPoints - 2 );
300  }
301  else
302  {
303  beforeVertex = vertexcounter - 1;
304  afterVertex = vertexcounter + 1;
305  }
306  }
307  if ( hasZValue ) //skip z-coordinate for 25D geometries
308  {
309  wkbPtr += sizeof( double );
310  }
311  ++vertexcounter;
312  }
313  }
314  }
315  break;
316  }
317 #endif //0
318  default:
319  break;
320  }
321  mDataIsCached = true;
322  return 0;
323 }