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