QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgssnapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssnapper.cpp
3  --------------
4  begin : June 7, 2007
5  copyright : (C) 2007 by Marco Hugentobler
6  email : marco dot hugentobler at karto dot baug dot ethz dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgssnapper.h"
19 #include "qgsmapsettings.h"
20 #include "qgsmaprenderer.h"
21 #include "qgsmaptopixel.h"
22 #include "qgsvectorlayer.h"
23 #include <QMultiMap>
24 #include <QPoint>
25 #include <cmath>
26 
27 
29  : mMapSettings( mapRenderer->mapSettings() )
30  , mSnapMode( SnapWithOneResult )
31 {
32 
33 }
34 
36  : mMapSettings( mapSettings )
37  , mSnapMode( SnapWithOneResult )
38 {
39 }
40 
41 int QgsSnapper::snapPoint( QPoint startPoint, QList<QgsSnappingResult>& snappingResult, const QList<QgsPoint>& excludePoints )
42 {
43  QgsPoint mapCoordPoint = mMapSettings.mapToPixel().toMapCoordinates( startPoint.x(), startPoint.y() );
44  return snapMapPoint( mapCoordPoint, snappingResult, excludePoints );
45 }
46 
47 int QgsSnapper::snapMapPoint( const QgsPoint& mapCoordPoint, QList<QgsSnappingResult>& snappingResult, const QList<QgsPoint>& excludePoints )
48 {
49  snappingResult.clear();
50 
51  QMultiMap<double, QgsSnappingResult> snappingResultList;//all snapping results
52  QMultiMap<double, QgsSnappingResult> currentResultList; //snapping results of examined layer
53 
54  //start point in (output) map coordinates
55 
56  QgsPoint layerCoordPoint; //start point in layer coordinates
57  QgsSnappingResult newResult;
58 
60  for ( snapLayerIt = mSnapLayers.begin(); snapLayerIt != mSnapLayers.end(); ++snapLayerIt )
61  {
62  if ( !snapLayerIt->mLayer->hasGeometryType() )
63  continue;
64 
65  currentResultList.clear();
66  //transform point from map coordinates to layer coordinates
67  layerCoordPoint = mMapSettings.mapToLayerCoordinates( snapLayerIt->mLayer, mapCoordPoint );
68 
69  double tolerance = QgsTolerance::toleranceInMapUnits( snapLayerIt->mTolerance, snapLayerIt->mLayer, mMapSettings, snapLayerIt->mUnitType );
70  if ( snapLayerIt->mLayer->snapWithContext( layerCoordPoint, tolerance,
71  currentResultList, snapLayerIt->mSnapTo ) != 0 )
72  {
73  //error
74  }
75 
76  //transform each result from layer crs to map crs (including distance)
78  for ( currentResultIt = currentResultList.begin(); currentResultIt != currentResultList.end(); ++currentResultIt )
79  {
80  //for each snapping result: transform start point, snap point and other points into map coordinates to find out distance
81  //store results in snapping result list
82  newResult = currentResultIt.value();
83  newResult.snappedVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().snappedVertex );
84  newResult.beforeVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().beforeVertex );
85  newResult.afterVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().afterVertex );
86  snappingResultList.insert( sqrt( newResult.snappedVertex.sqrDist( mapCoordPoint ) ), newResult );
87  }
88  }
89 
90  //excluded specific points from result
91  cleanResultList( snappingResultList, excludePoints );
92 
93  //evaluate results according to snap mode
94  QMultiMap<double, QgsSnappingResult>::iterator evalIt = snappingResultList.begin();
95  if ( evalIt == snappingResultList.end() )
96  {
97  return 0;
98  }
99 
100 
101  //Gives a priority to vertex snapping over segment snapping
102  QgsSnappingResult returnResult = evalIt.value();
103  for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
104  {
105  if ( evalIt.value().snappedVertexNr != -1 )
106  {
107  returnResult = evalIt.value();
108  snappingResultList.erase( evalIt );
109  break;
110  }
111  }
112 
113  //We return the preferred result
114  snappingResult.push_back( returnResult );
115 
116  if ( mSnapMode == QgsSnapper::SnapWithOneResult )
117  {
118  //return only a single result, nothing more to do
119  }
120  else if ( mSnapMode == QgsSnapper::SnapWithResultsForSamePosition )
121  {
122  //take all snapping results within a certain tolerance because rounding differences may occur
123  double tolerance = 0.000001;
124 
125  for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
126  {
127  if ( returnResult.snappedVertex.sqrDist( evalIt.value().snappedVertex ) < tolerance*tolerance )
128  {
129  snappingResult.push_back( evalIt.value() );
130  }
131  }
132 
133  }
134 
135  else //take all results
136  {
137  for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
138  {
139  snappingResult.push_back( evalIt.value() );
140  }
141  }
142 
143  return 0;
144 }
145 
147 {
148  mSnapLayers = snapLayers;
149 }
150 
151 
153 {
154  mSnapMode = snapMode;
155 }
156 
157 void QgsSnapper::cleanResultList( QMultiMap<double, QgsSnappingResult>& list, const QList<QgsPoint>& excludeList ) const
158 {
159  QgsPoint currentResultPoint;
160  QgsSnappingResult currentSnappingResult;
161  QList<double> keysToRemove;
162 
164  for ( ; result_it != list.end(); ++result_it )
165  {
166  currentSnappingResult = result_it.value();
167  if ( currentSnappingResult.snappedVertexNr != -1 )
168  {
169  currentResultPoint = currentSnappingResult.snappedVertex;
170  if ( excludeList.contains( currentResultPoint ) )
171  {
172  keysToRemove.push_back( result_it.key() );
173  }
174  }
175  }
176 
177  QList<double>::const_iterator remove_it = keysToRemove.constBegin();
178  for ( ; remove_it != keysToRemove.constEnd(); ++remove_it )
179  {
180  list.remove( *remove_it );
181  }
182 }
void clear()
iterator erase(iterator pos)
void push_back(const T &value)
QgsPoint toMapCoordinates(int x, int y) const
A non GUI class for rendering a map layer set onto a QPainter.
static double toleranceInMapUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, UnitType units=LayerUnits)
Static function to translate tolerance value into layer units.
void clear()
int x() const
int y() const
The QgsMapSettings class contains configuration for rendering of the map.
int snapMapPoint(const QgsPoint &mapCoordPoint, QList< QgsSnappingResult > &snappingResult, const QList< QgsPoint > &excludePoints=QList< QgsPoint >())
Does the snapping operation.
Definition: qgssnapper.cpp:47
Represents the result of a snapping operation.
Definition: qgssnapper.h:36
QMap< Key, T >::iterator insert(const Key &key, const T &value)
iterator end()
Several snapping results which have the same position are returned.
Definition: qgssnapper.h:81
T & value() const
A class to represent a point.
Definition: qgspoint.h:117
const QgsMapToPixel & mapToPixel() const
iterator begin()
iterator end()
QgsPoint beforeVertex
The layer coordinates of the vertex before snappedVertex.
Definition: qgssnapper.h:44
QgsPoint afterVertex
The layer coordinates of the vertex after snappedVertex.
Definition: qgssnapper.h:49
bool contains(const T &value) const
int snappedVertexNr
The vertex index of snappedVertex or -1 if no such vertex number (e.g.
Definition: qgssnapper.h:42
Only one snapping result is returned.
Definition: qgssnapper.h:78
QgsPoint layerToMapCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from layer&#39;s CRS to output CRS
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from output CRS to layer&#39;s CRS
const Key & key() const
QgsPoint snappedVertex
The coordinates of the snapping result.
Definition: qgssnapper.h:39
Q_DECL_DEPRECATED QgsSnapper(QgsMapRenderer *mapRender)
Definition: qgssnapper.cpp:28
Q_DECL_DEPRECATED int snapPoint(QPoint startPoint, QList< QgsSnappingResult > &snappingResult, const QList< QgsPoint > &excludePoints=QList< QgsPoint >())
Does the snapping operation.
Definition: qgssnapper.cpp:41
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
Definition: qgspoint.cpp:353
const_iterator constEnd() const
const_iterator constBegin() const
int remove(const Key &key)
void setSnapLayers(const QList< QgsSnapper::SnapLayer > &snapLayers)
Definition: qgssnapper.cpp:146
void setSnapMode(QgsSnapper::SnappingMode snapMode)
Definition: qgssnapper.cpp:152
iterator begin()