Rename QgsSpatialIndex::insertFeature to ::addFeature, for consistency

with other classes

And make QgsSpatialIndex a QgsFeatureSink
This commit is contained in:
Nyall Dawson 2018-09-28 13:21:01 +10:00
parent 63f597f934
commit 6110931f8a
21 changed files with 139 additions and 49 deletions

View File

@ -14,7 +14,7 @@
class QgsSpatialIndex
class QgsSpatialIndex : QgsFeatureSink
{
%Docstring
@ -75,18 +75,49 @@ Copy constructor
bool insertFeature( const QgsFeature &feature );
bool insertFeature( const QgsFeature &feature ) /Deprecated/;
%Docstring
Adds a ``feature`` to the index.
.. deprecated:: Use addFeature() instead
%End
bool insertFeature( QgsFeatureId id, const QgsRectangle &bounds );
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
%Docstring
Adds a ``feature`` to the index.
The ``flags`` argument is ignored.
.. versionadded:: 3.4
%End
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 );
%Docstring
Adds a list of ``features`` to the index.
The ``flags`` argument is ignored.
.. seealso:: :py:func:`addFeature`
%End
bool insertFeature( QgsFeatureId id, const QgsRectangle &bounds ) /Deprecated/;
%Docstring
Add a feature ``id`` to the index with a specified bounding box.
:return: true if feature was successfully added to index.
.. versionadded:: 3.0
.. deprecated:: Use addFeature() instead
%End
bool addFeature( QgsFeatureId id, const QgsRectangle &bounds );
%Docstring
Add a feature ``id`` to the index with a specified bounding box.
:return: true if feature was successfully added to index.
.. versionadded:: 3.4
%End
bool deleteFeature( const QgsFeature &feature );

View File

@ -28,6 +28,7 @@ __revision__ = '$Format:%H$'
from qgis.core import (QgsFeatureRequest,
QgsProcessingException,
QgsFeatureSink,
QgsSpatialIndex,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
@ -71,11 +72,13 @@ class DeleteDuplicateGeometries(QgisAlgorithm):
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
total = 100.0 / source.featureCount() if source.featureCount() else 0
geoms = dict()
index = QgsSpatialIndex()
for current, f in enumerate(features):
if feedback.isCanceled():
break
geoms[f.id()] = f.geometry()
#index.insertFeature
feedback.setProgress(int(current * total))
cleaned = dict(geoms)

View File

@ -116,7 +116,7 @@ class PointsDisplacement(QgisAlgorithm):
other_features_within_radius = index.intersects(searchRect(point))
if not other_features_within_radius:
index.insertFeature(f)
index.addFeature(f)
group = [f]
clustered_groups.append(group)
group_index[f.id()] = len(clustered_groups) - 1

View File

@ -163,7 +163,7 @@ class RandomPointsAlongLines(QgisAlgorithm):
f.setAttribute('id', nPoints)
f.setGeometry(geom)
sink.addFeature(f, QgsFeatureSink.FastInsert)
index.insertFeature(f)
index.addFeature(f)
points[nPoints] = p
nPoints += 1
feedback.setProgress(int(nPoints * total))

View File

@ -142,7 +142,7 @@ class RandomPointsExtent(QgisAlgorithm):
f.setAttribute('id', nPoints)
f.setGeometry(geom)
sink.addFeature(f, QgsFeatureSink.FastInsert)
index.insertFeature(f)
index.addFeature(f)
points[nPoints] = p
nPoints += 1
feedback.setProgress(int(nPoints * total))

View File

@ -151,7 +151,7 @@ class RandomPointsLayer(QgisAlgorithm):
f.setAttribute('id', nPoints)
f.setGeometry(geom)
sink.addFeature(f, QgsFeatureSink.FastInsert)
index.insertFeature(f)
index.addFeature(f)
points[nPoints] = p
nPoints += 1
feedback.setProgress(int(nPoints * total))

View File

@ -197,7 +197,7 @@ class RandomPointsPolygons(QgisAlgorithm):
f.setAttribute('id', nPoints)
f.setGeometry(geom)
sink.addFeature(f, QgsFeatureSink.FastInsert)
index.insertFeature(f)
index.addFeature(f)
points[nPoints] = p
nPoints += 1
feedback.setProgress(current_progress + int(nPoints * feature_total))

View File

@ -190,7 +190,7 @@ class TopoColor(QgisAlgorithm):
if id_graph:
id_graph.add_edge(f.id(), f2.id())
index.insertFeature(f)
index.addFeature(f)
i += 1
feedback.setProgress(int(i * total))

View File

@ -118,7 +118,7 @@ QVariantMap QgsSplitWithLinesAlgorithm::processAlgorithm( const QVariantMap &par
}
splitGeoms.insert( aSplitFeature.id(), aSplitFeature.geometry() );
spatialIndex.insertFeature( aSplitFeature );
spatialIndex.addFeature( aSplitFeature );
}
QgsFeature outFeat;

