Skip to content

Commit 6bbd17c

Browse files
committed
QgsGeometry refactoring:
* rework wkb parsing using Qgs(Const)WkbPtr * replaces pointer dereferencing with memcpy * should work on platform that don't allow unaligned accesses * "fix" adjacentVertices() for invalid inputs * improved support for MULTIPOINT * fixes insertion of first vertex into linestrings * fixes inserting into multipolygons
1 parent 37df792 commit 6bbd17c

File tree

7 files changed

+1744
-2805
lines changed

7 files changed

+1744
-2805
lines changed

src/analysis/interpolation/qgsinterpolator.cpp

+57-90
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,10 @@ int QgsInterpolator::cacheBaseData()
103103
int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double attributeValue )
104104
{
105105
if ( !geom )
106-
{
107106
return 1;
108-
}
109107

110108
bool hasZValue = false;
111-
const unsigned char* currentWkbPtr = geom->asWkb();
109+
QgsConstWkbPtr currentWkbPtr( geom->asWkb() + 1 + sizeof( int ) );
112110
vertexData theVertex; //the current vertex
113111

114112
QGis::WkbType wkbType = geom->wkbType();
@@ -118,14 +116,10 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
118116
hasZValue = true;
119117
case QGis::WKBPoint:
120118
{
121-
currentWkbPtr += ( 1 + sizeof( int ) );
122-
theVertex.x = *(( double * )( currentWkbPtr ) );
123-
currentWkbPtr += sizeof( double );
124-
theVertex.y = *(( double * )( currentWkbPtr ) );
119+
currentWkbPtr >> theVertex.x >> theVertex.y;
125120
if ( zCoord && hasZValue )
126121
{
127-
currentWkbPtr += sizeof( double );
128-
theVertex.z = *(( double * )( currentWkbPtr ) );
122+
currentWkbPtr >> theVertex.z;
129123
}
130124
else
131125
{
@@ -138,19 +132,14 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
138132
hasZValue = true;
139133
case QGis::WKBLineString:
140134
{
141-
currentWkbPtr += ( 1 + sizeof( int ) );
142-
int* npoints = ( int* )currentWkbPtr;
143-
currentWkbPtr += sizeof( int );
144-
for ( int index = 0; index < *npoints; ++index )
135+
int nPoints;
136+
currentWkbPtr >> nPoints;
137+
for ( int index = 0; index < nPoints; ++index )
145138
{
146-
theVertex.x = *(( double * )( currentWkbPtr ) );
147-
currentWkbPtr += sizeof( double );
148-
theVertex.y = *(( double * )( currentWkbPtr ) );
149-
currentWkbPtr += sizeof( double );
139+
currentWkbPtr >> theVertex.x >> theVertex.y;
150140
if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
151141
{
152-
theVertex.z = *(( double * )( currentWkbPtr ) );
153-
currentWkbPtr += sizeof( double );
142+
currentWkbPtr >> theVertex.z;
154143
}
155144
else
156145
{
@@ -165,23 +154,19 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
165154
hasZValue = true;
166155
case QGis::WKBPolygon:
167156
{
168-
int* nrings = ( int* )( mGeometry + 5 );
169-
int* npoints;
170-
unsigned char* ptr = mGeometry + 9;
171-
for ( int index = 0; index < *nrings; ++index )
157+
int nRings;
158+
wkbPtr >> nRings;
159+
for ( int index = 0; index < nRings; ++index )
172160
{
173-
npoints = ( int* )ptr;
174-
ptr += sizeof( int );
161+
int nPoints;
162+
wkbPtr >> nPoints;
175163
for ( int index2 = 0; index2 < *npoints; ++index2 )
176164
{
177-
tempx = ( double* )ptr;
178-
ptr += sizeof( double );
179-
tempy = ( double* )ptr;
180-
if ( point.sqrDist( *tempx, *tempy ) < actdist )
165+
double x, y;
166+
wkbPtr >> x >> y;
167+
if ( point.sqrDist( x, y ) < actdist )
181168
{
182-
x = *tempx;
183-
y = *tempy;
184-
actdist = point.sqrDist( *tempx, *tempy );
169+
actdist = point.sqrDist( x, y );
185170
vertexnr = vertexcounter;
186171
//assign the rubber band indices
187172
if ( index2 == 0 )
@@ -200,10 +185,9 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
200185
afterVertex = vertexcounter + 1;
201186
}
202187
}
203-
ptr += sizeof( double );
204188
if ( hasZValue ) //skip z-coordinate for 25D geometries
205189
{
206-
ptr += sizeof( double );
190+
wkbPtr += sizeof( double );
207191
}
208192
++vertexcounter;
209193
}
@@ -214,25 +198,22 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
214198
hasZValue = true;
215199
case QGis::WKBMultiPoint:
216200
{
217-
unsigned char* ptr = mGeometry + 5;
218-
int* npoints = ( int* )ptr;
219-
ptr += sizeof( int );
220-
for ( int index = 0; index < *npoints; ++index )
201+
int nPoints;
202+
wkbPtr >> nPoints;
203+
for ( int index = 0; index < nPoints; ++index )
221204
{
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 )
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 )
226210
{
227-
x = *tempx;
228-
y = *tempy;
229-
actdist = point.sqrDist( *tempx, *tempy );
211+
actdist = point.sqrDist( x, y );
230212
vertexnr = index;
231213
}
232-
ptr += ( 2 * sizeof( double ) );
233214
if ( hasZValue ) //skip z-coordinate for 25D geometries
234215
{
235-
ptr += sizeof( double );
216+
wkbPtr += sizeof( double );
236217
}
237218
}
238219
break;
@@ -241,26 +222,19 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
241222
hasZValue = true;
242223
case QGis::WKBMultiLineString:
243224
{
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 )
225+
int nLines;
226+
wkbPtr >> nLines;
227+
for ( int index = 0; index < nLines; ++index )
249228
{
250-
ptr += ( sizeof( int ) + 1 );
251-
npoints = ( int* )ptr;
252-
ptr += sizeof( int );
253-
for ( int index2 = 0; index2 < *npoints; ++index2 )
229+
int nPoints;
230+
wkbPtr >> nPoints;
231+
for ( int index2 = 0; index2 < nPoints; ++index2 )
254232
{
255-
tempx = ( double* )ptr;
256-
ptr += sizeof( double );
257-
tempy = ( double* )ptr;
258-
ptr += sizeof( double );
259-
if ( point.sqrDist( *tempx, *tempy ) < actdist )
233+
double x, y;
234+
wkbPtr >> x >> y;
235+
if ( point.sqrDist( x, y ) < actdist )
260236
{
261-
x = *tempx;
262-
y = *tempy;
263-
actdist = point.sqrDist( *tempx, *tempy );
237+
actdist = point.sqrDist( x, y );
264238
vertexnr = vertexcounter;
265239

266240
if ( index2 == 0 )//assign the rubber band indices
@@ -271,7 +245,7 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
271245
{
272246
beforeVertex = vertexnr - 1;
273247
}
274-
if ( index2 == ( *npoints ) - 1 )
248+
if ( index2 == nPoints - 1 )
275249
{
276250
afterVertex = -1;
277251
}
@@ -282,7 +256,7 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
282256
}
283257
if ( hasZValue ) //skip z-coordinate for 25D geometries
284258
{
285-
ptr += sizeof( double );
259+
wkbPtr += sizeof( double );
286260
}
287261
++vertexcounter;
288262
}
@@ -293,53 +267,46 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
293267
hasZValue = true;
294268
case QGis::WKBMultiPolygon:
295269
{
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 )
270+
int nPolys;
271+
wkbPtr >> nPolys;
272+
for ( int index = 0; index < nPolys; ++index )
302273
{
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 )
274+
wkbPtr += 1 + sizeof( int ); //skip endian and polygon type
275+
int nRings;
276+
wkbPtr >> nRings;
277+
for ( int index2 = 0; index2 < nRings; ++index2 )
307278
{
308-
npoints = ( int* )ptr;
309-
ptr += sizeof( int );
310-
for ( int index3 = 0; index3 < *npoints; ++index3 )
279+
int nPoints;
280+
wkbPtr >> nPoints;
281+
for ( int index3 = 0; index3 < nPoints; ++index3 )
311282
{
312-
tempx = ( double* )ptr;
313-
ptr += sizeof( double );
314-
tempy = ( double* )ptr;
315-
if ( point.sqrDist( *tempx, *tempy ) < actdist )
283+
double x, y;
284+
wkbPtr >> x >> y;
285+
if ( point.sqrDist( x, y ) < actdist )
316286
{
317-
x = *tempx;
318-
y = *tempy;
319-
actdist = point.sqrDist( *tempx, *tempy );
287+
actdist = point.sqrDist( x, y );
320288
vertexnr = vertexcounter;
321289

322290
//assign the rubber band indices
323291
if ( index3 == 0 )
324292
{
325-
beforeVertex = vertexcounter + ( *npoints - 2 );
293+
beforeVertex = vertexcounter + ( nPoints - 2 );
326294
afterVertex = vertexcounter + 1;
327295
}
328296
else if ( index3 == ( *npoints - 1 ) )
329297
{
330298
beforeVertex = vertexcounter - 1;
331-
afterVertex = vertexcounter - ( *npoints - 2 );
299+
afterVertex = vertexcounter - ( nPoints - 2 );
332300
}
333301
else
334302
{
335303
beforeVertex = vertexcounter - 1;
336304
afterVertex = vertexcounter + 1;
337305
}
338306
}
339-
ptr += sizeof( double );
340307
if ( hasZValue ) //skip z-coordinate for 25D geometries
341308
{
342-
ptr += sizeof( double );
309+
wkbPtr += sizeof( double );
343310
}
344311
++vertexcounter;
345312
}

0 commit comments

Comments
 (0)