Skip to content

Commit

Permalink
Make operations on the feature selection more memory friendly
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kuhn committed Sep 22, 2014
1 parent 30ada28 commit e613c8b
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 88 deletions.
5 changes: 4 additions & 1 deletion src/app/qgsmaptoolmovefeature.cpp
Expand Up @@ -120,7 +120,10 @@ void QgsMapToolMoveFeature::canvasPressEvent( QMouseEvent * e )
mMovedFeatures = vlayer->selectedFeaturesIds();

mRubberBand = createRubberBand( vlayer->geometryType() );
Q_FOREACH( const QgsFeature& feat, vlayer->selectedFeatures() )
QgsFeature feat;
QgsFeatureIterator it = vlayer->selectedFeaturesIterator( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );

while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( feat.geometry(), vlayer );
}
Expand Down
7 changes: 5 additions & 2 deletions src/app/qgsmaptoolrotatefeature.cpp
Expand Up @@ -163,9 +163,12 @@ void QgsMapToolRotateFeature::canvasPressEvent( QMouseEvent * e )
mRotatedFeatures = vlayer->selectedFeaturesIds();

mRubberBand = createRubberBand( vlayer->geometryType() );
for ( int i = 0; i < vlayer->selectedFeatureCount(); i++ )

QgsFeature feat;
QgsFeatureIterator it = vlayer->selectedFeaturesIterator();
while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( vlayer->selectedFeatures()[i].geometry(), vlayer );
mRubberBand->addGeometry( feat.geometry(), vlayer );
}
}

Expand Down
18 changes: 11 additions & 7 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -2301,13 +2301,7 @@ QgsFeatureList QgsVectorLayer::selectedFeatures()
{
QgsFeatureList features;

QgsFeatureRequest req;
if ( geometryType() == QGis::NoGeometry )
req.setFlags( QgsFeatureRequest::NoGeometry );

req.setFilterFids( mSelectedFeatureIds );

QgsFeatureIterator it = getFeatures( req );
QgsFeatureIterator it = selectedFeaturesIterator();

QgsFeature f;
while ( it.nextFeature( f ) )
Expand All @@ -2318,6 +2312,16 @@ QgsFeatureList QgsVectorLayer::selectedFeatures()
return features;
}

QgsFeatureIterator QgsVectorLayer::selectedFeaturesIterator( QgsFeatureRequest request )
{
if ( geometryType() == QGis::NoGeometry )
request.setFlags( QgsFeatureRequest::NoGeometry );

request.setFilterFids( mSelectedFeatureIds );

return getFeatures( request );
}

bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
{
if ( !mEditBuffer || !mDataProvider )
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -734,6 +734,18 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
*/
QgsFeatureList selectedFeatures();

/**
* Get an iterator of the selected features
*
* @param request You may specify a request, e.g. to limit the set of requested attributes.
* Any filter on the request will be discarded.
*
* @return Iterator over the selected features
*
* @see selectedFeaturesIds()
*/
QgsFeatureIterator selectedFeaturesIterator( QgsFeatureRequest request = QgsFeatureRequest() );

/**
* Return reference to identifiers of selected features
*
Expand Down
41 changes: 17 additions & 24 deletions src/core/qgsvectorlayereditutils.cpp
Expand Up @@ -198,12 +198,12 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo
int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
int numberOfSplittedFeatures = 0;

QgsFeatureList featureList;
QgsFeatureIterator features;
const QgsFeatureIds selectedIds = L->selectedFeaturesIds();

if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
{
featureList = L->selectedFeatures();
features = L->selectedFeaturesIterator();
}
else //else consider all the feature that intersect the bounding box of the split line
{
Expand Down Expand Up @@ -243,28 +243,24 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo
}
}

QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );

QgsFeature f;
while ( fit.nextFeature( f ) )
featureList << QgsFeature( f );
features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
}

QgsFeatureList::iterator select_it = featureList.begin();
for ( ; select_it != featureList.end(); ++select_it )
QgsFeature feat;
while ( features.nextFeature( feat ) )
{
if ( !select_it->geometry() )
if ( !feat.geometry() )
{
continue;
}
QList<QgsGeometry*> newGeometries;
QList<QgsPoint> topologyTestPoints;
QgsGeometry* newGeometry = 0;
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
if ( splitFunctionReturn == 0 )
{
//change this geometry
L->editBuffer()->changeGeometry( select_it->id(), select_it->geometry() );
L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );

//insert new features
for ( int i = 0; i < newGeometries.size(); ++i )
Expand All @@ -275,7 +271,7 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo

//use default value where possible for primary key (e.g. autoincrement),
//and use the value from the original (split) feature if not primary key
QgsAttributes newAttributes = select_it->attributes();
QgsAttributes newAttributes = feat.attributes();
foreach ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
{
const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
Expand Down Expand Up @@ -335,12 +331,11 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool
int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
int numberOfSplittedParts = 0;

QgsFeatureList featureList;
const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
QgsFeatureIterator fit;

if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
{
featureList = L->selectedFeatures();
fit = L->selectedFeaturesIterator();
}
else //else consider all the feature that intersect the bounding box of the split line
{
Expand Down Expand Up @@ -380,15 +375,13 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool
}
}

QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );

QgsFeature f;
while ( fit.nextFeature( f ) )
featureList << QgsFeature( f );
fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
}

int addPartRet = 0;
foreach ( const QgsFeature& feat, featureList )

QgsFeature feat;
while ( fit.nextFeature( feat ) )
{
QList<QgsGeometry*> newGeometries;
QList<QgsPoint> topologyTestPoints;
Expand Down Expand Up @@ -448,7 +441,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool
qDeleteAll( newGeometries );
}

if ( numberOfSplittedParts == 0 && selectedIds.size() > 0 && returnCode == 0 )
if ( numberOfSplittedParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
{
//There is a selection but no feature has been split.
//Maybe user forgot that only the selected features are split
Expand Down
34 changes: 2 additions & 32 deletions src/plugins/spatialquery/qgsreaderfeatures.cpp
Expand Up @@ -28,49 +28,19 @@ QgsReaderFeatures::QgsReaderFeatures( QgsVectorLayer *layer, bool useSelection )

} // QgsReaderFeatures::QgsReaderFeatures(QgsVectorLayer *layer, bool useSelection)

QgsReaderFeatures::~QgsReaderFeatures()
{
if ( mListSelectedFeature.count() > 0 )
{
mListSelectedFeature.clear();
}

} // QgsReaderFeatures::~QgsReaderFeatures()

bool QgsReaderFeatures::nextFeature( QgsFeature & feature )
{
return ( this->*mFuncNextFeature )( feature );

return mFit.nextFeature( feature );
} // bool QgsReaderFeatures::nextFeature(QgsFeature & feature)

void QgsReaderFeatures::initReader( bool useSelection )
{
if ( useSelection )
{
mListSelectedFeature = mLayer->selectedFeatures();
mIterSelectedFeature = mListSelectedFeature.begin();
mFuncNextFeature = &QgsReaderFeatures::nextFeatureSelected;
mFit = mLayer->selectedFeaturesIterator( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
}
else
{
mFit = mLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
mFuncNextFeature = &QgsReaderFeatures::nextFeatureTotal;
}

} // void QgsReaderFeatures::initReader()

bool QgsReaderFeatures::nextFeatureTotal( QgsFeature & feature )
{
return mFit.nextFeature( feature );
} // bool QgsReaderFeatures::nextFeatureTotal ( QgsFeature & feature )

bool QgsReaderFeatures::nextFeatureSelected( QgsFeature & feature )
{
if ( mIterSelectedFeature == mListSelectedFeature.end() )
return false;

feature = *mIterSelectedFeature;
++mIterSelectedFeature;

return true;
} // bool QgsReaderFeatures::nextFeatureSelected( QgsFeature &feature )
22 changes: 0 additions & 22 deletions src/plugins/spatialquery/qgsreaderfeatures.h
Expand Up @@ -35,11 +35,6 @@ class QgsReaderFeatures
*/
QgsReaderFeatures( QgsVectorLayer *layer, bool useSelection );

/**
* \brief Destructor
*/
~QgsReaderFeatures();

/**
* \brief Next feature
* \param feature reference to next Feature.
Expand All @@ -54,24 +49,7 @@ class QgsReaderFeatures
*/
void initReader( bool useSelection );

/**
* \brief Next feature, not using the features selected
* \param feature reference to next Feature.
* \returns True if has next feature.
*/
bool nextFeatureTotal( QgsFeature & feature );

/**
* \brief Next feature, using the features selected
* \param feature reference to next Feature.
* \returns True if has next feature.
*/
bool nextFeatureSelected( QgsFeature & feature );

QgsVectorLayer * mLayer;
QgsFeatureList mListSelectedFeature;
QList<QgsFeature>::iterator mIterSelectedFeature;
bool ( QgsReaderFeatures::* mFuncNextFeature )( QgsFeature & );
QgsFeatureIterator mFit;
};

Expand Down

0 comments on commit e613c8b

Please sign in to comment.