QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  {
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 
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.
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.
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
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:75
const QgsMapToPixel & mapToPixel() const
const_iterator insert(const T &value)
Interface that allows rejection of some matches in intersection queries (e.g.
QgsSnappingUtils(QObject *parent=0)
void clear()
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.
int size() const
The QgsMapSettings class contains configuration for rendering of the map.
QList< LayerConfig > layers() const
Query layers used for snapping.
int elapsed() const
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.
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.
Definition: qgsmaplayer.cpp:99
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsTolerance::UnitType unit
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 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)
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
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
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)
Creates a new geometry from a QgsPolyline object.
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...
void start()
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.
iterator insert(const Key &key, const T &value)
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)
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