View File

@ -298,7 +298,7 @@ void QgsOverlayUtils::resolveOverlaps( const QgsFeatureSource &source, QgsFeatur
std::unique_ptr< QgsGeometryEngine > g1engine;
geometries.insert( fid1, g1 );
index.insertFeature( f );
index.addFeature( f );
QgsRectangle bbox( f.geometry().boundingBox() );
const QList<QgsFeatureId> ids = index.intersects( bbox );
@ -335,7 +335,7 @@ void QgsOverlayUtils::resolveOverlaps( const QgsFeatureSource &source, QgsFeatur
QgsFeature fx( newFid );
fx.setGeometry( geomIntersection );
index.insertFeature( fx );
index.addFeature( fx );
// figure out which feature IDs belong to this intersection. Some of the IDs can be of the newly
// created geometries - in such case we need to retrieve original IDs
@ -365,7 +365,7 @@ void QgsOverlayUtils::resolveOverlaps( const QgsFeatureSource &source, QgsFeatur
QgsFeature f1x( fid1 );
f1x.setGeometry( g12 );
index.insertFeature( f1x );
index.addFeature( f1x );
}
//
@ -386,7 +386,7 @@ void QgsOverlayUtils::resolveOverlaps( const QgsFeatureSource &source, QgsFeatur
QgsFeature f2x( fid2 );
f2x.setGeometry( g21 );
index.insertFeature( f2x );
index.addFeature( f2x );
}
// update our temporary copy of the geometry to what is left from it

View File

@ -57,7 +57,7 @@ bool QgsFeaturePool::getFeature( QgsFeatureId id, QgsFeature &feature )
}
locker.changeMode( QgsReadWriteLocker::Write );
mFeatureCache.insert( id, new QgsFeature( feature ) );
mIndex.insertFeature( feature );
mIndex.addFeature( feature );
}
return true;
}
@ -90,7 +90,8 @@ void QgsFeaturePool::insertFeature( const QgsFeature &feature )
{
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
mIndex.insertFeature( feature );
QgsFeature indexFeature( feature );
mIndex.addFeature( indexFeature );
}
void QgsFeaturePool::refreshCache( const QgsFeature &feature )

View File

@ -768,7 +768,7 @@ QgsGeometry QgsInternalGeometrySnapper::snapFeature( const QgsFeature &feature )
}
}
mProcessedGeometries.insert( feat.id(), geometry );
mProcessedIndex.insertFeature( feat );
mProcessedIndex.addFeature( feat );
mFirstFeature = false;
return geometry;
}

View File

@ -70,7 +70,7 @@ static void buildSnapIndex( QgsFeatureIterator &fi, QgsSpatialIndex &index, QVec
if ( ids.isEmpty() )
{
// add to tree and to structure
index.insertFeature( pntId, pt.boundingBox() );
index.addFeature( pntId, pt.boundingBox() );
AnchorPoint xp;
xp.x = pt.x();

View File

@ -395,7 +395,7 @@ bool QgsMemoryProvider::addFeatures( QgsFeatureList &flist, Flags )
// update spatial index
if ( mSpatialIndex )
mSpatialIndex->insertFeature( *it );
mSpatialIndex->addFeature( *it );
}
mNextFeatureId++;
@ -541,7 +541,7 @@ bool QgsMemoryProvider::changeGeometryValues( const QgsGeometryMap &geometry_map
// update spatial index
if ( mSpatialIndex )
mSpatialIndex->insertFeature( *fit );
mSpatialIndex->addFeature( *fit );
}
updateExtents();
@ -583,9 +583,9 @@ bool QgsMemoryProvider::createSpatialIndex()
mSpatialIndex = new QgsSpatialIndex();
// add existing features to index
for ( QgsFeatureMap::const_iterator it = mFeatures.constBegin(); it != mFeatures.constEnd(); ++it )
for ( QgsFeatureMap::iterator it = mFeatures.begin(); it != mFeatures.end(); ++it )
{
mSpatialIndex->insertFeature( *it );
mSpatialIndex->addFeature( *it );
}
}
return true;

View File

