QGIS API Documentation  2.14.0-Essen
qgstolerance.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstolerance.cpp - wrapper for tolerance handling
3  ----------------------
4  begin : March 2009
5  copyright : (C) 2009 by Richard Kostecky
6  email : csf.kostej at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgstolerance.h"
17 #include <QSettings>
18 #include <QPoint>
19 #include <cmath>
20 
21 
22 // return ratio [mu/lu] between map units and layer units
23 // this is of course only an approximation
24 double _ratioMU2LU( const QgsMapSettings& mapSettings, QgsMapLayer* layer )
25 {
26  double distMU = mapSettings.mapUnitsPerPixel();
27  QgsPoint ptMapCenterMU = mapSettings.visibleExtent().center();
28  QgsPoint ptMapCenterRightMU( ptMapCenterMU.x() + distMU, ptMapCenterMU.y() );
29  QgsPoint ptMapCenterLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterMU );
30  QgsPoint ptMapCenterRightLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterRightMU );
31  double distLU = sqrt( ptMapCenterLU.sqrDist( ptMapCenterRightLU ) );
32  double ratio = distMU / distLU;
33  return ratio;
34 }
35 
36 double QgsTolerance::toleranceInProjectUnits( double tolerance, QgsMapLayer* layer, const QgsMapSettings& mapSettings, QgsTolerance::UnitType units )
37 {
38  // converts to map units
39  if ( units == ProjectUnits )
40  return tolerance;
41  else if ( units == Pixels )
42  return tolerance * mapSettings.mapUnitsPerPixel();
43  else // units == LayerUnits
44  {
45  // [mu] = [lu] * [mu/lu]
46  return tolerance * _ratioMU2LU( mapSettings, layer );
47  }
48 }
49 
50 
51 double QgsTolerance::toleranceInMapUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings& mapSettings, QgsTolerance::UnitType units )
52 {
53  // converts to layer units
54  if ( units == LayerUnits )
55  {
56  return tolerance;
57  }
58  else if ( units == Pixels )
59  {
60  double layerUnitsPerPixel = computeMapUnitPerPixel( layer, mapSettings );
61  return tolerance * layerUnitsPerPixel;
62  }
63  else // ProjectUnits
64  {
65  // [lu] = [mu] / [mu/lu]
66  return tolerance / _ratioMU2LU( mapSettings, layer );
67  }
68 }
69 
70 double QgsTolerance::toleranceInMapUnits( double tolerance, QgsMapLayer* layer, QgsMapRenderer* renderer, UnitType units )
71 {
72  return toleranceInMapUnits( tolerance, layer, renderer->mapSettings(), units );
73 }
74 
76 {
77  QSettings settings;
78  double tolerance = settings.value( "/qgis/digitizing/search_radius_vertex_edit", 10 ).toDouble();
79  UnitType units = static_cast< QgsTolerance::UnitType >( settings.value( "/qgis/digitizing/search_radius_vertex_edit_unit", QgsTolerance::Pixels ).toInt() );
80  if ( units == LayerUnits )
81  units = ProjectUnits;
82  return toleranceInProjectUnits( tolerance, nullptr, mapSettings, units );
83 }
84 
85 double QgsTolerance::vertexSearchRadius( QgsMapLayer *layer, const QgsMapSettings &mapSettings )
86 {
87  QSettings settings;
88  double tolerance = settings.value( "/qgis/digitizing/search_radius_vertex_edit", 10 ).toDouble();
89  UnitType units = static_cast< QgsTolerance::UnitType >( settings.value( "/qgis/digitizing/search_radius_vertex_edit_unit", QgsTolerance::Pixels ).toInt() );
90  return toleranceInMapUnits( tolerance, layer, mapSettings, units );
91 }
92 
94 {
95  return vertexSearchRadius( layer, renderer->mapSettings() );
96 }
97 
98 double QgsTolerance::defaultTolerance( QgsMapLayer *layer, const QgsMapSettings& mapSettings )
99 {
100  QSettings settings;
101  double tolerance = settings.value( "/qgis/digitizing/default_snapping_tolerance", 0 ).toDouble();
102  UnitType units = static_cast< QgsTolerance::UnitType >( settings.value( "/qgis/digitizing/default_snapping_tolerance_unit", ProjectUnits ).toInt() );
103  return toleranceInMapUnits( tolerance, layer, mapSettings, units );
104 }
105 
106 
108 {
109  return defaultTolerance( layer, renderer->mapSettings() );
110 }
111 
112 
113 double QgsTolerance::computeMapUnitPerPixel( QgsMapLayer* layer, const QgsMapSettings& mapSettings )
114 {
115  if ( ! mapSettings.hasCrsTransformEnabled() )
116  {
117  // if the on-the-fly projections are not enabled, layer units pre pixel are the same as map units per pixel
118  return mapSettings.mapUnitsPerPixel();
119  }
120 
121  // the layer is projected. Find out how many pixels are in one map unit - either horizontal and vertical direction
122  // this check might not work correctly in some cases
123  // (on a large area the pixels projected around "0,0" can have different properties from the actual point)
124  QgsPoint p1 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 1 ) );
125  QgsPoint p2 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 2 ) );
126  QgsPoint p3 = toLayerCoordinates( layer, mapSettings, QPoint( 1, 0 ) );
127  QgsPoint p4 = toLayerCoordinates( layer, mapSettings, QPoint( 2, 0 ) );
128  double x = p1.sqrDist( p2 );
129  double y = p3.sqrDist( p4 );
130  if ( x > y )
131  {
132  return sqrt( x );
133  }
134  else
135  {
136  return sqrt( y );
137  }
138 }
139 
140 
141 QgsPoint QgsTolerance::toLayerCoordinates( QgsMapLayer* layer, const QgsMapSettings& mapSettings, QPoint point )
142 {
143  QgsPoint pt = mapSettings.mapToPixel().toMapCoordinates( point );
144  return mapSettings.mapToLayerCoordinates( layer, pt );
145 }
const QgsMapSettings & mapSettings()
bridge to QgsMapSettings
Base class for all map layer types.
Definition: qgsmaplayer.h:49
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
UnitType
Type of unit of tolerance value from settings.
Definition: qgstolerance.h:33
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
const QgsMapToPixel & mapToPixel() const
A non GUI class for rendering a map layer set onto a QPainter.
static double toleranceInMapUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, UnitType units=LayerUnits)
Static function to translate tolerance value into layer units.
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from output CRS to layer&#39;s CRS
double sqrDist(double x, double y) const
Returns the squared distance between this point and x,y.
Definition: qgspoint.cpp:345
double x() const
Get the x value of the point.
Definition: qgspoint.h:128
The QgsMapSettings class contains configuration for rendering of the map.
int toInt(bool *ok) const
Pixels unit of tolerance.
Definition: qgstolerance.h:40
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map.
static double defaultTolerance(QgsMapLayer *layer, const QgsMapSettings &mapSettings)
Static function to get default tolerance value for a layer.
A class to represent a point.
Definition: qgspoint.h:65
Layer unit value.
Definition: qgstolerance.h:38
QgsPoint toMapCoordinates(int x, int y) const
static double vertexSearchRadius(const QgsMapSettings &mapSettings)
Static function to get vertex tolerance value.
QVariant value(const QString &key, const QVariant &defaultValue) const
Map (project) units.
Definition: qgstolerance.h:42
static double toleranceInProjectUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units)
Static function to translate tolerance value into map units.
double y() const
Get the y value of the point.
Definition: qgspoint.h:136
double _ratioMU2LU(const QgsMapSettings &mapSettings, QgsMapLayer *layer)
double toDouble(bool *ok) const
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:217