21 #include <spatialindex/SpatialIndex.h>
23 #include <QMutexLocker>
30 static Region faceToRegion(
const QgsMesh &mesh,
int id )
33 const QVector<QgsMeshVertex> &vertices = mesh.
vertices;
34 Q_ASSERT( face.size() > 0 );
35 double xMinimum = vertices[face[0]].x();
36 double yMinimum = vertices[face[0]].y();
37 double xMaximum = vertices[face[0]].x();
38 double yMaximum = vertices[face[0]].y();
40 for (
int i = 1; i < face.size(); ++i )
42 xMinimum = std::min( vertices[face[i]].x(), xMinimum );
43 yMinimum = std::min( vertices[face[i]].y(), yMinimum );
44 xMaximum = std::max( vertices[face[i]].x(), xMaximum );
45 yMaximum = std::max( vertices[face[i]].y(), yMaximum );
48 double pt1[2] = { xMinimum, yMinimum };
49 double pt2[2] = { xMaximum, yMaximum };
50 return SpatialIndex::Region( pt1, pt2, 2 );
53 static Region edgeToRegion(
const QgsMesh &mesh,
int id )
58 double xMinimum = std::min( firstVertex.
x(), secondVertex.
x() );
59 double yMinimum = std::min( firstVertex.
y(), secondVertex.
y() );
60 double xMaximum = std::max( firstVertex.
x(), secondVertex.
x() );
61 double yMaximum = std::max( firstVertex.
y(), secondVertex.
y() );
62 double pt1[2] = { xMinimum, yMinimum };
63 double pt2[2] = { xMaximum, yMaximum };
64 return SpatialIndex::Region( pt1, pt2, 2 );
71 return SpatialIndex::Region( pt1, pt2, 2 );
80 class QgisMeshVisitor :
public SpatialIndex::IVisitor
83 explicit QgisMeshVisitor( QList<int> &list )
86 void visitNode(
const INode &n )
override
89 void visitData(
const IData &d )
override
91 mList.append(
static_cast<int>( d.getIdentifier() ) );
94 void visitData( std::vector<const IData *> &v )
override
106 class QgsMeshSpatialIndexCopyVisitor :
public SpatialIndex::IVisitor
109 explicit QgsMeshSpatialIndexCopyVisitor( SpatialIndex::ISpatialIndex *newIndex )
110 : mNewIndex( newIndex ) {}
112 void visitNode(
const INode &n )
override
115 void visitData(
const IData &d )
override
117 SpatialIndex::IShape *shape =
nullptr;
118 d.getShape( &shape );
119 mNewIndex->insertData( 0,
nullptr, *shape, d.getIdentifier() );
123 void visitData( std::vector<const IData *> &v )
override
127 SpatialIndex::ISpatialIndex *mNewIndex =
nullptr;
137 class QgsMeshIteratorDataStream :
public IDataStream
141 explicit QgsMeshIteratorDataStream(
const QgsMesh &mesh,
143 std::function<Region(
const QgsMesh &mesh,
int id )> featureToRegionFunction,
146 , mFeaturesCount( featuresCount )
147 , mFeatureToRegionFunction( featureToRegionFunction )
148 , mFeedback( feedback )
153 ~QgsMeshIteratorDataStream()
override
159 IData *getNext()
override
161 if ( mFeedback && mFeedback->isCanceled() )
164 RTree::Data *ret = mNextData;
171 bool hasNext()
override
173 return nullptr != mNextData;
177 uint32_t size()
override
179 return static_cast<uint32_t
>( mFeaturesCount );
183 void rewind()
override
191 SpatialIndex::Region r;
192 if ( mIterator < mFeaturesCount )
194 r = mFeatureToRegionFunction( mMesh, mIterator );
195 mNextData =
new RTree::Data(
207 int mFeaturesCount = 0;
208 std::function<Region(
const QgsMesh &mesh,
int id )> mFeatureToRegionFunction;
209 RTree::Data *mNextData =
nullptr;
219 class QgsMeshSpatialIndexData :
public QSharedData
222 QgsMeshSpatialIndexData()
237 switch ( elementType )
239 case QgsMesh::ElementType::Edge:
241 QgsMeshIteratorDataStream fids( fi, fi.
edgeCount(), edgeToRegion, feedback );
247 QgsMeshIteratorDataStream fids( fi, fi.
faceCount(), faceToRegion, feedback );
258 QgsMeshSpatialIndexData(
const QgsMeshSpatialIndexData &other )
259 : QSharedData( other )
261 QMutexLocker locker( &other.mMutex );
266 double low[] = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
267 double high[] = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
268 SpatialIndex::Region query( low, high, 2 );
269 QgsMeshSpatialIndexCopyVisitor visitor( mRTree.get() );
270 other.mRTree->intersectsWithQuery( query, visitor );
273 ~QgsMeshSpatialIndexData() =
default;
275 QgsMeshSpatialIndexData &operator=(
const QgsMeshSpatialIndexData &rh ) =
delete;
277 void initTree( IDataStream *inputStream =
nullptr )
280 mStorage.reset( StorageManager::createNewMemoryStorageManager() );
283 double fillFactor = 0.7;
284 unsigned int indexCapacity = 10;
285 unsigned int leafCapacity = 10;
286 unsigned int dimension = 2;
287 RTree::RTreeVariant variant = RTree::RV_RSTAR;
290 SpatialIndex::id_type indexId;
292 if ( inputStream && inputStream->hasNext() )
294 RTree::createAndBulkLoadNewRTree(
297 *mStorage, fillFactor,
306 RTree::createNewRTree(
318 std::unique_ptr<SpatialIndex::IStorageManager> mStorage;
321 std::unique_ptr<SpatialIndex::ISpatialIndex> mRTree;
323 mutable QMutex mMutex;
330 d =
new QgsMeshSpatialIndexData;
334 : mElementType( elementType )
336 d =
new QgsMeshSpatialIndexData( mesh, feedback,
elementType );
348 if (
this != &other )
356 QgisMeshVisitor visitor( list );
358 SpatialIndex::Region r = rectToRegion( rect );
360 QMutexLocker locker( &d->mMutex );
361 d->mRTree->intersectsWithQuery( r, visitor );
369 QgisMeshVisitor visitor( list );
371 double pt[2] = { point.
x(), point.
y() };
374 QMutexLocker locker( &d->mMutex );
375 d->mRTree->nearestNeighborQuery(
static_cast<uint32_t
>( neighbors ), p, visitor );