Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for 3D types in the PostGIS provider
  • Loading branch information
Hugo Mercier authored and jef-n committed Sep 15, 2013
1 parent 47e27d1 commit 9c8bc7d
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/providers/postgres/qgspostgresconn.cpp
Expand Up @@ -1242,7 +1242,7 @@ QString QgsPostgresConn::postgisTypeFilter( QString geomCol, QGis::WkbType geomT
case QGis::WKBPolygon25D:
case QGis::WKBMultiPolygon:
case QGis::WKBMultiPolygon25D:
return QString( "upper(geometrytype(%1)) IN ('POLYGON','MULTIPOLYGON','POLYGONM','MULTIPOLYGONM')" ).arg( geomCol );
return QString( "upper(geometrytype(%1)) IN ('POLYGON','MULTIPOLYGON','POLYGONM','MULTIPOLYGONM', 'POLYHEDRALSURFACE', 'TIN')" ).arg( geomCol );
case QGis::WKBNoGeometry:
return QString( "geometrytype(%1) IS NULL" ).arg( geomCol );
case QGis::WKBUnknown:
Expand Down
119 changes: 118 additions & 1 deletion src/providers/postgres/qgspostgresfeatureiterator.cpp
Expand Up @@ -362,7 +362,124 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
unsigned char *featureGeom = new unsigned char[returnedLength + 1];
memset( featureGeom, 0, returnedLength + 1 );
memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength );
feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 );

// 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;
}
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;
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;
}
memcpy( wkb + 1, &localType, sizeof( localType) );

// skip endian and type info
wkb += sizeof( unsigned int ) + 1;

// skip coordinates
switch ( wkbType )
{
case QGis::WKBMultiPoint25D:
wkb += sizeof( double ) * 3;
break;
case QGis::WKBMultiLineString25D:
{
unsigned int nPoints = *(( int* ) wkb );
wkb += sizeof( nPoints );
wkb += sizeof( double ) * 3 * nPoints;
}
break;
default:
case QGis::WKBMultiPolygon25D:
{
unsigned int nRings = *(( int* ) wkb );
wkb += sizeof( nRings );
for ( unsigned int j = 0; j < nRings; ++j )
{
unsigned int nPoints = *(( int* ) wkb );
wkb += sizeof( nPoints );
wkb += sizeof( double ) * 3 * nPoints;
}
}
break;
}
}
}

feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 );
}
else
{
Expand Down

0 comments on commit 9c8bc7d

Please sign in to comment.