QGIS API Documentation  3.0.2-Girona (307d082)
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.enumValue( 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.enumValue( 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.enumValue( 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 }
T enumValue(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
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...
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