Skip to content

Commit

Permalink
fix(qgsfeaturepool): cache management - fixes #58113
Browse files Browse the repository at this point in the history
Geometry checker does not work with memory layers, so we change
how the cache in the QgsFeaturePool object is managed, to refresh it
more often.
  • Loading branch information
Djedouas committed Jul 16, 2024
1 parent 3caa616 commit 5680f9a
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/analysis/vector/geometry_checker/qgsfeaturepool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ bool QgsFeaturePool::getFeature( QgsFeatureId id, QgsFeature &feature )
{
// Feature not in cache, retrieve from layer
// TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
mFeatureSource = std::make_unique<QgsVectorLayerFeatureSource>( mLayer );
if ( !mFeatureSource->getFeatures( QgsFeatureRequest( id ) ).nextFeature( feature ) )
{
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,14 @@ void QgsVectorLayerFeaturePool::onGeometryChanged( QgsFeatureId fid, const QgsGe
{
Q_UNUSED( geometry )

if ( isFeatureCached( fid ) )
{
QgsFeature feature;
getFeature( fid, feature );
refreshCache( feature );
}
// Always update the cache and the spatial index on geometry change.
// A feature that was not in the cache previously might now have to be.
// For instance a geometry that was not in a previously requested area was not cached,
// but if it is now in the area it will be correctly added

QgsFeature feature;
getFeature( fid, feature );
refreshCache( feature );
}

void QgsVectorLayerFeaturePool::onFeatureDeleted( QgsFeatureId fid )
Expand Down
20 changes: 6 additions & 14 deletions tests/src/geometry_checker/testqgsvectorlayerfeaturepool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,29 +140,21 @@ void TestQgsVectorLayerFeaturePool::changeGeometry()

// Update a feature to be outside the AOI
feat.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((100 100, 110 100, 110 110, 100 110, 100 100))" ) ) );
vl->updateFeature( feat );
vl->updateFeature( feat ); // updates the geometry and triggers refreshing the cache

// Still working on the cached data
// Now no feature inside the AOI
const QgsFeatureIds ids3 = pool.getIntersects( QgsRectangle( 0, 0, 10, 10 ) );
QCOMPARE( ids3.size(), 1 );

// Repopulate the cache
QCOMPARE( ids3.size(), 0 );
const QgsFeatureIds ids4 = pool.getFeatures( QgsFeatureRequest().setFilterRect( QgsRectangle( 0, 0, 10, 10 ) ) );
QCOMPARE( ids4.size(), 0 );

// Still working on the cached data
const QgsFeatureIds ids5 = pool.getIntersects( QgsRectangle( 0, 0, 10, 10 ) );
QCOMPARE( ids5.size(), 0 );

// Update a feature to be inside the AOI
feat.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) ) );
vl->updateFeature( feat );
vl->updateFeature( feat ); // updates the geometry and triggers refreshing the cache

// Still cached
// Now one feature inside the AOI again
const QgsFeatureIds ids6 = pool.getIntersects( QgsRectangle( 0, 0, 10, 10 ) );
QCOMPARE( ids6.size(), 0 );

// One in there again
QCOMPARE( ids6.size(), 1 );
const QgsFeatureIds ids7 = pool.getFeatures( QgsFeatureRequest().setFilterRect( QgsRectangle( 0, 0, 10, 10 ) ) );
QCOMPARE( ids7.size(), 1 );
}
Expand Down

0 comments on commit 5680f9a

Please sign in to comment.