Branch data Line data Source code
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 : 0 : double _ratioMU2LU( const QgsMapSettings &mapSettings, QgsMapLayer *layer ) 28 : : { 29 : 0 : double distMU = mapSettings.mapUnitsPerPixel(); 30 : 0 : QgsPointXY ptMapCenterMU = mapSettings.visibleExtent().center(); 31 : 0 : QgsPointXY ptMapCenterRightMU( ptMapCenterMU.x() + distMU, ptMapCenterMU.y() ); 32 : 0 : QgsPointXY ptMapCenterLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterMU ); 33 : 0 : QgsPointXY ptMapCenterRightLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterRightMU ); 34 : 0 : double distLU = std::sqrt( ptMapCenterLU.sqrDist( ptMapCenterRightLU ) ); 35 : 0 : double ratio = distMU / distLU; 36 : 0 : return ratio; 37 : : } 38 : : 39 : 0 : double QgsTolerance::toleranceInProjectUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units ) 40 : : { 41 : : // converts to map units 42 : 0 : if ( units == ProjectUnits ) 43 : 0 : return tolerance; 44 : 0 : else if ( units == Pixels ) 45 : 0 : return tolerance * mapSettings.mapUnitsPerPixel(); 46 : : else // units == LayerUnits 47 : : { 48 : : // [mu] = [lu] * [mu/lu] 49 : 0 : return tolerance * _ratioMU2LU( mapSettings, layer ); 50 : : } 51 : 0 : } 52 : : 53 : : 54 : 0 : double QgsTolerance::toleranceInMapUnits( double tolerance, QgsMapLayer *layer, const QgsMapSettings &mapSettings, QgsTolerance::UnitType units ) 55 : : { 56 : : // converts to layer units 57 : 0 : if ( units == LayerUnits ) 58 : : { 59 : 0 : return tolerance; 60 : : } 61 : 0 : else if ( units == Pixels ) 62 : : { 63 : 0 : double layerUnitsPerPixel = computeMapUnitPerPixel( layer, mapSettings ); 64 : 0 : return tolerance * layerUnitsPerPixel; 65 : : } 66 : : else // ProjectUnits 67 : : { 68 : : // [lu] = [mu] / [mu/lu] 69 : 0 : return tolerance / _ratioMU2LU( mapSettings, layer ); 70 : : } 71 : 0 : } 72 : : 73 : 0 : double QgsTolerance::vertexSearchRadius( const QgsMapSettings &mapSettings ) 74 : : { 75 : 0 : QgsSettings settings; 76 : 0 : double tolerance = settings.value( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit" ), 10 ).toDouble(); 77 : 0 : UnitType units = settings.enumValue( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit_unit" ), QgsTolerance::Pixels ); 78 : 0 : if ( units == LayerUnits ) 79 : 0 : units = ProjectUnits; 80 : 0 : return toleranceInProjectUnits( tolerance, nullptr, mapSettings, units ); 81 : 0 : } 82 : : 83 : 0 : double QgsTolerance::vertexSearchRadius( QgsMapLayer *layer, const QgsMapSettings &mapSettings ) 84 : : { 85 : 0 : QgsSettings settings; 86 : 0 : double tolerance = settings.value( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit" ), 10 ).toDouble(); 87 : 0 : UnitType units = settings.enumValue( QStringLiteral( "qgis/digitizing/search_radius_vertex_edit_unit" ), QgsTolerance::Pixels ); 88 : 0 : return toleranceInMapUnits( tolerance, layer, mapSettings, units ); 89 : 0 : } 90 : : 91 : 0 : double QgsTolerance::defaultTolerance( QgsMapLayer *layer, const QgsMapSettings &mapSettings ) 92 : : { 93 : 0 : QgsSettings settings; 94 : 0 : double tolerance = settings.value( QStringLiteral( "qgis/digitizing/default_snapping_tolerance" ), Qgis::DEFAULT_SNAP_TOLERANCE ).toDouble(); 95 : 0 : UnitType units = settings.enumValue( QStringLiteral( "qgis/digitizing/default_snapping_tolerance_unit" ), Qgis::DEFAULT_SNAP_UNITS ); 96 : 0 : return toleranceInMapUnits( tolerance, layer, mapSettings, units ); 97 : 0 : } 98 : : 99 : : 100 : 0 : 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 : 0 : QgsPointXY p1 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 1 ) ); 106 : 0 : QgsPointXY p2 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 2 ) ); 107 : 0 : QgsPointXY p3 = toLayerCoordinates( layer, mapSettings, QPoint( 1, 0 ) ); 108 : 0 : QgsPointXY p4 = toLayerCoordinates( layer, mapSettings, QPoint( 2, 0 ) ); 109 : 0 : double x = p1.sqrDist( p2 ); 110 : 0 : double y = p3.sqrDist( p4 ); 111 : 0 : if ( x > y ) 112 : : { 113 : 0 : return std::sqrt( x ); 114 : : } 115 : : else 116 : : { 117 : 0 : return std::sqrt( y ); 118 : : } 119 : 0 : } 120 : : 121 : : 122 : 0 : QgsPointXY QgsTolerance::toLayerCoordinates( QgsMapLayer *layer, const QgsMapSettings &mapSettings, QPoint point ) 123 : : { 124 : 0 : QgsPointXY pt = mapSettings.mapToPixel().toMapCoordinates( point ); 125 : 0 : return mapSettings.mapToLayerCoordinates( layer, pt ); 126 : : }