Use sets for index results

This commit is contained in:
Nyall Dawson 2018-07-06 13:56:31 +10:00
parent 682671d18f
commit 612c9cb047
5 changed files with 45 additions and 23 deletions

View File

@ -65,15 +65,15 @@ Copy constructor
~QgsSpatialIndexKDBush(); ~QgsSpatialIndexKDBush();
QList<QgsFeatureId> intersect( const QgsRectangle &rectangle ) const; QSet<QgsFeatureId> intersect( const QgsRectangle &rectangle ) const;
%Docstring %Docstring
Returns a list of features which fall within the specified ``rectangle``. Returns the set of features which fall within the specified ``rectangle``.
%End %End
QList<QgsFeatureId> within( const QgsPointXY &point, double radius ) const; QSet<QgsFeatureId> within( const QgsPointXY &point, double radius ) const;
%Docstring %Docstring
Returns a list of features which are within the given search ``radius`` Returns the set of features which are within the given search ``radius``
of ``point``. of ``point``.
%End %End
@ -84,6 +84,11 @@ Fetches the point from the index with matching ``id`` and stores it in ``point``
Returns true if the point was found, or false if no matching feature ID is present Returns true if the point was found, or false if no matching feature ID is present
in the index. in the index.
%End
qgssize size() const;
%Docstring
Returns the size of the index, i.e. the number of points contained within the index.
%End %End
}; };

View File

