Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgsmapcanvassnapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmapcanvassnapper.cpp
3  -----------------------
4  begin : June 21, 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 "qgsmapcanvassnapper.h"
19 #include "qgsmapcanvas.h"
20 #include "qgsmaplayerregistry.h"
21 #include "qgsmaptopixel.h"
22 #include "qgsproject.h"
23 #include "qgsvectorlayer.h"
24 #include "qgstolerance.h"
25 #include <QSettings>
26 
27 
28 QgsMapCanvasSnapper::QgsMapCanvasSnapper( QgsMapCanvas* canvas ): mMapCanvas( canvas ), mSnapper( 0 )
29 {
30  if ( canvas )
31  {
32  QgsMapRenderer* canvasRender = canvas->mapRenderer();
33  if ( canvasRender )
34  {
35  mSnapper = new QgsSnapper( canvasRender );
36  }
37  }
38 }
39 
40 QgsMapCanvasSnapper::QgsMapCanvasSnapper(): mMapCanvas( 0 ), mSnapper( 0 )
41 {
42 
43 }
44 
46 {
47  delete mSnapper;
48 }
49 
51 {
52  mMapCanvas = canvas;
53  delete mSnapper;
54  if ( mMapCanvas )
55  {
56  mSnapper = new QgsSnapper( canvas->mapRenderer() );
57  }
58  else
59  {
60  mSnapper = 0;
61  }
62 }
63 
64 int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QList<QgsSnappingResult>& results, QgsSnapper::SnappingType snap_to, double snappingTol, const QList<QgsPoint>& excludePoints )
65 {
66  results.clear();
67 
68  if ( mSnapper && mMapCanvas )
69  {
70 
71  //topological editing on?
72  int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
73  if ( topologicalEditing == 0 )
74  {
76  }
77  else
78  {
80  }
81 
82  //current vector layer
83  QgsMapLayer* currentLayer = mMapCanvas->currentLayer();
84  if ( !currentLayer )
85  {
86  return 2;
87  }
88  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( currentLayer );
89  if ( !vlayer )
90  {
91  return 3;
92  }
93 
94  QgsSnapper::SnapLayer snapLayer;
95  snapLayer.mLayer = vlayer;
96  snapLayer.mSnapTo = snap_to;
98 
99  QSettings settings;
100 
101  if ( snappingTol < 0 )
102  {
103  //use search tolerance for vertex editing
105  }
106  else
107  {
108  snapLayer.mTolerance = snappingTol;
109  }
110 
111  QList<QgsSnapper::SnapLayer> snapLayers;
112  snapLayers.append( snapLayer );
113  mSnapper->setSnapLayers( snapLayers );
114 
115  if ( mSnapper->snapPoint( p, results, excludePoints ) != 0 )
116  {
117  return 4;
118  }
119 
120  return 0;
121  }
122  else
123  {
124  return 1;
125  }
126 }
127 
128 int QgsMapCanvasSnapper::snapToBackgroundLayers( const QPoint& p, QList<QgsSnappingResult>& results, const QList<QgsPoint>& excludePoints )
129 {
130  results.clear();
131 
132  if ( mSnapper )
133  {
134  //topological editing on?
135  int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
136  if ( topologicalEditing == 0 )
137  {
139  }
140  else
141  {
143  }
144 
145  //read snapping settings from project
146  bool ok; //todo: take the default snapping tolerance for all vector layers if snapping not defined in project
147  bool snappingDefinedInProject = true;
148  QStringList layerIdList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingList", &ok );
149  if ( !ok )
150  {
151  snappingDefinedInProject = false;
152  }
153  QStringList enabledList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingEnabledList", &ok );
154  QStringList toleranceList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceList", &ok );
155  QStringList toleranceUnitList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceUnitList", &ok );
156  QStringList snapToList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnapToList", &ok );
157 
158  if ( !( layerIdList.size() == enabledList.size() && layerIdList.size() == toleranceList.size() && layerIdList.size() == toleranceUnitList.size() && layerIdList.size() == snapToList.size() ) )
159  {
160  return 1; //lists must have the same size, otherwise something is wrong
161  }
162 
163  QList<QgsSnapper::SnapLayer> snapLayers;
164  QgsSnapper::SnapLayer snapLayer;
165 
166  //Use snapping information from the project
167  if ( snappingDefinedInProject )
168  {
169  //set layers, tolerances, snap to segment/vertex to QgsSnapper
170  QgsMapLayer* layer = 0;
171  QgsVectorLayer* vlayer = 0;
172 
173  QStringList::const_iterator layerIt = layerIdList.constBegin();
174  QStringList::const_iterator tolIt = toleranceList.constBegin();
175  QStringList::const_iterator tolUnitIt = toleranceUnitList.constBegin();
176  QStringList::const_iterator snapIt = snapToList.constBegin();
177  QStringList::const_iterator enabledIt = enabledList.constBegin();
178 
179  for ( ; layerIt != layerIdList.constEnd(); ++layerIt, ++tolIt, ++tolUnitIt, ++snapIt, ++enabledIt )
180  {
181  if (( *enabledIt ) != "enabled" ) //skip layer if snapping is not enabled
182  {
183  continue;
184  }
185 
186  //layer
187  layer = QgsMapLayerRegistry::instance()->mapLayer( *layerIt );
188  if ( layer == NULL )
189  continue;
190  vlayer = qobject_cast<QgsVectorLayer *>( layer );
191  if ( vlayer == NULL )
192  continue;
193 
194  snapLayer.mLayer = vlayer;
195 
196  //tolerance
197  snapLayer.mTolerance = tolIt->toDouble();
198  snapLayer.mUnitType = ( QgsTolerance::UnitType ) tolUnitIt->toInt();
199 
200  //segment or vertex
201  if (( *snapIt ) == "to_vertex" )
202  {
203  snapLayer.mSnapTo = QgsSnapper::SnapToVertex;
204  }
205  else if (( *snapIt ) == "to_segment" )
206  {
208  }
209  else //to vertex and segment
210  {
212  }
213 
214  snapLayers.append( snapLayer );
215  }
216  }
217  else //nothing in project. Use default snapping tolerance to vertex of current layer
218  {
219  QgsMapLayer* currentLayer = mMapCanvas->currentLayer();
220  if ( !currentLayer )
221  {
222  return 2;
223  }
224 
225  QgsVectorLayer* currentVectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer );
226  if ( !currentVectorLayer )
227  {
228  return 3;
229  }
230 
231  snapLayer.mLayer = currentVectorLayer;
232  QSettings settings;
233 
234  //default snap mode
235  QString defaultSnapString = settings.value( "/qgis/digitizing/default_snap_mode", "to vertex" ).toString();
236  if ( defaultSnapString == "to segment" )
237  {
239  }
240  else if ( defaultSnapString == "to vertex and segment" )
241  {
243  }
244  else
245  {
246  snapLayer.mSnapTo = QgsSnapper::SnapToVertex;
247  }
248 
249  //default snapping tolerance (returned in map units)
250  snapLayer.mTolerance = QgsTolerance::defaultTolerance( currentVectorLayer, mMapCanvas->mapRenderer() );
251  snapLayer.mUnitType = QgsTolerance::MapUnits;
252 
253  snapLayers.append( snapLayer );
254  }
255 
256  mSnapper->setSnapLayers( snapLayers );
257 
258  if ( mSnapper->snapPoint( p, results, excludePoints ) != 0 )
259  {
260  return 4;
261  }
262  return 0;
263  }
264  else
265  {
266  return 5;
267  }
268 }