Skip to content

Commit 9c8bc7d

Browse files
Hugo Mercierjef-n
authored andcommitted
Add support for 3D types in the PostGIS provider
1 parent 47e27d1 commit 9c8bc7d

File tree

2 files changed

+119
-2
lines changed

2 files changed

+119
-2
lines changed

src/providers/postgres/qgspostgresconn.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ QString QgsPostgresConn::postgisTypeFilter( QString geomCol, QGis::WkbType geomT
12421242
case QGis::WKBPolygon25D:
12431243
case QGis::WKBMultiPolygon:
12441244
case QGis::WKBMultiPolygon25D:
1245-
return QString( "upper(geometrytype(%1)) IN ('POLYGON','MULTIPOLYGON','POLYGONM','MULTIPOLYGONM')" ).arg( geomCol );
1245+
return QString( "upper(geometrytype(%1)) IN ('POLYGON','MULTIPOLYGON','POLYGONM','MULTIPOLYGONM', 'POLYHEDRALSURFACE', 'TIN')" ).arg( geomCol );
12461246
case QGis::WKBNoGeometry:
12471247
return QString( "geometrytype(%1) IS NULL" ).arg( geomCol );
12481248
case QGis::WKBUnknown:

src/providers/postgres/qgspostgresfeatureiterator.cpp

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,124 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
362362
unsigned char *featureGeom = new unsigned char[returnedLength + 1];
363363
memset( featureGeom, 0, returnedLength + 1 );
364364
memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength );
365-
feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 );
365+
366+
// modify 2.5D WKB types to make them compliant with OGR
367+
unsigned int wkbType;
368+
memcpy( &wkbType, featureGeom + 1, sizeof( wkbType) );
369+
370+
// convert unsupported types to supported ones
371+
switch ( wkbType )
372+
{
373+
case 15:
374+
// 2D polyhedral => multipolygon
375+
wkbType = 6;
376+
break;
377+
case 1015:
378+
// 3D polyhedral => multipolygon
379+
wkbType = 1006;
380+
break;
381+
case 17:
382+
// 2D triangle => polygon
383+
wkbType = 3;
384+
break;
385+
case 1017:
386+
// 3D triangle => polygon
387+
wkbType = 1003;
388+
break;
389+
case 16:
390+
// 2D TIN => multipolygon
391+
wkbType = 6;
392+
break;
393+
case 1016:
394+
// TIN => multipolygon
395+
wkbType = 1006;
396+
break;
397+
}
398+
// convert from postgis types to qgis types
399+
if ( wkbType >= 1000 )
400+
{
401+
wkbType = wkbType - 1000 + QGis::WKBPoint25D - 1;
402+
}
403+
memcpy( featureGeom + 1, &wkbType, sizeof( wkbType) );
404+
405+
// change wkb type of inner geometries
406+
if ( wkbType == QGis::WKBMultiPoint25D ||
407+
wkbType == QGis::WKBMultiLineString25D ||
408+
wkbType == QGis::WKBMultiPolygon25D )
409+
{
410+
unsigned int numGeoms = *(( int* )( featureGeom + 5 ));
411+
unsigned char* wkb = featureGeom + 9;
412+
for ( unsigned int i = 0; i < numGeoms; ++i )
413+
{
414+
unsigned int localType;
415+
memcpy( &localType, wkb + 1, sizeof( localType) );
416+
switch ( localType )
417+
{
418+
case 15:
419+
// 2D polyhedral => multipolygon
420+
localType = 6;
421+
break;
422+
case 1015:
423+
// 3D polyhedral => multipolygon
424+
localType = 1006;
425+
break;
426+
case 17:
427+
// 2D triangle => polygon
428+
localType = 3;
429+
break;
430+
case 1017:
431+
// 3D triangle => polygon
432+
localType = 1003;
433+
break;
434+
case 16:
435+
// 2D TIN => multipolygon
436+
localType = 6;
437+
break;
438+
case 1016:
439+
// TIN => multipolygon
440+
localType = 1006;
441+
break;
442+
}
443+
if ( localType >= 1000 )
444+
{
445+
localType = localType - 1000 + QGis::WKBPoint25D - 1;
446+
}
447+
memcpy( wkb + 1, &localType, sizeof( localType) );
448+
449+
// skip endian and type info
450+
wkb += sizeof( unsigned int ) + 1;
451+
452+
// skip coordinates
453+
switch ( wkbType )
454+
{
455+
case QGis::WKBMultiPoint25D:
456+
wkb += sizeof( double ) * 3;
457+
break;
458+
case QGis::WKBMultiLineString25D:
459+
{
460+
unsigned int nPoints = *(( int* ) wkb );
461+
wkb += sizeof( nPoints );
462+
wkb += sizeof( double ) * 3 * nPoints;
463+
}
464+
break;
465+
default:
466+
case QGis::WKBMultiPolygon25D:
467+
{
468+
unsigned int nRings = *(( int* ) wkb );
469+
wkb += sizeof( nRings );
470+
for ( unsigned int j = 0; j < nRings; ++j )
471+
{
472+
unsigned int nPoints = *(( int* ) wkb );
473+
wkb += sizeof( nPoints );
474+
wkb += sizeof( double ) * 3 * nPoints;
475+
}
476+
}
477+
break;
478+
}
479+
}
480+
}
481+
482+
feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 );
366483
}
367484
else
368485
{

0 commit comments

Comments
 (0)