QGIS API Documentation  3.1.0-Master (f35745f)
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 "qgsmapsettings.h"
18 #include "qgssettings.h"
19 
20 #include <QPoint>
21 #include <cmath>
22 
23 
24 // return ratio [mu/lu] between map units and layer units
25 // this is of course only an approximation
26 double _ratioMU2LU( const QgsMapSettings &mapSettings, QgsMapLayer *layer )
27 {
28  double distMU = mapSettings.mapUnitsPerPixel();
29  QgsPointXY ptMapCenterMU = mapSettings.visibleExtent().center();
30  QgsPointXY ptMapCenterRightMU( ptMapCenterMU.x() + distMU, ptMapCenterMU.y() );
31  QgsPointXY ptMapCenterLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterMU );
32  QgsPointXY ptMapCenterRightLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterRightMU );
33  double distLU = std::sqrt( ptMapCenterLU.sqrDist( ptMapCenterRightLU ) );
34  double ratio = distMU / distLU;
35  return ratio;
36 }
37 
38 double QgsTolerance::toleranceInProjectUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units )
39 {
40  // converts to map units
41  if ( units == ProjectUnits )
42  return tolerance;
43  else if ( units == Pixels )
44  return tolerance * mapSettings.mapUnitsPerPixel();
45  else // units == LayerUnits
46  {
47  // [mu] = [lu] * [mu/lu]
48  return tolerance * _ratioMU2LU( mapSettings, layer );
49  }
50 }
51 
52 
53 double QgsTolerance::toleranceInMapUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units )
54 {
55  // converts to layer units
56  if ( units == LayerUnits )
57  {
58  return tolerance;
59  }
60  else if ( units == Pixels )
61  {
62  double layerUnitsPerPixel = computeMapUnitPerPixel( layer, mapSettings );
63  return tolerance * layerUnitsPerPixel;
64  }
65  else // ProjectUnits
66  {
67  // [lu] = [mu] / [mu/lu]
68  return tolerance / _ratioMU2LU( mapSettings, layer );
69  }
70 }
71 
73 {
74  QgsSettings settings;
75  double tolerance = settings.value( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit" ), 10 ).toDouble();
76  UnitType units = settings.enumSettingValue( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit_unit" ), QgsTolerance::Pixels );
77  if ( units == LayerUnits )
78  units = ProjectUnits;
79  return toleranceInProjectUnits( tolerance, nullptr, mapSettings, units );
80 }
81 
82 double QgsTolerance::vertexSearchRadius( QgsMapLayer *layer, const QgsMapSettings &mapSettings )
83 {
84  QgsSettings settings;
85  double tolerance = settings.value( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit" ), 10 ).toDouble();
86  UnitType units = settings.enumSettingValue( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit_unit" ), QgsTolerance::Pixels );
87  return toleranceInMapUnits( tolerance, layer, mapSettings, units );
88 }
89 
90 double QgsTolerance::defaultTolerance( QgsMapLayer *layer, const QgsMapSettings &mapSettings )
91 {
92  QgsSettings settings;
93  double tolerance = settings.value( QStringLiteral( "qgis/digitizing/default_snapping_tolerance" ), Qgis::DEFAULT_SNAP_TOLERANCE ).toDouble();
94  UnitType units = settings.enumSettingValue( QStringLiteral( "qgis/digitizing/default_snapping_tolerance_unit" ), Qgis::DEFAULT_SNAP_UNITS );
95  return toleranceInMapUnits( tolerance, layer, mapSettings, units );
96 }
97 
98 
99 double QgsTolerance::computeMapUnitPerPixel( QgsMapLayer *layer, const QgsMapSettings &mapSettings )
100 {
101  // the layer is projected. Find out how many pixels are in one map unit - either horizontal and vertical direction
102  // this check might not work correctly in some cases
103  // (on a large area the pixels projected around "0,0" can have different properties from the actual point)
104  QgsPointXY p1 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 1 ) );
105  QgsPointXY p2 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 2 ) );
106  QgsPointXY p3 = toLayerCoordinates( layer, mapSettings, QPoint( 1, 0 ) );
107  QgsPointXY p4 = toLayerCoordinates( layer, mapSettings, QPoint( 2, 0 ) );
108  double x = p1.sqrDist( p2 );
109  double y = p3.sqrDist( p4 );
110  if ( x > y )
111  {
112  return std::sqrt( x );
113  }
114  else
115  {
116  return std::sqrt( y );
117  }
118 }
119 
120 
121 QgsPointXY QgsTolerance::toLayerCoordinates( QgsMapLayer *layer, const QgsMapSettings &mapSettings, QPoint point )
122 {
123  QgsPointXY pt = mapSettings.mapToPixel().toMapCoordinates( point );
124  return mapSettings.mapToLayerCoordinates( layer, pt );
125 }
Base class for all map layer types.
Definition: qgsmaplayer.h:56
This class is a composition of two QSettings instances:
Definition: qgssettings.h:57
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
UnitType
Type of unit of tolerance value from settings.
Definition: qgstolerance.h:40
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...
T enumSettingValue(const QString &key, const T &defaultValue, const Section section=NoSection, bool flag=false) const
Return the setting value for a setting based on an enum.
Definition: qgssettings.h:231
The QgsMapSettings class contains configuration for rendering of the map.
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
Definition: qgspointxy.cpp:68
static const double DEFAULT_SNAP_TOLERANCE
Default snapping distance tolerance.
Definition: qgis.h:157
Pixels unit of tolerance.
Definition: qgstolerance.h:45
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.
static const QgsTolerance::UnitType DEFAULT_SNAP_UNITS
Default snapping distance units.
Definition: qgis.h:163
const QgsMapToPixel & mapToPixel() const
double x
Definition: qgspointxy.h:47
Layer unit value.
Definition: qgstolerance.h:43
static double vertexSearchRadius(const QgsMapSettings &mapSettings)
Static function to get vertex tolerance value.
Map (project) units. Added in 2.8.
Definition: qgstolerance.h:47
static double toleranceInProjectUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units)
Static function to translate tolerance value into map units.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
double _ratioMU2LU(const QgsMapSettings &mapSettings, QgsMapLayer *layer)
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:170
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer&#39;s CRS
QgsPointXY toMapCoordinates(int x, int y) const