27#include <spatialindex/SpatialIndex.h> 
   29#include <QMutexLocker> 
   52      mList.append( d.getIdentifier() );
 
 
   55    void visitData( std::vector<const IData *> &v )
 override 
 
   59    QList<QgsFeatureId> &mList;
 
 
   71      : mNewIndex( newIndex ) {}
 
 
   78      SpatialIndex::IShape *shape = 
nullptr;
 
   80      mNewIndex->insertData( 0, 
nullptr, *shape, d.getIdentifier() );
 
 
   84    void visitData( std::vector<const IData *> &v )
 override 
 
   88    SpatialIndex::ISpatialIndex *mNewIndex = 
nullptr;
 
 
   92class QgsNearestNeighborComparator : 
public INearestNeighborComparator
 
   96    QgsNearestNeighborComparator( 
const QHash< QgsFeatureId, QgsGeometry > *geometries, 
const QgsPointXY &point, 
double maxDistance )
 
   97      : mGeometries( geometries )
 
   99      , mMaxDistance( maxDistance )
 
  103    QgsNearestNeighborComparator( 
const QHash< QgsFeatureId, QgsGeometry > *geometries, 
const QgsGeometry &geometry, 
double maxDistance )
 
  104      : mGeometries( geometries )
 
  106      , mMaxDistance( maxDistance )
 
  110    const QHash< QgsFeatureId, QgsGeometry > *mGeometries = 
nullptr;
 
  112    double mMaxDistance = 0;
 
  113    QSet< QgsFeatureId > mFeaturesOutsideMaxDistance;
 
  115    double getMinimumDistance( 
const IShape &query, 
const IShape &entry )
 override 
  117      return query.getMinimumDistance( entry );
 
  120    double getMinimumDistance( 
const IShape &query, 
const IData &data )
 override 
  124      data.getShape( &pS );
 
  125      double dist = query.getMinimumDistance( *pS );
 
  133      if ( mGeometries && ( mMaxDistance <= 0.0 || dist <= mMaxDistance ) )
 
  135        const QgsGeometry other = mGeometries->value( data.getIdentifier() );
 
  139      if ( mMaxDistance > 0 && dist > mMaxDistance )
 
  149        mFeaturesOutsideMaxDistance.insert( data.getIdentifier() );
 
  150        return mMaxDistance + 0.00000001;
 
  162class QgsFeatureIteratorDataStream : 
public IDataStream
 
  166    explicit QgsFeatureIteratorDataStream( 
const QgsFeatureIterator &fi, 
QgsFeedback *feedback = 
nullptr, QgsSpatialIndex::Flags flags = QgsSpatialIndex::Flags(),
 
  167                                           const std::function< 
bool( 
const QgsFeature & ) > *callback = 
nullptr )
 
  169      , mFeedback( feedback )
 
  171      , mCallback( callback )
 
  176    ~QgsFeatureIteratorDataStream()
 override 
  182    IData *getNext()
 override 
  184      if ( mFeedback && mFeedback->isCanceled() )
 
  187      RTree::Data *ret = mNextData;
 
  194    bool hasNext()
 override { 
return nullptr != mNextData; }
 
  197    uint32_t size()
 override { Q_ASSERT( 
false && 
"not available" ); 
return 0; }
 
  200    void rewind()
 override { Q_ASSERT( 
false && 
"not available" ); }
 
  202    QHash< QgsFeatureId, QgsGeometry > geometries;
 
  208      SpatialIndex::Region r;
 
  210      while ( mFi.nextFeature( f ) )
 
  214          const bool res = ( *mCallback )( f );
 
  221        if ( QgsSpatialIndex::featureInfo( f, r, 
id ) )
 
  223          mNextData = 
new RTree::Data( 0, 
nullptr, r, 
id );
 
  233    RTree::Data *mNextData = 
nullptr;
 
  235    QgsSpatialIndex::Flags mFlags = QgsSpatialIndex::Flags();
 
  236    const std::function< bool( 
const QgsFeature & ) > *mCallback = 
nullptr;
 
  247class QgsSpatialIndexData : 
public QSharedData
 
  250    QgsSpatialIndexData( QgsSpatialIndex::Flags flags )
 
  256    QgsSpatialIndex::Flags mFlags = QgsSpatialIndex::Flags();
 
  258    QHash< QgsFeatureId, QgsGeometry > mGeometries;
 
  268    explicit QgsSpatialIndexData( 
const QgsFeatureIterator &fi, 
QgsFeedback *feedback = 
nullptr, QgsSpatialIndex::Flags flags = QgsSpatialIndex::Flags(),
 
  269                                  const std::function< 
bool( 
const QgsFeature & ) > *callback = 
nullptr )
 
  272      QgsFeatureIteratorDataStream fids( fi, feedback, mFlags, callback );
 
  275        mGeometries = fids.geometries;
 
  278    QgsSpatialIndexData( 
const QgsSpatialIndexData &other )
 
  279      : QSharedData( other )
 
  280      , mFlags( other.mFlags )
 
  281      , mGeometries( other.mGeometries )
 
  283      const QMutexLocker locker( &other.mMutex );
 
  288      double low[]  = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
 
  289      double high[] = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
 
  290      const SpatialIndex::Region query( low, high, 2 );
 
  292      other.mRTree->intersectsWithQuery( query, visitor );
 
  295    ~QgsSpatialIndexData()
 
  301    QgsSpatialIndexData &operator=( 
const QgsSpatialIndexData &rh ) = 
delete;
 
  303    void initTree( IDataStream *inputStream = 
nullptr )
 
  306      mStorage = StorageManager::createNewMemoryStorageManager();
 
  309      const double fillFactor = 0.7;
 
  310      const unsigned long indexCapacity = 10;
 
  311      const unsigned long leafCapacity = 10;
 
  312      const unsigned long dimension = 2;
 
  313      const RTree::RTreeVariant variant = RTree::RV_RSTAR;
 
  316      SpatialIndex::id_type indexId;
 
  318      if ( inputStream && inputStream->hasNext() )
 
  319        mRTree = RTree::createAndBulkLoadNewRTree( RTree::BLM_STR, *inputStream, *mStorage, fillFactor, indexCapacity,
 
  320                 leafCapacity, dimension, variant, indexId );
 
  322        mRTree = RTree::createNewRTree( *mStorage, fillFactor, indexCapacity,
 
  323                                        leafCapacity, dimension, variant, indexId );
 
  327    SpatialIndex::IStorageManager *mStorage = 
