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;
 
 
   72      : mNewIndex( newIndex ) {}
 
 
   79      SpatialIndex::IShape *shape = 
nullptr;
 
   81      mNewIndex->insertData( 0, 
nullptr, *shape, d.getIdentifier() );
 
 
   85    void visitData( std::vector<const IData *> &v )
 override 
 
   89    SpatialIndex::ISpatialIndex *mNewIndex = 
nullptr;
 
 
   93class QgsNearestNeighborComparator : 
public INearestNeighborComparator
 
   97    QgsNearestNeighborComparator( 
const QHash< QgsFeatureId, QgsGeometry > *geometries, 
const QgsPointXY &point, 
double maxDistance )
 
   98      : mGeometries( geometries )
 
  100      , mMaxDistance( maxDistance )
 
  104    QgsNearestNeighborComparator( 
const QHash< QgsFeatureId, QgsGeometry > *geometries, 
const QgsGeometry &geometry, 
double maxDistance )
 
  105      : mGeometries( geometries )
 
  107      , mMaxDistance( maxDistance )
 
  111    const QHash< QgsFeatureId, QgsGeometry > *mGeometries = 
nullptr;
 
  113    double mMaxDistance = 0;
 
  114    QSet< QgsFeatureId > mFeaturesOutsideMaxDistance;
 
  116    double getMinimumDistance( 
const IShape &query, 
const IShape &entry )
 override 
  118      return query.getMinimumDistance( entry );
 
  121    double getMinimumDistance( 
const IShape &query, 
const IData &data )
 override 
  125      data.getShape( &pS );
 
  126      double dist = query.getMinimumDistance( *pS );
 
  134      if ( mGeometries && ( mMaxDistance <= 0.0 || dist <= mMaxDistance ) )
 
  136        const QgsGeometry other = mGeometries->value( data.getIdentifier() );
 
  140      if ( mMaxDistance > 0 && dist > mMaxDistance )
 
  150        mFeaturesOutsideMaxDistance.insert( data.getIdentifier() );
 
  151        return mMaxDistance + 0.00000001;
 
  163class QgsFeatureIteratorDataStream : 
public IDataStream
 
  168                                           const std::function< 
bool( 
const QgsFeature & ) > *callback = 
nullptr )
 
  170      , mFeedback( feedback )
 
  172      , mCallback( callback )
 
  177    ~QgsFeatureIteratorDataStream()
 override 
  183    IData *getNext()
 override 
  185      if ( mFeedback && mFeedback->isCanceled() )
 
  188      RTree::Data *ret = mNextData;
 
  195    bool hasNext()
 override { 
return nullptr != mNextData; }
 
  198    uint32_t size()
 override { Q_ASSERT( 
false && 
"not available" ); 
return 0; }
 
  201    void rewind()
 override { Q_ASSERT( 
false && 
"not available" ); }
 
  203    QHash< QgsFeatureId, QgsGeometry > geometries;
 
  209      SpatialIndex::Region r;
 
  211      while ( mFi.nextFeature( f ) )
 
  215          const bool res = ( *mCallback )( f );
 
  222        if ( QgsSpatialIndex::featureInfo( f, r, 
id ) )
 
  224          mNextData = 
new RTree::Data( 0, 
nullptr, r, 
id );
 
  234    RTree::Data *mNextData = 
nullptr;
 
  237    const std::function< bool( 
const QgsFeature & ) > *mCallback = 
nullptr;
 
  248class QgsSpatialIndexData : 
public QSharedData
 
  259    QHash< QgsFeatureId, QgsGeometry > mGeometries;
 
  270                                  const std::function< 
