Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgsmapcanvassnapper.cpp 00003 ----------------------- 00004 begin : June 21, 2007 00005 copyright : (C) 2007 by Marco Hugentobler 00006 email : marco dot hugentobler at karto dot baug dot ethz dot ch 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "qgsmapcanvassnapper.h" 00019 #include "qgsmapcanvas.h" 00020 #include "qgsmaplayerregistry.h" 00021 #include "qgsmaptopixel.h" 00022 #include "qgsproject.h" 00023 #include "qgsvectorlayer.h" 00024 #include "qgstolerance.h" 00025 #include <QSettings> 00026 00027 00028 QgsMapCanvasSnapper::QgsMapCanvasSnapper( QgsMapCanvas* canvas ): mMapCanvas( canvas ), mSnapper( 0 ) 00029 { 00030 if ( canvas ) 00031 { 00032 QgsMapRenderer* canvasRender = canvas->mapRenderer(); 00033 if ( canvasRender ) 00034 { 00035 mSnapper = new QgsSnapper( canvasRender ); 00036 } 00037 } 00038 } 00039 00040 QgsMapCanvasSnapper::QgsMapCanvasSnapper(): mMapCanvas( 0 ), mSnapper( 0 ) 00041 { 00042 00043 } 00044 00045 QgsMapCanvasSnapper::~QgsMapCanvasSnapper() 00046 { 00047 delete mSnapper; 00048 } 00049 00050 void QgsMapCanvasSnapper::setMapCanvas( QgsMapCanvas* canvas ) 00051 { 00052 mMapCanvas = canvas; 00053 delete mSnapper; 00054 if ( mMapCanvas ) 00055 { 00056 mSnapper = new QgsSnapper( canvas->mapRenderer() ); 00057 } 00058 else 00059 { 00060 mSnapper = 0; 00061 } 00062 } 00063 00064 int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QList<QgsSnappingResult>& results, QgsSnapper::SnappingType snap_to, double snappingTol, const QList<QgsPoint>& excludePoints ) 00065 { 00066 results.clear(); 00067 00068 if ( mSnapper && mMapCanvas ) 00069 { 00070 00071 //topological editing on? 00072 int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); 00073 if ( topologicalEditing == 0 ) 00074 { 00075 mSnapper->setSnapMode( QgsSnapper::SnapWithOneResult ); 00076 } 00077 else 00078 { 00079 mSnapper->setSnapMode( QgsSnapper::SnapWithResultsForSamePosition ); 00080 } 00081 00082 //current vector layer 00083 QgsMapLayer* currentLayer = mMapCanvas->currentLayer(); 00084 if ( !currentLayer ) 00085 { 00086 return 2; 00087 } 00088 QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( currentLayer ); 00089 if ( !vlayer ) 00090 { 00091 return 3; 00092 } 00093 00094 QgsSnapper::SnapLayer snapLayer; 00095 snapLayer.mLayer = vlayer; 00096 snapLayer.mSnapTo = snap_to; 00097 snapLayer.mUnitType = QgsTolerance::MapUnits; 00098 00099 QSettings settings; 00100 00101 if ( snappingTol < 0 ) 00102 { 00103 //use search tolerance for vertex editing 00104 snapLayer.mTolerance = QgsTolerance::vertexSearchRadius( vlayer, mMapCanvas->mapRenderer() ); 00105 } 00106 else 00107 { 00108 snapLayer.mTolerance = snappingTol; 00109 } 00110 00111 QList<QgsSnapper::SnapLayer> snapLayers; 00112 snapLayers.append( snapLayer ); 00113 mSnapper->setSnapLayers( snapLayers ); 00114 00115 if ( mSnapper->snapPoint( p, results, excludePoints ) != 0 ) 00116 { 00117 return 4; 00118 } 00119 00120 return 0; 00121 } 00122 else 00123 { 00124 return 1; 00125 } 00126 } 00127 00128 int QgsMapCanvasSnapper::snapToBackgroundLayers( const QPoint& p, QList<QgsSnappingResult>& results, const QList<QgsPoint>& excludePoints ) 00129 { 00130 results.clear(); 00131 00132 if ( mSnapper ) 00133 { 00134 //topological editing on? 00135 int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); 00136 if ( topologicalEditing == 0 ) 00137 { 00138 mSnapper->setSnapMode( QgsSnapper::SnapWithOneResult ); 00139 } 00140 else 00141 { 00142 mSnapper->setSnapMode( QgsSnapper::SnapWithResultsForSamePosition ); 00143 } 00144 00145 //read snapping settings from project 00146 bool ok; //todo: take the default snapping tolerance for all vector layers if snapping not defined in project 00147 bool snappingDefinedInProject = true; 00148 QStringList layerIdList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingList", &ok ); 00149 if ( !ok ) 00150 { 00151 snappingDefinedInProject = false; 00152 } 00153 QStringList enabledList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingEnabledList", &ok ); 00154 QStringList toleranceList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceList", &ok ); 00155 QStringList toleranceUnitList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceUnitList", &ok ); 00156 QStringList snapToList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnapToList", &ok ); 00157 00158 if ( !( layerIdList.size() == enabledList.size() && layerIdList.size() == toleranceList.size() && layerIdList.size() == toleranceUnitList.size() && layerIdList.size() == snapToList.size() ) ) 00159 { 00160 return 1; //lists must have the same size, otherwise something is wrong 00161 } 00162 00163 QList<QgsSnapper::SnapLayer> snapLayers; 00164 QgsSnapper::SnapLayer snapLayer; 00165 00166 //Use snapping information from the project 00167 if ( snappingDefinedInProject ) 00168 { 00169 //set layers, tolerances, snap to segment/vertex to QgsSnapper 00170 QgsMapLayer* layer = 0; 00171 QgsVectorLayer* vlayer = 0; 00172 00173 QStringList::const_iterator layerIt = layerIdList.constBegin(); 00174 QStringList::const_iterator tolIt = toleranceList.constBegin(); 00175 QStringList::const_iterator tolUnitIt = toleranceUnitList.constBegin(); 00176 QStringList::const_iterator snapIt = snapToList.constBegin(); 00177 QStringList::const_iterator enabledIt = enabledList.constBegin(); 00178 00179 for ( ; layerIt != layerIdList.constEnd(); ++layerIt, ++tolIt, ++tolUnitIt, ++snapIt, ++enabledIt ) 00180 { 00181 if (( *enabledIt ) != "enabled" ) //skip layer if snapping is not enabled 00182 { 00183 continue; 00184 } 00185 00186 //layer 00187 layer = QgsMapLayerRegistry::instance()->mapLayer( *layerIt ); 00188 if ( layer == NULL ) 00189 continue; 00190 vlayer = qobject_cast<QgsVectorLayer *>( layer ); 00191 if ( vlayer == NULL ) 00192 continue; 00193 00194 snapLayer.mLayer = vlayer; 00195 00196 //tolerance 00197 snapLayer.mTolerance = tolIt->toDouble(); 00198 snapLayer.mUnitType = ( QgsTolerance::UnitType ) tolUnitIt->toInt(); 00199 00200 //segment or vertex 00201 if (( *snapIt ) == "to_vertex" ) 00202 { 00203 snapLayer.mSnapTo = QgsSnapper::SnapToVertex; 00204 } 00205 else if (( *snapIt ) == "to_segment" ) 00206 { 00207 snapLayer.mSnapTo = QgsSnapper::SnapToSegment; 00208 } 00209 else //to vertex and segment 00210 { 00211 snapLayer.mSnapTo = QgsSnapper::SnapToVertexAndSegment; 00212 } 00213 00214 snapLayers.append( snapLayer ); 00215 } 00216 } 00217 else //nothing in project. Use default snapping tolerance to vertex of current layer 00218 { 00219 QgsMapLayer* currentLayer = mMapCanvas->currentLayer(); 00220 if ( !currentLayer ) 00221 { 00222 return 2; 00223 } 00224 00225 QgsVectorLayer* currentVectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer ); 00226 if ( !currentVectorLayer ) 00227 { 00228 return 3; 00229 } 00230 00231 snapLayer.mLayer = currentVectorLayer; 00232 QSettings settings; 00233 00234 //default snap mode 00235 QString defaultSnapString = settings.value( "/qgis/digitizing/default_snap_mode", "to vertex" ).toString(); 00236 if ( defaultSnapString == "to segment" ) 00237 { 00238 snapLayer.mSnapTo = QgsSnapper::SnapToSegment; 00239 } 00240 else if ( defaultSnapString == "to vertex and segment" ) 00241 { 00242 snapLayer.mSnapTo = QgsSnapper::SnapToVertexAndSegment; 00243 } 00244 else 00245 { 00246 snapLayer.mSnapTo = QgsSnapper::SnapToVertex; 00247 } 00248 00249 //default snapping tolerance (returned in map units) 00250 snapLayer.mTolerance = QgsTolerance::defaultTolerance( currentVectorLayer, mMapCanvas->mapRenderer() ); 00251 snapLayer.mUnitType = QgsTolerance::MapUnits; 00252 00253 snapLayers.append( snapLayer ); 00254 } 00255 00256 mSnapper->setSnapLayers( snapLayers ); 00257 00258 if ( mSnapper->snapPoint( p, results, excludePoints ) != 0 ) 00259 { 00260 return 4; 00261 } 00262 return 0; 00263 } 00264 else 00265 { 00266 return 5; 00267 } 00268 }