Skip to content

Commit

Permalink
postgres provider: convert M to Z geometries (fixes #9032)
Browse files Browse the repository at this point in the history
  • Loading branch information
jef-n committed Feb 11, 2014
1 parent c9a88c1 commit 85f6fb8
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 75 deletions.
24 changes: 24 additions & 0 deletions src/providers/postgres/qgspostgresconn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,30 @@ QGis::WkbType QgsPostgresConn::wkbTypeFromPostgis( QString type )
}
}

QGis::WkbType QgsPostgresConn::wkbTypeFromOgcWkbType( unsigned int wkbType )
{
// polyhedralsurface / TIN / triangle => Polygon
if ( wkbType % 100 >= 15 )
wkbType = wkbType / 1000 * 1000 + QGis::WKBPolygon;

switch ( wkbType / 1000 )
{
case 0:
break;
case 1: // Z
wkbType = 0x80000000 + wkbType % 100;
break;
case 2: // M => Z
wkbType = 0x80000000 + wkbType % 100;
break;
case 3: // ZM
wkbType = 0xc0000000 + wkbType % 100;
break;
}

return ( QGis::WkbType ) wkbType;
}

QString QgsPostgresConn::displayStringForWkbType( QGis::WkbType type )
{
switch ( type )
Expand Down
1 change: 1 addition & 0 deletions src/providers/postgres/qgspostgresconn.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ class QgsPostgresConn : public QObject
static QString postgisTypeFilter( QString geomCol, QGis::WkbType wkbType, bool isGeography );

static QGis::WkbType wkbTypeFromGeomType( QGis::GeometryType geomType );
static QGis::WkbType wkbTypeFromOgcWkbType( unsigned int ogcWkbType );

static QStringList connectionList();
static QString selectedConnection();
Expand Down
89 changes: 14 additions & 75 deletions src/providers/postgres/qgspostgresfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,84 +410,22 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
// modify 2.5D WKB types to make them compliant with OGR
unsigned int wkbType;
memcpy( &wkbType, featureGeom + 1, sizeof( wkbType ) );

// convert unsupported types to supported ones
switch ( wkbType )
{
case 15:
// 2D polyhedral => multipolygon
wkbType = 6;
break;
case 1015:
// 3D polyhedral => multipolygon
wkbType = 1006;
break;
case 17:
// 2D triangle => polygon
wkbType = 3;
break;
case 1017:
// 3D triangle => polygon
wkbType = 1003;
break;
case 16:
// 2D TIN => multipolygon
wkbType = 6;
break;
case 1016:
// TIN => multipolygon
wkbType = 1006;
break;
}
// convert from postgis types to qgis types
if ( wkbType >= 1000 )
{
wkbType = wkbType - 1000 + QGis::WKBPoint25D - 1;
}
wkbType = QgsPostgresConn::wkbTypeFromOgcWkbType( wkbType );
memcpy( featureGeom + 1, &wkbType, sizeof( wkbType ) );

// change wkb type of inner geometries
if ( wkbType == QGis::WKBMultiPoint25D ||
wkbType == QGis::WKBMultiLineString25D ||
wkbType == QGis::WKBMultiPolygon25D )
{
unsigned int numGeoms = *(( int* )( featureGeom + 5 ) );
unsigned char* wkb = featureGeom + 9;
unsigned int numGeoms;
memcpy( &numGeoms, featureGeom + 5, sizeof( unsigned int ) );
unsigned char *wkb = featureGeom + 9;
for ( unsigned int i = 0; i < numGeoms; ++i )
{
unsigned int localType;
memcpy( &localType, wkb + 1, sizeof( localType ) );
switch ( localType )
{
case 15:
// 2D polyhedral => multipolygon
localType = 6;
break;
case 1015:
// 3D polyhedral => multipolygon
localType = 1006;
break;
case 17:
// 2D triangle => polygon
localType = 3;
break;
case 1017:
// 3D triangle => polygon
localType = 1003;
break;
case 16:
// 2D TIN => multipolygon
localType = 6;
break;
case 1016:
// TIN => multipolygon
localType = 1006;
break;
}
if ( localType >= 1000 )
{
localType = localType - 1000 + QGis::WKBPoint25D - 1;
}
localType = QgsPostgresConn::wkbTypeFromOgcWkbType( localType );
memcpy( wkb + 1, &localType, sizeof( localType ) );

// skip endian and type info
Expand All @@ -501,21 +439,22 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
break;
case QGis::WKBMultiLineString25D:
{
unsigned int nPoints = *(( int* ) wkb );
wkb += sizeof( nPoints );
wkb += sizeof( double ) * 3 * nPoints;
unsigned int nPoints;
memcpy( &nPoints, wkb, sizeof( int ) );
wkb += sizeof( int ) + sizeof( double ) * 3 * nPoints;
}
break;
default:
case QGis::WKBMultiPolygon25D:
{
unsigned int nRings = *(( int* ) wkb );
wkb += sizeof( nRings );
unsigned int nRings;
memcpy( &nRings, wkb, sizeof( int ) );
wkb += sizeof( int );
for ( unsigned int j = 0; j < nRings; ++j )
{
unsigned int nPoints = *(( int* ) wkb );
wkb += sizeof( nPoints );
wkb += sizeof( double ) * 3 * nPoints;
unsigned int nPoints;
memcpy( &nPoints, wkb, sizeof( int ) );
wkb += sizeof( nPoints ) + sizeof( double ) * 3 * nPoints;
}
}
break;
Expand Down

0 comments on commit 85f6fb8

Please sign in to comment.