1
/***************************************************************************
5
copyright : (C) 2007 by Marco Hugentobler
6
email : marco dot hugentobler at karto dot baug dot ethz dot ch
7
***************************************************************************/
9
/***************************************************************************
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. *
16
***************************************************************************/
18
#include "qgssnapper.h"
19
#include "qgsmaprenderer.h"
20
#include "qgsmaptopixel.h"
21
#include "qgsvectorlayer.h"
27
QgsSnapper::QgsSnapper( QgsMapRenderer* mapRenderer ): mMapRenderer( mapRenderer )
32
QgsSnapper::QgsSnapper()
37
QgsSnapper::~QgsSnapper()
42
int QgsSnapper::snapPoint( const QPoint& startPoint, QList<QgsSnappingResult>& snappingResult, const QList<QgsPoint>& excludePoints )
44
snappingResult.clear();
46
QMultiMap<double, QgsSnappingResult> snappingResultList;//all snapping results
47
QMultiMap<double, QgsSnappingResult> currentResultList; //snapping results of examined layer
49
//start point in (output) map coordinates
50
QgsPoint mapCoordPoint = mMapRenderer->coordinateTransform()->toMapCoordinates( startPoint.x(), startPoint.y() );
51
QgsPoint layerCoordPoint; //start point in layer coordinates
52
QgsSnappingResult newResult;
54
QList<QgsSnapper::SnapLayer>::iterator snapLayerIt;
55
for ( snapLayerIt = mSnapLayers.begin(); snapLayerIt != mSnapLayers.end(); ++snapLayerIt )
57
//transform point from map coordinates to layer coordinates
58
layerCoordPoint = mMapRenderer->mapToLayerCoordinates( snapLayerIt->mLayer, mapCoordPoint );
60
double tolerance = QgsTolerance::toleranceInMapUnits( snapLayerIt->mTolerance, snapLayerIt->mLayer, mMapRenderer, snapLayerIt->mUnitType );
61
if ( snapLayerIt->mLayer->snapWithContext( layerCoordPoint, tolerance,
62
currentResultList, snapLayerIt->mSnapTo ) != 0 )
67
//transform each result from layer crs to map crs (including distance)
68
QMultiMap<double, QgsSnappingResult>::iterator currentResultIt;
69
for ( currentResultIt = currentResultList.begin(); currentResultIt != currentResultList.end(); ++currentResultIt )
71
//for each snapping result: transform start point, snap point and other points into map coordinates to find out distance
72
//store results in snapping result list
73
newResult = currentResultIt.value();
74
newResult.snappedVertex = mMapRenderer->layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().snappedVertex );
75
newResult.beforeVertex = mMapRenderer->layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().beforeVertex );
76
newResult.afterVertex = mMapRenderer->layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().afterVertex );
77
snappingResultList.insert( sqrt( newResult.snappedVertex.sqrDist( mapCoordPoint ) ), newResult );
81
//excluded specific points from result
82
cleanResultList( snappingResultList, excludePoints );
84
//evaluate results according to snap mode
85
QMultiMap<double, QgsSnappingResult>::iterator evalIt = snappingResultList.begin();
86
if ( evalIt == snappingResultList.end() )
91
if ( mSnapMode == QgsSnapper::SnapWithOneResult )
93
//return only closest result
94
snappingResult.push_back( evalIt.value() );
96
else if ( mSnapMode == QgsSnapper::SnapWithResultsForSamePosition )
98
//take all snapping Results within a certain tolerance because rounding differences may occur
99
double tolerance = 0.000001;
100
double minDistance = evalIt.key();
102
for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
104
if ( evalIt.key() > ( minDistance + tolerance ) )
108
snappingResult.push_back( evalIt.value() );
113
else //take all results
115
for ( ; evalIt != snappingResultList.end(); ++evalIt )
117
snappingResult.push_back( evalIt.value() );
124
void QgsSnapper::setSnapLayers( const QList<QgsSnapper::SnapLayer>& snapLayers )
126
mSnapLayers = snapLayers;
130
void QgsSnapper::setSnapMode( QgsSnapper::SnappingMode snapMode )
132
mSnapMode = snapMode;
135
void QgsSnapper::cleanResultList( QMultiMap<double, QgsSnappingResult>& list, const QList<QgsPoint>& excludeList ) const
137
QgsPoint currentResultPoint;
138
QgsSnappingResult currentSnappingResult;
139
QList<double> keysToRemove;
141
QMultiMap<double, QgsSnappingResult>::iterator result_it = list.begin();
142
for ( ; result_it != list.end(); ++result_it )
144
currentSnappingResult = result_it.value();
145
if ( currentSnappingResult.snappedVertexNr != -1 )
147
currentResultPoint = currentSnappingResult.snappedVertex;
148
if ( excludeList.contains( currentResultPoint ) )
150
keysToRemove.push_back( result_it.key() );
155
QList<double>::const_iterator remove_it = keysToRemove.constBegin();
156
for ( ; remove_it != keysToRemove.constEnd(); ++remove_it )
158
list.remove( *remove_it );