QGIS API Documentation  2.12.0-Lyon
qgssnappingutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssnappingutils.cpp
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 #include "qgssnappingutils.h"
17 
18 #include "qgsgeometry.h"
19 #include "qgsmaplayerregistry.h"
20 #include "qgsproject.h"
21 #include "qgsvectorlayer.h"
22 
23 
25  : QObject( parent )
26  , mCurrentLayer( 0 )
27  , mSnapToMapMode( SnapCurrentLayer )
28  , mStrategy( IndexHybrid )
29  , mDefaultType( QgsPointLocator::Vertex )
30  , mDefaultTolerance( 10 )
31  , mDefaultUnit( QgsTolerance::Pixels )
32  , mSnapOnIntersection( false )
33  , mIsIndexing( false )
34 {
35  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( onLayersWillBeRemoved( QStringList ) ) );
36 }
37 
39 {
40  clearAllLocators();
41 }
42 
43 
45 {
46  if ( !vl )
47  return 0;
48 
49  if ( !mLocators.contains( vl ) )
50  {
51  QgsPointLocator* vlpl = new QgsPointLocator( vl, destCRS() );
52  mLocators.insert( vl, vlpl );
53  }
54  return mLocators.value( vl );
55 }
56 
57 void QgsSnappingUtils::clearAllLocators()
58 {
59  Q_FOREACH ( QgsPointLocator* vlpl, mLocators )
60  delete vlpl;
61  mLocators.clear();
62 
63  Q_FOREACH ( QgsPointLocator* vlpl, mTemporaryLocators )
64  delete vlpl;
65  mTemporaryLocators.clear();
66 }
67 
68 
69 QgsPointLocator* QgsSnappingUtils::locatorForLayerUsingStrategy( QgsVectorLayer* vl, const QgsPoint& pointMap, double tolerance )
70 {
71  if ( willUseIndex( vl ) )
72  return locatorForLayer( vl );
73  else
74  return temporaryLocatorForLayer( vl, pointMap, tolerance );
75 }
76 
77 QgsPointLocator* QgsSnappingUtils::temporaryLocatorForLayer( QgsVectorLayer* vl, const QgsPoint& pointMap, double tolerance )
78 {
79  if ( mTemporaryLocators.contains( vl ) )
80  delete mTemporaryLocators.take( vl );
81 
82  QgsRectangle rect( pointMap.x() - tolerance, pointMap.y() - tolerance,
83  pointMap.x() + tolerance, pointMap.y() + tolerance );
84  QgsPointLocator* vlpl = new QgsPointLocator( vl, destCRS(), &rect );
85  mTemporaryLocators.insert( vl, vlpl );
86  return mTemporaryLocators.value( vl );
87 }
88 
89 bool QgsSnappingUtils::willUseIndex( QgsVectorLayer* vl ) const
90 {
91  if ( vl->geometryType() == QGis::NoGeometry )
92  return false;
93  if ( mStrategy == IndexAlwaysFull )
94  return true;
95  else if ( mStrategy == IndexNeverFull )
96  return false;
97  else
98  {
99  if ( mHybridNonindexableLayers.contains( vl->id() ) )
100  return false;
101 
102  // if the layer is too big, the locator will later stop indexing it after reaching a threshold
103  return true;
104  }
105 }
106 
107 
109 {
110  if ( segments.isEmpty() )
111  return QgsPointLocator::Match();
112 
113  QSet<QgsPoint> endpoints;
114 
115  // make a geometry
116  QList<QgsGeometry*> geoms;
117  Q_FOREACH ( const QgsPointLocator::Match& m, segments )
118  {
119  if ( m.hasEdge() )
120  {
121  QgsPolyline pl( 2 );
122  m.edgePoints( pl[0], pl[1] );
123  geoms << QgsGeometry::fromPolyline( pl );
124  endpoints << pl[0] << pl[1];
125  }
126  }
127 
128  QgsGeometry* g = QgsGeometry::unaryUnion( geoms );
129  qDeleteAll( geoms );
130 
131  // get intersection points
132  QList<QgsPoint> newPoints;
133  if ( g->wkbType() == QGis::WKBLineString )
134  {
135  Q_FOREACH ( const QgsPoint& p, g->asPolyline() )
136  {
137  if ( !endpoints.contains( p ) )
138  newPoints << p;
139  }
140  }
141  if ( g->wkbType() == QGis::WKBMultiLineString )
142  {
143  Q_FOREACH ( const QgsPolyline& pl, g->asMultiPolyline() )
144  {
145  Q_FOREACH ( const QgsPoint& p, pl )
146  {
147  if ( !endpoints.contains( p ) )
148  newPoints << p;
149  }
150  }
151  }
152  delete g;
153 
154  if ( newPoints.isEmpty() )
155  return QgsPointLocator::Match();
156 
157  // find the closest points
158  QgsPoint minP;
159  double minSqrDist = 1e20; // "infinity"
160  Q_FOREACH ( const QgsPoint& p, newPoints )
161  {
162  double sqrDist = pt.sqrDist( p.x(), p.y() );
163  if ( sqrDist < minSqrDist )
164  {
165  minSqrDist = sqrDist;
166  minP = p;
167  }
168  }
169 
170  return QgsPointLocator::Match( QgsPointLocator::Vertex, 0, 0, sqrt( minSqrDist ), minP );
171 }
172 
173 
174 static void _replaceIfBetter( QgsPointLocator::Match& mBest, const QgsPointLocator::Match& mNew, double maxDistance )
175 {
176  // is other match relevant?
177  if ( !mNew.isValid() || mNew.distance() > maxDistance )
178  return;
179 
180  // is other match actually better?
181  if ( mBest.isValid() && mBest.type() == mNew.type() && mBest.distance() - 10e-6 < mNew.distance() )
182  return;
183 
184  // prefer vertex matches to edge matches (even if they are closer)
185  if ( mBest.type() == QgsPointLocator::Vertex && mNew.type() == QgsPointLocator::Edge )
186  return;
187 
188  mBest = mNew; // the other match is better!
189 }
190 
191 
192 static void _updateBestMatch( QgsPointLocator::Match& bestMatch, const QgsPoint& pointMap, QgsPointLocator* loc, int type, double tolerance, QgsPointLocator::MatchFilter* filter )
193 {
194  if ( type & QgsPointLocator::Vertex )
195  {
196  _replaceIfBetter( bestMatch, loc->nearestVertex( pointMap, tolerance, filter ), tolerance );
197  }
198  if ( bestMatch.type() != QgsPointLocator::Vertex && ( type & QgsPointLocator::Edge ) )
199  {
200  _replaceIfBetter( bestMatch, loc->nearestEdge( pointMap, tolerance, filter ), tolerance );
201  }
202 }
203 
204 
206 {
207  return snapToMap( mMapSettings.mapToPixel().toMapCoordinates( point ), filter );
208 }
209 
211 {
212  if ( !mMapSettings.hasValidSettings() )
213  return QgsPointLocator::Match();
214 
215  if ( mSnapToMapMode == SnapCurrentLayer )
216  {
217  if ( !mCurrentLayer )
218  return QgsPointLocator::Match();
219 
220  prepareIndex( QList<QgsVectorLayer*>() << mCurrentLayer );
221 
222  // data from project
223  double tolerance = QgsTolerance::toleranceInProjectUnits( mDefaultTolerance, mCurrentLayer, mMapSettings, mDefaultUnit );
224  int type = mDefaultType;
225 
226  // use ad-hoc locator
227  QgsPointLocator* loc = locatorForLayerUsingStrategy( mCurrentLayer, pointMap, tolerance );
228  if ( !loc )
229  return QgsPointLocator::Match();
230 
231  QgsPointLocator::Match bestMatch;
232  _updateBestMatch( bestMatch, pointMap, loc, type, tolerance, filter );
233 
234  if ( mSnapOnIntersection )
235  {
236  QgsPointLocator* locEdges = locatorForLayerUsingStrategy( mCurrentLayer, pointMap, tolerance );
237  QgsPointLocator::MatchList edges = locEdges->edgesInRect( pointMap, tolerance );
238  _replaceIfBetter( bestMatch, _findClosestSegmentIntersection( pointMap, edges ), tolerance );
239  }
240 
241  return bestMatch;
242  }
243  else if ( mSnapToMapMode == SnapAdvanced )
244  {
246  Q_FOREACH ( const LayerConfig& layerConfig, mLayers )
247  layers << layerConfig.layer;
248  prepareIndex( layers );
249 
250  QgsPointLocator::Match bestMatch;
251  QgsPointLocator::MatchList edges; // for snap on intersection
252  double maxSnapIntTolerance = 0;
253 
254  Q_FOREACH ( const LayerConfig& layerConfig, mLayers )
255  {
256  double tolerance = QgsTolerance::toleranceInProjectUnits( layerConfig.tolerance, layerConfig.layer, mMapSettings, layerConfig.unit );
257  if ( QgsPointLocator* loc = locatorForLayerUsingStrategy( layerConfig.layer, pointMap, tolerance ) )
258  {
259  _updateBestMatch( bestMatch, pointMap, loc, layerConfig.type, tolerance, filter );
260 
261  if ( mSnapOnIntersection )
262  {
263  edges << loc->edgesInRect( pointMap, tolerance );
264  maxSnapIntTolerance = qMax( maxSnapIntTolerance, tolerance );
265  }
266  }
267  }
268 
269  if ( mSnapOnIntersection )
270  _replaceIfBetter( bestMatch, _findClosestSegmentIntersection( pointMap, edges ), maxSnapIntTolerance );
271 
272  return bestMatch;
273  }
274  else if ( mSnapToMapMode == SnapAllLayers )
275  {
276  // data from project
277  double tolerance = QgsTolerance::toleranceInProjectUnits( mDefaultTolerance, 0, mMapSettings, mDefaultUnit );
278  int type = mDefaultType;
279 
281  Q_FOREACH ( const QString& layerID, mMapSettings.layers() )
282  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerID ) ) )
283  layers << vl;
284  prepareIndex( layers );
285 
286  QgsPointLocator::MatchList edges; // for snap on intersection
287  QgsPointLocator::Match bestMatch;
288 
289  Q_FOREACH ( QgsVectorLayer* vl, layers )
290  {
291  if ( QgsPointLocator* loc = locatorForLayerUsingStrategy( vl, pointMap, tolerance ) )
292  {
293  _updateBestMatch( bestMatch, pointMap, loc, type, tolerance, filter );
294 
295  if ( mSnapOnIntersection )
296  edges << loc->edgesInRect( pointMap, tolerance );
297  }
298  }
299 
300  if ( mSnapOnIntersection )
301  _replaceIfBetter( bestMatch, _findClosestSegmentIntersection( pointMap, edges ), tolerance );
302 
303  return bestMatch;
304  }
305 
306  return QgsPointLocator::Match();
307 }
308 
309 
310 void QgsSnappingUtils::prepareIndex( const QList<QgsVectorLayer*>& layers )
311 {
312  if ( mIsIndexing )
313  return;
314  mIsIndexing = true;
315 
316  // check if we need to build any index
317  QList<QgsVectorLayer*> layersToIndex;
318  Q_FOREACH ( QgsVectorLayer* vl, layers )
319  {
320  if ( willUseIndex( vl ) && !locatorForLayer( vl )->hasIndex() )
321  layersToIndex << vl;
322  }
323  if ( !layersToIndex.isEmpty() )
324  {
325  // build indexes
326  QTime t; t.start();
327  int i = 0;
328  prepareIndexStarting( layersToIndex.count() );
329  Q_FOREACH ( QgsVectorLayer* vl, layersToIndex )
330  {
331  QTime tt; tt.start();
332  if ( !locatorForLayer( vl )->init( mStrategy == IndexHybrid ? 1000000 : -1 ) )
333  mHybridNonindexableLayers.insert( vl->id() );
334  QgsDebugMsg( QString( "Index init: %1 ms (%2)" ).arg( tt.elapsed() ).arg( vl->id() ) );
335  prepareIndexProgress( ++i );
336  }
337  QgsDebugMsg( QString( "Prepare index total: %1 ms" ).arg( t.elapsed() ) );
338  }
339  mIsIndexing = false;
340 }
341 
342 
344 {
345  if ( !mCurrentLayer )
346  return QgsPointLocator::Match();
347 
348  QgsPoint pointMap = mMapSettings.mapToPixel().toMapCoordinates( point );
349  double tolerance = QgsTolerance::vertexSearchRadius( mMapSettings );
350 
351  QgsPointLocator* loc = locatorForLayerUsingStrategy( mCurrentLayer, pointMap, tolerance );
352  if ( !loc )
353  return QgsPointLocator::Match();
354 
355  QgsPointLocator::Match bestMatch;
356  _updateBestMatch( bestMatch, pointMap, loc, type, tolerance, filter );
357  return bestMatch;
358 }
359 
361 {
362  QString oldDestCRS = mMapSettings.hasCrsTransformEnabled() ? mMapSettings.destinationCrs().authid() : QString();
363  QString newDestCRS = settings.hasCrsTransformEnabled() ? settings.destinationCrs().authid() : QString();
364  mMapSettings = settings;
365 
366  if ( newDestCRS != oldDestCRS )
367  clearAllLocators();
368 }
369 
370 void QgsSnappingUtils::setDefaultSettings( int type, double tolerance, QgsTolerance::UnitType unit )
371 {
372  // force map units - can't use layer units for just any layer
373  if ( unit == QgsTolerance::LayerUnits )
375 
376  mDefaultType = type;
377  mDefaultTolerance = tolerance;
378  mDefaultUnit = unit;
379 }
380 
381 void QgsSnappingUtils::defaultSettings( int& type, double& tolerance, QgsTolerance::UnitType& unit )
382 {
383  type = mDefaultType;
384  tolerance = mDefaultTolerance;
385  unit = mDefaultUnit;
386 }
387 
388 const QgsCoordinateReferenceSystem* QgsSnappingUtils::destCRS()
389 {
390  return mMapSettings.hasCrsTransformEnabled() ? &mMapSettings.destinationCrs() : 0;
391 }
392 
393 
395 {
396  mSnapToMapMode = SnapCurrentLayer;
397  mLayers.clear();
398 
399  QString snapMode = QgsProject::instance()->readEntry( "Digitizing", "/SnappingMode" );
400 
401  int type = 0;
402  QString snapType = QgsProject::instance()->readEntry( "Digitizing", "/DefaultSnapType", QString( "off" ) );
403  if ( snapType == "to segment" )
404  type = QgsPointLocator::Edge;
405  else if ( snapType == "to vertex and segment" )
407  else if ( snapType == "to vertex" )
409  double tolerance = QgsProject::instance()->readDoubleEntry( "Digitizing", "/DefaultSnapTolerance", 0 );
410  QgsTolerance::UnitType unit = ( QgsTolerance::UnitType ) QgsProject::instance()->readNumEntry( "Digitizing", "/DefaultSnapToleranceUnit", QgsTolerance::ProjectUnits );
411  setDefaultSettings( type, tolerance, unit );
412 
413  //snapping on intersection on?
414  setSnapOnIntersections( QgsProject::instance()->readNumEntry( "Digitizing", "/IntersectionSnapping", 0 ) );
415 
416  //read snapping settings from project
417  bool snappingDefinedInProject, ok;
418  QStringList layerIdList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingList", QStringList(), &snappingDefinedInProject );
419  QStringList enabledList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingEnabledList", QStringList(), &ok );
420  QStringList toleranceList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceList", QStringList(), &ok );
421  QStringList toleranceUnitList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceUnitList", QStringList(), &ok );
422  QStringList snapToList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnapToList", QStringList(), &ok );
423 
424  // lists must have the same size, otherwise something is wrong
425  if ( layerIdList.size() != enabledList.size() ||
426  layerIdList.size() != toleranceList.size() ||
427  layerIdList.size() != toleranceUnitList.size() ||
428  layerIdList.size() != snapToList.size() )
429  return;
430 
431  if ( !snappingDefinedInProject )
432  return; // nothing defined in project - use current layer
433 
434  // Use snapping information from the project
435  if ( snapMode == "current_layer" )
436  mSnapToMapMode = SnapCurrentLayer;
437  else if ( snapMode == "all_layers" )
438  mSnapToMapMode = SnapAllLayers;
439  else // either "advanced" or empty (for background compatibility)
440  mSnapToMapMode = SnapAdvanced;
441 
442 
443 
444  // load layers, tolerances, snap type
445  QStringList::const_iterator layerIt( layerIdList.constBegin() );
446  QStringList::const_iterator tolIt( toleranceList.constBegin() );
447  QStringList::const_iterator tolUnitIt( toleranceUnitList.constBegin() );
448  QStringList::const_iterator snapIt( snapToList.constBegin() );
449  QStringList::const_iterator enabledIt( enabledList.constBegin() );
450  for ( ; layerIt != layerIdList.constEnd(); ++layerIt, ++tolIt, ++tolUnitIt, ++snapIt, ++enabledIt )
451  {
452  // skip layer if snapping is not enabled
453  if ( *enabledIt != "enabled" )
454  continue;
455 
456  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( QgsMapLayerRegistry::instance()->mapLayer( *layerIt ) );
457  if ( !vlayer || !vlayer->hasGeometryType() )
458  continue;
459 
460  QgsPointLocator::Types t( *snapIt == "to_vertex" ? QgsPointLocator::Vertex :
461  ( *snapIt == "to_segment" ? QgsPointLocator::Edge :
463  )
464  );
465  mLayers.append( LayerConfig( vlayer, t, tolIt->toDouble(), ( QgsTolerance::UnitType ) tolUnitIt->toInt() ) );
466  }
467 
468 }
469 
470 void QgsSnappingUtils::onLayersWillBeRemoved( const QStringList& layerIds )
471 {
472  // remove locators for layers that are going to be deleted
473  Q_FOREACH ( const QString& layerId, layerIds )
474  {
475  for ( LocatorsMap::iterator it = mLocators.begin(); it != mLocators.end(); )
476  {
477  if ( it.key()->id() == layerId )
478  {
479  delete it.value();
480  it = mLocators.erase( it );
481  }
482  else
483  {
484  ++it;
485  }
486  }
487 
488  for ( LocatorsMap::iterator it = mTemporaryLocators.begin(); it != mTemporaryLocators.end(); )
489  {
490  if ( it.key()->id() == layerId )
491  {
492  delete it.value();
493  it = mTemporaryLocators.erase( it );
494  }
495  else
496  {
497  ++it;
498  }
499  }
500  }
501 }
502 
The class defines interface for querying point location:
A rectangle specified with double values.
Definition: qgsrectangle.h:35
void setSnapOnIntersections(bool enabled)
Set whether to consider intersections of nearby segments for snapping.
iterator erase(iterator pos)
bool contains(const Key &key) const
virtual void prepareIndexProgress(int index)
Called when finished indexing a layer. When index == count the indexing is complete.
snap to all rendered layers (tolerance and type from defaultSettings())
QgsPointLocator::Match snapToMap(const QPoint &point, QgsPointLocator::MatchFilter *filter=0)
Snap to map according to the current configuration (mode).
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
Match nearestEdge(const QgsPoint &point, double tolerance, MatchFilter *filter=0)
Find nearest edges to the specified point - up to distance specified by tolerance Optional filter may...
QgsMultiPolyline asMultiPolyline() const
Return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
const QgsMapToPixel & mapToPixel() const
Map (project) units.
Definition: qgstolerance.h:42
const_iterator insert(const T &value)
Interface that allows rejection of some matches in intersection queries (e.g.
QgsSnappingUtils(QObject *parent=0)
double sqrDist(double x, double y) const
Returns the squared distance between this point and x,y.
Definition: qgspoint.cpp:345
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=0) const
double x() const
Get the x value of the point.
Definition: qgspoint.h:126
void readConfigFromProject()
Read snapping configuration from the project.
int size() const
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
The QgsMapSettings class contains configuration for rendering of the map.
QList< LayerConfig > layers() const
Query layers used for snapping.
int elapsed() const
For all layers build index of full extent. Uses more memory, but queries are faster.
int count(const T &value) const
For "big" layers using IndexNeverFull, for the rest IndexAlwaysFull. Compromise between speed and mem...
static void _updateBestMatch(QgsPointLocator::Match &bestMatch, const QgsPoint &pointMap, QgsPointLocator *loc, int type, double tolerance, QgsPointLocator::MatchFilter *filter)
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
bool isEmpty() const
This is the class is providing tolerance value in map unit values.
Definition: qgstolerance.h:26
static void _replaceIfBetter(QgsPointLocator::Match &mBest, const QgsPointLocator::Match &mNew, double maxDistance)
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QGis::GeometryType geometryType() const
Returns point, line or polygon.
QgsTolerance::UnitType unit
The units in which the tolerance is specified.
iterator end()
snap according to the configuration set in setLayers()
double distance() const
for vertex / edge match units depending on what class returns it (geom.cache: layer units...
void setMapSettings(const QgsMapSettings &settings)
Assign current map settings to the utils - used for conversion between screen coords to map coords...
class QList< Match > MatchList
A class to represent a point.
Definition: qgspoint.h:63
iterator begin()
double tolerance
The range around snapping targets in which snapping should occur.
double readDoubleEntry(const QString &scope, const QString &key, double def=0, bool *ok=0) const
For all layers only create temporary indexes of small extent. Low memory usage, slower queries...
bool contains(const T &value) const
static QgsPointLocator::Match _findClosestSegmentIntersection(const QgsPoint &pt, const QgsPointLocator::MatchList &segments)
QgsPointLocator::Match snapToCurrentLayer(const QPoint &point, int type, QgsPointLocator::MatchFilter *filter=0)
Snap to current layer.
QgsPoint toMapCoordinates(int x, int y) const
static double vertexSearchRadius(const QgsMapSettings &mapSettings)
Static function to get vertex tolerance value.
QgsPolyline asPolyline() const
Return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
virtual void prepareIndexStarting(int count)
Called when starting to index - can be overridden and e.g. progress dialog can be provided...
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsPointLocator * locatorForLayer(QgsVectorLayer *vl)
Get a point locator for the given layer.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=0) const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
static double toleranceInProjectUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units)
Static function to translate tolerance value into map units.
Layer unit value.
Definition: qgstolerance.h:38
QgsVectorLayer * layer
The layer to configure.
Configures how a certain layer should be handled in a snapping operation.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:353
Class for storing a coordinate reference system (CRS)
This class has all the configuration of snapping and can return answers to snapping queries...
QString authid() const
Get the authority identifier for this srs.
void edgePoints(QgsPoint &pt1, QgsPoint &pt2) const
Only for a valid edge match - obtain endpoints of the edge.
static QgsGeometry * fromPolyline(const QgsPolyline &polyline)
Creates a new geometry from a QgsPolyline object.
QgsPointLocator::Types type
To which geometry properties of this layers a snapping should happen.
double y() const
Get the y value of the point.
Definition: qgspoint.h:134
QStringList layers() const
Get list of layer IDs for map rendering The layers are stored in the reverse order of how they are re...
void start()
static QgsGeometry * unaryUnion(const QList< QgsGeometry * > &geometryList)
Compute the unary union on a list of geometries.
iterator insert(const Key &key, const T &value)
UnitType
Type of unit of tolerance value from settings.
Definition: qgstolerance.h:33
const_iterator constEnd() const
const_iterator constBegin() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
snap just to current layer (tolerance and type from defaultSettings())
Represents a vector layer which manages a vector based data sets.
void setDefaultSettings(int type, double tolerance, QgsTolerance::UnitType unit)
Configure options used when the mode is snap to current layer.
T take(const Key &key)
QStringList readListEntry(const QString &scope, const QString &key, const QStringList &def=QStringList(), bool *ok=0) const
Key value accessors.
Match nearestVertex(const QgsPoint &point, double tolerance, MatchFilter *filter=0)
Find nearest vertex to the specified point - up to distance specified by tolerance Optional filter ma...
MatchList edgesInRect(const QgsRectangle &rect, MatchFilter *filter=0)
Find edges within a specified recangle Optional filter may discard unwanted matches.
const T value(const Key &key) const
void defaultSettings(int &type, double &tolerance, QgsTolerance::UnitType &unit)
Query options used when the mode is snap to current layer.