Merge pull request #4661 from nyalldawson/feature_index

Add method for manually inserting features into spatial indexes
This commit is contained in:
Nyall Dawson 2017-06-01 18:24:44 +10:00 committed by GitHub
commit 2f9bfc5653
5 changed files with 79 additions and 14 deletions

View File

@ -2060,6 +2060,11 @@ QgsSnapper {#qgis_api_break_3_0_QgsSnapper}
- Constructor variant with QgsMapRenderer has been removed. Use the variant with QgsMapSettings.
- Signature for snapPoint() has changed.
QgsSpatialIndex {#qgis_api_break_3_0_QgsSpatialIndex}
---------------
- The protected members were made private. QgsSpatialIndex is not designed to be subclassed.
QgsSublayersDialog {#qgis_api_break_3_0_QgsSublayersDialog}
------------------

View File

@ -54,6 +54,14 @@ Add feature to index
:rtype: bool
%End
bool insertFeature( 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.0
:rtype: bool
%End
bool deleteFeature( const QgsFeature &f );
%Docstring
Remove feature from index
@ -81,9 +89,6 @@ get reference count - just for debugging!
:rtype: QAtomicInt
%End
protected:
};

View File

@ -253,24 +253,38 @@ SpatialIndex::Region QgsSpatialIndex::rectToRegion( const QgsRectangle &rect )
bool QgsSpatialIndex::featureInfo( const QgsFeature &f, SpatialIndex::Region &r, QgsFeatureId &id )
{
if ( !f.hasGeometry() )
QgsRectangle rect;
if ( !featureInfo( f, rect, id ) )
return false;
QgsGeometry g = f.geometry();
id = f.id();
r = rectToRegion( g.boundingBox() );
r = rectToRegion( rect );
return true;
}
bool QgsSpatialIndex::featureInfo( const QgsFeature &f, QgsRectangle &rect, QgsFeatureId &id )
{
if ( !f.hasGeometry() )
return false;
id = f.id();
rect = f.geometry().boundingBox();
return true;
}
bool QgsSpatialIndex::insertFeature( const QgsFeature &f )
{
SpatialIndex::Region r;
QgsRectangle rect;
QgsFeatureId id;
if ( !featureInfo( f, r, id ) )
if ( !featureInfo( f, rect, id ) )
return false;
return insertFeature( id, rect );
}
bool QgsSpatialIndex::insertFeature( QgsFeatureId id, const QgsRectangle &rect )
{
SpatialIndex::Region r( rectToRegion( rect ) );
// TODO: handle possible exceptions correctly
try
{

View File

@ -81,6 +81,13 @@ class CORE_EXPORT QgsSpatialIndex
//! Add feature to index
bool insertFeature( const QgsFeature &f );
/**
* 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
*/
bool insertFeature( QgsFeatureId id, const QgsRectangle &bounds );
//! Remove feature from index
bool deleteFeature( const QgsFeature &f );
@ -98,12 +105,29 @@ class CORE_EXPORT QgsSpatialIndex
//! get reference count - just for debugging!
QAtomicInt SIP_PYTYPE( int ) refs() const;
protected:
//! \note not available in Python bindings
static SpatialIndex::Region rectToRegion( const QgsRectangle &rect ) SIP_SKIP;
//! \note not available in Python bindings
private:
static SpatialIndex::Region rectToRegion( const QgsRectangle &rect );
/** Calculates feature info to insert into index.
* \param f input feature
* \param r will be set to spatial index region
* \param id will be set to feature's ID
* \returns true if feature info was successfully retrieved and the feature can be added to
* the index
*/
static bool featureInfo( const QgsFeature &f, SpatialIndex::Region &r, QgsFeatureId &id ) SIP_SKIP;
/** Calculates feature info to insert into index.
* \param f input feature
* \param rect will be set to feature's geometry bounding box
* \param id will be set to feature's ID
* \returns true if feature info was successfully retrieved and the feature can be added to
* the index
* \since QGIS 3.0
*/
static bool featureInfo( const QgsFeature &f, QgsRectangle &rect, QgsFeatureId &id );
friend class QgsFeatureIteratorDataStream; // for access to featureInfo()
private:

View File

@ -82,6 +82,23 @@ class TestQgsSpatialIndex : public QObject
QVERIFY( fids2.contains( 3 ) );
}
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 ) );
QList<QgsFeatureId> fids = index.intersects( QgsRectangle( 1, 2, 3, 4 ) );
QVERIFY( fids.count() == 1 );
QVERIFY( fids.at( 0 ) == 1 );
QList<QgsFeatureId> fids2 = index.intersects( QgsRectangle( 10, 12, 15, 14 ) );
QVERIFY( fids2.count() == 2 );
QVERIFY( fids2.contains( 2 ) );
QVERIFY( fids2.contains( 3 ) );
}
void testCopy()
{
QgsSpatialIndex *index = new QgsSpatialIndex;