[api] Allow a feature callback to be specified when building QgsSpatialIndexKDBush

This commit is contained in:
Nyall Dawson 2021-07-26 10:28:07 +10:00
parent ea2957507b
commit 8a3d4e736c
4 changed files with 41 additions and 4 deletions

View File

@ -58,6 +58,7 @@ that of the spatial index construction.
Any non-single point features encountered during iteration will be ignored and not included in the index.
%End
QgsSpatialIndexKDBush( const QgsSpatialIndexKDBush &other );
%Docstring
Copy constructor

View File

@ -32,6 +32,11 @@ QgsSpatialIndexKDBush::QgsSpatialIndexKDBush( const QgsFeatureSource &source, Qg
{
}
QgsSpatialIndexKDBush::QgsSpatialIndexKDBush( QgsFeatureIterator &fi, const std::function<bool ( const QgsFeature & )> &callback, QgsFeedback *feedback )
: d( new QgsSpatialIndexKDBushPrivate( fi, callback, feedback ) )
{
}
QgsSpatialIndexKDBush::QgsSpatialIndexKDBush( const QgsSpatialIndexKDBush &other ): d( other.d )
{
d->ref.ref();

View File

@ -23,6 +23,7 @@ class QgsFeedback;
class QgsFeatureSource;
class QgsSpatialIndexKDBushPrivate;
class QgsRectangle;
class QgsFeature;
#include "qgis_core.h"
#include "qgsspatialindexkdbushdata.h"
@ -76,6 +77,28 @@ class CORE_EXPORT QgsSpatialIndexKDBush
*/
explicit QgsSpatialIndexKDBush( const QgsFeatureSource &source, QgsFeedback *feedback = nullptr );
#ifndef SIP_RUN
/**
* Constructor - creates KDBush index and bulk loads it with features from the source.
*
* This constructor allows for a \a callback function to be specified, which is
* called for each added feature in turn. It allows for bulk spatial index load along with other feature
* based operations on a single iteration through a feature source. If \a callback returns FALSE, the
* load and iteration is canceled.
*
* The optional \a feedback object can be used to allow cancellation of bulk feature loading. Ownership
* of \a feedback is not transferred, and callers must take care that the lifetime of feedback exceeds
* that of the spatial index construction.
*
* Any non-single point features encountered during iteration will be ignored and not included in the index.
*
* \note Not available in Python bindings
* \since QGIS 3.22
*/
explicit QgsSpatialIndexKDBush( QgsFeatureIterator &fi, const std::function< bool( const QgsFeature & ) > &callback, QgsFeedback *feedback = nullptr );
#endif
//! Copy constructor
QgsSpatialIndexKDBush( const QgsSpatialIndexKDBush &other );

View File

@ -39,25 +39,26 @@
#include <memory>
#include <QList>
#include "kdbush.hpp"
#include <functional>
class PointXYKDBush : public kdbush::KDBush< std::pair<double, double>, QgsSpatialIndexKDBushData, std::size_t >
{
public:
explicit PointXYKDBush( QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr )
explicit PointXYKDBush( QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr, const std::function< bool( const QgsFeature & ) > *callback = nullptr )
{
fillFromIterator( fi, feedback );
fillFromIterator( fi, feedback, callback );
}
explicit PointXYKDBush( const QgsFeatureSource &source, QgsFeedback *feedback )
{
points.reserve( source.featureCount() );
QgsFeatureIterator it = source.getFeatures( QgsFeatureRequest().setNoAttributes() );
fillFromIterator( it, feedback );
fillFromIterator( it, feedback, nullptr );
}
void fillFromIterator( QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr )
void fillFromIterator( QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr, const std::function< bool( const QgsFeature & ) > *callback = nullptr )
{
std::size_t size = 0;
@ -67,6 +68,9 @@ class PointXYKDBush : public kdbush::KDBush< std::pair<double, double>, QgsSpati
if ( feedback && feedback->isCanceled() )
return;
if ( callback && !( *callback )( f ) )
return;
if ( !f.hasGeometry() )
continue;
@ -109,6 +113,10 @@ class QgsSpatialIndexKDBushPrivate
: index( std::make_unique < PointXYKDBush >( source, feedback ) )
{}
explicit QgsSpatialIndexKDBushPrivate( QgsFeatureIterator &fi, const std::function< bool( const QgsFeature & ) > &callback, QgsFeedback *feedback = nullptr )
: index( std::make_unique < PointXYKDBush >( fi, feedback, &callback ) )
{}
QAtomicInt ref = 1;
std::unique_ptr< PointXYKDBush > index;
};