QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
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"
19 #include "qgssettingsentryimpl.h"
21 #include "qgspointxy.h"
22 
23 #include <QPoint>
24 #include <cmath>
25 
26 
27 // return ratio [mu/lu] between map units and layer units
28 // this is of course only an approximation
29 double _ratioMU2LU( const QgsMapSettings &mapSettings, QgsMapLayer *layer )
30 {
31  const double distMU = mapSettings.mapUnitsPerPixel();
32  const QgsPointXY ptMapCenterMU = mapSettings.visibleExtent().center();
33  const QgsPointXY ptMapCenterRightMU( ptMapCenterMU.x() + distMU, ptMapCenterMU.y() );
34  const QgsPointXY ptMapCenterLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterMU );
35  const QgsPointXY ptMapCenterRightLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterRightMU );
36  const double distLU = std::sqrt( ptMapCenterLU.sqrDist( ptMapCenterRightLU ) );
37  const double ratio = distMU / distLU;
38  return ratio;
39 }
40 
41 double QgsTolerance::toleranceInProjectUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, Qgis::MapToolUnit units )
42 {
43  // converts to map units
44  if ( units == Qgis::MapToolUnit::Project )
45  return tolerance;
46  else if ( units == Qgis::MapToolUnit::Pixels )
47  return tolerance * mapSettings.mapUnitsPerPixel();
48  else // units == LayerUnits
49  {
50  // [mu] = [lu] * [mu/lu]
51  return tolerance * _ratioMU2LU( mapSettings, layer );
52  }
53 }
54 
55 
56 double QgsTolerance::toleranceInMapUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, Qgis::MapToolUnit units )
57 {
58  // converts to layer units
59  if ( units == Qgis::MapToolUnit::Layer )
60  {
61  return tolerance;
62  }
63  else if ( units == Qgis::MapToolUnit::Pixels )
64  {
65  const double layerUnitsPerPixel = computeMapUnitPerPixel( layer, mapSettings );
66  return tolerance * layerUnitsPerPixel;
67  }
68  else // ProjectUnits
69  {
70  // [lu] = [mu] / [mu/lu]
71  return tolerance / _ratioMU2LU( mapSettings, layer );
72  }
73 }
74 
76 {
79  if ( units == Qgis::MapToolUnit::Layer )
81  return toleranceInProjectUnits( tolerance, nullptr, mapSettings, units );
82 }
83 
84 double QgsTolerance::vertexSearchRadius( QgsMapLayer *layer, const QgsMapSettings &mapSettings )
85 {
88  return toleranceInMapUnits( tolerance, layer, mapSettings, units );
89 }
90 
91 double QgsTolerance::defaultTolerance( QgsMapLayer *layer, const QgsMapSettings &mapSettings )
92 {
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  const QgsPointXY p1 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 1 ) );
105  const QgsPointXY p2 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 2 ) );
106  const QgsPointXY p3 = toLayerCoordinates( layer, mapSettings, QPoint( 1, 0 ) );
107  const QgsPointXY p4 = toLayerCoordinates( layer, mapSettings, QPoint( 2, 0 ) );
108  const double x = p1.sqrDist( p2 );
109  const 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  const QgsPointXY pt = mapSettings.mapToPixel().toMapCoordinates( point );
124  return mapSettings.mapToLayerCoordinates( layer, pt );
125 }
MapToolUnit
Type of unit of tolerance value from settings.
Definition: qgis.h:4058
@ Layer
Layer unit value.
@ Project
Map (project) units.
@ Pixels
Pixels unit of tolerance.
Base class for all map layer types.
Definition: qgsmaplayer.h:75
The QgsMapSettings class contains configuration for rendering of the map.
double mapUnitsPerPixel() const
Returns the distance in geographical coordinates that equals to one pixel in the map.
const QgsMapToPixel & mapToPixel() const
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
A class to represent a 2D point.
Definition: qgspointxy.h:60
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
Definition: qgspointxy.h:187
double y
Definition: qgspointxy.h:64
Q_GADGET double x
Definition: qgspointxy.h:63
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:262
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
static const QgsSettingsEntryDouble * settingsDigitizingSearchRadiusVertexEdit
Settings entry digitizing search radius vertex edit.
static const QgsSettingsEntryEnumFlag< Qgis::MapToolUnit > * settingsDigitizingDefaultSnappingToleranceUnit
Settings entry digitizing default snapping tolerance unit.
static const QgsSettingsEntryEnumFlag< Qgis::MapToolUnit > * settingsDigitizingSearchRadiusVertexEditUnit
Settings entry digitizing search radius vertex edit unit.
static const QgsSettingsEntryDouble * settingsDigitizingDefaultSnappingTolerance
Settings entry digitizing default snapping tolerance.
static double toleranceInMapUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, Qgis::MapToolUnit units=Qgis::MapToolUnit::Layer)
Static function to translate tolerance value into layer units.
static double vertexSearchRadius(const QgsMapSettings &mapSettings)
Static function to get vertex tolerance value.
static double defaultTolerance(QgsMapLayer *layer, const QgsMapSettings &mapSettings)
Static function to get default tolerance value for a layer.
static double toleranceInProjectUnits(double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, Qgis::MapToolUnit units)
Static function to translate tolerance value into map units.
double _ratioMU2LU(const QgsMapSettings &mapSettings, QgsMapLayer *layer)