QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgscoordinateutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscoordinateutils.cpp
3  ----------------------
4  begin : February 2016
5  copyright : (C) 2016 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscoordinateutils.h"
20 #include "qgscoordinatetransform.h"
21 #include "qgsproject.h"
22 #include "qgis.h"
23 #include "qgsexception.h"
24 #include "qgscoordinateformatter.h"
26 
27 int QgsCoordinateUtils::calculateCoordinatePrecision( double mapUnitsPerPixel, const QgsCoordinateReferenceSystem &mapCrs, QgsProject *project )
28 {
29  if ( !project )
30  project = QgsProject::instance();
31  // Get the display precision from the project settings
32  bool automatic = project->readBoolEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/Automatic" ) );
33  int dp = 0;
34 
35  if ( automatic )
36  {
37  QString format = project->readEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/DegreeFormat" ), QStringLiteral( "MU" ) );
38  bool formatGeographic = ( format == QLatin1String( "DM" ) || format == QLatin1String( "DMS" ) || format == QLatin1String( "D" ) );
39 
40  // we can only calculate an automatic precision if one of these is true:
41  // - both map CRS and format are geographic
42  // - both map CRS and format are not geographic
43  // - map CRS is geographic but format is not geographic (i.e. map units)
44  if ( mapCrs.isGeographic() || !formatGeographic )
45  {
46  // Work out a suitable number of decimal places for the coordinates with the aim of always
47  // having enough decimal places to show the difference in position between adjacent pixels.
48  // Also avoid taking the log of 0.
49  if ( !qgsDoubleNear( mapUnitsPerPixel, 0.0 ) )
50  dp = static_cast<int>( std::ceil( -1.0 * std::log10( mapUnitsPerPixel ) ) );
51  }
52  else
53  {
54  if ( format == QLatin1String( "D" ) )
55  dp = 4;
56  else
57  dp = 2;
58  }
59  }
60  else
61  dp = project->readNumEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/DecimalPlaces" ) );
62 
63  // Keep dp sensible
64  if ( dp < 0 )
65  dp = 0;
66 
67  return dp;
68 }
69 
70 QString QgsCoordinateUtils::formatCoordinateForProject( QgsProject *project, const QgsPointXY &point, const QgsCoordinateReferenceSystem &destCrs, int precision )
71 {
72  if ( !project )
73  return QString();
74 
75  QString format = project->readEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/DegreeFormat" ), QStringLiteral( "MU" ) );
76 
77  QgsPointXY geo = point;
78  if ( format == QLatin1String( "DM" ) || format == QLatin1String( "DMS" ) || format == QLatin1String( "D" ) )
79  {
80  // degrees
81  if ( destCrs.isValid() && !destCrs.isGeographic() )
82  {
83  // need to transform to geographic coordinates
84  QgsCoordinateTransform ct( destCrs, QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ), project );
85  try
86  {
87  geo = ct.transform( point );
88  }
89  catch ( QgsCsException & )
90  {
91  return QString();
92  }
93  }
94 
95  if ( format == QLatin1String( "DM" ) )
97  else if ( format == QLatin1String( "DMS" ) )
99  else
100  return QgsCoordinateFormatter::asPair( geo.x(), geo.y(), precision );
101  }
102  else
103  {
104  // coordinates in map units
105  return QgsCoordinateFormatter::asPair( point.x(), point.y(), precision );
106  }
107 }
108 
QgsPointXY::y
double y
Definition: qgspointxy.h:48
qgscoordinateutils.h
qgis.h
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:458
QgsProject::readEntry
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Definition: qgsproject.cpp:2448
QgsProject::readBoolEntry
bool readBoolEntry(const QString &scope, const QString &key, bool def=false, bool *ok=nullptr) const
Definition: qgsproject.cpp:2519
QgsProject
Definition: qgsproject.h:92
QgsCoordinateFormatter::FormatDegreesMinutes
@ FormatDegreesMinutes
Degrees and decimal minutes, eg 30degrees 45.55'.
Definition: qgscoordinateformatter.h:51
precision
int precision
Definition: qgswfsgetfeature.cpp:103
QgsCoordinateReferenceSystem::isGeographic
bool isGeographic
Definition: qgscoordinatereferencesystem.h:211
QgsCsException
Definition: qgsexception.h:65
QgsCoordinateFormatter::asPair
static QString asPair(double x, double y, int precision=12)
Formats coordinates as an "\a x,\a y" pair, with optional decimal precision (number of decimal places...
Definition: qgscoordinateformatter.cpp:67
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:902
qgscoordinatetransform.h
QgsCoordinateFormatter::format
static QString format(const QgsPointXY &point, Format format, int precision=12, FormatFlags flags=FlagDegreesUseStringSuffix)
Formats a point according to the specified parameters.
Definition: qgscoordinateformatter.cpp:61
QgsCoordinateReferenceSystem
Definition: qgscoordinatereferencesystem.h:206
QgsPointXY
Definition: qgspointxy.h:43
QgsCoordinateFormatter::FormatDegreesMinutesSeconds
@ FormatDegreesMinutesSeconds
Degrees, minutes and seconds, eg 30 degrees 45'30".
Definition: qgscoordinateformatter.h:50
QgsCoordinateFormatter::FlagDegreesUseStringSuffix
@ FlagDegreesUseStringSuffix
Include a direction suffix (eg 'N', 'E', 'S' or 'W'), otherwise a "-" prefix is used for west and sou...
Definition: qgscoordinateformatter.h:60
QgsPointXY::x
double x
Definition: qgspointxy.h:47
qgsexception.h
QgsCoordinateFormatter::FlagDegreesPadMinutesSeconds
@ FlagDegreesPadMinutesSeconds
Pad minute and second values with leading zeros, eg '05' instead of '5'.
Definition: qgscoordinateformatter.h:61
qgscoordinateformatter.h
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
qgscoordinatereferencesystem.h
qgsproject.h
QgsProject::readNumEntry
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
Definition: qgsproject.cpp:2472