22#include <spatialindex/SpatialIndex.h> 
   24#include <QMutexLocker> 
   31static Region faceToRegion( 
const QgsMesh &mesh, 
int id, 
bool &ok )
 
   41  const QVector<QgsMeshVertex> &vertices = mesh.
vertices;
 
   43  double xMinimum = vertices[face[0]].x();
 
   44  double yMinimum = vertices[face[0]].y();
 
   45  double xMaximum = vertices[face[0]].x();
 
   46  double yMaximum = vertices[face[0]].y();
 
   48  for ( 
int i = 1; i < face.size(); ++i )
 
   50    xMinimum = std::min( vertices[face[i]].x(), xMinimum );
 
   51    yMinimum = std::min( vertices[face[i]].y(), yMinimum );
 
   52    xMaximum = std::max( vertices[face[i]].x(), xMaximum );
 
   53    yMaximum = std::max( vertices[face[i]].y(), yMaximum );
 
   56  double pt1[2] = { xMinimum, yMinimum };
 
   57  double pt2[2] = { xMaximum, yMaximum };
 
   60  return SpatialIndex::Region( pt1, pt2, 2 );
 
   63static Region edgeToRegion( 
const QgsMesh &mesh, 
int id, 
bool &ok )
 
   68  const double xMinimum = std::min( firstVertex.
x(), secondVertex.
x() );
 
   69  const double yMinimum = std::min( firstVertex.
y(), secondVertex.
y() );
 
   70  const double xMaximum = std::max( firstVertex.
x(), secondVertex.
x() );
 
   71  const double yMaximum = std::max( firstVertex.
y(), secondVertex.
y() );
 
   72  double pt1[2] = { xMinimum, yMinimum };
 
   73  double pt2[2] = { xMaximum, yMaximum };
 
   75  return SpatialIndex::Region( pt1, pt2, 2 );
 
   84class QgisMeshVisitor : 
public SpatialIndex::IVisitor
 
   87    explicit QgisMeshVisitor( QList<int> &list )
 
   90    void visitNode( 
const INode &n )
 override 
   93    void visitData( 
const IData &d )
 override 
   95      mList.append( 
static_cast<int>( d.getIdentifier() ) );
 
   98    void visitData( std::vector<const IData *> &v )
 override 
  111class QgsMeshSpatialIndexCopyVisitor : 
public SpatialIndex::IVisitor
 
  114    explicit QgsMeshSpatialIndexCopyVisitor( SpatialIndex::ISpatialIndex *newIndex )
 
  115      : mNewIndex( newIndex ) {}
 
  117    void visitNode( 
const INode &n )
 override 
  120    void visitData( 
const IData &d )
 override 
  122      SpatialIndex::IShape *shape = 
nullptr;
 
  123      d.getShape( &shape );
 
  124      mNewIndex->insertData( 0, 
nullptr, *shape, d.getIdentifier() );
 
  128    void visitData( std::vector<const IData *> &v )
 override 
  132    SpatialIndex::ISpatialIndex *mNewIndex = 
nullptr;
 
  142class QgsMeshIteratorDataStream : 