nullptr;
 
  330    SpatialIndex::ISpatialIndex *mRTree = 
nullptr;
 
  332    mutable QRecursiveMutex mMutex;
 
  343  d = 
new QgsSpatialIndexData( flags );
 
 
  348  d = 
new QgsSpatialIndexData( fi, feedback, flags );
 
 
  354  d = 
new QgsSpatialIndexData( fi, 
nullptr, flags, &callback );
 
  374  if ( 
this != &other )
 
 
  382  if ( !featureInfo( f, rect, 
id ) )
 
  407  if ( !featureInfo( feature, rect, 
id ) )
 
  414      const QMutexLocker locker( &d->mMutex );
 
  415      d->mGeometries.insert( feature.
id(), feature.
geometry() );
 
 
  424  QgsFeatureList::iterator fIt = features.begin();
 
  426  for ( ; fIt != features.end(); ++fIt )
 
 
  448  const QMutexLocker locker( &d->mMutex );
 
  456  catch ( Tools::Exception &e )
 
  459    QgsDebugError( QStringLiteral( 
"Tools::Exception caught: " ).arg( e.what().c_str() ) );
 
  461  catch ( 
const std::exception &e )
 
  464    QgsDebugError( QStringLiteral( 
"std::exception caught: " ).arg( e.what() ) );
 
  468    QgsDebugError( QStringLiteral( 
"unknown spatial index exception caught" ) );
 
 
  476  SpatialIndex::Region r;
 
  478  if ( !featureInfo( f, r, 
id ) )
 
  481  const QMutexLocker locker( &d->mMutex );
 
  484    d->mGeometries.remove( f.
id() );
 
 
  492  const QMutexLocker locker( &d->mMutex );
 
  495    d->mGeometries.remove( 
id );
 
 
  501  QList<QgsFeatureId> list;
 
  506  const QMutexLocker locker( &d->mMutex );
 
  507  d->mRTree->intersectsWithQuery( r, visitor );
 
 
  514  QList<QgsFeatureId> list;
 
  517  double pt[2] = { point.
x(), point.
y() };
 
  518  const Point p( pt, 2 );
 
  520  const QMutexLocker locker( &d->mMutex );
 
  522                                    point, maxDistance );
 
  523  d->mRTree->nearestNeighborQuery( neighbors, p, visitor, nnc );
 
  525  if ( maxDistance > 0 )
 
  528    list.erase( std::remove_if( list.begin(), list.end(),
 
  531      return nnc.mFeaturesOutsideMaxDistance.contains( id );
 
 
  540  QList<QgsFeatureId> list;
 
  545  const QMutexLocker locker( &d->mMutex );
 
  548  d->mRTree->nearestNeighborQuery( neighbors, r, visitor, nnc );
 
  550  if ( maxDistance > 0 )
 
  553    list.erase( std::remove_if( list.begin(), list.end(),
 
  556      return nnc.mFeaturesOutsideMaxDistance.contains( id );
 
 
  565  const QMutexLocker locker( &d->mMutex );
 
  566  return d->mGeometries.value( 
id );
 
 
Custom visitor that adds found features to list.
void visitNode(const INode &n) override
void visitData(std::vector< const IData * > &v) override
QgisVisitor(QList< QgsFeatureId > &list)
void visitData(const IData &d) override
Wrapper for iterator of features from vector data provider or vector layer.
This class wraps a request for features to a vector layer (or directly its vector data provider).
An interface for objects which provide features via a getFeatures method.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
A geometry is the spatial representation of a feature.
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
A class to represent a 2D point.
A rectangle specified with double values.
bool isFinite() const
Returns true if the rectangle has finite boundaries.
void visitData(std::vector< const IData * > &v) override
void visitData(const IData &d) override
QgsSpatialIndexCopyVisitor(SpatialIndex::ISpatialIndex *newIndex)
void visitNode(const INode &n) override
static SpatialIndex::Region rectangleToRegion(const QgsRectangle &rectangle)
Converts a QGIS rectangle to a SpatialIndex region.
A spatial index for QgsFeature objects.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the index.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
QgsSpatialIndex & operator=(const QgsSpatialIndex &other)
Implement assignment operator.
QgsSpatialIndex(QgsSpatialIndex::Flags flags=QgsSpatialIndex::Flags())
Constructor for QgsSpatialIndex.
QAtomicInt refs() const
Gets reference count - just for debugging!
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
~QgsSpatialIndex() override
Destructor finalizes work with spatial index.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a feature to the index.
Q_DECL_DEPRECATED bool insertFeature(const QgsFeature &feature)
Adds a feature to the index.
QgsGeometry geometry(QgsFeatureId id) const
Returns the stored geometry for the indexed feature with matching id.
bool deleteFeature(const QgsFeature &feature)
Removes a feature from the index.
QList< QgsFeature > QgsFeatureList
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define FID_TO_NUMBER(fid)
#define QgsDebugError(str)