@ -56,10 +56,10 @@ QgsSpatialIndexKDBush::~QgsSpatialIndexKDBush()
delete d; delete d;
} }
QList<QgsFeatureId> QgsSpatialIndexKDBush::within( const QgsPointXY &point, double radius ) const QSet<QgsFeatureId> QgsSpatialIndexKDBush::within( const QgsPointXY &point, double radius ) const
{ {
QList<QgsFeatureId> result; QSet<QgsFeatureId> result;
d->index->within( point.x(), point.y(), radius, [&result]( const QgsFeatureId id ) { result << id; } ); d->index->within( point.x(), point.y(), radius, [&result]( const QgsFeatureId id ) { result.insert( id ); } );
return result; return result;
} }
@ -73,9 +73,14 @@ bool QgsSpatialIndexKDBush::point( QgsFeatureId id, QgsPointXY &point ) const
return d->index->point( id, point ); return d->index->point( id, point );
} }
QList<QgsFeatureId> QgsSpatialIndexKDBush::intersect( const QgsRectangle &rectangle ) const qgssize QgsSpatialIndexKDBush::size() const
{ {
QList<QgsFeatureId> result; return d->index->size();
}
QSet<QgsFeatureId> QgsSpatialIndexKDBush::intersect( const QgsRectangle &rectangle ) const
{
QSet<QgsFeatureId> result;
d->index->range( rectangle.xMinimum(), d->index->range( rectangle.xMinimum(),
rectangle.yMinimum(), rectangle.yMinimum(),
rectangle.xMaximum(), rectangle.xMaximum(),

View File

@ -83,9 +83,9 @@ class CORE_EXPORT QgsSpatialIndexKDBush
~QgsSpatialIndexKDBush(); ~QgsSpatialIndexKDBush();
/** /**
* Returns a list of features which fall within the specified \a rectangle. * Returns the set of features which fall within the specified \a rectangle.
*/ */
QList<QgsFeatureId> intersect( const QgsRectangle &rectangle ) const; QSet<QgsFeatureId> intersect( const QgsRectangle &rectangle ) const;
/** /**
* Calls a \a visitor function for all features which fall within the specified \a rectangle. * Calls a \a visitor function for all features which fall within the specified \a rectangle.
@ -95,10 +95,10 @@ class CORE_EXPORT QgsSpatialIndexKDBush
void intersect( const QgsRectangle &rectangle, const std::function<void( QgsFeatureId )> &visitor ) const SIP_SKIP; void intersect( const QgsRectangle &rectangle, const std::function<void( QgsFeatureId )> &visitor ) const SIP_SKIP;
/** /**
* Returns a list of features which are within the given search \a radius * Returns the set of features which are within the given search \a radius
* of \a point. * of \a point.
*/ */
QList<QgsFeatureId> within( const QgsPointXY &point, double radius ) const; QSet<QgsFeatureId> within( const QgsPointXY &point, double radius ) const;
/** /**
* Calls a \a visitor function for all features which are within the given search \a radius * Calls a \a visitor function for all features which are within the given search \a radius
@ -116,6 +116,11 @@ class CORE_EXPORT QgsSpatialIndexKDBush
*/ */
bool point( QgsFeatureId id, QgsPointXY &point ) const; bool point( QgsFeatureId id, QgsPointXY &point ) const;
/**
* Returns the size of the index, i.e. the number of points contained within the index.
*/
qgssize size() const;
private: private:
//! Implicitly shared data pointer //! Implicitly shared data pointer

View File

@ -99,6 +99,11 @@ class PointXYKDBush : public kdbush::KDBush< std::pair<double, double>, QgsFeatu
return true; return true;
} }
std::size_t size() const
{
return points.size();
}
private: private:
QHash< QgsFeatureId, QgsPointXY > mIdToPoint; QHash< QgsFeatureId, QgsPointXY > mIdToPoint;

View File

@ -73,27 +73,28 @@ class TestQgsSpatialIndexKdBush : public QObject
for ( QgsFeature f : _pointFeatures() ) for ( QgsFeature f : _pointFeatures() )
vl->dataProvider()->addFeature( f ); vl->dataProvider()->addFeature( f );
QgsSpatialIndexKDBush index( *vl->dataProvider() ); QgsSpatialIndexKDBush index( *vl->dataProvider() );
QCOMPARE( index.size(), 4 );
QList<QgsFeatureId> fids = index.intersect( QgsRectangle( 0, 0, 10, 10 ) ); QSet<QgsFeatureId> fids = index.intersect( QgsRectangle( 0, 0, 10, 10 ) );
QVERIFY( fids.count() == 1 ); QVERIFY( fids.count() == 1 );
QCOMPARE( fids[0], 1 ); QVERIFY( fids.contains( 1 ) );
QList<QgsFeatureId> fids2 = index.intersect( QgsRectangle( -10, -10, 0, 10 ) ); QSet<QgsFeatureId> fids2 = index.intersect( QgsRectangle( -10, -10, 0, 10 ) );
QCOMPARE( fids2.count(), 2 ); QCOMPARE( fids2.count(), 2 );
QVERIFY( fids2.contains( 2 ) ); QVERIFY( fids2.contains( 2 ) );
QVERIFY( fids2.contains( 3 ) ); QVERIFY( fids2.contains( 3 ) );
QList<QgsFeatureId> fids3 = index.within( QgsPointXY( 0, 0 ), 2 ); QSet<QgsFeatureId> fids3 = index.within( QgsPointXY( 0, 0 ), 2 );
QCOMPARE( fids3.count(), 4 ); QCOMPARE( fids3.count(), 4 );
QVERIFY( fids3.contains( 1 ) ); QVERIFY( fids3.contains( 1 ) );
QVERIFY( fids3.contains( 2 ) ); QVERIFY( fids3.contains( 2 ) );
QVERIFY( fids3.contains( 3 ) ); QVERIFY( fids3.contains( 3 ) );
QVERIFY( fids3.contains( 4 ) ); QVERIFY( fids3.contains( 4 ) );
QList<QgsFeatureId> fids4 = index.within( QgsPointXY( 0, 0 ), 1 ); QSet<QgsFeatureId> fids4 = index.within( QgsPointXY( 0, 0 ), 1 );
QCOMPARE( fids4.count(), 0 ); QCOMPARE( fids4.count(), 0 );
QList<QgsFeatureId> fids5 = index.within( QgsPointXY( -1, -1 ), 2.1 ); QSet<QgsFeatureId> fids5 = index.within( QgsPointXY( -1, -1 ), 2.1 );
QCOMPARE( fids5.count(), 3 ); QCOMPARE( fids5.count(), 3 );
QVERIFY( fids5.contains( 2 ) ); QVERIFY( fids5.contains( 2 ) );
QVERIFY( fids5.contains( 3 ) ); QVERIFY( fids5.contains( 3 ) );
@ -127,9 +128,9 @@ class TestQgsSpatialIndexKdBush : public QObject
QVERIFY( index->d->ref == 2 ); QVERIFY( index->d->ref == 2 );
// test that copied index works // test that copied index works
QList<QgsFeatureId> fids = indexCopy->intersect( QgsRectangle( 0, 0, 10, 10 ) ); QSet<QgsFeatureId> fids = indexCopy->intersect( QgsRectangle( 0, 0, 10, 10 ) );
QVERIFY( fids.count() == 1 ); QVERIFY( fids.count() == 1 );
QCOMPARE( fids[0], 1 ); QVERIFY( fids.contains( 1 ) );
// check that the index is still shared // check that the index is still shared
QCOMPARE( index->d, indexCopy->d ); QCOMPARE( index->d, indexCopy->d );
@ -140,12 +141,13 @@ class TestQgsSpatialIndexKdBush : public QObject
// test that copied index still works // test that copied index still works
fids = indexCopy->intersect( QgsRectangle( 0, 0, 10, 10 ) ); fids = indexCopy->intersect( QgsRectangle( 0, 0, 10, 10 ) );
QVERIFY( fids.count() == 1 ); QVERIFY( fids.count() == 1 );
QCOMPARE( fids[0], 1 ); QVERIFY( fids.contains( 1 ) );
QVERIFY( indexCopy->d->ref == 1 ); QVERIFY( indexCopy->d->ref == 1 );
// assignment operator // assignment operator
std::unique_ptr< QgsVectorLayer > vl2 = qgis::make_unique< QgsVectorLayer >( "Point", QString(), QStringLiteral( "memory" ) ); std::unique_ptr< QgsVectorLayer > vl2 = qgis::make_unique< QgsVectorLayer >( "Point", QString(), QStringLiteral( "memory" ) );
QgsSpatialIndexKDBush index3( *vl2->dataProvider() ); QgsSpatialIndexKDBush index3( *vl2->dataProvider() );
QCOMPARE( index3.size(), 0 );
fids = index3.intersect( QgsRectangle( 0, 0, 10, 10 ) ); fids = index3.intersect( QgsRectangle( 0, 0, 10, 10 ) );
QCOMPARE( fids.count(), 0 ); QCOMPARE( fids.count(), 0 );
QVERIFY( index3.d->ref == 1 ); QVERIFY( index3.d->ref == 1 );
@ -155,7 +157,7 @@ class TestQgsSpatialIndexKdBush : public QObject
QVERIFY( index3.d->ref == 2 ); QVERIFY( index3.d->ref == 2 );
fids = index3.intersect( QgsRectangle( 0, 0, 10, 10 ) ); fids = index3.intersect( QgsRectangle( 0, 0, 10, 10 ) );
QVERIFY( fids.count() == 1 ); QVERIFY( fids.count() == 1 );
QCOMPARE( fids[0], 1 ); QVERIFY( fids.contains( 1 ) );
indexCopy.reset(); indexCopy.reset();
QVERIFY( index3.d->ref == 1 ); QVERIFY( index3.d->ref == 1 );