QGIS API Documentation  3.20.0-Odense (decaadbb31)
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  QgsLineString line( geom.vertexAt( mVertexIndex ), geom.vertexAt( mVertexIndex + 1 ) );
273 
274  point = QgsGeometryUtils::closestPoint( line, QgsPoint( mPoint ) );
275  }
276  return point;
277  }
278 
279  bool operator==( const QgsPointLocator::Match &other ) const
280  {
281  return mType == other.mType &&
282  mDist == other.mDist &&
283  mPoint == other.mPoint &&
284  mLayer == other.mLayer &&
285  mFid == other.mFid &&
286  mVertexIndex == other.mVertexIndex &&
287  mEdgePoints == other.mEdgePoints &&
288  mCentroid == other.mCentroid &&
289  mMiddleOfSegment == other.mMiddleOfSegment;
290  }
291 
292  protected:
293  Type mType = Invalid;
294  double mDist = 0;
296  QgsVectorLayer *mLayer = nullptr;
297  QgsFeatureId mFid = 0;
298  int mVertexIndex = 0; // e.g. vertex index
299  QgsPointXY mEdgePoints[2];
302  };
303 
304 #ifndef SIP_RUN
305  typedef class QList<QgsPointLocator::Match> MatchList;
306 #else
307  typedef QList<QgsPointLocator::Match> MatchList;
308 #endif
309 
315  struct MatchFilter
316  {
317  virtual ~MatchFilter() = default;
318  virtual bool acceptMatch( const QgsPointLocator::Match &match ) = 0;
319  };
320 
321  // intersection queries
322 
328  Match nearestVertex( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
329 
336  Match nearestCentroid( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
337 
344  Match nearestMiddleOfSegment( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
345 
352  Match nearestLineEndpoints( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
353 
359  Match nearestEdge( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
360 
369  Match nearestArea( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
370 
376  MatchList edgesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
377 
382  MatchList edgesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
383 
390  MatchList verticesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
391 
397  MatchList verticesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
398 
399  // point-in-polygon query
400 
401  // TODO: function to return just the first match?
402 
408  MatchList pointInPolygon( const QgsPointXY &point, bool relaxed = false );
409 
414  int cachedGeometryCount() const { return mGeoms.count(); }
415 
422  bool isIndexing() const { return mIsIndexing; }
423 
428  void waitForIndexingFinished();
429 
430  signals:
431 
437  void initFinished( bool ok );
438 
439  protected:
440  bool rebuildIndex( int maxFeaturesToIndex = -1 );
441 
442  protected slots:
443  void destroyIndex();
444  private slots:
445  void onInitTaskFinished();
446  void onFeatureAdded( QgsFeatureId fid );
447  void onFeatureDeleted( QgsFeatureId fid );
448  void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
449  void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
450 
451  private:
452 
457  bool prepare( bool relaxed );
458 
460  std::unique_ptr< SpatialIndex::IStorageManager > mStorage;
461 
462  QHash<QgsFeatureId, QgsGeometry *> mGeoms;
463  std::unique_ptr< SpatialIndex::ISpatialIndex > mRTree;
464 
466  bool mIsEmptyLayer = false;
467 
468 
470  QgsCoordinateTransform mTransform;
471  QgsVectorLayer *mLayer = nullptr;
472  std::unique_ptr< QgsRectangle > mExtent;
473 
474  std::unique_ptr<QgsRenderContext> mContext;
475  std::unique_ptr<QgsFeatureRenderer> mRenderer;
476  std::unique_ptr<QgsVectorLayerFeatureSource> mSource;
477  int mMaxFeaturesToIndex = -1;
478  bool mIsIndexing = false;
479  bool mIsDestroying = false;
480  QgsFeatureIds mAddedFeatures;
481  QgsFeatureIds mDeletedFeatures;
482  QPointer<QgsPointLocatorInitTask> mInitTask;
483 
491  friend class QgsPointLocatorInitTask;
492  friend class TestQgsPointLocator;
496 };
497 
498 
499 #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