Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Correctly handle tin wkb types when querying ogr sublayers
  • Loading branch information
nyalldawson committed Jul 12, 2021
1 parent 59f7b4c commit aba7f13
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 17 deletions.
15 changes: 1 addition & 14 deletions src/core/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -711,20 +711,7 @@ OGRwkbGeometryType QgsOgrProvider::getOgrGeomType( const QString &driverName, OG
if ( !nextFeature )
break;

OGRGeometryH geometry = OGR_F_GetGeometryRef( nextFeature.get() );
if ( geometry )
{
geomType = OGR_G_GetGeometryType( geometry );

// Shapefile MultiPatch can be reported as GeometryCollectionZ of TINZ
if ( wkbFlatten( geomType ) == wkbGeometryCollection &&
driverName == QLatin1String( "ESRI Shapefile" ) &&
OGR_G_GetGeometryCount( geometry ) >= 1 &&
wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geometry, 0 ) ) ) == wkbTIN )
{
geomType = wkbMultiPolygon25D;
}
}
geomType = QgsOgrProviderUtils::resolveGeometryTypeForFeature( nextFeature.get(), driverName );
if ( geomType != wkbNone )
break;
}
Expand Down
27 changes: 24 additions & 3 deletions src/core/providers/ogr/qgsogrproviderutils.cpp
Expand Up @@ -2025,6 +2025,28 @@ QString QgsOgrProviderUtils::ogrWkbGeometryTypeName( OGRwkbGeometryType type )
return geom;
}

OGRwkbGeometryType QgsOgrProviderUtils::resolveGeometryTypeForFeature( OGRFeatureH feature, const QString &driverName )
{
if ( OGRGeometryH geom = OGR_F_GetGeometryRef( feature ) )
{
OGRwkbGeometryType gType = OGR_G_GetGeometryType( geom );

// Shapefile MultiPatch can be reported as GeometryCollectionZ of TINZ
if ( wkbFlatten( gType ) == wkbGeometryCollection &&
driverName == QLatin1String( "ESRI Shapefile" ) &&
OGR_G_GetGeometryCount( geom ) >= 1 &&
wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
{
gType = wkbMultiPolygon25D;
}
return gType;
}
else
{
return wkbNone;
}
}

QString QgsOgrProviderUtils::expandAuthConfig( const QString &dsName )
{
QString uri( dsName );
Expand Down Expand Up @@ -2378,10 +2400,9 @@ QList< QgsProviderSublayerDetails > QgsOgrProviderUtils::querySubLayerList( int
gdal::ogr_feature_unique_ptr fet;
while ( fet.reset( layer->GetNextFeature() ), fet )
{
OGRGeometryH geom = OGR_F_GetGeometryRef( fet.get() );
if ( geom )
const OGRwkbGeometryType gType = QgsOgrProviderUtils::ogrWkbSingleFlatten( resolveGeometryTypeForFeature( fet.get(), driverName ) );
if ( gType != wkbNone )
{
OGRwkbGeometryType gType = QgsOgrProviderUtils::ogrWkbSingleFlatten( OGR_G_GetGeometryType( geom ) );
fCount[gType] = fCount.value( gType ) + 1;
}

Expand Down
3 changes: 3 additions & 0 deletions src/core/providers/ogr/qgsogrproviderutils.h
Expand Up @@ -241,6 +241,9 @@ class CORE_EXPORT QgsOgrProviderUtils

static QString ogrWkbGeometryTypeName( OGRwkbGeometryType type );

//! Resolves the geometry type for a feature, with special handling for some drivers
static OGRwkbGeometryType resolveGeometryTypeForFeature( OGRFeatureH feature, const QString &driverName );

static QString analyzeURI( QString const &uri,
bool &isSubLayer,
int &layerIndex,
Expand Down
24 changes: 24 additions & 0 deletions tests/src/python/test_provider_ogr.py
Expand Up @@ -1530,6 +1530,30 @@ def test_provider_sublayer_details(self):
self.assertEqual(res[0].wkbType(), QgsWkbTypes.LineString)
self.assertEqual(res[0].geometryColumnName(), '')

# geometry collection sublayers -- requires a scan to resolve geometry type
res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, 'multipatch.shp'))
self.assertEqual(len(res), 1)
self.assertEqual(res[0].layerNumber(), 0)
self.assertEqual(res[0].name(), "multipatch")
self.assertEqual(res[0].description(), '')
self.assertEqual(res[0].uri(), TEST_DATA_DIR + "/multipatch.shp")
self.assertEqual(res[0].providerKey(), "ogr")
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
self.assertEqual(res[0].wkbType(), QgsWkbTypes.Unknown)
self.assertEqual(res[0].geometryColumnName(), '')

# retry with retrieving geometry types
res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, 'multipatch.shp'), Qgis.SublayerQueryFlag.ResolveGeometryType)
self.assertEqual(len(res), 1)
self.assertEqual(res[0].layerNumber(), 0)
self.assertEqual(res[0].name(), "multipatch")
self.assertEqual(res[0].description(), '')
self.assertEqual(res[0].uri(), TEST_DATA_DIR + "/multipatch.shp")
self.assertEqual(res[0].providerKey(), "ogr")
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
self.assertEqual(res[0].wkbType(), QgsWkbTypes.Polygon)
self.assertEqual(res[0].geometryColumnName(), '')

# single layer geopackage -- sublayers MUST have the layerName set on the uri,
# in case more layers are added in future to the gpkg
res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, 'curved_polys.gpkg'))
Expand Down

0 comments on commit aba7f13

Please sign in to comment.