mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-25 00:05:03 -04:00
143 lines
4.5 KiB
C++
143 lines
4.5 KiB
C++
/***************************************************************************
|
|
* qgsfeaturepool.cpp *
|
|
* ------------------- *
|
|
* copyright : (C) 2014 by Sandro Mani / Sourcepole AG *
|
|
* email : smani@sourcepole.ch *
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsfeaturepool.h"
|
|
#include "qgsfeature.h"
|
|
#include "qgsfeatureiterator.h"
|
|
#include "qgsgeometry.h"
|
|
#include "qgsvectorlayer.h"
|
|
#include "qgsvectordataprovider.h"
|
|
#include "qgsgeometryutils.h"
|
|
|
|
#include <QMutexLocker>
|
|
#include <limits>
|
|
|
|
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, double mapToLayerUnits, bool selectedOnly )
|
|
: mFeatureCache( CACHE_SIZE )
|
|
, mLayer( layer )
|
|
, mMapToLayerUnits( mapToLayerUnits )
|
|
, mSelectedOnly( selectedOnly )
|
|
{
|
|
if ( selectedOnly )
|
|
{
|
|
mFeatureIds = layer->selectedFeatureIds();
|
|
}
|
|
else
|
|
{
|
|
mFeatureIds = layer->allFeatureIds();
|
|
}
|
|
|
|
// Build spatial index
|
|
QgsFeature feature;
|
|
QgsFeatureRequest req;
|
|
req.setSubsetOfAttributes( QgsAttributeList() );
|
|
QgsFeatureIterator it = layer->getFeatures( req );
|
|
while ( it.nextFeature( feature ) )
|
|
{
|
|
if ( feature.geometry() )
|
|
{
|
|
mIndex.insertFeature( feature );
|
|
}
|
|
else
|
|
{
|
|
mFeatureIds.remove( feature.id() );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool QgsFeaturePool::get( QgsFeatureId id, QgsFeature &feature )
|
|
{
|
|
QMutexLocker lock( &mLayerMutex );
|
|
QgsFeature *pfeature = mFeatureCache.object( id );
|
|
if ( pfeature )
|
|
{
|
|
//feature was cached
|
|
feature = *pfeature;
|
|
}
|
|
|
|
// Feature not in cache, retrieve from layer
|
|
pfeature = new QgsFeature();
|
|
// TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
|
|
if ( !mLayer->getFeatures( QgsFeatureRequest( id ) ).nextFeature( *pfeature ) )
|
|
{
|
|
delete pfeature;
|
|
return false;
|
|
}
|
|
//make a copy of pfeature into feature parameter
|
|
feature = QgsFeature( *pfeature );
|
|
//ownership of pfeature is transferred to cache
|
|
mFeatureCache.insert( id, pfeature );
|
|
return true;
|
|
}
|
|
|
|
void QgsFeaturePool::addFeature( QgsFeature &feature )
|
|
{
|
|
QgsFeatureList features;
|
|
features.append( feature );
|
|
mLayerMutex.lock();
|
|
mLayer->dataProvider()->addFeatures( features );
|
|
feature.setId( features.front().id() );
|
|
if ( mSelectedOnly )
|
|
{
|
|
QgsFeatureIds selectedFeatureIds = mLayer->selectedFeatureIds();
|
|
selectedFeatureIds.insert( feature.id() );
|
|
mLayer->selectByIds( selectedFeatureIds );
|
|
}
|
|
mLayerMutex.unlock();
|
|
mIndexMutex.lock();
|
|
mIndex.insertFeature( feature );
|
|
mIndexMutex.unlock();
|
|
}
|
|
|
|
void QgsFeaturePool::updateFeature( QgsFeature &feature )
|
|
{
|
|
QgsGeometryMap geometryMap;
|
|
geometryMap.insert( feature.id(), QgsGeometry( feature.geometry().geometry()->clone() ) );
|
|
QgsChangedAttributesMap changedAttributesMap;
|
|
QgsAttributeMap attribMap;
|
|
for ( int i = 0, n = feature.attributes().size(); i < n; ++i )
|
|
{
|
|
attribMap.insert( i, feature.attributes().at( i ) );
|
|
}
|
|
changedAttributesMap.insert( feature.id(), attribMap );
|
|
mLayerMutex.lock();
|
|
mFeatureCache.remove( feature.id() ); // Remove to force reload on next get()
|
|
mLayer->dataProvider()->changeGeometryValues( geometryMap );
|
|
mLayer->dataProvider()->changeAttributeValues( changedAttributesMap );
|
|
mLayerMutex.unlock();
|
|
mIndexMutex.lock();
|
|
mIndex.deleteFeature( feature );
|
|
mIndex.insertFeature( feature );
|
|
mIndexMutex.unlock();
|
|
}
|
|
|
|
void QgsFeaturePool::deleteFeature( QgsFeature &feature )
|
|
{
|
|
mIndexMutex.lock();
|
|
mIndex.deleteFeature( feature );
|
|
mIndexMutex.unlock();
|
|
mLayerMutex.lock();
|
|
mFeatureCache.remove( feature.id() );
|
|
mLayer->dataProvider()->deleteFeatures( QgsFeatureIds() << feature.id() );
|
|
mLayerMutex.unlock();
|
|
}
|
|
|
|
QgsFeatureIds QgsFeaturePool::getIntersects( const QgsRectangle &rect )
|
|
{
|
|
QMutexLocker lock( &mIndexMutex );
|
|
return QgsFeatureIds::fromList( mIndex.intersects( rect ) );
|
|
}
|