QGIS API Documentation  3.21.0-Master (5b68dc587e)
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 << 0,
159  Edge = 1 << 1,
160  Area = 1 << 2,
161  Centroid = 1 << 3,
162  MiddleOfSegment = 1 << 4,
163  LineEndpoint = 1 << 5,
164  All = Vertex | Edge | Area | Centroid | MiddleOfSegment
165  };
166 
167  Q_DECLARE_FLAGS( Types, Type )
168 
169 
182  bool init( int maxFeaturesToIndex = -1, bool relaxed = false );
183 
185  bool hasIndex() const;
186 
187  struct Match
188  {
190  Match() = default;
191 
192  Match( QgsPointLocator::Type t, QgsVectorLayer *vl, QgsFeatureId fid, double dist, const QgsPointXY &pt, int vertexIndex = 0, QgsPointXY *edgePoints = nullptr )
193  : mType( t )
194  , mDist( dist )
195  , mPoint( pt )
196  , mLayer( vl )
197  , mFid( fid )
198  , mVertexIndex( vertexIndex )
199  {
200  if ( edgePoints )
201  {
202  mEdgePoints[0] = edgePoints[0];
203  mEdgePoints[1] = edgePoints[1];
204  }
205  }
206 
207  QgsPointLocator::Type type() const { return mType; }
208 
209  bool isValid() const { return mType != Invalid; }
211  bool hasVertex() const { return mType == Vertex; }
213  bool hasEdge() const { return mType == Edge; }
215  bool hasCentroid() const { return mType == Centroid; }
217  bool hasArea() const { return mType == Area; }
219  bool hasMiddleSegment() const { return mType == MiddleOfSegment; }
220 
226  bool hasLineEndpoint() const { return mType == LineEndpoint; }
227 
232  double distance() const { return mDist; }
233 
238  QgsPointXY point() const { return mPoint; }
239 
241  int vertexIndex() const { return mVertexIndex; }
242 
247  QgsVectorLayer *layer() const { return mLayer; }
248 
252  QgsFeatureId featureId() const { return mFid; }
253 
255  void edgePoints( QgsPointXY &pt1 SIP_OUT, QgsPointXY &pt2 SIP_OUT ) const
256  {
257  pt1 = mEdgePoints[0];
258  pt2 = mEdgePoints[1];
259  }
260 
267  {
268  QgsPoint point;
269  const QgsGeometry geom = mLayer->getGeometry( mFid );
270  if ( !( geom.isNull() || geom.isEmpty() ) )
271  {
272  const QgsLineString line( geom.vertexAt( mVertexIndex ), geom.vertexAt( mVertexIndex + 1 ) );
273 
274  point = QgsGeometryUtils::closestPoint( line, QgsPoint( mPoint ) );
275  }
276  return point;
277  }
278 
279  // TODO c++20 - replace with = default
280  bool operator==( const QgsPointLocator::Match &other ) const
281  {
282  return mType == other.mType &&
283  mDist == other.mDist &&
284  mPoint == other.mPoint &&
285  mLayer == other.mLayer &&
286  mFid == other.mFid &&
287  mVertexIndex == other.mVertexIndex &&
288  mEdgePoints == other.mEdgePoints &&
289  mCentroid == other.mCentroid &&
290  mMiddleOfSegment == other.mMiddleOfSegment;
291  }
292 
293  protected:
294  Type mType = Invalid;
295  double mDist = 0;
297  QgsVectorLayer *mLayer = nullptr;
298  QgsFeatureId mFid = 0;
299  int mVertexIndex = 0; // e.g. vertex index
300  QgsPointXY mEdgePoints[2];
303  };
304 
305 #ifndef SIP_RUN
306  typedef class QList<QgsPointLocator::Match> MatchList;
307 #else
308  typedef QList<QgsPointLocator::Match> MatchList;
309 #endif
310 
316  struct MatchFilter
317  {
318  virtual ~MatchFilter() = default;
319  virtual bool acceptMatch( const QgsPointLocator::Match &match ) = 0;
320  };
321 
322  // intersection queries
323 
329  Match nearestVertex( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
330 
337  Match nearestCentroid( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
338 
345  Match nearestMiddleOfSegment( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
346 
353  Match nearestLineEndpoints( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
354 
360  Match nearestEdge( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
361 
370  Match nearestArea( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
371 
377  MatchList edgesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
378 
383  MatchList edgesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
384 
391  MatchList verticesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
392 
398  MatchList verticesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
399 
400  // point-in-polygon query
401 
402  // TODO: function to return just the first match?
403 
409  MatchList pointInPolygon( const QgsPointXY &point, bool relaxed = false );
410 
415  int cachedGeometryCount() const { return mGeoms.count(); }
416 
423  bool isIndexing() const { return mIsIndexing; }
424 
429  void waitForIndexingFinished();
430 
431  signals:
432 
438  void initFinished( bool ok );
439 
440  protected:
441  bool rebuildIndex( int maxFeaturesToIndex = -1 );
442 
443  protected slots:
444  void destroyIndex();
445  private slots:
446  void onInitTaskFinished();
447  void onFeatureAdded( QgsFeatureId fid );
448  void onFeatureDeleted( QgsFeatureId fid );
449  void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
450  void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
451 
452  private:
453 
458  bool prepare( bool relaxed );
459 
461  std::unique_ptr< SpatialIndex::IStorageManager > mStorage;
462 
463  QHash<QgsFeatureId, QgsGeometry *> mGeoms;
464  std::unique_ptr< SpatialIndex::ISpatialIndex > mRTree;
465 
467  bool mIsEmptyLayer = false;
468 
469 
471  QgsCoordinateTransform mTransform;
472  QgsVectorLayer *mLayer = nullptr;
473  std::unique_ptr< QgsRectangle > mExtent;
474 
475  std::unique_ptr<QgsRenderContext> mContext;
476  std::unique_ptr<QgsFeatureRenderer> mRenderer;
477  std::unique_ptr<QgsVectorLayerFeatureSource> mSource;
478  int mMaxFeaturesToIndex = -1;
479  bool mIsIndexing = false;
480  bool mIsDestroying = false;
481  QgsFeatureIds mAddedFeatures;
482  QgsFeatureIds mDeletedFeatures;
483  QPointer<QgsPointLocatorInitTask> mInitTask;
484 
492  friend class QgsPointLocatorInitTask;
493  friend class TestQgsPointLocator;
497 };
498 
499 
500 #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 line endpoints (start or end vertex) - builds...
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:59
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
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 hasLineEndpoint() const
Returns true if the Match is a line endpoint (start or end vertex).
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