QGIS API Documentation  3.15.0-Master (dbe1ef8aa2)
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 
43 
51 
59 
66 
73 
80 
82 {
83  class IStorageManager;
84  class ISpatialIndex;
85 }
86 
99 class CORE_EXPORT QgsPointLocator : public QObject
100 {
101  Q_OBJECT
102  public:
103 
116  const QgsRectangle *extent = nullptr );
117 
118  ~QgsPointLocator() override;
119 
124  QgsVectorLayer *layer() const { return mLayer; }
125 
130  QgsCoordinateReferenceSystem destinationCrs() const;
131 
136  const QgsRectangle *extent() const { return mExtent.get(); }
137 
142  void setExtent( const QgsRectangle *extent );
143 
148  void setRenderContext( const QgsRenderContext *context );
149 
153  enum Type
154  {
155  Invalid = 0,
156  Vertex = 1,
157  Edge = 2,
158  Area = 4,
159  Centroid = 8,
160  MiddleOfSegment = 16,
161  All = Vertex | Edge | Area | Centroid | MiddleOfSegment
162  };
163 
164  Q_DECLARE_FLAGS( Types, Type )
165 
166 
179  bool init( int maxFeaturesToIndex = -1, bool relaxed = false );
180 
182  bool hasIndex() const;
183 
184  struct Match
185  {
187  Match() = default;
188 
189  Match( QgsPointLocator::Type t, QgsVectorLayer *vl, QgsFeatureId fid, double dist, const QgsPointXY &pt, int vertexIndex = 0, QgsPointXY *edgePoints = nullptr )
190  : mType( t )
191  , mDist( dist )
192  , mPoint( pt )
193  , mLayer( vl )
194  , mFid( fid )
195  , mVertexIndex( vertexIndex )
196  {
197  if ( edgePoints )
198  {
199  mEdgePoints[0] = edgePoints[0];
200  mEdgePoints[1] = edgePoints[1];
201  }
202  }
203 
204  QgsPointLocator::Type type() const { return mType; }
205 
206  bool isValid() const { return mType != Invalid; }
208  bool hasVertex() const { return mType == Vertex; }
210  bool hasEdge() const { return mType == Edge; }
212  bool hasCentroid() const { return mType == Centroid; }
214  bool hasArea() const { return mType == Area; }
216  bool hasMiddleSegment() const { return mType == MiddleOfSegment; }
217 
222  double distance() const { return mDist; }
223 
228  QgsPointXY point() const { return mPoint; }
229 
231  int vertexIndex() const { return mVertexIndex; }
232 
237  QgsVectorLayer *layer() const { return mLayer; }
238 
242  QgsFeatureId featureId() const { return mFid; }
243 
245  void edgePoints( QgsPointXY &pt1 SIP_OUT, QgsPointXY &pt2 SIP_OUT ) const
246  {
247  pt1 = mEdgePoints[0];
248  pt2 = mEdgePoints[1];
249  }
250 
257  {
258  QgsPoint point;
259  const QgsGeometry geom = mLayer->getGeometry( mFid );
260  if ( !( geom.isNull() || geom.isEmpty() ) )
261  {
262  QgsLineString line( geom.vertexAt( mVertexIndex ), geom.vertexAt( mVertexIndex + 1 ) );
263 
264  point = QgsGeometryUtils::closestPoint( line, QgsPoint( mPoint ) );
265  }
266  return point;
267  }
268 
269  bool operator==( const QgsPointLocator::Match &other ) const
270  {
271  return mType == other.mType &&
272  mDist == other.mDist &&
273  mPoint == other.mPoint &&
274  mLayer == other.mLayer &&
275  mFid == other.mFid &&
276  mVertexIndex == other.mVertexIndex &&
277  mEdgePoints == other.mEdgePoints &&
278  mCentroid == other.mCentroid &&
279  mMiddleOfSegment == other.mMiddleOfSegment;
280  }
281 
282  protected:
283  Type mType = Invalid;
284  double mDist = 0;
286  QgsVectorLayer *mLayer = nullptr;
287  QgsFeatureId mFid = 0;
288  int mVertexIndex = 0; // e.g. vertex index
289  QgsPointXY mEdgePoints[2];
292  };
293 
294 #ifndef SIP_RUN
295  typedef class QList<QgsPointLocator::Match> MatchList;
296 #else
297  typedef QList<QgsPointLocator::Match> MatchList;
298 #endif
299 
305  struct MatchFilter
306  {
307  virtual ~MatchFilter() = default;
308  virtual bool acceptMatch( const QgsPointLocator::Match &match ) = 0;
309  };
310 
311  // intersection queries
312 
318  Match nearestVertex( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
319 
326  Match nearestCentroid( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
327 
334  Match nearestMiddleOfSegment( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
335 
341  Match nearestEdge( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
342 
351  Match nearestArea( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
352 
358  MatchList edgesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
359 
364  MatchList edgesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
365 
372  MatchList verticesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
373 
379  MatchList verticesInRect( const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter = nullptr, bool relaxed = false );
380 
381  // point-in-polygon query
382 
383  // TODO: function to return just the first match?
384 
389  MatchList pointInPolygon( const QgsPointXY &point, bool relaxed = false );
391 
396  int cachedGeometryCount() const { return mGeoms.count(); }
397 
404  bool isIndexing() const { return mIsIndexing; }
405 
410  void waitForIndexingFinished();
411 
412  signals:
413 
419  void initFinished( bool ok );
420 
421  protected:
422  bool rebuildIndex( int maxFeaturesToIndex = -1 );
423 
424  protected slots:
425  void destroyIndex();
426  private slots:
427  void onInitTaskFinished();
428  void onFeatureAdded( QgsFeatureId fid );
429  void onFeatureDeleted( QgsFeatureId fid );
430  void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
431  void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
432 
433  private:
434 
439  bool prepare( bool relaxed );
440 
442  std::unique_ptr< SpatialIndex::IStorageManager > mStorage;
443 
444  QHash<QgsFeatureId, QgsGeometry *> mGeoms;
445  std::unique_ptr< SpatialIndex::ISpatialIndex > mRTree;
446 
448  bool mIsEmptyLayer = false;
449 
450 
452  QgsCoordinateTransform mTransform;
453  QgsVectorLayer *mLayer = nullptr;
454  std::unique_ptr< QgsRectangle > mExtent;
455 
456  std::unique_ptr<QgsRenderContext> mContext;
457  std::unique_ptr<QgsFeatureRenderer> mRenderer;
458  std::unique_ptr<QgsVectorLayerFeatureSource> mSource;
459  int mMaxFeaturesToIndex = -1;
460  bool mIsIndexing = false;
461  bool mIsDestroying = false;
462  QgsFeatureIds mAddedFeatures;
463  QgsFeatureIds mDeletedFeatures;
464  QPointer<QgsPointLocatorInitTask> mInitTask;
465 
473  friend class QgsPointLocatorInitTask;
474  friend class TestQgsPointLocator;
477 };
478 
479 
480 #endif // QGSPOINTLOCATOR_H
The class defines interface for querying point location:
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
QgsPointLocator::Type type() const
A class to represent a 2D point.
Definition: qgspointxy.h:43
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features ...
Definition: qgsfeatureid.h:28
class QList< QgsPointLocator::Match > MatchList
Helper class used when traversing the index looking for edges - builds a list of matches.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:123
bool hasEdge() const
Returns true if the Match is an edge.
Interface that allows rejection of some matches in intersection queries (e.g.
bool operator==(const QgsPointLocator::Match &other) const
Helper class used when traversing the index looking for centroid - builds a list of matches...
Helper class used when traversing the index looking for centroid - builds a list of matches...
QgsPoint interpolatedPoint() const
Convenient method to return a point on an edge with linear interpolation of the Z value...
#define SIP_SKIP
Definition: qgis_sip.h:126
bool hasVertex() const
Returns true if the Match is a vertex.
void edgePoints(QgsPointXY &pt1, QgsPointXY &pt2) const
Only for a valid edge match - obtain endpoints of the edge.
Helper class used when traversing the index looking for middle segment - builds a list of matches...
Match(QgsPointLocator::Type t, QgsVectorLayer *vl, QgsFeatureId fid, double dist, const QgsPointXY &pt, int vertexIndex=0, QgsPointXY *edgePoints=nullptr)
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Helper class used when traversing the index with areas - builds a list of matches.
QgsVectorLayer * mLayer
bool isIndexing() const
Returns true if the point locator is currently indexing the data.
Contains information about the context in which a coordinate transform is executed.
Helper class used when traversing the index looking for vertices - builds a list of matches...
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
const QgsRectangle * extent() const
Gets extent of the area point locator covers - if nullptr then it caches the whole layer...
Helper class used when traversing the index looking for middle segment - builds a list of matches...
Partial snapshot of vector layer&#39;s state (only the members necessary for access to features) ...
int cachedGeometryCount() const
Returns how many geometries are cached in the index.
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords...
Contains information about the context of a rendering operation.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
int vertexIndex() const
for vertex / edge match (first vertex of the edge)
#define SIP_OUT
Definition: qgis_sip.h:58
bool hasMiddleSegment() const
Returns true if the Match is the middle of a segment.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
This class represents a coordinate reference system (CRS).
Class for doing transforms between two map coordinate systems.
bool hasCentroid() const
Returns true if the Match is a centroid.
Helper class used when traversing the index looking for vertices - builds a list of matches...
double distance() const
for vertex / edge match units depending on what class returns it (geom.cache: layer units...
Helper class used when traversing the index looking for edges - builds a list of matches.
bool hasArea() const
Returns true if the Match is an area.
static QgsPoint closestPoint(const QgsAbstractGeometry &geometry, const QgsPoint &point)
Returns the nearest point on a segment of a geometry for the specified point.
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
Represents a vector layer which manages a vector based data sets.
QgsVectorLayer * layer() const
Gets associated layer.
Type
The type of a snap result or the filter type for a snap request.