27 , mSnapToMapMode( SnapCurrentLayer )
28 , mStrategy( IndexHybrid )
30 , mDefaultTolerance( 10 )
32 , mSnapOnIntersection( false )
48 if ( !mLocators.contains( vl ) )
51 mLocators.insert( vl, vlpl );
53 return mLocators.value( vl );
56 void QgsSnappingUtils::clearAllLocators()
64 mTemporaryLocators.clear();
70 if ( willUseIndex( vl ) )
73 return temporaryLocatorForLayer( vl, pointMap, tolerance );
78 if ( mTemporaryLocators.contains( vl ) )
79 delete mTemporaryLocators.take( vl );
81 QgsRectangle rect( pointMap.
x() - tolerance, pointMap.
y() - tolerance,
82 pointMap.
x() + tolerance, pointMap.
y() + tolerance );
84 mTemporaryLocators.insert( vl, vlpl );
85 return mTemporaryLocators.value( vl );
96 if ( mHybridNonindexableLayers.contains( vl->
id() ) )
107 if ( segments.isEmpty() )
110 QSet<QgsPoint> endpoints;
113 QList<QgsGeometry*> geoms;
121 endpoints << pl[0] << pl[1];
129 QList<QgsPoint> newPoints;
134 if ( !endpoints.contains( p ) )
144 if ( !endpoints.contains( p ) )
151 if ( newPoints.isEmpty() )
156 double minSqrDist = 1e20;
157 foreach (
const QgsPoint& p, newPoints )
159 double sqrDist = pt.
sqrDist( p.
x(), p.
y() );
160 if ( sqrDist < minSqrDist )
162 minSqrDist = sqrDist;
214 if ( !mCurrentLayer )
217 prepareIndex( QList<QgsVectorLayer*>() << mCurrentLayer );
221 int type = mDefaultType;
224 QgsPointLocator* loc = locatorForLayerUsingStrategy( mCurrentLayer, pointMap, tolerance );
231 if ( mSnapOnIntersection )
233 QgsPointLocator* locEdges = locatorForLayerUsingStrategy( mCurrentLayer, pointMap, tolerance );
242 QList<QgsVectorLayer*>
layers;
243 foreach (
const LayerConfig& layerConfig, mLayers )
244 layers << layerConfig.
layer;
245 prepareIndex( layers );
249 double maxSnapIntTolerance = 0;
251 foreach (
const LayerConfig& layerConfig, mLayers )
254 if (
QgsPointLocator* loc = locatorForLayerUsingStrategy( layerConfig.
layer, pointMap, tolerance ) )
258 if ( mSnapOnIntersection )
260 edges << loc->edgesInRect( pointMap, tolerance );
261 maxSnapIntTolerance = qMax( maxSnapIntTolerance, tolerance );
266 if ( mSnapOnIntersection )
275 int type = mDefaultType;
277 QList<QgsVectorLayer*>
layers;
278 foreach (
const QString& layerID, mMapSettings.
layers() )
281 prepareIndex( layers );
288 if (
QgsPointLocator* loc = locatorForLayerUsingStrategy( vl, pointMap, tolerance ) )
292 if ( mSnapOnIntersection )
293 edges << loc->edgesInRect( pointMap, tolerance );
297 if ( mSnapOnIntersection )
307 void QgsSnappingUtils::prepareIndex(
const QList<QgsVectorLayer*>&
layers )
310 QList<QgsVectorLayer*> layersToIndex;
316 if ( layersToIndex.isEmpty() )
325 QTime tt; tt.start();
327 mHybridNonindexableLayers.insert( vl->
id() );
328 QgsDebugMsg( QString(
"Index init: %1 ms (%2)" ).arg( tt.elapsed() ).arg( vl->
id() ) );
331 QgsDebugMsg( QString(
"Prepare index total: %1 ms" ).arg( t.elapsed() ) );
337 if ( !mCurrentLayer )
343 QgsPointLocator* loc = locatorForLayerUsingStrategy( mCurrentLayer, pointMap, tolerance );
356 mMapSettings = settings;
358 if ( newDestCRS != oldDestCRS )
369 mDefaultTolerance = tolerance;
376 tolerance = mDefaultTolerance;
395 if ( snapType ==
"to segment" )
397 else if ( snapType ==
"to vertex and segment" )
399 else if ( snapType ==
"to vertex" )
409 bool snappingDefinedInProject, ok;
417 if ( layerIdList.size() != enabledList.size() ||
418 layerIdList.size() != toleranceList.size() ||
419 layerIdList.size() != toleranceUnitList.size() ||
420 layerIdList.size() != snapToList.size() )
423 if ( !snappingDefinedInProject )
427 if ( snapMode ==
"current_layer" )
429 else if ( snapMode ==
"all_layers" )
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 )
445 if ( *enabledIt !=
"enabled" )
460 void QgsSnappingUtils::onLayersWillBeRemoved( QStringList layerIds )
463 foreach ( QString layerId, layerIds )
465 for ( LocatorsMap::iterator it = mLocators.begin(); it != mLocators.end(); )
467 if ( it.key()->id() == layerId )
470 it = mLocators.erase( it );
478 for ( LocatorsMap::iterator it = mTemporaryLocators.begin(); it != mTemporaryLocators.end(); )
480 if ( it.key()->id() == layerId )
483 it = mTemporaryLocators.erase( it );
The class defines interface for querying point location:
A rectangle specified with double values.
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).
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
static QgsMapLayerRegistry * instance()
UnitType
Type of unit of tolerance value from settings.
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.
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=0) const
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.
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 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.
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)
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 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
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
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