QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
268  {
269  QgsPoint point;
270 
271  if ( mLayer )
272  {
273  QgsPointXY snappedPoint( mPoint );
274  const QgsGeometry geom = mLayer->getGeometry( mFid );
275  QgsCoordinateTransform transform( destinationCrs, mLayer->crs(), mLayer->transformContext() );
276  if ( transform.isValid() )
277  {
278  try
279  {
280  snappedPoint = transform.transform( snappedPoint );
281  }
282  catch ( QgsCsException & )
283  {
284  QgsDebugMsg( QStringLiteral( "transformation to layer coordinate failed" ) );
285  }
286  }
287 
288  if ( !( geom.isNull() || geom.isEmpty() ) )
289  {
290  const QgsLineString line( geom.vertexAt( mVertexIndex ), geom.vertexAt( mVertexIndex + 1 ) );
291  point = QgsGeometryUtils::closestPoint( line, QgsPoint( snappedPoint ) );
292  }
293 
294 
295  if ( transform.isValid() )
296  {
297  try
298  {
299  point.transform( transform, Qgis::TransformDirection::Reverse );
300  }
301  catch ( QgsCsException & )
302  {
303  QgsDebugMsg( QStringLiteral( "transformation to destination coordinate failed" ) );
304  }
305  }
306  }
307 
308  return point;
309  }
310 
311  // TODO c++20 - replace with = default
312  bool operator==( const QgsPointLocator::Match &other ) const
313  {
314  return mType == other.mType &&
315  mDist == other.mDist &&
316  mPoint == other.mPoint &&
317  mLayer == other.mLayer &&
318  mFid == other.mFid &&
319  mVertexIndex == other.mVertexIndex &&
320  mEdgePoints[0] == other.mEdgePoints[0] &&
321  mEdgePoints[1] == other.mEdgePoints[1] &&
322  mCentroid == other.mCentroid &&
323  mMiddleOfSegment == other.mMiddleOfSegment;
324  }
325 
326  protected:
327  Type mType = Invalid;
328  double mDist = 0;
330  QgsVectorLayer *mLayer = nullptr;
331  QgsFeatureId mFid = 0;
332  int mVertexIndex = 0; // e.g. vertex index
333  QgsPointXY mEdgePoints[2];
336  };
337 
338 #ifndef SIP_RUN
339  typedef class QList<QgsPointLocator::Match> MatchList;
340 #else
341  typedef QList<QgsPointLocator::Match> MatchList;
342 #endif
343 
349  struct MatchFilter
350  {
351  virtual ~MatchFilter() = default;
352  virtual bool acceptMatch( const QgsPointLocator::Match &match ) = 0;
353  };
354 
355  // intersection queries
356 
362  Match nearestVertex( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
363 
370  Match nearestCentroid( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
371 
378  Match nearestMiddleOfSegment( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
379 
386  Match nearestLineEndpoints( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
387 
393  Match nearestEdge( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
394 
403  Match nearestArea( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
404 
410  MatchList edgesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
411 
416  MatchList edgesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
417 
424  MatchList verticesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
425 
431  MatchList verticesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
432 
433  // point-in-polygon query
434 
435  // TODO: function to return just the first match?
436 
441  MatchList pointInPolygon( const QgsPointXY &point, bool relaxed = false );
443 
448  int cachedGeometryCount() const { return mGeoms.count(); }
449 
456  bool isIndexing() const { return mIsIndexing; }
457 
462  void waitForIndexingFinished();
463 
464  signals:
465 
471  void initFinished( bool ok );
472 
473  protected:
474  bool rebuildIndex( int maxFeaturesToIndex = -1 );
475 
476  protected slots:
477  void destroyIndex();
478  private slots:
479  void onInitTaskFinished();
480  void onFeatureAdded( QgsFeatureId fid );
481  void onFeatureDeleted( QgsFeatureId fid );
482  void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
483  void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
484 
485  private:
486 
491  bool prepare( bool relaxed );
492 
494  std::unique_ptr< SpatialIndex::IStorageManager > mStorage;
495 
496  QHash<QgsFeatureId, QgsGeometry *> mGeoms;
497  std::unique_ptr< SpatialIndex::ISpatialIndex > mRTree;
498 
500  bool mIsEmptyLayer = false;
501 
502 
504  QgsCoordinateTransform mTransform;
505  QgsVectorLayer *mLayer = nullptr;
506  std::unique_ptr< QgsRectangle > mExtent;
507 
508  std::unique_ptr<QgsRenderContext> mContext;
509  std::unique_ptr<QgsFeatureRenderer> mRenderer;
510  std::unique_ptr<QgsVectorLayerFeatureSource> mSource;
511  int mMaxFeaturesToIndex = -1;
512  bool mIsIndexing = false;
513  bool mIsDestroying = false;
514  QgsFeatureIds mAddedFeatures;
515  QgsFeatureIds mDeletedFeatures;
516  QPointer<QgsPointLocatorInitTask> mInitTask;
517 
525  friend class QgsPointLocatorInitTask;
526  friend class TestQgsPointLocator;
530 };
531 
532 
533 #endif // QGSPOINTLOCATOR_H
QgsPointLocator::Match::operator==
bool operator==(const QgsPointLocator::Match &other) const
Definition: qgspointlocator.h:312
SpatialIndex
Definition: qgspointlocator.h:83
QgsPointLocator_VisitorArea
Helper class used when traversing the index with areas - builds a list of matches.
Definition: qgspointlocator.cpp:425
QgsCoordinateTransformContext
Contains information about the context in which a coordinate transform is executed.
Definition: qgscoordinatetransformcontext.h:57
QgsPointLocator::Match::hasMiddleSegment
bool hasMiddleSegment() const
Returns true if the Match is the middle of a segment.
Definition: qgspointlocator.h:219
qgslinestring.h
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
QgsPointLocator::isIndexing
bool isIndexing() const
Returns true if the point locator is currently indexing the data.
Definition: qgspointlocator.h:456
SIP_OUT
#define SIP_OUT
Definition: qgis_sip.h:58
QgsPointLocator::Match::Match
Match(QgsPointLocator::Type t, QgsVectorLayer *vl, QgsFeatureId fid, double dist, const QgsPointXY &pt, int vertexIndex=0, QgsPointXY *edgePoints=nullptr)
Definition: qgspointlocator.h:192
QgsPointLocator::Match::mDist
double mDist
Definition: qgspointlocator.h:328
QgsPointLocator::Match::edgePoints
void edgePoints(QgsPointXY &pt1, QgsPointXY &pt2) const
Only for a valid edge match - obtain endpoints of the edge.
Definition: qgspointlocator.h:255
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsPointLocator::cachedGeometryCount
int cachedGeometryCount() const
Returns how many geometries are cached in the index.
Definition: qgspointlocator.h:448
QgsGeometryUtils::closestPoint
static QgsPoint closestPoint(const QgsAbstractGeometry &geometry, const QgsPoint &point)
Returns the nearest point on a segment of a geometry for the specified point.
Definition: qgsgeometryutils.cpp:101
qgsfeatureid.h
QgsPointLocator::Match::point
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords,...
Definition: qgspointlocator.h:238
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsPointLocator_VisitorNearestVertex
Helper class used when traversing the index looking for vertices - builds a list of matches.
Definition: qgspointlocator.cpp:98
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
QgsCoordinateTransform::isValid
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Definition: qgscoordinatetransform.cpp:900
QgsPointLocator_VisitorCentroidsInRect
Helper class used when traversing the index looking for centroid - builds a list of matches.
Definition: qgspointlocator.cpp:719
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsPointLocator::Match::hasVertex
bool hasVertex() const
Returns true if the Match is a vertex.
Definition: qgspointlocator.h:211
QgsPointLocator::Match::interpolatedPoint
QgsPoint interpolatedPoint(const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem()) const
Convenient method to return a point on an edge with linear interpolation of the Z value.
Definition: qgspointlocator.h:267
QgsPointLocator_VisitorNearestMiddleOfSegment
Helper class used when traversing the index looking for middle segment - builds a list of matches.
Definition: qgspointlocator.cpp:202
QgsPointLocator::Match::mFid
QgsFeatureId mFid
Definition: qgspointlocator.h:331
QgsPointLocator_VisitorNearestCentroid
Helper class used when traversing the index looking for centroid - builds a list of matches.
Definition: qgspointlocator.cpp:148
QgsPointLocator::Match::mEdgePoints
QgsPointXY mEdgePoints[2]
Definition: qgspointlocator.h:333
QgsPointLocator::Match::hasCentroid
bool hasCentroid() const
Returns true if the Match is a centroid.
Definition: qgspointlocator.h:215
QgsPointLocator::Match::mType
Type mType
Definition: qgspointlocator.h:327
QgsPointLocator::Match::vertexIndex
int vertexIndex() const
for vertex / edge match (first vertex of the edge)
Definition: qgspointlocator.h:241
QgsPointLocator::Match::mMiddleOfSegment
QgsPointXY mMiddleOfSegment
Definition: qgspointlocator.h:335
QgsPointLocator::Match::hasEdge
bool hasEdge() const
Returns true if the Match is an edge.
Definition: qgspointlocator.h:213
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
SIP_SKIP
#define SIP_SKIP
Definition: qgis_sip.h:126
QgsPointLocator::Match::mLayer
QgsVectorLayer * mLayer
Definition: qgspointlocator.h:330
QgsPointLocator_VisitorNearestLineEndpoint
Helper class used when traversing the index looking for line endpoints (start or end vertex) - builds...
Definition: qgspointlocator.cpp:265
QgsPoint::transform
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
Definition: qgspoint.cpp:382
QgsPointLocator::MatchList
class QList< QgsPointLocator::Match > MatchList
Definition: qgspointlocator.h:339
QgsPointLocator::Match::hasLineEndpoint
bool hasLineEndpoint() const
Returns true if the Match is a line endpoint (start or end vertex).
Definition: qgspointlocator.h:226
QgsPointLocator_VisitorNearestEdge
Helper class used when traversing the index looking for edges - builds a list of matches.
Definition: qgspointlocator.cpp:372
QgsPointLocator::Match::isValid
bool isValid() const
Definition: qgspointlocator.h:209
qgscoordinatetransform.h
QgsGeometry::isEmpty
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Definition: qgsgeometry.cpp:379
QgsPointLocator_VisitorVerticesInRect
Helper class used when traversing the index looking for vertices - builds a list of matches.
Definition: qgspointlocator.cpp:670
QgsPointLocator::Match::layer
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
Definition: qgspointlocator.h:247
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:127
QgsPointLocator::extent
const QgsRectangle * extent() const
Gets extent of the area point locator covers - if nullptr then it caches the whole layer.
Definition: qgspointlocator.h:138
QgsPointLocator_VisitorMiddlesInRect
Helper class used when traversing the index looking for middle segment - builds a list of matches.
Definition: qgspointlocator.cpp:764
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
qgsgeometryutils.h
QgsGeometry::vertexAt
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
Definition: qgsgeometry.cpp:683
QgsPointLocator::Match
Definition: qgspointlocator.h:187
qgsvectorlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsPointLocator_VisitorEdgesInRect
Helper class used when traversing the index looking for edges - builds a list of matches.
Definition: qgspointlocator.cpp:624
QgsPointLocator::Match::mVertexIndex
int mVertexIndex
Definition: qgspointlocator.h:332
QgsPointLocator::Match::featureId
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
Definition: qgspointlocator.h:252
QgsPointLocator::Match::mPoint
QgsPointXY mPoint
Definition: qgspointlocator.h:329
qgsgeometry.h
QgsFeatureRenderer
Definition: qgsrenderer.h:101
QgsPointLocator::Match::mCentroid
QgsPointXY mCentroid
Definition: qgspointlocator.h:334
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsPointLocator::Match::type
QgsPointLocator::Type type() const
Definition: qgspointlocator.h:207
QgsVectorLayerFeatureSource
Partial snapshot of vector layer's state (only the members necessary for access to features)
Definition: qgsvectorlayerfeatureiterator.h:52
QgsPointLocator
The class defines interface for querying point location:
Definition: qgspointlocator.h:101
QgsPointLocator::layer
QgsVectorLayer * layer() const
Gets associated layer.
Definition: qgspointlocator.h:126
QgsPointLocator::MatchFilter
Interface that allows rejection of some matches in intersection queries (e.g.
Definition: qgspointlocator.h:349
qgspointlocatorinittask.h
QgsCoordinateTransform::transform
QgsPointXY transform(const QgsPointXY &point, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:272
QgsPointLocator::Type
Type
The type of a snap result or the filter type for a snap request.
Definition: qgspointlocator.h:155
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
qgscoordinatereferencesystem.h
qgspointxy.h
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QgsPointLocator::Match::hasArea
bool hasArea() const
Returns true if the Match is an area.
Definition: qgspointlocator.h:217
QgsPointLocator::Match::distance
double distance() const
for vertex / edge match units depending on what class returns it (geom.cache: layer units,...
Definition: qgspointlocator.h:232