Skip to content

Commit

Permalink
[OGR provider] Make feature iterator work on GeometryCollection subla…
Browse files Browse the repository at this point in the history
…yers

When trying to reproduce http://hub.qgis.org/issues/10485, I noticed a regression.
Now attribute table no longer shows features with OGR GeometryCollection.

Fixes also issues where sublayer geometry type is too strict regarding 2D vs 2.5D
geometry types.

Fixes #15675

Conflicts:
	src/providers/ogr/qgsogrfeatureiterator.cpp
	tests/src/python/test_provider_ogr.py
  • Loading branch information
rouault committed Oct 7, 2016
1 parent 872d86e commit bc5ac29
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
11 changes: 8 additions & 3 deletions src/providers/ogr/qgsogrfeatureiterator.cpp
Expand Up @@ -418,8 +418,13 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
else
feature.setGeometry( nullptr );

if (( useIntersect && ( !feature.constGeometry() || !feature.constGeometry()->intersects( mRequest.filterRect() ) ) )
|| ( geometryTypeFilter && ( !feature.constGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.constGeometry()->wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) )
if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection &&
geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection )
{
// OK
}
else if (( useIntersect && ( !feature.constGeometry() || !feature.constGeometry()->intersects( mRequest.filterRect() ) ) )
|| ( geometryTypeFilter && ( !feature.constGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.constGeometry()->wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) )
{
OGR_F_Destroy( fet );
return false;
Expand Down Expand Up @@ -463,7 +468,7 @@ QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider* p )
mEncoding = p->mEncoding; // no copying - this is a borrowed pointer from Qt
mFields = p->mAttributeFields;
mDriverName = p->ogrDriverName;
mOgrGeometryTypeFilter = wkbFlatten( p->mOgrGeometryTypeFilter );
mOgrGeometryTypeFilter = QgsOgrProvider::ogrWkbSingleFlatten( p->mOgrGeometryTypeFilter );
QgsOgrConnPool::instance()->ref( mDataSource );
}

Expand Down
5 changes: 4 additions & 1 deletion src/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -2905,13 +2905,16 @@ void QgsOgrProvider::recalculateFeatureCount()
setRelevantFields( ogrLayer, true, QgsAttributeList() );
OGR_L_ResetReading( ogrLayer );
OGRFeatureH fet;
const OGRwkbGeometryType flattenGeomTypeFilter =
QgsOgrProvider::ogrWkbSingleFlatten( mOgrGeometryTypeFilter );
while (( fet = OGR_L_GetNextFeature( ogrLayer ) ) )
{
OGRGeometryH geom = OGR_F_GetGeometryRef( fet );
if ( geom )
{
OGRwkbGeometryType gType = OGR_G_GetGeometryType( geom );
if ( gType == mOgrGeometryTypeFilter ) mFeaturesCounted++;
gType = QgsOgrProvider::ogrWkbSingleFlatten( gType );
if ( gType == flattenGeomTypeFilter ) mFeaturesCounted++;
}
OGR_F_Destroy( fet );
}
Expand Down
19 changes: 19 additions & 0 deletions tests/src/python/test_provider_ogr.py
Expand Up @@ -171,5 +171,24 @@ def testGpxElevation(self):
self.assertEqual(f.constGeometry().geometry().pointN(1).z(), 2)
self.assertEqual(f.constGeometry().geometry().pointN(2).z(), 3)

def testGeometryCollection(self):
''' Test that we can at least retrieves attribute of features with geometry collection '''

datasource = os.path.join(self.basetestpath, 'testGeometryCollection.csv')
with open(datasource, 'wt') as f:
f.write('id,WKT\n')
f.write('1,POINT Z(2 49 0)\n')
f.write('2,GEOMETRYCOLLECTION Z (POINT Z (2 49 0))\n')

vl = QgsVectorLayer('{}|layerid=0|geometrytype=GeometryCollection'.format(datasource), 'test', 'ogr')
self.assertTrue(vl.isValid())
self.assertTrue(vl.featureCount(), 1)
values = [f['id'] for f in vl.getFeatures()]
self.assertEqual(values, ['2'])
del vl

os.unlink(datasource)
self.assertFalse(os.path.exists(datasource))

if __name__ == '__main__':
unittest.main()

0 comments on commit bc5ac29

Please sign in to comment.