Skip to content

Commit

Permalink
[api] Allow a feature callback to be specified when building QgsSpati…
Browse files Browse the repository at this point in the history
…alIndexKDBush
  • Loading branch information
nyalldawson committed Jul 26, 2021
1 parent ea29575 commit 8a3d4e7
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 4 deletions.
1 change: 1 addition & 0 deletions python/core/auto_generated/qgsspatialindexkdbush.sip.in
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsspatialindexkdbush.cpp
Expand Up @@ -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();
Expand Down
23 changes: 23 additions & 0 deletions src/core/qgsspatialindexkdbush.h
Expand Up @@ -23,6 +23,7 @@ class QgsFeedback;
class QgsFeatureSource;
class QgsSpatialIndexKDBushPrivate;
class QgsRectangle;
class QgsFeature;

#include "qgis_core.h"
#include "qgsspatialindexkdbushdata.h"
Expand Down Expand Up @@ -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 );

Expand Down
16 changes: 12 additions & 4 deletions src/core/qgsspatialindexkdbush_p.h
Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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;
};
Expand Down

0 comments on commit 8a3d4e7

Please sign in to comment.