26 #include <spatialindex/SpatialIndex.h> 28 #include <QMutexLocker> 51 mList.append( d.getIdentifier() );
54 void visitData( std::vector<const IData *> &v )
override 58 QList<QgsFeatureId> &mList;
70 : mNewIndex( newIndex ) {}
77 SpatialIndex::IShape *shape =
nullptr;
79 mNewIndex->insertData( 0,
nullptr, *shape, d.getIdentifier() );
83 void visitData( std::vector<const IData *> &v )
override 87 SpatialIndex::ISpatialIndex *mNewIndex =
nullptr;
91 class QgsNearestNeighborComparator :
public INearestNeighborComparator
95 QgsNearestNeighborComparator(
const QHash< QgsFeatureId, QgsGeometry > *geometries,
const QgsPointXY &point,
double maxDistance )
96 : mGeometries( geometries )
98 , mMaxDistance( maxDistance )
102 QgsNearestNeighborComparator(
const QHash< QgsFeatureId, QgsGeometry > *geometries,
const QgsGeometry &geometry,
double maxDistance )
103 : mGeometries( geometries )
105 , mMaxDistance( maxDistance )
109 const QHash< QgsFeatureId, QgsGeometry > *mGeometries =
nullptr;
111 double mMaxDistance = 0;
112 QSet< QgsFeatureId > mFeaturesOutsideMaxDistance;
114 double getMinimumDistance(
const IShape &query,
const IShape &entry )
override 116 return query.getMinimumDistance( entry );
119 double getMinimumDistance(
const IShape &query,
const IData &data )
override 123 data.getShape( &pS );
124 double dist = query.getMinimumDistance( *pS );
132 if ( mGeometries && ( mMaxDistance <= 0.0 || dist <= mMaxDistance ) )
134 QgsGeometry other = mGeometries->value( data.getIdentifier() );
138 if ( mMaxDistance > 0 && dist > mMaxDistance )
148 mFeaturesOutsideMaxDistance.insert( data.getIdentifier() );
149 return mMaxDistance + 0.00000001;
161 class QgsFeatureIteratorDataStream :
public IDataStream
165 explicit QgsFeatureIteratorDataStream(
const QgsFeatureIterator &fi,
QgsFeedback *feedback =
nullptr, QgsSpatialIndex::Flags flags =
nullptr )
167 , mFeedback( feedback )
173 ~QgsFeatureIteratorDataStream()
override 179 IData *getNext()
override 181 if ( mFeedback && mFeedback->isCanceled() )
184 RTree::Data *ret = mNextData;
191 bool hasNext()
override {
return nullptr != mNextData; }
194 uint32_t size()
override { Q_ASSERT(
false &&
"not available" );
return 0; }
197 void rewind()
override { Q_ASSERT(
false &&
"not available" ); }
199 QHash< QgsFeatureId, QgsGeometry > geometries;
205 SpatialIndex::Region r;
207 while ( mFi.nextFeature( f ) )
209 if ( QgsSpatialIndex::featureInfo( f, r,
id ) )
211 mNextData =
new RTree::Data( 0,
nullptr, r,
id );
221 RTree::Data *mNextData =
nullptr;
223 QgsSpatialIndex::Flags mFlags =
nullptr;
234 class QgsSpatialIndexData :
public QSharedData
237 QgsSpatialIndexData( QgsSpatialIndex::Flags flags )
243 QgsSpatialIndex::Flags mFlags =
nullptr;
245 QHash< QgsFeatureId, QgsGeometry > mGeometries;
258 QgsFeatureIteratorDataStream fids( fi, feedback, mFlags );
261 mGeometries = fids.geometries;
264 QgsSpatialIndexData(
const QgsSpatialIndexData &other )
265 : QSharedData( other )
266 , mFlags( other.mFlags )
267 , mGeometries( other.mGeometries )
269 QMutexLocker locker( &other.mMutex );
274 double low[] = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
275 double high[] = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
276 SpatialIndex::Region query( low, high, 2 );
278 other.mRTree->intersectsWithQuery( query, visitor );
281 ~QgsSpatialIndexData()
287 QgsSpatialIndexData &operator=(
const QgsSpatialIndexData &rh ) =
delete;
289 void initTree( IDataStream *inputStream =
nullptr )
292 mStorage = StorageManager::createNewMemoryStorageManager();
295 double fillFactor = 0.7;
296 unsigned long indexCapacity = 10;
297 unsigned long leafCapacity = 10;
298 unsigned long dimension = 2;
299 RTree::RTreeVariant variant = RTree::RV_RSTAR;
302 SpatialIndex::id_type indexId;
304 if ( inputStream && inputStream->hasNext() )
305 mRTree = RTree::createAndBulkLoadNewRTree( RTree::BLM_STR, *inputStream, *mStorage, fillFactor, indexCapacity,
306 leafCapacity, dimension, variant, indexId );
308 mRTree = RTree::createNewRTree( *mStorage, fillFactor, indexCapacity,
309 leafCapacity, dimension, variant, indexId );
313 SpatialIndex::IStorageManager *mStorage =
nullptr;
316 SpatialIndex::ISpatialIndex *mRTree =
nullptr;
318 mutable QMutex mMutex;
329 d =
new QgsSpatialIndexData( flags );
334 d =
new QgsSpatialIndexData( fi, feedback, flags );
353 if (
this != &other )
358 SpatialIndex::Region QgsSpatialIndex::rectToRegion(
const QgsRectangle &rect )
362 return SpatialIndex::Region( pt1, pt2, 2 );
368 if ( !featureInfo( f, rect,
id ) )
371 r = rectToRegion( rect );
393 if ( !featureInfo( feature, rect,
id ) )
400 QMutexLocker locker( &d->mMutex );
401 d->mGeometries.insert( feature.
id(), feature.
geometry() );
410 QgsFeatureList::iterator fIt = features.begin();
412 for ( ; fIt != features.end(); ++fIt )
432 SpatialIndex::Region r( rectToRegion( bounds ) );
434 QMutexLocker locker( &d->mMutex );
442 catch ( Tools::Exception &e )
445 QgsDebugMsg( QStringLiteral(
"Tools::Exception caught: " ).arg( e.what().c_str() ) );
447 catch (
const std::exception &e )
450 QgsDebugMsg( QStringLiteral(
"std::exception caught: " ).arg( e.what() ) );
454 QgsDebugMsg( QStringLiteral(
"unknown spatial index exception caught" ) );
462 SpatialIndex::Region r;
464 if ( !featureInfo( f, r,
id ) )
467 QMutexLocker locker( &d->mMutex );
470 d->mGeometries.remove( f.
id() );
476 QList<QgsFeatureId> list;
479 SpatialIndex::Region r = rectToRegion( rect );
481 QMutexLocker locker( &d->mMutex );
482 d->mRTree->intersectsWithQuery( r, visitor );
489 QList<QgsFeatureId> list;
492 double pt[2] = { point.
x(), point.
y() };
495 QMutexLocker locker( &d->mMutex );
497 point, maxDistance );
498 d->mRTree->nearestNeighborQuery( neighbors, p, visitor, nnc );
500 if ( maxDistance > 0 )
503 list.erase( std::remove_if( list.begin(), list.end(),
506 return nnc.mFeaturesOutsideMaxDistance.contains(
id );
515 QList<QgsFeatureId> list;
518 SpatialIndex::Region r = rectToRegion( geometry.
boundingBox() );
520 QMutexLocker locker( &d->mMutex );
522 geometry, maxDistance );
523 d->mRTree->nearestNeighborQuery( neighbors, r, visitor, nnc );
525 if ( maxDistance > 0 )
528 list.erase( std::remove_if( list.begin(), list.end(),
531 return nnc.mFeaturesOutsideMaxDistance.contains(
id );
540 QMutexLocker locker( &d->mMutex );
541 return d->mGeometries.value(
id );
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
QgsGeometry geometry(QgsFeatureId id) const
Returns the stored geometry for the indexed feature with matching id.
QgsSpatialIndex & operator=(const QgsSpatialIndex &other)
Implement assignment operator.
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry.
QList< QgsFeature > QgsFeatureList
A class to represent a 2D point.
void visitNode(const INode &n) override
A geometry is the spatial representation of a feature.
Q_DECL_DEPRECATED bool insertFeature(const QgsFeature &feature)
Adds a feature to the index.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
QgsSpatialIndexCopyVisitor(SpatialIndex::ISpatialIndex *newIndex)
void visitNode(const INode &n) override
Base class for feedback objects to be used for cancellation of something running in a worker thread...
QgisVisitor(QList< QgsFeatureId > &list)
void visitData(std::vector< const IData *> &v) override
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void visitData(const IData &d) override
void visitData(std::vector< const IData *> &v) override
bool isFinite() const
Returns true if the rectangle has finite boundaries.
QgsSpatialIndex(QgsSpatialIndex::Flags flags=nullptr)
Constructor for QgsSpatialIndex.
void visitData(const IData &d) override
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
bool deleteFeature(const QgsFeature &feature)
Removes a feature from the index.
A spatial index for QgsFeature objects.
An interface for objects which provide features via a getFeatures method.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the index.
Custom visitor that adds found features to list.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
#define FID_TO_NUMBER(fid)
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) override
Adds a feature to the index.
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
~QgsSpatialIndex() override
Destructor finalizes work with spatial index.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
Indicates that the spatial index should also store feature geometries. This requires more memory...
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
QAtomicInt refs() const
Gets reference count - just for debugging!