Quantum GIS API Documentation  1.7.4
src/gui/qgsmapcanvassnapper.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines