21 #include <spatialindex/SpatialIndex.h> 
   23 #include <QMutexLocker> 
   30 static Region faceToRegion( 
const QgsMesh &mesh, 
int id, 
bool &ok )
 
   40   const QVector<QgsMeshVertex> &vertices = mesh.
vertices;
 
   42   double xMinimum = vertices[face[0]].x();
 
   43   double yMinimum = vertices[face[0]].y();
 
   44   double xMaximum = vertices[face[0]].x();
 
   45   double yMaximum = vertices[face[0]].y();
 
   47   for ( 
int i = 1; i < face.size(); ++i )
 
   49     xMinimum = std::min( vertices[face[i]].x(), xMinimum );
 
   50     yMinimum = std::min( vertices[face[i]].y(), yMinimum );
 
   51     xMaximum = std::max( vertices[face[i]].x(), xMaximum );
 
   52     yMaximum = std::max( vertices[face[i]].y(), yMaximum );
 
   55   double pt1[2] = { xMinimum, yMinimum };
 
   56   double pt2[2] = { xMaximum, yMaximum };
 
   59   return SpatialIndex::Region( pt1, pt2, 2 );
 
   62 static Region edgeToRegion( 
const QgsMesh &mesh, 
int id, 
bool &ok )
 
   67   const double xMinimum = std::min( firstVertex.
x(), secondVertex.
x() );
 
   68   const double yMinimum = std::min( firstVertex.
y(), secondVertex.
y() );
 
   69   const double xMaximum = std::max( firstVertex.
x(), secondVertex.
x() );
 
   70   const double yMaximum = std::max( firstVertex.
y(), secondVertex.
y() );
 
   71   double pt1[2] = { xMinimum, yMinimum };
 
   72   double pt2[2] = { xMaximum, yMaximum };
 
   74   return SpatialIndex::Region( pt1, pt2, 2 );
 
   81   return SpatialIndex::Region( pt1, pt2, 2 );
 
   90 class QgisMeshVisitor : 
public SpatialIndex::IVisitor
 
   93     explicit QgisMeshVisitor( QList<int> &list )
 
   96     void visitNode( 
const INode &n )
 override 
   99     void visitData( 
const IData &d )
 override 
  101       mList.append( 
static_cast<int>( d.getIdentifier() ) );
 
  104     void visitData( std::vector<const IData *> &v )
 override 
  117 class QgsMeshSpatialIndexCopyVisitor : 
public SpatialIndex::IVisitor
 
  120     explicit QgsMeshSpatialIndexCopyVisitor( SpatialIndex::ISpatialIndex *newIndex )
 
  121       : mNewIndex( newIndex ) {}
 
  123     void visitNode( 
const INode &n )
 override 
  126     void visitData( 
const IData &d )
 override 
  128       SpatialIndex::IShape *shape = 
nullptr;
 
  129       d.getShape( &shape );
 
  130       mNewIndex->insertData( 0, 
nullptr, *shape, d.getIdentifier() );
 
  134     void visitData( std::vector<const IData *> &v )
 override 
  138     SpatialIndex::ISpatialIndex *mNewIndex = 
nullptr;
 
  148 class QgsMeshIteratorDataStream : 
public IDataStream
 
  152     explicit QgsMeshIteratorDataStream( 
const QgsMesh &mesh,
 
  154                                         std::function<Region( 
const QgsMesh &mesh, 
int id, 
bool &ok )> featureToRegionFunction,
 
  157       , mFeaturesCount( featuresCount )
 
  158       , mFeatureToRegionFunction( featureToRegionFunction )
 
  159       , mFeedback( feedback )
 
  164     ~QgsMeshIteratorDataStream()
 override 
  170     IData *getNext()
 override 
  172       if ( mFeedback && mFeedback->isCanceled() )
 
  175       RTree::Data *ret = mNextData;
 
  182     bool hasNext()
 override 
  184       return nullptr != mNextData;
 
  188     uint32_t size()
 override 
  190       return static_cast<uint32_t
>( mFeaturesCount );
 
  194     void rewind()
 override 
  202       SpatialIndex::Region r;
 
  203       while ( mIterator < mFeaturesCount )
 
  206         r = mFeatureToRegionFunction( mMesh, mIterator, ok );
 
  209           mNextData = 
new RTree::Data( 0, 
nullptr, r, mIterator );
 
  224     int mFeaturesCount = 0;
 
  225     std::function<Region( 
const QgsMesh &mesh, 
int id, 
bool &ok )> mFeatureToRegionFunction;
 
  226     RTree::Data *mNextData = 
nullptr;
 
  236 class QgsMeshSpatialIndexData : 
public QSharedData
 
  239     QgsMeshSpatialIndexData()
 
  254       switch ( elementType )
 
  256         case QgsMesh::ElementType::Edge:
 
  258           QgsMeshIteratorDataStream fids( fi, fi.
edgeCount(), edgeToRegion, feedback );
 
  262         case QgsMesh::ElementType::Face:
 
  264           QgsMeshIteratorDataStream fids( fi, fi.
faceCount(), faceToRegion, feedback );
 
  275     QgsMeshSpatialIndexData( 
const QgsMeshSpatialIndexData &other )
 
  276       : QSharedData( other )
 
  278       const QMutexLocker locker( &other.mMutex );
 
  283       double low[]  = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
 
  284       double high[] = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
 
  285       const SpatialIndex::Region query( low, high, 2 );
 
  286       QgsMeshSpatialIndexCopyVisitor visitor( mRTree.get() );
 
  287       other.mRTree->intersectsWithQuery( query, visitor );
 
  290     ~QgsMeshSpatialIndexData() = 
default;
 
  292     QgsMeshSpatialIndexData &operator=( 
const QgsMeshSpatialIndexData &rh ) = 
delete;
 
  294     void initTree( IDataStream *inputStream = 
nullptr )
 
  297       mStorage.reset( StorageManager::createNewMemoryStorageManager() );
 
  300       const double fillFactor = 0.7;
 
  301       const unsigned int indexCapacity = 10;
 
  302       const unsigned int leafCapacity = 10;
 
  303       const unsigned int dimension = 2;
 
  304       const RTree::RTreeVariant variant = RTree::RV_RSTAR;
 
  307       SpatialIndex::id_type indexId;
 
  309       if ( inputStream && inputStream->hasNext() )
 
  311           RTree::createAndBulkLoadNewRTree(
 
  314             *mStorage, fillFactor,
 
  323           RTree::createNewRTree(
 
  335     std::unique_ptr<SpatialIndex::IStorageManager> mStorage;
 
  338     std::unique_ptr<SpatialIndex::ISpatialIndex> mRTree;
 
  340     mutable QMutex mMutex;
 
  347   d = 
new QgsMeshSpatialIndexData;
 
  351   : mElementType( elementType )
 
  353   d = 
new QgsMeshSpatialIndexData( mesh, feedback, 
elementType );
 
  365   if ( 
this != &other )
 
  373   QgisMeshVisitor visitor( list );
 
  375   const SpatialIndex::Region r = rectToRegion( rect );
 
  377   const QMutexLocker locker( &d->mMutex );
 
  378   d->mRTree->intersectsWithQuery( r, visitor );
 
  386   QgisMeshVisitor visitor( list );
 
  388   double pt[2] = { point.
x(), point.
y() };
 
  389   const Point p( pt, 2 );
 
  391   const QMutexLocker locker( &d->mMutex );
 
  392   d->mRTree->nearestNeighborQuery( 
static_cast<uint32_t
>( neighbors ), p, visitor );
 
  404   if ( mesh.
face( faceIndex ).isEmpty() )
 
  408   const SpatialIndex::Region r( faceToRegion( mesh, faceIndex, ok ) );
 
  412   const QMutexLocker locker( &d.constData()->mMutex );
 
  416     d.constData()->mRTree->insertData( 0, 
nullptr, r, faceIndex );
 
  418   catch ( Tools::Exception &e )
 
  421     QgsDebugMsg( QStringLiteral( 
"Tools::Exception caught: " ).arg( e.what().c_str() ) );
 
  423   catch ( 
const std::exception &e )
 
  426     QgsDebugMsg( QStringLiteral( 
"std::exception caught: " ).arg( e.what() ) );
 
  430     QgsDebugMsg( QStringLiteral( 
"unknown spatial index exception caught" ) );
 
  436   if ( mesh.
face( faceIndex ).isEmpty() )
 
  438   const QMutexLocker locker( &d.constData()->mMutex );
 
  440   d.constData()->mRTree->deleteData( faceToRegion( mesh, faceIndex, ok ), faceIndex );
 
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.
 
void addFace(int faceIndex, const QgsMesh &mesh)
Adds a face with faceIndex from the mesh in the spatial index.
 
void removeFace(int faceIndex, const QgsMesh &mesh)
Removes a face with faceIndex from the mesh in the spatial index.
 
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.