QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 {
31 
32 }
33 
35  : mMapSettings( mapSettings )
36 {
37 }
38 
40 {
41 
42 }
43 
44 int QgsSnapper::snapPoint( const QPoint& startPoint, QList<QgsSnappingResult>& snappingResult, const QList<QgsPoint>& excludePoints )
45 {
46  QgsPoint mapCoordPoint = mMapSettings.mapToPixel().toMapCoordinates( startPoint.x(), startPoint.y() );
47  return snapPoint( mapCoordPoint, snappingResult, excludePoints);
48 }
49 
50 int QgsSnapper::snapPoint( const QgsPoint& mapCoordPoint, QList<QgsSnappingResult>& snappingResult, const QList<QgsPoint>& excludePoints )
51  {
52  snappingResult.clear();
53 
54  QMultiMap<double, QgsSnappingResult> snappingResultList;//all snapping results
55  QMultiMap<double, QgsSnappingResult> currentResultList; //snapping results of examined layer
56 
57  //start point in (output) map coordinates
58 
59  QgsPoint layerCoordPoint; //start point in layer coordinates
60  QgsSnappingResult newResult;
61 
62  QList<QgsSnapper::SnapLayer>::iterator snapLayerIt;
63  for ( snapLayerIt = mSnapLayers.begin(); snapLayerIt != mSnapLayers.end(); ++snapLayerIt )
64  {
65  if ( !snapLayerIt->mLayer->hasGeometryType() )
66  continue;
67 
68  currentResultList.clear();
69  //transform point from map coordinates to layer coordinates
70  layerCoordPoint = mMapSettings.mapToLayerCoordinates( snapLayerIt->mLayer, mapCoordPoint );
71 
72  double tolerance = QgsTolerance::toleranceInMapUnits( snapLayerIt->mTolerance, snapLayerIt->mLayer, mMapSettings, snapLayerIt->mUnitType );
73  if ( snapLayerIt->mLayer->snapWithContext( layerCoordPoint, tolerance,
74  currentResultList, snapLayerIt->mSnapTo ) != 0 )
75  {
76  //error
77  }
78 
79  //transform each result from layer crs to map crs (including distance)
80  QMultiMap<double, QgsSnappingResult>::iterator currentResultIt;
81  for ( currentResultIt = currentResultList.begin(); currentResultIt != currentResultList.end(); ++currentResultIt )
82  {
83  //for each snapping result: transform start point, snap point and other points into map coordinates to find out distance
84  //store results in snapping result list
85  newResult = currentResultIt.value();
86  newResult.snappedVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().snappedVertex );
87  newResult.beforeVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().beforeVertex );
88  newResult.afterVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().afterVertex );
89  snappingResultList.insert( sqrt( newResult.snappedVertex.sqrDist( mapCoordPoint ) ), newResult );
90  }
91  }
92 
93  //excluded specific points from result
94  cleanResultList( snappingResultList, excludePoints );
95 
96  //evaluate results according to snap mode
97  QMultiMap<double, QgsSnappingResult>::iterator evalIt = snappingResultList.begin();
98  if ( evalIt == snappingResultList.end() )
99  {
100  return 0;
101  }
102 
103 
104  //Gives a priority to vertex snapping over segment snapping
105  QgsSnappingResult returnResult = evalIt.value();
106  for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
107  {
108  if ( evalIt.value().snappedVertexNr != -1 )
109  {
110  returnResult = evalIt.value();
111  snappingResultList.erase( evalIt );
112  break;
113  }
114  }
115 
116  //We return the preferred result
117  snappingResult.push_back( returnResult );
118 
119  if ( mSnapMode == QgsSnapper::SnapWithOneResult )
120  {
121  //return only a single result, nothing more to do
122  }
123  else if ( mSnapMode == QgsSnapper::SnapWithResultsForSamePosition )
124  {
125  //take all snapping results within a certain tolerance because rounding differences may occur
126  double tolerance = 0.000001;
127 
128  for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
129  {
130  if ( returnResult.snappedVertex.sqrDist( evalIt.value().snappedVertex ) < tolerance*tolerance )
131  {
132  snappingResult.push_back( evalIt.value() );
133  }
134  }
135 
136  }
137 
138  else //take all results
139  {
140  for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
141  {
142  snappingResult.push_back( evalIt.value() );
143  }
144  }
145 
146  return 0;
147 }
148 
149 void QgsSnapper::setSnapLayers( const QList<QgsSnapper::SnapLayer>& snapLayers )
150 {
151  mSnapLayers = snapLayers;
152 }
153 
154 
156 {
157  mSnapMode = snapMode;
158 }
159 
160 void QgsSnapper::cleanResultList( QMultiMap<double, QgsSnappingResult>& list, const QList<QgsPoint>& excludeList ) const
161 {
162  QgsPoint currentResultPoint;
163  QgsSnappingResult currentSnappingResult;
164  QList<double> keysToRemove;
165 
166  QMultiMap<double, QgsSnappingResult>::iterator result_it = list.begin();
167  for ( ; result_it != list.end(); ++result_it )
168  {
169  currentSnappingResult = result_it.value();
170  if ( currentSnappingResult.snappedVertexNr != -1 )
171  {
172  currentResultPoint = currentSnappingResult.snappedVertex;
173  if ( excludeList.contains( currentResultPoint ) )
174  {
175  keysToRemove.push_back( result_it.key() );
176  }
177  }
178  }
179 
180  QList<double>::const_iterator remove_it = keysToRemove.constBegin();
181  for ( ; remove_it != keysToRemove.constEnd(); ++remove_it )
182  {
183  list.remove( *remove_it );
184  }
185 }
QgsPoint layerToMapCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from layer's CRS to output CRS
static double toleranceInMapUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, UnitType units=MapUnits)
Static function to translate tolerance value into current map unit value.
int snapPoint(const QPoint &startPoint, QList< QgsSnappingResult > &snappingResult, const QList< QgsPoint > &excludePoints=QList< QgsPoint >())
Does the snapping operation.
Definition: qgssnapper.cpp:44
const QgsMapToPixel & mapToPixel() const
A non GUI class for rendering a map layer set onto a QPainter.
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from output CRS to layer's CRS
double sqrDist(double x, double y) const
Returns the squared distance between this point and x,y.
Definition: qgspoint.cpp:333
The QgsMapSettings class contains configuration for rendering of the map.
Represents the result of a snapping operation.
Definition: qgssnapper.h:36
Several snapping results which have the same position are returned.
Definition: qgssnapper.h:80
A class to represent a point.
Definition: qgspoint.h:63
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
QgsPoint toMapCoordinates(int x, int y) 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:77
QgsPoint snappedVertex
The coordinates of the snapping result.
Definition: qgssnapper.h:39
Q_DECL_DEPRECATED QgsSnapper(QgsMapRenderer *mapRender)
@ deprecated since 2.4 - use constructor with QgsMapSettings
Definition: qgssnapper.cpp:28
void setSnapLayers(const QList< QgsSnapper::SnapLayer > &snapLayers)
Definition: qgssnapper.cpp:149
void setSnapMode(QgsSnapper::SnappingMode snapMode)
Definition: qgssnapper.cpp:155