QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgspointlocator.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointlocator.h
3  --------------------------------------
4  Date : November 2014
5  Copyright : (C) 2014 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #ifndef QGSPOINTLOCATOR_H
17 #define QGSPOINTLOCATOR_H
18 
19 class QgsPointXY;
20 class QgsFeatureRenderer;
21 class QgsRenderContext;
22 class QgsRectangle;
24 
25 #include "qgis_core.h"
26 #include "qgspointxy.h"
28 #include "qgscoordinatetransform.h"
29 #include "qgsfeatureid.h"
30 #include "qgsgeometry.h"
31 #include "qgsgeometryutils.h"
32 #include "qgsvectorlayer.h"
33 #include "qgslinestring.h"
35 #include <memory>
36 
37 #include <QPointer>
38 
45 
53 
61 
68 
75 
82 
84 {
85  class IStorageManager;
86  class ISpatialIndex;
87 }
88 
101 class CORE_EXPORT QgsPointLocator : public QObject
102 {
103  Q_OBJECT
104  public:
105 
118  const QgsRectangle *extent = nullptr );
119 
120  ~QgsPointLocator() override;
121 
126  QgsVectorLayer *layer() const { return mLayer; }
127 
132  QgsCoordinateReferenceSystem destinationCrs() const;
133 
138  const QgsRectangle *extent() const { return mExtent.get(); }
139 
144  void setExtent( const QgsRectangle *extent );
145 
150  void setRenderContext( const QgsRenderContext *context );
151 
155  enum Type
156  {
157  Invalid = 0,
158  Vertex = 1,
159  Edge = 2,
160  Area = 4,
161  Centroid = 8,
162  MiddleOfSegment = 16,
163  All = Vertex | Edge | Area | Centroid | MiddleOfSegment
164  };
165 
166  Q_DECLARE_FLAGS( Types, Type )
167 
168 
181  bool init( int maxFeaturesToIndex = -1, bool relaxed = false );
182 
184  bool hasIndex() const;
185 
186  struct Match
187  {
189  Match() = default;
190 
191  Match( QgsPointLocator::Type t, QgsVectorLayer *vl, QgsFeatureId fid, double dist, const QgsPointXY &pt, int vertexIndex = 0, QgsPointXY *edgePoints = nullptr )
192  : mType( t )
193  , mDist( dist )
194  , mPoint( pt )
195  , mLayer( vl )
196  , mFid( fid )
197  , mVertexIndex( vertexIndex )
198  {
199  if ( edgePoints )
200  {
201  mEdgePoints[0] = edgePoints[0];
202  mEdgePoints[1] = edgePoints[1];
203  }
204  }
205 
206  QgsPointLocator::Type type() const { return mType; }
207 
208  bool isValid() const { return mType != Invalid; }
210  bool hasVertex() const { return mType == Vertex; }
212  bool hasEdge() const { return mType == Edge; }
214  bool hasCentroid() const { return mType == Centroid; }
216  bool hasArea() const { return mType == Area; }
218  bool hasMiddleSegment() const { return mType == MiddleOfSegment; }
219 
224  double distance() const { return mDist; }
225 
230  QgsPointXY point() const { return mPoint; }
231 
233  int vertexIndex() const { return mVertexIndex; }
234 
239  QgsVectorLayer *layer() const { return mLayer; }
240 
244  QgsFeatureId featureId() const { return mFid; }
245 
247  void edgePoints( QgsPointXY &pt1 SIP_OUT, QgsPointXY &pt2 SIP_OUT ) const
248  {
249  pt1 = mEdgePoints[0];
250  pt2 = mEdgePoints[1];
251  }
252 
259  {
260  QgsPoint point;
261  const QgsGeometry geom = mLayer->getGeometry( mFid );
262  if ( !( geom.isNull() || geom.isEmpty() ) )
263  {
264  QgsLineString line( geom.vertexAt( mVertexIndex ), geom.vertexAt( mVertexIndex + 1 ) );
265 
266  point = QgsGeometryUtils::closestPoint( line, QgsPoint( mPoint ) );
267  }
268  return point;
269  }
270 
271  bool operator==( const QgsPointLocator::Match &other ) const
272  {
273  return mType == other.mType &&
274  mDist == other.mDist &&
275  mPoint == other.mPoint &&
276  mLayer == other.mLayer &&
277  mFid == other.mFid &&
278  mVertexIndex == other.mVertexIndex &&
279  mEdgePoints == other.mEdgePoints &&
280  mCentroid == other.mCentroid &&
281  mMiddleOfSegment == other.mMiddleOfSegment;
282  }
283 
284  protected:
285  Type mType = Invalid;
286  double mDist = 0;
288  QgsVectorLayer *mLayer = nullptr;
289  QgsFeatureId mFid = 0;
290  int mVertexIndex = 0; // e.g. vertex index
291  QgsPointXY mEdgePoints[2];
294  };
295 
296 #ifndef SIP_RUN
297  typedef class QList<QgsPointLocator::Match> MatchList;
298 #else
299  typedef QList<QgsPointLocator::Match> MatchList;
300 #endif
301 
307  struct MatchFilter
308  {
309  virtual ~MatchFilter() = default;
310  virtual bool acceptMatch( const QgsPointLocator::Match &match ) = 0;
311  };
312 
313  // intersection queries
314 
320  Match nearestVertex( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
321 
328  Match nearestCentroid( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
329 
336  Match nearestMiddleOfSegment( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
337 
343  Match nearestEdge( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
344 
353  Match nearestArea( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
354 
360  MatchList edgesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
361 
366  MatchList edgesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
367 
374  MatchList verticesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
375 
381  MatchList verticesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
382 
383  // point-in-polygon query
384 
385  // TODO: function to return just the first match?
386 
392  MatchList pointInPolygon( const QgsPointXY &point, bool relaxed = false );
393 
398  int cachedGeometryCount() const { return mGeoms.count(); }
399 
406  bool isIndexing() const { return mIsIndexing; }
407 
412  void waitForIndexingFinished();
413 
414  signals:
415 
421  void initFinished( bool ok );
422 
423  protected:
424  bool rebuildIndex( int maxFeaturesToIndex = -1 );
425 
426  protected slots:
427  void destroyIndex();
428  private slots:
429  void onInitTaskFinished();
430  void onFeatureAdded( QgsFeatureId fid );
431  void onFeatureDeleted( QgsFeatureId fid );
432  void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
433  void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
434 
435  private:
436 
441  bool prepare( bool relaxed );
442 
444  std::unique_ptr< SpatialIndex::IStorageManager > mStorage;
445 
446  QHash<QgsFeatureId, QgsGeometry *> mGeoms;
447  std::unique_ptr< SpatialIndex::ISpatialIndex > mRTree;
448 
450  bool mIsEmptyLayer = false;
451 
452 
454  QgsCoordinateTransform mTransform;
455  QgsVectorLayer *mLayer = nullptr;
456  std::unique_ptr< QgsRectangle > mExtent;
457 
458  std::unique_ptr<QgsRenderContext> mContext;
459  std::unique_ptr<QgsFeatureRenderer> mRenderer;
460  std::unique_ptr<QgsVectorLayerFeatureSource> mSource;
461  int mMaxFeaturesToIndex = -1;
462  bool mIsIndexing = false;
463  bool mIsDestroying = false;
464  QgsFeatureIds mAddedFeatures;
465  QgsFeatureIds mDeletedFeatures;
466  QPointer<QgsPointLocatorInitTask> mInitTask;
467 
475  friend class QgsPointLocatorInitTask;
476  friend class TestQgsPointLocator;
479 };
480 
481 
482 #endif // QGSPOINTLOCATOR_H
This class represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
static QgsPoint closestPoint(const QgsAbstractGeometry &geometry, const QgsPoint &point)
Returns the nearest point on a segment of a geometry for the specified point.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
Helper class used when traversing the index with areas - builds a list of matches.
Helper class used when traversing the index looking for centroid - builds a list of matches.
Helper class used when traversing the index looking for edges - builds a list of matches.
Helper class used when traversing the index looking for middle segment - builds a list of matches.
Helper class used when traversing the index looking for centroid - builds a list of matches.
Helper class used when traversing the index looking for edges - builds a list of matches.
Helper class used when traversing the index looking for middle segment - builds a list of matches.
Helper class used when traversing the index looking for vertices - builds a list of matches.
Helper class used when traversing the index looking for vertices - builds a list of matches.
The class defines interface for querying point location:
const QgsRectangle * extent() const
Gets extent of the area point locator covers - if nullptr then it caches the whole layer.
int cachedGeometryCount() const
Returns how many geometries are cached in the index.
class QList< QgsPointLocator::Match > MatchList
QgsVectorLayer * layer() const
Gets associated layer.
bool isIndexing() const
Returns true if the point locator is currently indexing the data.
void initFinished(bool ok)
Emitted whenever index has been built and initialization is finished.
Type
The type of a snap result or the filter type for a snap request.
A class to represent a 2D point.
Definition: qgspointxy.h:44
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
A rectangle specified with double values.
Definition: qgsrectangle.h:42
Contains information about the context of a rendering operation.
Partial snapshot of vector layer's state (only the members necessary for access to features)
Represents a vector layer which manages a vector based data sets.
#define SIP_SKIP
Definition: qgis_sip.h:126
#define SIP_OUT
Definition: qgis_sip.h:58
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
Interface that allows rejection of some matches in intersection queries (e.g.
virtual bool acceptMatch(const QgsPointLocator::Match &match)=0
virtual ~MatchFilter()=default
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
bool hasCentroid() const
Returns true if the Match is a centroid.
double distance() const
for vertex / edge match units depending on what class returns it (geom.cache: layer units,...
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords,...
bool hasEdge() const
Returns true if the Match is an edge.
void edgePoints(QgsPointXY &pt1, QgsPointXY &pt2) const
Only for a valid edge match - obtain endpoints of the edge.
bool hasArea() const
Returns true if the Match is an area.
QgsPoint interpolatedPoint() const
Convenient method to return a point on an edge with linear interpolation of the Z value.
QgsVectorLayer * mLayer
Match()=default
construct invalid match
Match(QgsPointLocator::Type t, QgsVectorLayer *vl, QgsFeatureId fid, double dist, const QgsPointXY &pt, int vertexIndex=0, QgsPointXY *edgePoints=nullptr)
QgsPointLocator::Type type() const
bool hasMiddleSegment() const
Returns true if the Match is the middle of a segment.
int vertexIndex() const
for vertex / edge match (first vertex of the edge)
bool hasVertex() const
Returns true if the Match is a vertex.
bool operator==(const QgsPointLocator::Match &other) const