21#include <spatialindex/SpatialIndex.h> 
   23#include <QMutexLocker> 
   30static 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 );
 
   62static 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 );
 
   90class 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 
  117class 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;
 
  148class 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;
 
  236class QgsMeshSpatialIndexData : 
public QSharedData
 
  239    QgsMeshSpatialIndexData()
 
  254      switch ( elementType )
 
  258          QgsMeshIteratorDataStream fids( fi, fi.
edgeCount(), edgeToRegion, feedback );
 
  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 );
 
 
  357  : mElementType( other.mElementType )
 
 
  366  if ( 
this != &other )
 
  368    mElementType = other.mElementType;
 
 
  377  QgisMeshVisitor visitor( list );
 
  379  const SpatialIndex::Region r = rectToRegion( rect );
 
  381  const QMutexLocker locker( &d->mMutex );
 
  382  d->mRTree->intersectsWithQuery( r, visitor );
 
 
  390  QgisMeshVisitor visitor( list );
 
  392  double pt[2] = { point.
x(), point.
y() };
 
  393  const Point p( pt, 2 );
 
  395  const QMutexLocker locker( &d->mMutex );
 
  396  d->mRTree->nearestNeighborQuery( 
static_cast<uint32_t
>( neighbors ), p, visitor );
 
 
  408  if ( mesh.
face( faceIndex ).isEmpty() )
 
  412  const SpatialIndex::Region r( faceToRegion( mesh, faceIndex, ok ) );
 
  416  const QMutexLocker locker( &d.constData()->mMutex );
 
  420    d.constData()->mRTree->insertData( 0, 
nullptr, r, faceIndex );
 
  422  catch ( Tools::Exception &e )
 
  425    QgsDebugError( QStringLiteral( 
"Tools::Exception caught: " ).arg( e.what().c_str() ) );
 
  427  catch ( 
const std::exception &e )
 
  430    QgsDebugError( QStringLiteral( 
"std::exception caught: " ).arg( e.what() ) );
 
  434    QgsDebugError( QStringLiteral( 
"unknown spatial index exception caught" ) );
 
 
  440  if ( mesh.
face( faceIndex ).isEmpty() )
 
  442  const QMutexLocker locker( &d.constData()->mMutex );
 
  444  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.
 
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 xMinimum() const
Returns the x minimum value (left side of rectangle).
 
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
 
double xMaximum() const
Returns the x maximum value (right side of rectangle).
 
double yMaximum() const
Returns the y maximum value (top side of rectangle).
 
#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.