diff --git a/python/core/auto_generated/qgsspatialindexkdbush.sip.in b/python/core/auto_generated/qgsspatialindexkdbush.sip.in index a698091f897..af8178bb327 100644 --- a/python/core/auto_generated/qgsspatialindexkdbush.sip.in +++ b/python/core/auto_generated/qgsspatialindexkdbush.sip.in @@ -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 diff --git a/src/core/qgsspatialindexkdbush.cpp b/src/core/qgsspatialindexkdbush.cpp index 93be1eba451..4b5f32922e0 100644 --- a/src/core/qgsspatialindexkdbush.cpp +++ b/src/core/qgsspatialindexkdbush.cpp @@ -32,6 +32,11 @@ QgsSpatialIndexKDBush::QgsSpatialIndexKDBush( const QgsFeatureSource &source, Qg { } +QgsSpatialIndexKDBush::QgsSpatialIndexKDBush( QgsFeatureIterator &fi, const std::function &callback, QgsFeedback *feedback ) + : d( new QgsSpatialIndexKDBushPrivate( fi, callback, feedback ) ) +{ +} + QgsSpatialIndexKDBush::QgsSpatialIndexKDBush( const QgsSpatialIndexKDBush &other ): d( other.d ) { d->ref.ref(); diff --git a/src/core/qgsspatialindexkdbush.h b/src/core/qgsspatialindexkdbush.h index 3574855f825..470af854946 100644 --- a/src/core/qgsspatialindexkdbush.h +++ b/src/core/qgsspatialindexkdbush.h @@ -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 ); diff --git a/src/core/qgsspatialindexkdbush_p.h b/src/core/qgsspatialindexkdbush_p.h index adc71c968fc..b8ef8e985d5 100644 --- a/src/core/qgsspatialindexkdbush_p.h +++ b/src/core/qgsspatialindexkdbush_p.h @@ -39,25 +39,26 @@ #include #include #include "kdbush.hpp" +#include class PointXYKDBush : public kdbush::KDBush< std::pair, 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, 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; };