Skip to content

Commit

Permalink
Split tool: create new features all at once (fixes #40860)
Browse files Browse the repository at this point in the history
The cause of the slowness of split tool on layers with many features
(e.g. more than 100k) was due to lots of QgsVectorLayer::uniqueValues()
calls when creating features. If we create the new features all at once,
the returned unique values get calculated just once and cached,
which makes things much faster.

Results on testing datasets:
- ~130k polygons: before ~6s, after ~0.5s
- ~1M lines: before ~100+s, after ~3s

(cherry picked from commit 5454d22)
  • Loading branch information
wonder-sk authored and nyalldawson committed Jan 6, 2021
1 parent b75b875 commit d73fd7c
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/core/qgsvectorlayereditutils.cpp
Expand Up @@ -356,6 +356,8 @@ QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitFeatures( const QgsCu
features = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
}

QgsVectorLayerUtils::QgsFeaturesDataList featuresDataToAdd;

QgsFeature feat;
while ( features.nextFeature( feat ) )
{
Expand All @@ -377,8 +379,7 @@ QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitFeatures( const QgsCu
QgsAttributeMap attributeMap = feat.attributes().toMap();
for ( const QgsGeometry &geom : qgis::as_const( newGeometries ) )
{
QgsFeature f = QgsVectorLayerUtils::createFeature( mLayer, geom, attributeMap );
mLayer->addFeature( f );
featuresDataToAdd << QgsVectorLayerUtils::QgsFeatureData( geom, attributeMap );
}

if ( topologicalEditing )
Expand All @@ -397,6 +398,14 @@ QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitFeatures( const QgsCu
}
}

if ( !featuresDataToAdd.isEmpty() )
{
// finally create and add all bits of geometries cut off the original geometries
// (this is much faster than creating features one by one)
QgsFeatureList featuresListToAdd = QgsVectorLayerUtils::createFeatures( mLayer, featuresDataToAdd );
mLayer->addFeatures( featuresListToAdd );
}

if ( numberOfSplitFeatures == 0 )
{
returnCode = QgsGeometry::OperationResult::NothingHappened;
Expand Down

0 comments on commit d73fd7c

Please sign in to comment.