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
  • Loading branch information
rouault committed Oct 7, 2016
1 parent 6d5e735 commit 319bb9d
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
12 changes: 9 additions & 3 deletions src/providers/ogr/qgsogrfeatureiterator.cpp
Expand Up @@ -313,8 +313,13 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
else else
feature.setGeometry( nullptr ); feature.setGeometry( nullptr );


if (( useIntersect && ( !feature.constGeometry() || !feature.constGeometry()->intersects( mRequest.filterRect() ) ) ) if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection &&
|| ( geometryTypeFilter && ( !feature.constGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.constGeometry()->wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) 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 ); OGR_F_Destroy( fet );
return false; return false;
Expand Down Expand Up @@ -361,7 +366,8 @@ QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider* p )
mFieldsWithoutFid.append( mFields.at( i ) ); mFieldsWithoutFid.append( mFields.at( i ) );
mDriverName = p->ogrDriverName; mDriverName = p->ogrDriverName;
mFirstFieldIsFid = p->mFirstFieldIsFid; mFirstFieldIsFid = p->mFirstFieldIsFid;
mOgrGeometryTypeFilter = wkbFlatten( p->mOgrGeometryTypeFilter ); mOgrGeometryTypeFilter = QgsOgrProvider::ogrWkbSingleFlatten( p->mOgrGeometryTypeFilter );
QgsDebugMsg( QString( "mOgrGeometryTypeFilter: %1" ).arg( mOgrGeometryTypeFilter ) );
QgsOgrConnPool::instance()->ref( mDataSource ); QgsOgrConnPool::instance()->ref( mDataSource );
} }


Expand Down
5 changes: 4 additions & 1 deletion src/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -3157,13 +3157,16 @@ void QgsOgrProvider::recalculateFeatureCount()
setRelevantFields( ogrLayer, true, QgsAttributeList() ); setRelevantFields( ogrLayer, true, QgsAttributeList() );
OGR_L_ResetReading( ogrLayer ); OGR_L_ResetReading( ogrLayer );
OGRFeatureH fet; OGRFeatureH fet;
const OGRwkbGeometryType flattenGeomTypeFilter =
QgsOgrProvider::ogrWkbSingleFlatten( mOgrGeometryTypeFilter );
while (( fet = OGR_L_GetNextFeature( ogrLayer ) ) ) while (( fet = OGR_L_GetNextFeature( ogrLayer ) ) )
{ {
OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); OGRGeometryH geom = OGR_F_GetGeometryRef( fet );
if ( geom ) if ( geom )
{ {
OGRwkbGeometryType gType = OGR_G_GetGeometryType( geom ); OGRwkbGeometryType gType = OGR_G_GetGeometryType( geom );
if ( gType == mOgrGeometryTypeFilter ) mFeaturesCounted++; gType = QgsOgrProvider::ogrWkbSingleFlatten( gType );
if ( gType == flattenGeomTypeFilter ) mFeaturesCounted++;
} }
OGR_F_Destroy( fet ); OGR_F_Destroy( fet );
} }
Expand Down
19 changes: 19 additions & 0 deletions tests/src/python/test_provider_ogr.py
Expand Up @@ -221,5 +221,24 @@ def testNoDanglingFileDescriptorAfterCloseVariant2(self):
os.unlink(datasource) os.unlink(datasource)
self.assertFalse(os.path.exists(datasource)) self.assertFalse(os.path.exists(datasource))


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__': if __name__ == '__main__':
unittest.main() unittest.main()

0 comments on commit 319bb9d

Please sign in to comment.