QGIS API Documentation  2.99.0-Master (8ec3eaf)
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 <QSettings>
19 #include <QPoint>
20 #include <cmath>
21 
22 
23 // return ratio [mu/lu] between map units and layer units
24 // this is of course only an approximation
25 double _ratioMU2LU( const QgsMapSettings& mapSettings, QgsMapLayer* layer )
26 {
27  double distMU = mapSettings.mapUnitsPerPixel();
28  QgsPoint ptMapCenterMU = mapSettings.visibleExtent().center();
29  QgsPoint ptMapCenterRightMU( ptMapCenterMU.x() + distMU, ptMapCenterMU.y() );
30  QgsPoint ptMapCenterLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterMU );
31  QgsPoint ptMapCenterRightLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterRightMU );
32  double distLU = sqrt( ptMapCenterLU.sqrDist( ptMapCenterRightLU ) );
33  double ratio = distMU / distLU;
34  return ratio;
35 }
36 
37 double QgsTolerance::toleranceInProjectUnits( double tolerance, QgsMapLayer* layer, const QgsMapSettings& mapSettings, QgsTolerance::UnitType units )
38 {
39  // converts to map units
40  if ( units == ProjectUnits )
41  return tolerance;
42  else if ( units == Pixels )
43  return tolerance * mapSettings.mapUnitsPerPixel();
44  else // units == LayerUnits
45  {
46  // [mu] = [lu] * [mu/lu]
47  return tolerance * _ratioMU2LU( mapSettings, layer );
48  }
49 }
50 
51 
52 double QgsTolerance::toleranceInMapUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings& mapSettings, QgsTolerance::UnitType units )
53 {
54  // converts to layer units
55  if ( units == LayerUnits )
56  {
57  return tolerance;
58  }
59  else if ( units == Pixels )
60  {
61  double layerUnitsPerPixel = computeMapUnitPerPixel( layer, mapSettings );
62  return tolerance * layerUnitsPerPixel;
63  }
64  else // ProjectUnits
65  {
66  // [lu] = [mu] / [mu/lu]
67  return tolerance / _ratioMU2LU( mapSettings, layer );
68  }
69 }
70 
72 {
73  QSettings settings;
74  double tolerance = settings.value( QStringLiteral( "/qgis/digitizing/search_radius_vertex_edit" ), 10 ).toDouble();
75  UnitType units = static_cast< QgsTolerance::UnitType >( settings.value( QStringLiteral( "/qgis/digitizing/search_radius_vertex_edit_unit" ), QgsTolerance::Pixels ).toInt() );
76  if ( units == LayerUnits )
77  units = ProjectUnits;
78  return toleranceInProjectUnits( tolerance, nullptr, mapSettings, units );
79 }
80 
81 double QgsTolerance::vertexSearchRadius( QgsMapLayer *layer, const QgsMapSettings &mapSettings )
82 {
83  QSettings settings;
84  double tolerance = settings.value( QStringLiteral( "/qgis/digitizing/search_radius_vertex_edit" ), 10 ).toDouble();
85  UnitType units = static_cast< QgsTolerance::UnitType >( settings.value( QStringLiteral( "/qgis/digitizing/search_radius_vertex_edit_unit" ), QgsTolerance::Pixels ).toInt() );
86  return toleranceInMapUnits( tolerance, layer, mapSettings, units );
87 }
88 
89 double QgsTolerance::defaultTolerance( QgsMapLayer *layer, const QgsMapSettings& mapSettings )
90 {
91  QSettings settings;
92  double tolerance = settings.value( QStringLiteral( "/qgis/digitizing/default_snapping_tolerance" ), 0 ).toDouble();
93  UnitType units = static_cast< QgsTolerance::UnitType >( settings.value( QStringLiteral( "/qgis/digitizing/default_snapping_tolerance_unit" ), ProjectUnits ).toInt() );
94  return toleranceInMapUnits( tolerance, layer, mapSettings, units );
95 }
96 
97 
98 double QgsTolerance::computeMapUnitPerPixel( QgsMapLayer* layer, const QgsMapSettings& mapSettings )
99 {
100  if ( ! mapSettings.hasCrsTransformEnabled() )
101  {
102  // if the on-the-fly projections are not enabled, layer units pre pixel are the same as map units per pixel
103  return mapSettings.mapUnitsPerPixel();
104  }
105 
106  // the layer is projected. Find out how many pixels are in one map unit - either horizontal and vertical direction
107  // this check might not work correctly in some cases
108  // (on a large area the pixels projected around "0,0" can have different properties from the actual point)
109  QgsPoint p1 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 1 ) );
110  QgsPoint p2 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 2 ) );
111  QgsPoint p3 = toLayerCoordinates( layer, mapSettings, QPoint( 1, 0 ) );
112  QgsPoint p4 = toLayerCoordinates( layer, mapSettings, QPoint( 2, 0 ) );
113  double x = p1.sqrDist( p2 );
114  double y = p3.sqrDist( p4 );
115  if ( x > y )
116  {
117  return sqrt( x );
118  }
119  else
120  {
121  return sqrt( y );
122  }
123 }
124 
125 
126 QgsPoint QgsTolerance::toLayerCoordinates( QgsMapLayer* layer, const QgsMapSettings& mapSettings, QPoint point )
127 {
128  QgsPoint pt = mapSettings.mapToPixel().toMapCoordinates( point );
129  return mapSettings.mapToLayerCoordinates( layer, pt );
130 }
Base class for all map layer types.
Definition: qgsmaplayer.h:49
double y
Definition: qgspoint.h:147
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:221
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:35
QgsPoint toMapCoordinates(int x, int y) const
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.
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:142
const QgsMapToPixel & mapToPixel() const
Layer unit value.
Definition: qgstolerance.h:38
static double vertexSearchRadius(const QgsMapSettings &mapSettings)
Static function to get vertex tolerance value.
Map (project) units. Added in 2.8.
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 sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
Definition: qgspoint.cpp:382
double x
Definition: qgspoint.h:146