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.