QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:217
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
UnitType
Type of unit of tolerance value from settings.
Definition: qgstolerance.h:33
QgsPoint toMapCoordinates(int x, int y) 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.
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
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:117
const QgsMapToPixel & mapToPixel() const
Layer unit value.
Definition: qgstolerance.h:38
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
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from output CRS to layer&#39;s CRS
static double toleranceInProjectUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units)
Static function to translate tolerance value into map units.
double _ratioMU2LU(const QgsMapSettings &mapSettings, QgsMapLayer *layer)
double toDouble(bool *ok) const
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
Definition: qgspoint.cpp:353
double x() const
Get the x value of the point.
Definition: qgspoint.h:185