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