public IDataStream
 
  146    explicit QgsMeshIteratorDataStream( 
const QgsMesh &mesh,
 
  148                                        std::function<Region( 
const QgsMesh &mesh, 
int id, 
bool &ok )> featureToRegionFunction,
 
  151      , mFeaturesCount( featuresCount )
 
  152      , mFeatureToRegionFunction( std::move( featureToRegionFunction ) )
 
  153      , mFeedback( feedback )
 
  158    ~QgsMeshIteratorDataStream()
 override 
  164    IData *getNext()
 override 
  166      if ( mFeedback && mFeedback->isCanceled() )
 
  169      RTree::Data *ret = mNextData;
 
  176    bool hasNext()
 override 
  178      return nullptr != mNextData;
 
  182    uint32_t size()
 override 
  184      return static_cast<uint32_t
>( mFeaturesCount );
 
  188    void rewind()
 override 
  196      SpatialIndex::Region r;
 
  197      while ( mIterator < mFeaturesCount )
 
  200        r = mFeatureToRegionFunction( mMesh, mIterator, ok );
 
  203          mNextData = 
new RTree::Data( 0, 
nullptr, r, mIterator );
 
  218    int mFeaturesCount = 0;
 
  219    std::function<Region( 
const QgsMesh &mesh, 
int id, 
bool &ok )> mFeatureToRegionFunction;
 
  220    RTree::Data *mNextData = 
nullptr;
 
  230class QgsMeshSpatialIndexData : 
public QSharedData
 
  233    QgsMeshSpatialIndexData()
 
  248      switch ( elementType )
 
  252          QgsMeshIteratorDataStream fids( fi, fi.
edgeCount(), edgeToRegion, feedback );
 
  258          QgsMeshIteratorDataStream fids( fi, fi.
faceCount(), faceToRegion, feedback );
 
  269    QgsMeshSpatialIndexData( 
const QgsMeshSpatialIndexData &other )
 
  270      : QSharedData( other )
 
  272      const QMutexLocker locker( &other.mMutex );
 
  277      double low[]  = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
 
  278      double high[] = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
 
  279      const SpatialIndex::Region query( low, high, 2 );
 
  280      QgsMeshSpatialIndexCopyVisitor visitor( mRTree.get() );
 
  281      other.mRTree->intersectsWithQuery( query, visitor );
 
  284    ~QgsMeshSpatialIndexData() = 
default;
 
  286    QgsMeshSpatialIndexData &operator=( 
const QgsMeshSpatialIndexData &rh ) = 
delete;
 
  288    void initTree( IDataStream *inputStream = 
nullptr )
 
  291      mStorage.reset( StorageManager::createNewMemoryStorageManager() );
 
  294      const double fillFactor = 0.7;
 
  295      const unsigned int indexCapacity = 10;
 
  296      const unsigned int leafCapacity = 10;
 
  297      const unsigned int dimension = 2;
 
  298      const RTree::RTreeVariant variant = RTree::RV_RSTAR;
 
  301      SpatialIndex::id_type indexId;
 
  303      if ( inputStream && inputStream->hasNext() )
 
  305          RTree::createAndBulkLoadNewRTree(
 
  308            *mStorage, fillFactor,
 
  317          RTree::createNewRTree(
 
  329    std::unique_ptr<SpatialIndex::IStorageManager> mStorage;
 
  332    std::unique_ptr<SpatialIndex::ISpatialIndex> mRTree;
 
  334    mutable QMutex mMutex;
 
  341  d = 
new QgsMeshSpatialIndexData;
 
 
  345  : mElementType( elementType )
 
  347  d = 
new QgsMeshSpatialIndexData( mesh, feedback, 
elementType );
 
 
  351  : mElementType( other.mElementType )
 
 
  360  if ( 
this != &other )
 
  362    mElementType = other.mElementType;
 
 
  371  QgisMeshVisitor visitor( list );
 
  375  const QMutexLocker locker( &d->mMutex );
 
  376  d->mRTree->intersectsWithQuery( r, visitor );
 
 
  384  QgisMeshVisitor visitor( list );
 
  386  double pt[2] = { point.
x(), point.
y() };
 
  387  const Point p( pt, 2 );
 
  389  const QMutexLocker locker( &d->mMutex );
 
  390  d->mRTree->nearestNeighborQuery( 
static_cast<uint32_t
>( neighbors ), p, visitor );
 
 
  402  if ( mesh.
face( faceIndex ).isEmpty() )
 
  406  const SpatialIndex::Region r( faceToRegion( mesh, faceIndex, ok ) );
 
  410  const QMutexLocker locker( &d.constData()->mMutex );
 
  414    d.constData()->mRTree->insertData( 0, 
nullptr, r, faceIndex );
 
  416  catch ( Tools::Exception &e )
 
  419    QgsDebugError( QStringLiteral( 
"Tools::Exception caught: " ).arg( e.what().c_str() ) );
 
  421  catch ( 
const std::exception &e )
 
  424    QgsDebugError( QStringLiteral( 
"std::exception caught: " ).arg( e.what() ) );
 
  428    QgsDebugError( QStringLiteral( 
"unknown spatial index exception caught" ) );
 
 
  434  if ( mesh.
face( faceIndex ).isEmpty() )
 
  436  const QMutexLocker locker( &d.constData()->mMutex );
 
  438  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)
 
QList< int > nearestNeighbor(const QgsPointXY &point, int neighbors) const
Returns nearest neighbors to a point.
 
~QgsMeshSpatialIndex()
Destructor finalizes work with spatial index.
 
Point geometry type, with support for z-dimension and m-values.
 
A rectangle specified with double values.
 
static SpatialIndex::Region rectangleToRegion(const QgsRectangle &rectangle)
Converts a QGIS rectangle to a SpatialIndex region.
 
#define QgsDebugError(str)
 
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.