Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jef-n committed Jan 23, 2014
1 parent 37df792 commit 6bbd17c
Show file tree
Hide file tree
Showing 7 changed files with 1,744 additions and 2,805 deletions.
147 changes: 57 additions & 90 deletions src/analysis/interpolation/qgsinterpolator.cpp
Expand Up @@ -103,12 +103,10 @@ int QgsInterpolator::cacheBaseData()
int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double attributeValue )
{
if ( !geom )
{
return 1;
}

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

QGis::WkbType wkbType = geom->wkbType();
Expand All @@ -118,14 +116,10 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
hasZValue = true;
case QGis::WKBPoint:
{
currentWkbPtr += ( 1 + sizeof( int ) );
theVertex.x = *(( double * )( currentWkbPtr ) );
currentWkbPtr += sizeof( double );
theVertex.y = *(( double * )( currentWkbPtr ) );
currentWkbPtr >> theVertex.x >> theVertex.y;
if ( zCoord && hasZValue )
{
currentWkbPtr += sizeof( double );
theVertex.z = *(( double * )( currentWkbPtr ) );
currentWkbPtr >> theVertex.z;
}
else
{
Expand All @@ -138,19 +132,14 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
hasZValue = true;
case QGis::WKBLineString:
{
currentWkbPtr += ( 1 + sizeof( int ) );
int* npoints = ( int* )currentWkbPtr;
currentWkbPtr += sizeof( int );
for ( int index = 0; index < *npoints; ++index )
int nPoints;
currentWkbPtr >> nPoints;
for ( int index = 0; index < nPoints; ++index )
{
theVertex.x = *(( double * )( currentWkbPtr ) );
currentWkbPtr += sizeof( double );
theVertex.y = *(( double * )( currentWkbPtr ) );
currentWkbPtr += sizeof( double );
currentWkbPtr >> theVertex.x >> theVertex.y;
if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
{
theVertex.z = *(( double * )( currentWkbPtr ) );
currentWkbPtr += sizeof( double );
currentWkbPtr >> theVertex.z;
}
else
{
Expand All @@ -165,23 +154,19 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
hasZValue = true;
case QGis::WKBPolygon:
{
int* nrings = ( int* )( mGeometry + 5 );
int* npoints;
unsigned char* ptr = mGeometry + 9;
for ( int index = 0; index < *nrings; ++index )
int nRings;
wkbPtr >> nRings;
for ( int index = 0; index < nRings; ++index )
{
npoints = ( int* )ptr;
ptr += sizeof( int );
int nPoints;
wkbPtr >> nPoints;
for ( int index2 = 0; index2 < *npoints; ++index2 )
{
tempx = ( double* )ptr;
ptr += sizeof( double );
tempy = ( double* )ptr;
if ( point.sqrDist( *tempx, *tempy ) < actdist )
double x, y;
wkbPtr >> x >> y;
if ( point.sqrDist( x, y ) < actdist )
{
x = *tempx;
y = *tempy;
actdist = point.sqrDist( *tempx, *tempy );
actdist = point.sqrDist( x, y );
vertexnr = vertexcounter;
//assign the rubber band indices
if ( index2 == 0 )
Expand All @@ -200,10 +185,9 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
afterVertex = vertexcounter + 1;
}
}
ptr += sizeof( double );
if ( hasZValue ) //skip z-coordinate for 25D geometries
{
ptr += sizeof( double );
wkbPtr += sizeof( double );
}
++vertexcounter;
}
Expand All @@ -214,25 +198,22 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
hasZValue = true;
case QGis::WKBMultiPoint:
{
unsigned char* ptr = mGeometry + 5;
int* npoints = ( int* )ptr;
ptr += sizeof( int );
for ( int index = 0; index < *npoints; ++index )
int nPoints;
wkbPtr >> nPoints;
for ( int index = 0; index < nPoints; ++index )
{
ptr += ( 1 + sizeof( int ) ); //skip endian and point type
tempx = ( double* )ptr;
tempy = ( double* )( ptr + sizeof( double ) );
if ( point.sqrDist( *tempx, *tempy ) < actdist )
wkbPtr += 1 + sizeof( int ); //skip endian and point type

double x, y;
wkbPtr >> x >> y;
if ( point.sqrDist( x, y ) < actdist )
{
x = *tempx;
y = *tempy;
actdist = point.sqrDist( *tempx, *tempy );
actdist = point.sqrDist( x, y );
vertexnr = index;
}
ptr += ( 2 * sizeof( double ) );
if ( hasZValue ) //skip z-coordinate for 25D geometries
{
ptr += sizeof( double );
wkbPtr += sizeof( double );
}
}
break;
Expand All @@ -241,26 +222,19 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
hasZValue = true;
case QGis::WKBMultiLineString:
{
unsigned char* ptr = mGeometry + 5;
int* nlines = ( int* )ptr;
int* npoints = 0;
ptr += sizeof( int );
for ( int index = 0; index < *nlines; ++index )
int nLines;
wkbPtr >> nLines;
for ( int index = 0; index < nLines; ++index )
{
ptr += ( sizeof( int ) + 1 );
npoints = ( int* )ptr;
ptr += sizeof( int );
for ( int index2 = 0; index2 < *npoints; ++index2 )
int nPoints;
wkbPtr >> nPoints;
for ( int index2 = 0; index2 < nPoints; ++index2 )
{
tempx = ( double* )ptr;
ptr += sizeof( double );
tempy = ( double* )ptr;
ptr += sizeof( double );
if ( point.sqrDist( *tempx, *tempy ) < actdist )
double x, y;
wkbPtr >> x >> y;
if ( point.sqrDist( x, y ) < actdist )
{
x = *tempx;
y = *tempy;
actdist = point.sqrDist( *tempx, *tempy );
actdist = point.sqrDist( x, y );
vertexnr = vertexcounter;

if ( index2 == 0 )//assign the rubber band indices
Expand All @@ -271,7 +245,7 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
{
beforeVertex = vertexnr - 1;
}
if ( index2 == ( *npoints ) - 1 )
if ( index2 == nPoints - 1 )
{
afterVertex = -1;
}
Expand All @@ -282,7 +256,7 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
}
if ( hasZValue ) //skip z-coordinate for 25D geometries
{
ptr += sizeof( double );
wkbPtr += sizeof( double );
}
++vertexcounter;
}
Expand All @@ -293,53 +267,46 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double
hasZValue = true;
case QGis::WKBMultiPolygon:
{
unsigned char* ptr = mGeometry + 5;
int* npolys = ( int* )ptr;
int* nrings;
int* npoints;
ptr += sizeof( int );
for ( int index = 0; index < *npolys; ++index )
int nPolys;
wkbPtr >> nPolys;
for ( int index = 0; index < nPolys; ++index )
{
ptr += ( 1 + sizeof( int ) ); //skip endian and polygon type
nrings = ( int* )ptr;
ptr += sizeof( int );
for ( int index2 = 0; index2 < *nrings; ++index2 )
wkbPtr += 1 + sizeof( int ); //skip endian and polygon type
int nRings;
wkbPtr >> nRings;
for ( int index2 = 0; index2 < nRings; ++index2 )
{
npoints = ( int* )ptr;
ptr += sizeof( int );
for ( int index3 = 0; index3 < *npoints; ++index3 )
int nPoints;
wkbPtr >> nPoints;
for ( int index3 = 0; index3 < nPoints; ++index3 )
{
tempx = ( double* )ptr;
ptr += sizeof( double );
tempy = ( double* )ptr;
if ( point.sqrDist( *tempx, *tempy ) < actdist )
double x, y;
wkbPtr >> x >> y;
if ( point.sqrDist( x, y ) < actdist )
{
x = *tempx;
y = *tempy;
actdist = point.sqrDist( *tempx, *tempy );
actdist = point.sqrDist( x, y );
vertexnr = vertexcounter;

//assign the rubber band indices
if ( index3 == 0 )
{
beforeVertex = vertexcounter + ( *npoints - 2 );
beforeVertex = vertexcounter + ( nPoints - 2 );
afterVertex = vertexcounter + 1;
}
else if ( index3 == ( *npoints - 1 ) )
{
beforeVertex = vertexcounter - 1;
afterVertex = vertexcounter - ( *npoints - 2 );
afterVertex = vertexcounter - ( nPoints - 2 );
}
else
{
beforeVertex = vertexcounter - 1;
afterVertex = vertexcounter + 1;
}
}
ptr += sizeof( double );
if ( hasZValue ) //skip z-coordinate for 25D geometries
{
ptr += sizeof( double );
wkbPtr += sizeof( double );
}
++vertexcounter;
}
Expand Down

0 comments on commit 6bbd17c

Please sign in to comment.