~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/core/qgssnapper.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "qgsmaprenderer.h"
 
20
#include "qgsmaptopixel.h"
 
21
#include "qgsvectorlayer.h"
 
22
#include <QMultiMap>
 
23
#include <QPoint>
 
24
#include <cmath>
 
25
 
 
26
 
 
27
QgsSnapper::QgsSnapper( QgsMapRenderer* mapRenderer ): mMapRenderer( mapRenderer )
 
28
{
 
29
 
 
30
}
 
31
 
 
32
QgsSnapper::QgsSnapper()
 
33
{
 
34
 
 
35
}
 
36
 
 
37
QgsSnapper::~QgsSnapper()
 
38
{
 
39
 
 
40
}
 
41
 
 
42
int QgsSnapper::snapPoint( const QPoint& startPoint, QList<QgsSnappingResult>& snappingResult, const QList<QgsPoint>& excludePoints )
 
43
{
 
44
  snappingResult.clear();
 
45
 
 
46
  QMultiMap<double, QgsSnappingResult> snappingResultList;//all snapping results
 
47
  QMultiMap<double, QgsSnappingResult> currentResultList; //snapping results of examined layer
 
48
 
 
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;
 
53
 
 
54
  QList<QgsSnapper::SnapLayer>::iterator snapLayerIt;
 
55
  for ( snapLayerIt = mSnapLayers.begin(); snapLayerIt != mSnapLayers.end(); ++snapLayerIt )
 
56
  {
 
57
    //transform point from map coordinates to layer coordinates
 
58
    layerCoordPoint = mMapRenderer->mapToLayerCoordinates( snapLayerIt->mLayer, mapCoordPoint );
 
59
 
 
60
    double tolerance = QgsTolerance::toleranceInMapUnits( snapLayerIt->mTolerance, snapLayerIt->mLayer, mMapRenderer, snapLayerIt->mUnitType );
 
61
    if ( snapLayerIt->mLayer->snapWithContext( layerCoordPoint, tolerance,
 
62
         currentResultList, snapLayerIt->mSnapTo ) != 0 )
 
63
    {
 
64
      //error
 
65
    }
 
66
 
 
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 )
 
70
    {
 
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 );
 
78
    }
 
79
  }
 
80
 
 
81
  //excluded specific points from result
 
82
  cleanResultList( snappingResultList, excludePoints );
 
83
 
 
84
  //evaluate results according to snap mode
 
85
  QMultiMap<double, QgsSnappingResult>::iterator evalIt =  snappingResultList.begin();
 
86
  if ( evalIt == snappingResultList.end() )
 
87
  {
 
88
    return 0;
 
89
  }
 
90
 
 
91
  if ( mSnapMode == QgsSnapper::SnapWithOneResult )
 
92
  {
 
93
    //return only closest result
 
94
    snappingResult.push_back( evalIt.value() );
 
95
  }
 
96
  else if ( mSnapMode == QgsSnapper::SnapWithResultsForSamePosition )
 
97
  {
 
98
    //take all snapping Results within a certain tolerance because rounding differences may occur
 
99
    double tolerance = 0.000001;
 
100
    double minDistance = evalIt.key();
 
101
 
 
102
    for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
 
103
    {
 
104
      if ( evalIt.key() > ( minDistance + tolerance ) )
 
105
      {
 
106
        break;
 
107
      }
 
108
      snappingResult.push_back( evalIt.value() );
 
109
    }
 
110
 
 
111
  }
 
112
 
 
113
  else //take all results
 
114
  {
 
115
    for ( ; evalIt != snappingResultList.end(); ++evalIt )
 
116
    {
 
117
      snappingResult.push_back( evalIt.value() );
 
118
    }
 
119
  }
 
120
 
 
121
  return 0;
 
122
}
 
123
 
 
124
void QgsSnapper::setSnapLayers( const QList<QgsSnapper::SnapLayer>& snapLayers )
 
125
{
 
126
  mSnapLayers = snapLayers;
 
127
}
 
128
 
 
129
 
 
130
void QgsSnapper::setSnapMode( QgsSnapper::SnappingMode snapMode )
 
131
{
 
132
  mSnapMode = snapMode;
 
133
}
 
134
 
 
135
void QgsSnapper::cleanResultList( QMultiMap<double, QgsSnappingResult>& list, const QList<QgsPoint>& excludeList ) const
 
136
{
 
137
  QgsPoint currentResultPoint;
 
138
  QgsSnappingResult currentSnappingResult;
 
139
  QList<double> keysToRemove;
 
140
 
 
141
  QMultiMap<double, QgsSnappingResult>::iterator result_it = list.begin();
 
142
  for ( ; result_it != list.end(); ++result_it )
 
143
  {
 
144
    currentSnappingResult = result_it.value();
 
145
    if ( currentSnappingResult.snappedVertexNr != -1 )
 
146
    {
 
147
      currentResultPoint = currentSnappingResult.snappedVertex;
 
148
      if ( excludeList.contains( currentResultPoint ) )
 
149
      {
 
150
        keysToRemove.push_back( result_it.key() );
 
151
      }
 
152
    }
 
153
  }
 
154
 
 
155
  QList<double>::const_iterator remove_it = keysToRemove.constBegin();
 
156
  for ( ; remove_it != keysToRemove.constEnd(); ++remove_it )
 
157
  {
 
158
    list.remove( *remove_it );
 
159
  }
 
160
}