QGIS API Documentation  3.17.0-Master (df2c9ff931)
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 
86  void featureSnapped();
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
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:609
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:614
Only snap the start/end points of lines to other start/end points of lines.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:123
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
Definition: qgspoint.cpp:520
Utility class for identifying a unique vertex within a geometry.
Only snap start/end points of lines (point features will also be snapped, polygon features will not b...
QgsGeometrySnapper allows a geometry to be snapped to the geometries within a different reference lay...
Abstract base class for all geometries.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
Prefer to snap to nodes, even when a segment may be closer than a node. New nodes will be inserted to...
A spatial index for QgsFeature objects.
Snap to closest point, regardless of it is a node or a segment. New nodes will be inserted to make ge...
An interface for objects which provide features via a getFeatures method.
SnapMode
Snapping modes.
Prefer to snap to nodes, even when a segment may be closer than a node. No new nodes will be inserted...
Only snap start/end points of lines (point features will also be snapped, polygon features will not b...
Represents a vector layer which manages a vector based data sets.
Snap to closest point, regardless of it is a node or a segment. No new nodes will be inserted...
QgsGeometryMap snappedGeometries() const
Returns a QgsGeometryMap of all feature geometries snapped by this object.
QgsInternalGeometrySnapper allows a set of geometries to be snapped to each other.