QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsgeometrysnapper.h
Go to the documentation of this file.
1 /***************************************************************************
2  * qgsgeometrysnapper.h *
3  * ------------------- *
4  * copyright : (C) 2014 by Sandro Mani / Sourcepole AG *
5  * email : [email protected] *
6  ***************************************************************************/
7 
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #ifndef QGS_GEOMETRY_SNAPPER_H
18 #define QGS_GEOMETRY_SNAPPER_H
19 
20 #include <QMutex>
21 #include <QFuture>
22 #include <QStringList>
23 #include "qgsspatialindex.h"
24 #include "qgsabstractgeometry.h"
25 #include "qgspoint.h"
26 #include "qgsgeometry.h"
27 #include "qgis_analysis.h"
28 
29 class QgsVectorLayer;
30 
39 class ANALYSIS_EXPORT QgsGeometrySnapper : public QObject
40 {
41  Q_OBJECT
42 
43  public:
44 
46  enum SnapMode
47  {
48  PreferNodes = 0,
55  };
56 
62  QgsGeometrySnapper( QgsFeatureSource *referenceSource );
63 
69  QgsGeometry snapGeometry( const QgsGeometry &geometry, double snapTolerance, SnapMode mode = PreferNodes ) const;
70 
76  QgsFeatureList snapFeatures( const QgsFeatureList &features, double snapTolerance, SnapMode mode = PreferNodes );
77 
81  static QgsGeometry snapGeometry( const QgsGeometry &geometry, double snapTolerance, const QList<QgsGeometry> &referenceGeometries, SnapMode mode = PreferNodes );
82 
83  signals:
84 
87 
88  private:
89  struct ProcessFeatureWrapper
90  {
91  QgsGeometrySnapper *instance = nullptr;
92  double snapTolerance;
93  SnapMode mode;
94  explicit ProcessFeatureWrapper( QgsGeometrySnapper *_instance, double snapTolerance, SnapMode mode )
95  : instance( _instance )
96  , snapTolerance( snapTolerance )
97  , mode( mode )
98  {}
99  void operator()( QgsFeature &feature ) { instance->processFeature( feature, snapTolerance, mode ); }
100  };
101 
102  enum PointFlag { SnappedToRefNode, SnappedToRefSegment, Unsnapped };
103 
104  QgsFeatureSource *mReferenceSource = nullptr;
105  QgsFeatureList mInputFeatures;
106 
107  QgsSpatialIndex mIndex;
108  mutable QMutex mIndexMutex;
109  mutable QMutex mReferenceLayerMutex;
110 
111  void processFeature( QgsFeature &feature, double snapTolerance, SnapMode mode );
112 
113  static int polyLineSize( const QgsAbstractGeometry *geom, int iPart, int iRing );
114 
115 };
116 
117 
133 class ANALYSIS_EXPORT QgsInternalGeometrySnapper
134 {
135 
136  public:
137 
143 
148  QgsGeometry snapFeature( const QgsFeature &feature );
149 
153  QgsGeometryMap snappedGeometries() const { return mProcessedGeometries; }
154 
155  private:
156 
157  bool mFirstFeature = true;
158  double mSnapTolerance = 0;
160  QgsSpatialIndex mProcessedIndex;
161  QgsGeometryMap mProcessedGeometries;
162 
163 };
164 
165 #ifndef SIP_RUN
166 
168 class QgsSnapIndex
169 {
170  public:
171  struct CoordIdx
172  {
173  CoordIdx( const QgsAbstractGeometry *_geom, QgsVertexId _vidx )
174  : geom( _geom )
175  , vidx( _vidx )
176  {}
177  QgsPoint point() const { return geom->vertexAt( vidx ); }
178 
179  const QgsAbstractGeometry *geom = nullptr;
180  QgsVertexId vidx;
181  };
182 
183  enum SnapType { SnapPoint, SnapEndPoint, SnapSegment };
184 
185  class SnapItem
186  {
187  public:
188  virtual ~SnapItem() = default;
189  SnapType type;
190  virtual QgsPoint getSnapPoint( const QgsPoint &p ) const = 0;
191 
192  protected:
193  explicit SnapItem( SnapType _type ) : type( _type ) {}
194  };
195 
196  class PointSnapItem : public QgsSnapIndex::SnapItem
197  {
198  public:
199  explicit PointSnapItem( const CoordIdx *_idx, bool isEndPoint );
200  QgsPoint getSnapPoint( const QgsPoint &/*p*/ ) const override;
201  const CoordIdx *idx = nullptr;
202  };
203 
204  class SegmentSnapItem : public QgsSnapIndex::SnapItem
205  {
206  public:
207  SegmentSnapItem( const CoordIdx *_idxFrom, const CoordIdx *_idxTo );
208  QgsPoint getSnapPoint( const QgsPoint &p ) const override;
209  bool getIntersection( const QgsPoint &p1, const QgsPoint &p2, QgsPoint &inter ) const;
210  bool getProjection( const QgsPoint &p, QgsPoint &pProj );
211  const CoordIdx *idxFrom = nullptr;
212  const CoordIdx *idxTo = nullptr;
213  };
214 
215  QgsSnapIndex( const QgsPoint &origin, double cellSize );
216  ~QgsSnapIndex();
217 
218  QgsSnapIndex( const QgsSnapIndex &rh ) = delete;
219  QgsSnapIndex &operator=( const QgsSnapIndex &rh ) = delete;
220 
221  void addGeometry( const QgsAbstractGeometry *geom );
222  QgsPoint getClosestSnapToPoint( const QgsPoint &p, const QgsPoint &q );
223  SnapItem *getSnapItem( const QgsPoint &pos, double tol, PointSnapItem **pSnapPoint = nullptr, SegmentSnapItem **pSnapSegment = nullptr, bool endPointOnly = false ) const;
224 
225  private:
226  typedef QList<SnapItem *> Cell;
227  typedef QPair<QgsPoint, QgsPoint> Segment;
228 
229  class GridRow
230  {
231  public:
232  GridRow() = default;
233  ~GridRow();
234  const Cell *getCell( int col ) const;
235  Cell &getCreateCell( int col );
236  QList<SnapItem *> getSnapItems( int colStart, int colEnd ) const;
237 
238  private:
239  QList<QgsSnapIndex::Cell> mCells;
240  int mColStartIdx = 0;
241  };
242 
243  QgsPoint mOrigin;
244  double mCellSize;
245 
246  QList<CoordIdx *> mCoordIdxs;
247  QList<GridRow> mGridRows;
248  int mRowsStartIdx;
249 
250  void addPoint( const CoordIdx *idx, bool isEndPoint );
251  void addSegment( const CoordIdx *idxFrom, const CoordIdx *idxTo );
252  const Cell *getCell( int col, int row ) const;
253  Cell &getCreateCell( int col, int row );
254 
255 };
256 
258 
259 #endif
260 
261 #endif // QGS_GEOMETRY_SNAPPER_H
QgsGeometrySnapper::PreferNodes
@ PreferNodes
Prefer to snap to nodes, even when a segment may be closer than a node. New nodes will be inserted to...
Definition: qgsgeometrysnapper.h:48
QgsGeometrySnapper::PreferClosestNoExtraVertices
@ PreferClosestNoExtraVertices
Snap to closest point, regardless of it is a node or a segment. No new nodes will be inserted.
Definition: qgsgeometrysnapper.h:51
QgsPoint::vertexAt
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
Definition: qgspoint.cpp:520
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
QgsFeatureSource
An interface for objects which provide features via a getFeatures method.
Definition: qgsfeaturesource.h:38
QgsGeometrySnapper::SnapMode
SnapMode
Snapping modes.
Definition: qgsgeometrysnapper.h:47
qgspoint.h
QgsGeometrySnapper::PreferClosest
@ PreferClosest
Snap to closest point, regardless of it is a node or a segment. New nodes will be inserted to make ge...
Definition: qgsgeometrysnapper.h:49
QgsInternalGeometrySnapper::snappedGeometries
QgsGeometryMap snappedGeometries() const
Returns a QgsGeometryMap of all feature geometries snapped by this object.
Definition: qgsgeometrysnapper.h:153
QgsGeometrySnapper::EndPointToEndPoint
@ EndPointToEndPoint
Only snap the start/end points of lines to other start/end points of lines.
Definition: qgsgeometrysnapper.h:54
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:583
QgsGeometrySnapper::EndPointPreferNodes
@ EndPointPreferNodes
Only snap start/end points of lines (point features will also be snapped, polygon features will not b...
Definition: qgsgeometrysnapper.h:52
QgsSpatialIndex
A spatial index for QgsFeature objects.
Definition: qgsspatialindex.h:68
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:74
qgsgeometry.h
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:387
QgsInternalGeometrySnapper
QgsInternalGeometrySnapper allows a set of geometries to be snapped to each other.
Definition: qgsgeometrysnapper.h:134
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1059
QgsGeometryMap
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:578
qgsspatialindex.h
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsGeometrySnapper::featureSnapped
void featureSnapped()
Emitted each time a feature has been processed when calling snapFeatures()
QgsGeometrySnapper
QgsGeometrySnapper allows a geometry to be snapped to the geometries within a different reference lay...
Definition: qgsgeometrysnapper.h:40
qgsabstractgeometry.h
QgsGeometrySnapper::PreferNodesNoExtraVertices
@ PreferNodesNoExtraVertices
Prefer to snap to nodes, even when a segment may be closer than a node. No new nodes will be inserted...
Definition: qgsgeometrysnapper.h:50
QgsGeometrySnapper::EndPointPreferClosest
@ EndPointPreferClosest
Only snap start/end points of lines (point features will also be snapped, polygon features will not b...
Definition: qgsgeometrysnapper.h:53