bool( 
const QgsFeature & ) > *callback = 
nullptr )
 
  273      QgsFeatureIteratorDataStream fids( fi, feedback, mFlags, callback );
 
  276        mGeometries = fids.geometries;
 
  279    QgsSpatialIndexData( 
const QgsSpatialIndexData &other )
 
  280      : QSharedData( other )
 
  281      , mFlags( other.mFlags )
 
  282      , mGeometries( other.mGeometries )
 
  284      const QMutexLocker locker( &other.mMutex );
 
  289      double low[]  = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
 
  290      double high[] = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
 
  291      const SpatialIndex::Region query( low, high, 2 );
 
  293      other.mRTree->intersectsWithQuery( query, visitor );
 
  296    ~QgsSpatialIndexData()
 
  302    QgsSpatialIndexData &operator=( 
const QgsSpatialIndexData &rh ) = 
delete;
 
  304    void initTree( IDataStream *inputStream = 
nullptr )
 
  307      mStorage = StorageManager::createNewMemoryStorageManager();
 
  310      const double fillFactor = 0.7;
 
  311      const unsigned long indexCapacity = 10;
 
  312      const unsigned long leafCapacity = 10;
 
  313      const unsigned long dimension = 2;
 
  314      const RTree::RTreeVariant variant = RTree::RV_RSTAR;
 
  317      SpatialIndex::id_type indexId;
 
  319      if ( inputStream && inputStream->hasNext() )
 
  320        mRTree = RTree::createAndBulkLoadNewRTree( RTree::BLM_STR, *inputStream, *mStorage, fillFactor, indexCapacity,
 
  321                 leafCapacity, dimension, variant, indexId );
 
  323        mRTree = RTree::createNewRTree( *mStorage, fillFactor, indexCapacity,
 
  324                                        leafCapacity, dimension, variant, indexId );
 
  328    SpatialIndex::IStorageManager *mStorage = 
nullptr;
 
  331    SpatialIndex::ISpatialIndex *mRTree = 
nullptr;
 
  333    mutable QRecursiveMutex mMutex;
 
  344  d = 
new QgsSpatialIndexData( flags );
 
 
  349  d = 
new QgsSpatialIndexData( fi, feedback, flags );
 
 
  355  d = 
new QgsSpatialIndexData( fi, 
nullptr, flags, &callback );
 
  375  if ( 
this != &other )
 
 
  383  if ( !featureInfo( f, rect, 
id ) )
 
  408  if ( !featureInfo( feature, rect, 
id ) )
 
  415      const QMutexLocker locker( &d->mMutex );
 
  416      d->mGeometries.insert( feature.
id(), feature.
geometry() );
 
 
  425  QgsFeatureList::iterator fIt = features.begin();
 
  427  for ( ; fIt != features.end(); ++fIt )
 
 
  449  const QMutexLocker locker( &d->mMutex );
 
  457  catch ( Tools::Exception &e )
 
  460    QgsDebugError( QStringLiteral( 
"Tools::Exception caught: " ).arg( e.what().c_str() ) );
 
  462  catch ( 
const std::exception &e )
 
  465    QgsDebugError( QStringLiteral( 
"std::exception caught: " ).arg( e.what() ) );
 
  469    QgsDebugError( QStringLiteral( 
"unknown spatial index exception caught" ) );
 
 
  477  SpatialIndex::Region r;
 
  479  if ( !featureInfo( f, r, 
id ) )
 
  482  const QMutexLocker locker( &d->mMutex );
 
  485    d->mGeometries.remove( f.
id() );
 
 
  493  const QMutexLocker locker( &d->mMutex );
 
  496    d->mGeometries.remove( 
id );
 
 
  502  QList<QgsFeatureId> list;
 
  507  const QMutexLocker locker( &d->mMutex );
 
  508  d->mRTree->intersectsWithQuery( r, visitor );
 
 
  515  QList<QgsFeatureId> list;
 
  518  double pt[2] = { point.
x(), point.
y() };
 
  519  const Point p( pt, 2 );
 
  521  const QMutexLocker locker( &d->mMutex );
 
  523                                    point, maxDistance );
 
  524  d->mRTree->nearestNeighborQuery( neighbors, p, visitor, nnc );
 
  526  if ( maxDistance > 0 )
 
  529    list.erase( std::remove_if( list.begin(), list.end(),
 
  532      return nnc.mFeaturesOutsideMaxDistance.contains( id );
 
 
  541  QList<QgsFeatureId> list;
 
  546  const QMutexLocker locker( &d->mMutex );
 
  549  d->mRTree->nearestNeighborQuery( neighbors, r, visitor, nnc );
 
  551  if ( maxDistance > 0 )
 
  554    list.erase( std::remove_if( list.begin(), list.end(),
 
  557      return nnc.mFeaturesOutsideMaxDistance.contains( id );
 
 
  566  const QMutexLocker locker( &d->mMutex );
 
  567  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.
 
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 rectangle specified with double values.
 
bool isFinite() const
Returns true if the rectangle has finite boundaries.
 
SpatialIndex visitor which copies data to a new index.
 
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)
 
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)