Skip to content

Commit ff171ea

Browse files
committed
Add method for manually inserting features into spatial indexes
i.e. inserting a feature with a different bounding box to that feature's actual geometry
1 parent 6eb3570 commit ff171ea

4 files changed

Lines changed: 84 additions & 7 deletions

File tree

python/core/qgsspatialindex.sip

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ Add feature to index
5454
:rtype: bool
5555
%End
5656

57+
bool insertFeature( QgsFeatureId id, const QgsRectangle &bounds );
58+
%Docstring
59+
Add a feature ``id`` to the index with a specified bounding box.
60+
:return: true if feature was successfully added to index.
61+
.. versionadded:: 3.0
62+
:rtype: bool
63+
%End
64+
5765
bool deleteFeature( const QgsFeature &f );
5866
%Docstring
5967
Remove feature from index
@@ -84,6 +92,19 @@ get reference count - just for debugging!
8492
protected:
8593

8694

95+
static bool featureInfo( const QgsFeature &f, QgsRectangle &rect, QgsFeatureId &id );
96+
%Docstring
97+
Calculates feature info to insert into index.
98+
\param f input feature
99+
\param rect will be set to feature's geometry bounding box
100+
\param id will be set to feature's ID
101+
:return: true if feature info was successfully retrieved and the feature can be added to
102+
the index
103+
.. versionadded:: 3.0
104+
:rtype: bool
105+
%End
106+
107+
87108
};
88109

89110

src/core/qgsspatialindex.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,24 +253,38 @@ SpatialIndex::Region QgsSpatialIndex::rectToRegion( const QgsRectangle &rect )
253253

254254
bool QgsSpatialIndex::featureInfo( const QgsFeature &f, SpatialIndex::Region &r, QgsFeatureId &id )
255255
{
256-
if ( !f.hasGeometry() )
256+
QgsRectangle rect;
257+
if ( !featureInfo( f, rect, id ) )
257258
return false;
258259

259-
QgsGeometry g = f.geometry();
260+
r = rectToRegion( rect );
261+
return true;
262+
}
263+
264+
bool QgsSpatialIndex::featureInfo( const QgsFeature &f, QgsRectangle &rect, QgsFeatureId &id )
265+
{
266+
if ( !f.hasGeometry() )
267+
return false;
260268

261269
id = f.id();
262-
r = rectToRegion( g.boundingBox() );
270+
rect = f.geometry().boundingBox();
263271
return true;
264272
}
265273

266-
267274
bool QgsSpatialIndex::insertFeature( const QgsFeature &f )
268275
{
269-
SpatialIndex::Region r;
276+
QgsRectangle rect;
270277
QgsFeatureId id;
271-
if ( !featureInfo( f, r, id ) )
278+
if ( !featureInfo( f, rect, id ) )
272279
return false;
273280

281+
return insertFeature( id, rect );
282+
}
283+
284+
bool QgsSpatialIndex::insertFeature( QgsFeatureId id, const QgsRectangle &rect )
285+
{
286+
SpatialIndex::Region r( rectToRegion( rect ) );
287+
274288
// TODO: handle possible exceptions correctly
275289
try
276290
{

src/core/qgsspatialindex.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ class CORE_EXPORT QgsSpatialIndex
8181
//! Add feature to index
8282
bool insertFeature( const QgsFeature &f );
8383

84+
/**
85+
* Add a feature \a id to the index with a specified bounding box.
86+
* \returns true if feature was successfully added to index.
87+
* \since QGIS 3.0
88+
*/
89+
bool insertFeature( QgsFeatureId id, const QgsRectangle &bounds );
90+
8491
//! Remove feature from index
8592
bool deleteFeature( const QgsFeature &f );
8693

@@ -101,9 +108,27 @@ class CORE_EXPORT QgsSpatialIndex
101108
protected:
102109
//! \note not available in Python bindings
103110
static SpatialIndex::Region rectToRegion( const QgsRectangle &rect ) SIP_SKIP;
104-
//! \note not available in Python bindings
111+
112+
/** Calculates feature info to insert into index.
113+
* \param f input feature
114+
* \param r will be set to spatial index region
115+
* \param id will be set to feature's ID
116+
* \returns true if feature info was successfully retrieved and the feature can be added to
117+
* the index
118+
* \note not available in Python bindings
119+
*/
105120
static bool featureInfo( const QgsFeature &f, SpatialIndex::Region &r, QgsFeatureId &id ) SIP_SKIP;
106121

122+
/** Calculates feature info to insert into index.
123+
* \param f input feature
124+
* \param rect will be set to feature's geometry bounding box
125+
* \param id will be set to feature's ID
126+
* \returns true if feature info was successfully retrieved and the feature can be added to
127+
* the index
128+
* \since QGIS 3.0
129+
*/
130+
static bool featureInfo( const QgsFeature &f, QgsRectangle &rect, QgsFeatureId &id );
131+
107132
friend class QgsFeatureIteratorDataStream; // for access to featureInfo()
108133

109134
private:

tests/src/core/testqgsspatialindex.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,23 @@ class TestQgsSpatialIndex : public QObject
8282
QVERIFY( fids2.contains( 3 ) );
8383
}
8484

85+
void testQueryManualInsert()
86+
{
87+
QgsSpatialIndex index;
88+
index.insertFeature( 1, QgsRectangle( 2, 3, 2, 3 ) );
89+
index.insertFeature( 2, QgsRectangle( 12, 13, 12, 13 ) );
90+
index.insertFeature( 3, QgsRectangle( 14, 13, 14, 13 ) );
91+
92+
QList<QgsFeatureId> fids = index.intersects( QgsRectangle( 1, 2, 3, 4 ) );
93+
QVERIFY( fids.count() == 1 );
94+
QVERIFY( fids.at( 0 ) == 1 );
95+
96+
QList<QgsFeatureId> fids2 = index.intersects( QgsRectangle( 10, 12, 15, 14 ) );
97+
QVERIFY( fids2.count() == 2 );
98+
QVERIFY( fids2.contains( 2 ) );
99+
QVERIFY( fids2.contains( 3 ) );
100+
}
101+
85102
void testCopy()
86103
{
87104
QgsSpatialIndex *index = new QgsSpatialIndex;

0 commit comments

Comments
 (0)