QGIS API Documentation  2.0.1-Dufour
 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  {
107  return 1;
108  }
109 
110  bool hasZValue = false;
111  const unsigned char* currentWkbPtr = geom->asWkb();
112  vertexData theVertex; //the current vertex
113 
114  QGis::WkbType wkbType = geom->wkbType();
115  switch ( wkbType )
116  {
117  case QGis::WKBPoint25D:
118  hasZValue = true;
119  case QGis::WKBPoint:
120  {
121  currentWkbPtr += ( 1 + sizeof( int ) );
122  theVertex.x = *(( double * )( currentWkbPtr ) );
123  currentWkbPtr += sizeof( double );
124  theVertex.y = *(( double * )( currentWkbPtr ) );
125  if ( zCoord && hasZValue )
126  {
127  currentWkbPtr += sizeof( double );
128  theVertex.z = *(( double * )( currentWkbPtr ) );
129  }
130  else
131  {
132  theVertex.z = attributeValue;
133  }
134  mCachedBaseData.push_back( theVertex );
135  break;
136  }
138  hasZValue = true;
139  case QGis::WKBLineString:
140  {
141  currentWkbPtr += ( 1 + sizeof( int ) );
142  int* npoints = ( int* )currentWkbPtr;
143  currentWkbPtr += sizeof( int );
144  for ( int index = 0; index < *npoints; ++index )
145  {
146  theVertex.x = *(( double * )( currentWkbPtr ) );
147  currentWkbPtr += sizeof( double );
148  theVertex.y = *(( double * )( currentWkbPtr ) );
149  currentWkbPtr += sizeof( double );
150  if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
151  {
152  theVertex.z = *(( double * )( currentWkbPtr ) );
153  currentWkbPtr += sizeof( double );
154  }
155  else
156  {
157  theVertex.z = attributeValue;
158  }
159  mCachedBaseData.push_back( theVertex );
160  }
161  break;
162  }
163 #if 0
164  case QGis::WKBPolygon25D:
165  hasZValue = true;
166  case QGis::WKBPolygon:
167  {
168  int* nrings = ( int* )( mGeometry + 5 );
169  int* npoints;
170  unsigned char* ptr = mGeometry + 9;
171  for ( int index = 0; index < *nrings; ++index )
172  {
173  npoints = ( int* )ptr;
174  ptr += sizeof( int );
175  for ( int index2 = 0; index2 < *npoints; ++index2 )
176  {
177  tempx = ( double* )ptr;
178  ptr += sizeof( double );
179  tempy = ( double* )ptr;
180  if ( point.sqrDist( *tempx, *tempy ) < actdist )
181  {
182  x = *tempx;
183  y = *tempy;
184  actdist = point.sqrDist( *tempx, *tempy );
185  vertexnr = vertexcounter;
186  //assign the rubber band indices
187  if ( index2 == 0 )
188  {
189  beforeVertex = vertexcounter + ( *npoints - 2 );
190  afterVertex = vertexcounter + 1;
191  }
192  else if ( index2 == ( *npoints - 1 ) )
193  {
194  beforeVertex = vertexcounter - 1;
195  afterVertex = vertexcounter - ( *npoints - 2 );
196  }
197  else
198  {
199  beforeVertex = vertexcounter - 1;
200  afterVertex = vertexcounter + 1;
201  }
202  }
203  ptr += sizeof( double );
204  if ( hasZValue ) //skip z-coordinate for 25D geometries
205  {
206  ptr += sizeof( double );
207  }
208  ++vertexcounter;
209  }
210  }
211  break;
212  }
214  hasZValue = true;
215  case QGis::WKBMultiPoint:
216  {
217  unsigned char* ptr = mGeometry + 5;
218  int* npoints = ( int* )ptr;
219  ptr += sizeof( int );
220  for ( int index = 0; index < *npoints; ++index )
221  {
222  ptr += ( 1 + sizeof( int ) ); //skip endian and point type
223  tempx = ( double* )ptr;
224  tempy = ( double* )( ptr + sizeof( double ) );
225  if ( point.sqrDist( *tempx, *tempy ) < actdist )
226  {
227  x = *tempx;
228  y = *tempy;
229  actdist = point.sqrDist( *tempx, *tempy );
230  vertexnr = index;
231  }
232  ptr += ( 2 * sizeof( double ) );
233  if ( hasZValue ) //skip z-coordinate for 25D geometries
234  {
235  ptr += sizeof( double );
236  }
237  }
238  break;
239  }
241  hasZValue = true;
243  {
244  unsigned char* ptr = mGeometry + 5;
245  int* nlines = ( int* )ptr;
246  int* npoints = 0;
247  ptr += sizeof( int );
248  for ( int index = 0; index < *nlines; ++index )
249  {
250  ptr += ( sizeof( int ) + 1 );
251  npoints = ( int* )ptr;
252  ptr += sizeof( int );
253  for ( int index2 = 0; index2 < *npoints; ++index2 )
254  {
255  tempx = ( double* )ptr;
256  ptr += sizeof( double );
257  tempy = ( double* )ptr;
258  ptr += sizeof( double );
259  if ( point.sqrDist( *tempx, *tempy ) < actdist )
260  {
261  x = *tempx;
262  y = *tempy;
263  actdist = point.sqrDist( *tempx, *tempy );
264  vertexnr = vertexcounter;
265 
266  if ( index2 == 0 )//assign the rubber band indices
267  {
268  beforeVertex = -1;
269  }
270  else
271  {
272  beforeVertex = vertexnr - 1;
273  }
274  if ( index2 == ( *npoints ) - 1 )
275  {
276  afterVertex = -1;
277  }
278  else
279  {
280  afterVertex = vertexnr + 1;
281  }
282  }
283  if ( hasZValue ) //skip z-coordinate for 25D geometries
284  {
285  ptr += sizeof( double );
286  }
287  ++vertexcounter;
288  }
289  }
290  break;
291  }
293  hasZValue = true;
295  {
296  unsigned char* ptr = mGeometry + 5;
297  int* npolys = ( int* )ptr;
298  int* nrings;
299  int* npoints;
300  ptr += sizeof( int );
301  for ( int index = 0; index < *npolys; ++index )
302  {
303  ptr += ( 1 + sizeof( int ) ); //skip endian and polygon type
304  nrings = ( int* )ptr;
305  ptr += sizeof( int );
306  for ( int index2 = 0; index2 < *nrings; ++index2 )
307  {
308  npoints = ( int* )ptr;
309  ptr += sizeof( int );
310  for ( int index3 = 0; index3 < *npoints; ++index3 )
311  {
312  tempx = ( double* )ptr;
313  ptr += sizeof( double );
314  tempy = ( double* )ptr;
315  if ( point.sqrDist( *tempx, *tempy ) < actdist )
316  {
317  x = *tempx;
318  y = *tempy;
319  actdist = point.sqrDist( *tempx, *tempy );
320  vertexnr = vertexcounter;
321 
322  //assign the rubber band indices
323  if ( index3 == 0 )
324  {
325  beforeVertex = vertexcounter + ( *npoints - 2 );
326  afterVertex = vertexcounter + 1;
327  }
328  else if ( index3 == ( *npoints - 1 ) )
329  {
330  beforeVertex = vertexcounter - 1;
331  afterVertex = vertexcounter - ( *npoints - 2 );
332  }
333  else
334  {
335  beforeVertex = vertexcounter - 1;
336  afterVertex = vertexcounter + 1;
337  }
338  }
339  ptr += sizeof( double );
340  if ( hasZValue ) //skip z-coordinate for 25D geometries
341  {
342  ptr += sizeof( double );
343  }
344  ++vertexcounter;
345  }
346  }
347  }
348  break;
349  }
350 #endif //0
351  default:
352  break;
353  }
354  mDataIsCached = true;
355  return 0;
356 }