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
107 class QgsMeshSpatialIndexCopyVisitor :
public SpatialIndex::IVisitor
110 explicit QgsMeshSpatialIndexCopyVisitor( SpatialIndex::ISpatialIndex *newIndex )
111 : mNewIndex( newIndex ) {}
113 void visitNode(
const INode &n )
override
116 void visitData(
const IData &d )
override
118 SpatialIndex::IShape *shape =
nullptr;
119 d.getShape( &shape );
120 mNewIndex->insertData( 0,
nullptr, *shape, d.getIdentifier() );
124 void visitData( std::vector<const IData *> &v )
override
128 SpatialIndex::ISpatialIndex *mNewIndex =
nullptr;
138 class QgsMeshIteratorDataStream :
public IDataStream
142 explicit QgsMeshIteratorDataStream(
const QgsMesh &mesh,
144 std::function<Region(
const QgsMesh &mesh,
int id )> featureToRegionFunction,
147 , mFeaturesCount( featuresCount )
148 , mFeatureToRegionFunction( featureToRegionFunction )
149 , mFeedback( feedback )
154 ~QgsMeshIteratorDataStream()
override
160 IData *getNext()
override
162 if ( mFeedback && mFeedback->isCanceled() )
165 RTree::Data *ret = mNextData;
172 bool hasNext()
override
174 return nullptr != mNextData;
178 uint32_t size()
override
180 return static_cast<uint32_t
>( mFeaturesCount );
184 void rewind()
override
192 SpatialIndex::Region r;
193 if ( mIterator < mFeaturesCount )
195 r = mFeatureToRegionFunction( mMesh, mIterator );
196 mNextData =
new RTree::Data(
208 int mFeaturesCount = 0;
209 std::function<Region(
const QgsMesh &mesh,
int id )> mFeatureToRegionFunction;
210 RTree::Data *mNextData =
nullptr;
220 class QgsMeshSpatialIndexData :
public QSharedData
223 QgsMeshSpatialIndexData()
238 switch ( elementType )
240 case QgsMesh::ElementType::Edge:
242 QgsMeshIteratorDataStream fids( fi, fi.
edgeCount(), edgeToRegion, feedback );
246 case QgsMesh::ElementType::Face:
248 QgsMeshIteratorDataStream fids( fi, fi.
faceCount(), faceToRegion, feedback );
259 QgsMeshSpatialIndexData(
const QgsMeshSpatialIndexData &other )
260 : QSharedData( other )
262 QMutexLocker locker( &other.mMutex );
267 double low[] = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
268 double high[] = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
269 SpatialIndex::Region query( low, high, 2 );
270 QgsMeshSpatialIndexCopyVisitor visitor( mRTree.get() );
271 other.mRTree->intersectsWithQuery( query, visitor );
274 ~QgsMeshSpatialIndexData() =
default;
276 QgsMeshSpatialIndexData &operator=(
const QgsMeshSpatialIndexData &rh ) =
delete;
278 void initTree( IDataStream *inputStream =
nullptr )
281 mStorage.reset( StorageManager::createNewMemoryStorageManager() );
284 double fillFactor = 0.7;
285 unsigned int indexCapacity = 10;
286 unsigned int leafCapacity = 10;
287 unsigned int dimension = 2;
288 RTree::RTreeVariant variant = RTree::RV_RSTAR;
291 SpatialIndex::id_type indexId;
293 if ( inputStream && inputStream->hasNext() )
295 RTree::createAndBulkLoadNewRTree(
298 *mStorage, fillFactor,
307 RTree::createNewRTree(
319 std::unique_ptr<SpatialIndex::IStorageManager> mStorage;
322 std::unique_ptr<SpatialIndex::ISpatialIndex> mRTree;
324 mutable QMutex mMutex;
331 d =
new QgsMeshSpatialIndexData;
335 : mElementType( elementType )
337 d =
new QgsMeshSpatialIndexData( mesh, feedback,
elementType );
349 if (
this != &other )
357 QgisMeshVisitor visitor( list );
359 SpatialIndex::Region r = rectToRegion( rect );
361 QMutexLocker locker( &d->mMutex );
362 d->mRTree->intersectsWithQuery( r, visitor );
370 QgisMeshVisitor visitor( list );
372 double pt[2] = { point.
x(), point.
y() };
375 QMutexLocker locker( &d->mMutex );
376 d->mRTree->nearestNeighborQuery(
static_cast<uint32_t
>( neighbors ), p, visitor );
Base class for feedback objects to be used for cancellation of something running in a worker thread.
A spatial index for QgsMeshFace or QgsMeshEdge objects.
QList< int > intersects(const QgsRectangle &rectangle) const
Returns a list of face ids with a bounding box which intersects the specified rectangle.
QgsMesh::ElementType elementType() const
Returns the type of mesh elements that are indexed.
QgsMeshSpatialIndex()
Constructor for QgsSpatialIndex.
QgsMeshSpatialIndex & operator=(const QgsMeshSpatialIndex &other)
Implement assignment operator.
QList< int > nearestNeighbor(const QgsPointXY &point, int neighbors) const
Returns nearest neighbors to a point.
~QgsMeshSpatialIndex()
Destructor finalizes work with spatial index.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
QVector< int > QgsMeshFace
List of vertex indexes.
QPair< int, int > QgsMeshEdge
Edge is a straight line seqment between 2 points.
Mesh - vertices, edges and faces.
QVector< QgsMeshVertex > vertices
QgsMeshFace face(int index) const
Returns a face at the index.
int faceCount() const
Returns number of faces.
ElementType
Defines type of mesh elements.
QgsMeshEdge edge(int index) const
Returns an edge at the index.
int edgeCount() const
Returns number of edge.