@ -299,19 +299,41 @@ bool QgsSpatialIndex::featureInfo( const QgsFeature &f, QgsRectangle &rect, QgsF
return true;
}
bool QgsSpatialIndex::insertFeature( const QgsFeature &f )
bool QgsSpatialIndex::addFeature( QgsFeature &feature, QgsFeatureSink::Flags )
{
QgsRectangle rect;
QgsFeatureId id;
if ( !featureInfo( f, rect, id ) )
if ( !featureInfo( feature, rect, id ) )
return false;
return insertFeature( id, rect );
return addFeature( id, rect );
}
bool QgsSpatialIndex::insertFeature( QgsFeatureId id, const QgsRectangle &rect )
bool QgsSpatialIndex::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags )
{
SpatialIndex::Region r( rectToRegion( rect ) );
QgsFeatureList::iterator fIt = features.begin();
bool result = true;
for ( ; fIt != features.end(); ++fIt )
{
result = result && addFeature( *fIt, flags );
}
return result;
}
bool QgsSpatialIndex::insertFeature( const QgsFeature &f )
{
QgsFeature feature( f );
return addFeature( feature );
}
bool QgsSpatialIndex::insertFeature( QgsFeatureId id, const QgsRectangle &bounds )
{
return addFeature( id, bounds );
}
bool QgsSpatialIndex::addFeature( QgsFeatureId id, const QgsRectangle &bounds )
{
SpatialIndex::Region r( rectToRegion( bounds ) );
QMutexLocker locker( &d->mMutex );
@ -324,16 +346,16 @@ bool QgsSpatialIndex::insertFeature( QgsFeatureId id, const QgsRectangle &rect )
catch ( Tools::Exception &e )
{
Q_UNUSED( e );
QgsDebugMsg( QString( "Tools::Exception caught: " ).arg( e.what().c_str() ) );
QgsDebugMsg( QStringLiteral( "Tools::Exception caught: " ).arg( e.what().c_str() ) );
}
catch ( const std::exception &e )
{
Q_UNUSED( e );
QgsDebugMsg( QString( "std::exception caught: " ).arg( e.what() ) );
QgsDebugMsg( QStringLiteral( "std::exception caught: " ).arg( e.what() ) );
}
catch ( ... )
{
QgsDebugMsg( "unknown spatial index exception caught" );
QgsDebugMsg( QStringLiteral( "unknown spatial index exception caught" ) );
}
return false;

View File

@ -40,6 +40,7 @@ class QgsPointXY;
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsfeaturesink.h"
#include <QList>
#include <QSharedDataPointer>
@ -63,7 +64,7 @@ class QgsFeatureSource;
*
* \see QgsSpatialIndexKDBush, which is an optimised non-mutable index for point geometries only.
*/
class CORE_EXPORT QgsSpatialIndex
class CORE_EXPORT QgsSpatialIndex : public QgsFeatureSink
{
public:
@ -104,7 +105,7 @@ class CORE_EXPORT QgsSpatialIndex
QgsSpatialIndex( const QgsSpatialIndex &other );
//! Destructor finalizes work with spatial index
~QgsSpatialIndex();
~QgsSpatialIndex() override;
//! Implement assignment operator
QgsSpatialIndex &operator=( const QgsSpatialIndex &other );
@ -113,15 +114,41 @@ class CORE_EXPORT QgsSpatialIndex
/**
* Adds a \a feature to the index.
* \deprecated Use addFeature() instead
*/
bool insertFeature( const QgsFeature &feature );
Q_DECL_DEPRECATED bool insertFeature( const QgsFeature &feature ) SIP_DEPRECATED;
/**
* Adds a \a feature to the index.
*
* The \a flags argument is ignored.
*
* \since QGIS 3.4
*/
bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = nullptr ) override;
/**
* Adds a list of \a features to the index.
*
* The \a flags argument is ignored.
*
* \see addFeature()
*/
bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = nullptr ) override;
/**
* Add a feature \a id to the index with a specified bounding box.
* \returns true if feature was successfully added to index.
* \since QGIS 3.0
* \deprecated Use addFeature() instead
*/
bool insertFeature( QgsFeatureId id, const QgsRectangle &bounds );
Q_DECL_DEPRECATED bool insertFeature( QgsFeatureId id, const QgsRectangle &bounds ) SIP_DEPRECATED;
/**
* Add a feature \a id to the index with a specified bounding box.
* \returns true if feature was successfully added to index.
* \since QGIS 3.4
*/
bool addFeature( QgsFeatureId id, const QgsRectangle &bounds );
/**
* Removes a \a feature from the index.

View File

@ -94,7 +94,7 @@ bool QgsPointDistanceRenderer::renderFeature( const QgsFeature &feature, QgsRend
QList<QgsFeatureId> intersectList = mSpatialIndex->intersects( searchRect( point, searchDistance ) );
if ( intersectList.empty() )
{
mSpatialIndex->insertFeature( transformedFeature );
mSpatialIndex->addFeature( transformedFeature );
// create new group
ClusteredGroup newGroup;
newGroup << GroupedFeature( transformedFeature, symbol->clone(), selected, label );

View File

@ -1369,7 +1369,7 @@ QgsSpatialIndex *topolTest::createIndex( QgsVectorLayer *layer, const QgsRectang
if ( f.hasGeometry() )
{
index->insertFeature( f );
index->addFeature( f );
mFeatureMap2[f.id()] = FeatureLayer( layer, f );
}
}

View File

@ -446,7 +446,7 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
QgsFeature f;
f.setId( mFile->recordId() );
f.setGeometry( geom );
mSpatialIndex->insertFeature( f );
mSpatialIndex->addFeature( f );
}
}
else
@ -501,7 +501,7 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
QgsFeature f;
f.setId( mFile->recordId() );
f.setGeometry( QgsGeometry::fromPointXY( pt ) );
mSpatialIndex->insertFeature( f );
mSpatialIndex->addFeature( f );
}
}
else
@ -770,7 +770,7 @@ void QgsDelimitedTextProvider::rescanFile() const
mExtent.combineExtentWith( bbox );
}
if ( buildSpatialIndex )
mSpatialIndex->insertFeature( f );
mSpatialIndex->addFeature( f );
}
if ( buildSubsetIndex )
mSubsetIndex.append( ( quintptr ) f.id() );

View File

@ -1037,7 +1037,7 @@ void QgsWFSSharedData::endOfDownload( bool success, int featureCount,
f.initAttributes( 1 );
f.setAttribute( 0, QVariant( bDownloadLimit ) );
mRegions.push_back( f );
mCachedRegions.insertFeature( f );
mCachedRegions.addFeature( f );
}
}

View File

@ -70,7 +70,10 @@ class TestQgsSpatialIndex : public QObject
{
QgsSpatialIndex index;
Q_FOREACH ( const QgsFeature &f, _pointFeatures() )
index.insertFeature( f );
{
QgsFeature indexFeature( f );
index.addFeature( indexFeature );
}
QList<QgsFeatureId> fids = index.intersects( QgsRectangle( 0, 0, 10, 10 ) );
QVERIFY( fids.count() == 1 );
@ -85,9 +88,9 @@ class TestQgsSpatialIndex : public QObject
void testQueryManualInsert()
{
QgsSpatialIndex index;
index.insertFeature( 1, QgsRectangle( 2, 3, 2, 3 ) );
index.insertFeature( 2, QgsRectangle( 12, 13, 12, 13 ) );
index.insertFeature( 3, QgsRectangle( 14, 13, 14, 13 ) );
index.addFeature( 1, QgsRectangle( 2, 3, 2, 3 ) );
index.addFeature( 2, QgsRectangle( 12, 13, 12, 13 ) );
index.addFeature( 3, QgsRectangle( 14, 13, 14, 13 ) );
QList<QgsFeatureId> fids = index.intersects( QgsRectangle( 1, 2, 3, 4 ) );
QVERIFY( fids.count() == 1 );
@ -110,7 +113,10 @@ class TestQgsSpatialIndex : public QObject
{
QgsSpatialIndex *index = new QgsSpatialIndex;
Q_FOREACH ( const QgsFeature &f, _pointFeatures() )
index->insertFeature( f );
{
QgsFeature indexFeature( f );
index->addFeature( indexFeature );
}
// create copy of the index
QgsSpatialIndex indexCopy( *index );
@ -154,7 +160,7 @@ class TestQgsSpatialIndex : public QObject
QgsFeature f( i * 1000 + k );
QgsGeometry g = QgsGeometry::fromPointXY( QgsPointXY( i / 10, i % 10 ) );
f.setGeometry( g );
index.insertFeature( f );
index.addFeature( f );
}
}
@ -207,7 +213,7 @@ class TestQgsSpatialIndex : public QObject
QgsFeature f;
indexInsert = new QgsSpatialIndex;
while ( fi.nextFeature( f ) )
indexInsert->insertFeature( f );
indexInsert->addFeature( f );
}
qDebug( "insert: %d ms", t.elapsed() );