geographiclib 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/AUTHORS +12 -0
- data/LICENSE +24 -0
- data/ext/geographiclib/Accumulator.cpp +23 -0
- data/ext/geographiclib/AlbersEqualArea.cpp +445 -0
- data/ext/geographiclib/AzimuthalEquidistant.cpp +41 -0
- data/ext/geographiclib/CassiniSoldner.cpp +89 -0
- data/ext/geographiclib/CircularEngine.cpp +96 -0
- data/ext/geographiclib/DMS.cpp +381 -0
- data/ext/geographiclib/Ellipsoid.cpp +125 -0
- data/ext/geographiclib/EllipticFunction.cpp +512 -0
- data/ext/geographiclib/GARS.cpp +122 -0
- data/ext/geographiclib/GeoCoords.cpp +175 -0
- data/ext/geographiclib/Geocentric.cpp +172 -0
- data/ext/geographiclib/Geodesic.cpp +1908 -0
- data/ext/geographiclib/GeodesicExact.cpp +927 -0
- data/ext/geographiclib/GeodesicExactC4.cpp +7879 -0
- data/ext/geographiclib/GeodesicLine.cpp +321 -0
- data/ext/geographiclib/GeodesicLineExact.cpp +289 -0
- data/ext/geographiclib/GeographicLib/Accumulator.hpp +184 -0
- data/ext/geographiclib/GeographicLib/AlbersEqualArea.hpp +312 -0
- data/ext/geographiclib/GeographicLib/AzimuthalEquidistant.hpp +139 -0
- data/ext/geographiclib/GeographicLib/CassiniSoldner.hpp +204 -0
- data/ext/geographiclib/GeographicLib/CircularEngine.hpp +195 -0
- data/ext/geographiclib/GeographicLib/Config.h +12 -0
- data/ext/geographiclib/GeographicLib/Constants.hpp +387 -0
- data/ext/geographiclib/GeographicLib/DMS.hpp +370 -0
- data/ext/geographiclib/GeographicLib/Ellipsoid.hpp +534 -0
- data/ext/geographiclib/GeographicLib/EllipticFunction.hpp +692 -0
- data/ext/geographiclib/GeographicLib/GARS.hpp +143 -0
- data/ext/geographiclib/GeographicLib/GeoCoords.hpp +544 -0
- data/ext/geographiclib/GeographicLib/Geocentric.hpp +267 -0
- data/ext/geographiclib/GeographicLib/Geodesic.hpp +970 -0
- data/ext/geographiclib/GeographicLib/GeodesicExact.hpp +862 -0
- data/ext/geographiclib/GeographicLib/GeodesicLine.hpp +701 -0
- data/ext/geographiclib/GeographicLib/GeodesicLineExact.hpp +667 -0
- data/ext/geographiclib/GeographicLib/Geohash.hpp +180 -0
- data/ext/geographiclib/GeographicLib/Geoid.hpp +472 -0
- data/ext/geographiclib/GeographicLib/Georef.hpp +160 -0
- data/ext/geographiclib/GeographicLib/Gnomonic.hpp +206 -0
- data/ext/geographiclib/GeographicLib/GravityCircle.hpp +301 -0
- data/ext/geographiclib/GeographicLib/GravityModel.hpp +520 -0
- data/ext/geographiclib/GeographicLib/LambertConformalConic.hpp +313 -0
- data/ext/geographiclib/GeographicLib/LocalCartesian.hpp +236 -0
- data/ext/geographiclib/GeographicLib/MGRS.hpp +355 -0
- data/ext/geographiclib/GeographicLib/MagneticCircle.hpp +178 -0
- data/ext/geographiclib/GeographicLib/MagneticModel.hpp +347 -0
- data/ext/geographiclib/GeographicLib/Math.hpp +920 -0
- data/ext/geographiclib/GeographicLib/NormalGravity.hpp +350 -0
- data/ext/geographiclib/GeographicLib/OSGB.hpp +249 -0
- data/ext/geographiclib/GeographicLib/PolarStereographic.hpp +150 -0
- data/ext/geographiclib/GeographicLib/PolygonArea.hpp +288 -0
- data/ext/geographiclib/GeographicLib/Rhumb.hpp +589 -0
- data/ext/geographiclib/GeographicLib/SphericalEngine.hpp +376 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic.hpp +354 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic1.hpp +281 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic2.hpp +315 -0
- data/ext/geographiclib/GeographicLib/TransverseMercator.hpp +196 -0
- data/ext/geographiclib/GeographicLib/TransverseMercatorExact.hpp +254 -0
- data/ext/geographiclib/GeographicLib/UTMUPS.hpp +421 -0
- data/ext/geographiclib/GeographicLib/Utility.hpp +612 -0
- data/ext/geographiclib/Geohash.cpp +102 -0
- data/ext/geographiclib/Geoid.cpp +509 -0
- data/ext/geographiclib/Georef.cpp +135 -0
- data/ext/geographiclib/Gnomonic.cpp +85 -0
- data/ext/geographiclib/GravityCircle.cpp +129 -0
- data/ext/geographiclib/GravityModel.cpp +360 -0
- data/ext/geographiclib/LambertConformalConic.cpp +456 -0
- data/ext/geographiclib/LocalCartesian.cpp +62 -0
- data/ext/geographiclib/MGRS.cpp +461 -0
- data/ext/geographiclib/MagneticCircle.cpp +52 -0
- data/ext/geographiclib/MagneticModel.cpp +269 -0
- data/ext/geographiclib/Math.cpp +63 -0
- data/ext/geographiclib/NormalGravity.cpp +262 -0
- data/ext/geographiclib/OSGB.cpp +167 -0
- data/ext/geographiclib/PolarStereographic.cpp +108 -0
- data/ext/geographiclib/PolygonArea.cpp +204 -0
- data/ext/geographiclib/Rhumb.cpp +383 -0
- data/ext/geographiclib/SphericalEngine.cpp +477 -0
- data/ext/geographiclib/TransverseMercator.cpp +603 -0
- data/ext/geographiclib/TransverseMercatorExact.cpp +464 -0
- data/ext/geographiclib/UTMUPS.cpp +296 -0
- data/ext/geographiclib/Utility.cpp +61 -0
- data/ext/geographiclib/extconf.rb +3 -0
- data/ext/geographiclib/geographiclib.cpp +62 -0
- data/lib/geographiclib.rb +20 -0
- metadata +140 -0
@@ -0,0 +1,196 @@
|
|
1
|
+
/**
|
2
|
+
* \file TransverseMercator.hpp
|
3
|
+
* \brief Header for GeographicLib::TransverseMercator class
|
4
|
+
*
|
5
|
+
* Copyright (c) Charles Karney (2008-2015) <charles@karney.com> and licensed
|
6
|
+
* under the MIT/X11 License. For more information, see
|
7
|
+
* http://geographiclib.sourceforge.net/
|
8
|
+
**********************************************************************/
|
9
|
+
|
10
|
+
#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP)
|
11
|
+
#define GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP 1
|
12
|
+
|
13
|
+
#include <GeographicLib/Constants.hpp>
|
14
|
+
|
15
|
+
#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER)
|
16
|
+
/**
|
17
|
+
* The order of the series approximation used in TransverseMercator.
|
18
|
+
* GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER can be set to any integer in [4, 8].
|
19
|
+
**********************************************************************/
|
20
|
+
# define GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER \
|
21
|
+
(GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
|
22
|
+
(GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8))
|
23
|
+
#endif
|
24
|
+
|
25
|
+
namespace GeographicLib {
|
26
|
+
|
27
|
+
/**
|
28
|
+
* \brief Transverse Mercator projection
|
29
|
+
*
|
30
|
+
* This uses Krüger's method which evaluates the projection and its
|
31
|
+
* inverse in terms of a series. See
|
32
|
+
* - L. Krüger,
|
33
|
+
* <a href="https://dx.doi.org/10.2312/GFZ.b103-krueger28"> Konforme
|
34
|
+
* Abbildung des Erdellipsoids in der Ebene</a> (Conformal mapping of the
|
35
|
+
* ellipsoidal earth to the plane), Royal Prussian Geodetic Institute, New
|
36
|
+
* Series 52, 172 pp. (1912).
|
37
|
+
* - C. F. F. Karney,
|
38
|
+
* <a href="https://dx.doi.org/10.1007/s00190-011-0445-3">
|
39
|
+
* Transverse Mercator with an accuracy of a few nanometers,</a>
|
40
|
+
* J. Geodesy 85(8), 475--485 (Aug. 2011);
|
41
|
+
* preprint
|
42
|
+
* <a href="http://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>.
|
43
|
+
*
|
44
|
+
* Krüger's method has been extended from 4th to 6th order. The maximum
|
45
|
+
* error is 5 nm (5 nanometers), ground distance, for all positions within 35
|
46
|
+
* degrees of the central meridian. The error in the convergence is 2
|
47
|
+
* × 10<sup>−15</sup>" and the relative error in the scale
|
48
|
+
* is 6 × 10<sup>−12</sup>%%. See Sec. 4 of
|
49
|
+
* <a href="http://arxiv.org/abs/1002.1417">arXiv:1002.1417</a> for details.
|
50
|
+
* The speed penalty in going to 6th order is only about 1%.
|
51
|
+
*
|
52
|
+
* There's a singularity in the projection at φ = 0°, λ
|
53
|
+
* − λ<sub>0</sub> = ±(1 − \e e)90° (≈
|
54
|
+
* ±82.6° for the WGS84 ellipsoid), where \e e is the
|
55
|
+
* eccentricity. Beyond this point, the series ceases to converge and the
|
56
|
+
* results from this method will be garbage. To be on the safe side, don't
|
57
|
+
* use this method if the angular distance from the central meridian exceeds
|
58
|
+
* (1 − 2e)90° (≈ 75° for the WGS84 ellipsoid)
|
59
|
+
*
|
60
|
+
* TransverseMercatorExact is an alternative implementation of the projection
|
61
|
+
* using exact formulas which yield accurate (to 8 nm) results over the
|
62
|
+
* entire ellipsoid.
|
63
|
+
*
|
64
|
+
* The ellipsoid parameters and the central scale are set in the constructor.
|
65
|
+
* The central meridian (which is a trivial shift of the longitude) is
|
66
|
+
* specified as the \e lon0 argument of the TransverseMercator::Forward and
|
67
|
+
* TransverseMercator::Reverse functions. The latitude of origin is taken to
|
68
|
+
* be the equator. There is no provision in this class for specifying a
|
69
|
+
* false easting or false northing or a different latitude of origin.
|
70
|
+
* However these are can be simply included by the calling function. For
|
71
|
+
* example, the UTMUPS class applies the false easting and false northing for
|
72
|
+
* the UTM projections. A more complicated example is the British National
|
73
|
+
* Grid (<a href="http://www.spatialreference.org/ref/epsg/7405/">
|
74
|
+
* EPSG:7405</a>) which requires the use of a latitude of origin. This is
|
75
|
+
* implemented by the GeographicLib::OSGB class.
|
76
|
+
*
|
77
|
+
* See TransverseMercator.cpp for more information on the implementation.
|
78
|
+
*
|
79
|
+
* See \ref transversemercator for a discussion of this projection.
|
80
|
+
*
|
81
|
+
* Example of use:
|
82
|
+
* \include example-TransverseMercator.cpp
|
83
|
+
*
|
84
|
+
* <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a
|
85
|
+
* command-line utility providing access to the functionality of
|
86
|
+
* TransverseMercator and TransverseMercatorExact.
|
87
|
+
**********************************************************************/
|
88
|
+
|
89
|
+
class GEOGRAPHICLIB_EXPORT TransverseMercator {
|
90
|
+
private:
|
91
|
+
typedef Math::real real;
|
92
|
+
static const int maxpow_ = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER;
|
93
|
+
static const int numit_ = 5;
|
94
|
+
real _a, _f, _k0, _e2, _es, _e2m, _c, _n;
|
95
|
+
// _alp[0] and _bet[0] unused
|
96
|
+
real _a1, _b1, _alp[maxpow_ + 1], _bet[maxpow_ + 1];
|
97
|
+
friend class Ellipsoid; // For access to taupf, tauf.
|
98
|
+
public:
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Constructor for a ellipsoid with
|
102
|
+
*
|
103
|
+
* @param[in] a equatorial radius (meters).
|
104
|
+
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
|
105
|
+
* Negative \e f gives a prolate ellipsoid.
|
106
|
+
* @param[in] k0 central scale factor.
|
107
|
+
* @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k0 is
|
108
|
+
* not positive.
|
109
|
+
**********************************************************************/
|
110
|
+
TransverseMercator(real a, real f, real k0);
|
111
|
+
|
112
|
+
/**
|
113
|
+
* Forward projection, from geographic to transverse Mercator.
|
114
|
+
*
|
115
|
+
* @param[in] lon0 central meridian of the projection (degrees).
|
116
|
+
* @param[in] lat latitude of point (degrees).
|
117
|
+
* @param[in] lon longitude of point (degrees).
|
118
|
+
* @param[out] x easting of point (meters).
|
119
|
+
* @param[out] y northing of point (meters).
|
120
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
121
|
+
* @param[out] k scale of projection at point.
|
122
|
+
*
|
123
|
+
* No false easting or northing is added. \e lat should be in the range
|
124
|
+
* [−90°, 90°].
|
125
|
+
**********************************************************************/
|
126
|
+
void Forward(real lon0, real lat, real lon,
|
127
|
+
real& x, real& y, real& gamma, real& k) const;
|
128
|
+
|
129
|
+
/**
|
130
|
+
* Reverse projection, from transverse Mercator to geographic.
|
131
|
+
*
|
132
|
+
* @param[in] lon0 central meridian of the projection (degrees).
|
133
|
+
* @param[in] x easting of point (meters).
|
134
|
+
* @param[in] y northing of point (meters).
|
135
|
+
* @param[out] lat latitude of point (degrees).
|
136
|
+
* @param[out] lon longitude of point (degrees).
|
137
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
138
|
+
* @param[out] k scale of projection at point.
|
139
|
+
*
|
140
|
+
* No false easting or northing is added. The value of \e lon returned is
|
141
|
+
* in the range [−180°, 180°).
|
142
|
+
**********************************************************************/
|
143
|
+
void Reverse(real lon0, real x, real y,
|
144
|
+
real& lat, real& lon, real& gamma, real& k) const;
|
145
|
+
|
146
|
+
/**
|
147
|
+
* TransverseMercator::Forward without returning the convergence and scale.
|
148
|
+
**********************************************************************/
|
149
|
+
void Forward(real lon0, real lat, real lon,
|
150
|
+
real& x, real& y) const {
|
151
|
+
real gamma, k;
|
152
|
+
Forward(lon0, lat, lon, x, y, gamma, k);
|
153
|
+
}
|
154
|
+
|
155
|
+
/**
|
156
|
+
* TransverseMercator::Reverse without returning the convergence and scale.
|
157
|
+
**********************************************************************/
|
158
|
+
void Reverse(real lon0, real x, real y,
|
159
|
+
real& lat, real& lon) const {
|
160
|
+
real gamma, k;
|
161
|
+
Reverse(lon0, x, y, lat, lon, gamma, k);
|
162
|
+
}
|
163
|
+
|
164
|
+
/** \name Inspector functions
|
165
|
+
**********************************************************************/
|
166
|
+
///@{
|
167
|
+
/**
|
168
|
+
* @return \e a the equatorial radius of the ellipsoid (meters). This is
|
169
|
+
* the value used in the constructor.
|
170
|
+
**********************************************************************/
|
171
|
+
Math::real MajorRadius() const { return _a; }
|
172
|
+
|
173
|
+
/**
|
174
|
+
* @return \e f the flattening of the ellipsoid. This is the value used in
|
175
|
+
* the constructor.
|
176
|
+
**********************************************************************/
|
177
|
+
Math::real Flattening() const { return _f; }
|
178
|
+
|
179
|
+
/**
|
180
|
+
* @return \e k0 central scale for the projection. This is the value of \e
|
181
|
+
* k0 used in the constructor and is the scale on the central meridian.
|
182
|
+
**********************************************************************/
|
183
|
+
Math::real CentralScale() const { return _k0; }
|
184
|
+
///@}
|
185
|
+
|
186
|
+
/**
|
187
|
+
* A global instantiation of TransverseMercator with the WGS84 ellipsoid
|
188
|
+
* and the UTM scale factor. However, unlike UTM, no false easting or
|
189
|
+
* northing is added.
|
190
|
+
**********************************************************************/
|
191
|
+
static const TransverseMercator& UTM();
|
192
|
+
};
|
193
|
+
|
194
|
+
} // namespace GeographicLib
|
195
|
+
|
196
|
+
#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP
|
@@ -0,0 +1,254 @@
|
|
1
|
+
/**
|
2
|
+
* \file TransverseMercatorExact.hpp
|
3
|
+
* \brief Header for GeographicLib::TransverseMercatorExact class
|
4
|
+
*
|
5
|
+
* Copyright (c) Charles Karney (2008-2015) <charles@karney.com> and licensed
|
6
|
+
* under the MIT/X11 License. For more information, see
|
7
|
+
* http://geographiclib.sourceforge.net/
|
8
|
+
**********************************************************************/
|
9
|
+
|
10
|
+
#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP)
|
11
|
+
#define GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP 1
|
12
|
+
|
13
|
+
#include <GeographicLib/Constants.hpp>
|
14
|
+
#include <GeographicLib/EllipticFunction.hpp>
|
15
|
+
|
16
|
+
namespace GeographicLib {
|
17
|
+
|
18
|
+
/**
|
19
|
+
* \brief An exact implementation of the transverse Mercator projection
|
20
|
+
*
|
21
|
+
* Implementation of the Transverse Mercator Projection given in
|
22
|
+
* - L. P. Lee,
|
23
|
+
* <a href="https://dx.doi.org/10.3138/X687-1574-4325-WM62"> Conformal
|
24
|
+
* Projections Based On Jacobian Elliptic Functions</a>, Part V of
|
25
|
+
* Conformal Projections Based on Elliptic Functions,
|
26
|
+
* (B. V. Gutsell, Toronto, 1976), 128pp.,
|
27
|
+
* ISBN: 0919870163
|
28
|
+
* (also appeared as:
|
29
|
+
* Monograph 16, Suppl. No. 1 to Canadian Cartographer, Vol 13).
|
30
|
+
* - C. F. F. Karney,
|
31
|
+
* <a href="https://dx.doi.org/10.1007/s00190-011-0445-3">
|
32
|
+
* Transverse Mercator with an accuracy of a few nanometers,</a>
|
33
|
+
* J. Geodesy 85(8), 475--485 (Aug. 2011);
|
34
|
+
* preprint
|
35
|
+
* <a href="http://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>.
|
36
|
+
*
|
37
|
+
* Lee gives the correct results for forward and reverse transformations
|
38
|
+
* subject to the branch cut rules (see the description of the \e extendp
|
39
|
+
* argument to the constructor). The maximum error is about 8 nm (8
|
40
|
+
* nanometers), ground distance, for the forward and reverse transformations.
|
41
|
+
* The error in the convergence is 2 × 10<sup>−15</sup>",
|
42
|
+
* the relative error in the scale is 7 × 10<sup>−12</sup>%%.
|
43
|
+
* See Sec. 3 of
|
44
|
+
* <a href="http://arxiv.org/abs/1002.1417">arXiv:1002.1417</a> for details.
|
45
|
+
* The method is "exact" in the sense that the errors are close to the
|
46
|
+
* round-off limit and that no changes are needed in the algorithms for them
|
47
|
+
* to be used with reals of a higher precision. Thus the errors using long
|
48
|
+
* double (with a 64-bit fraction) are about 2000 times smaller than using
|
49
|
+
* double (with a 53-bit fraction).
|
50
|
+
*
|
51
|
+
* This algorithm is about 4.5 times slower than the 6th-order Krüger
|
52
|
+
* method, TransverseMercator, taking about 11 us for a combined forward and
|
53
|
+
* reverse projection on a 2.66 GHz Intel machine (g++, version 4.3.0, -O3).
|
54
|
+
*
|
55
|
+
* The ellipsoid parameters and the central scale are set in the constructor.
|
56
|
+
* The central meridian (which is a trivial shift of the longitude) is
|
57
|
+
* specified as the \e lon0 argument of the TransverseMercatorExact::Forward
|
58
|
+
* and TransverseMercatorExact::Reverse functions. The latitude of origin is
|
59
|
+
* taken to be the equator. See the documentation on TransverseMercator for
|
60
|
+
* how to include a false easting, false northing, or a latitude of origin.
|
61
|
+
*
|
62
|
+
* See <a href="http://geographiclib.sourceforge.net/tm-grid.kmz"
|
63
|
+
* type="application/vnd.google-earth.kmz"> tm-grid.kmz</a>, for an
|
64
|
+
* illustration of the transverse Mercator grid in Google Earth.
|
65
|
+
*
|
66
|
+
* See TransverseMercatorExact.cpp for more information on the
|
67
|
+
* implementation.
|
68
|
+
*
|
69
|
+
* See \ref transversemercator for a discussion of this projection.
|
70
|
+
*
|
71
|
+
* Example of use:
|
72
|
+
* \include example-TransverseMercatorExact.cpp
|
73
|
+
*
|
74
|
+
* <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a
|
75
|
+
* command-line utility providing access to the functionality of
|
76
|
+
* TransverseMercator and TransverseMercatorExact.
|
77
|
+
**********************************************************************/
|
78
|
+
|
79
|
+
class GEOGRAPHICLIB_EXPORT TransverseMercatorExact {
|
80
|
+
private:
|
81
|
+
typedef Math::real real;
|
82
|
+
static const int numit_ = 10;
|
83
|
+
real tol_, tol1_, tol2_, taytol_;
|
84
|
+
real _a, _f, _k0, _mu, _mv, _e;
|
85
|
+
bool _extendp;
|
86
|
+
EllipticFunction _Eu, _Ev;
|
87
|
+
|
88
|
+
void zeta(real u, real snu, real cnu, real dnu,
|
89
|
+
real v, real snv, real cnv, real dnv,
|
90
|
+
real& taup, real& lam) const;
|
91
|
+
|
92
|
+
void dwdzeta(real u, real snu, real cnu, real dnu,
|
93
|
+
real v, real snv, real cnv, real dnv,
|
94
|
+
real& du, real& dv) const;
|
95
|
+
|
96
|
+
bool zetainv0(real psi, real lam, real& u, real& v) const;
|
97
|
+
void zetainv(real taup, real lam, real& u, real& v) const;
|
98
|
+
|
99
|
+
void sigma(real u, real snu, real cnu, real dnu,
|
100
|
+
real v, real snv, real cnv, real dnv,
|
101
|
+
real& xi, real& eta) const;
|
102
|
+
|
103
|
+
void dwdsigma(real u, real snu, real cnu, real dnu,
|
104
|
+
real v, real snv, real cnv, real dnv,
|
105
|
+
real& du, real& dv) const;
|
106
|
+
|
107
|
+
bool sigmainv0(real xi, real eta, real& u, real& v) const;
|
108
|
+
void sigmainv(real xi, real eta, real& u, real& v) const;
|
109
|
+
|
110
|
+
void Scale(real tau, real lam,
|
111
|
+
real snu, real cnu, real dnu,
|
112
|
+
real snv, real cnv, real dnv,
|
113
|
+
real& gamma, real& k) const;
|
114
|
+
|
115
|
+
public:
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Constructor for a ellipsoid with
|
119
|
+
*
|
120
|
+
* @param[in] a equatorial radius (meters).
|
121
|
+
* @param[in] f flattening of ellipsoid.
|
122
|
+
* @param[in] k0 central scale factor.
|
123
|
+
* @param[in] extendp use extended domain.
|
124
|
+
* @exception GeographicErr if \e a, \e f, or \e k0 is not positive.
|
125
|
+
*
|
126
|
+
* The transverse Mercator projection has a branch point singularity at \e
|
127
|
+
* lat = 0 and \e lon − \e lon0 = 90 (1 − \e e) or (for
|
128
|
+
* TransverseMercatorExact::UTM) x = 18381 km, y = 0m. The \e extendp
|
129
|
+
* argument governs where the branch cut is placed. With \e extendp =
|
130
|
+
* false, the "standard" convention is followed, namely the cut is placed
|
131
|
+
* along \e x > 18381 km, \e y = 0m. Forward can be called with any \e lat
|
132
|
+
* and \e lon then produces the transformation shown in Lee, Fig 46.
|
133
|
+
* Reverse analytically continues this in the ± \e x direction. As
|
134
|
+
* a consequence, Reverse may map multiple points to the same geographic
|
135
|
+
* location; for example, for TransverseMercatorExact::UTM, \e x =
|
136
|
+
* 22051449.037349 m, \e y = −7131237.022729 m and \e x =
|
137
|
+
* 29735142.378357 m, \e y = 4235043.607933 m both map to \e lat =
|
138
|
+
* −2°, \e lon = 88°.
|
139
|
+
*
|
140
|
+
* With \e extendp = true, the branch cut is moved to the lower left
|
141
|
+
* quadrant. The various symmetries of the transverse Mercator projection
|
142
|
+
* can be used to explore the projection on any sheet. In this mode the
|
143
|
+
* domains of \e lat, \e lon, \e x, and \e y are restricted to
|
144
|
+
* - the union of
|
145
|
+
* - \e lat in [0, 90] and \e lon − \e lon0 in [0, 90]
|
146
|
+
* - \e lat in (-90, 0] and \e lon − \e lon0 in [90 (1 − \e
|
147
|
+
e), 90]
|
148
|
+
* - the union of
|
149
|
+
* - <i>x</i>/(\e k0 \e a) in [0, ∞) and
|
150
|
+
* <i>y</i>/(\e k0 \e a) in [0, E(<i>e</i><sup>2</sup>)]
|
151
|
+
* - <i>x</i>/(\e k0 \e a) in [K(1 − <i>e</i><sup>2</sup>) −
|
152
|
+
* E(1 − <i>e</i><sup>2</sup>), ∞) and <i>y</i>/(\e k0 \e
|
153
|
+
* a) in (−∞, 0]
|
154
|
+
* .
|
155
|
+
* See Sec. 5 of
|
156
|
+
* <a href="http://arxiv.org/abs/1002.1417">arXiv:1002.1417</a> for a full
|
157
|
+
* discussion of the treatment of the branch cut.
|
158
|
+
*
|
159
|
+
* The method will work for all ellipsoids used in terrestrial geodesy.
|
160
|
+
* The method cannot be applied directly to the case of a sphere (\e f = 0)
|
161
|
+
* because some the constants characterizing this method diverge in that
|
162
|
+
* limit, and in practice, \e f should be larger than about
|
163
|
+
* numeric_limits<real>::epsilon(). However, TransverseMercator treats the
|
164
|
+
* sphere exactly.
|
165
|
+
**********************************************************************/
|
166
|
+
TransverseMercatorExact(real a, real f, real k0, bool extendp = false);
|
167
|
+
|
168
|
+
/**
|
169
|
+
* Forward projection, from geographic to transverse Mercator.
|
170
|
+
*
|
171
|
+
* @param[in] lon0 central meridian of the projection (degrees).
|
172
|
+
* @param[in] lat latitude of point (degrees).
|
173
|
+
* @param[in] lon longitude of point (degrees).
|
174
|
+
* @param[out] x easting of point (meters).
|
175
|
+
* @param[out] y northing of point (meters).
|
176
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
177
|
+
* @param[out] k scale of projection at point.
|
178
|
+
*
|
179
|
+
* No false easting or northing is added. \e lat should be in the range
|
180
|
+
* [−90°, 90°].
|
181
|
+
**********************************************************************/
|
182
|
+
void Forward(real lon0, real lat, real lon,
|
183
|
+
real& x, real& y, real& gamma, real& k) const;
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Reverse projection, from transverse Mercator to geographic.
|
187
|
+
*
|
188
|
+
* @param[in] lon0 central meridian of the projection (degrees).
|
189
|
+
* @param[in] x easting of point (meters).
|
190
|
+
* @param[in] y northing of point (meters).
|
191
|
+
* @param[out] lat latitude of point (degrees).
|
192
|
+
* @param[out] lon longitude of point (degrees).
|
193
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
194
|
+
* @param[out] k scale of projection at point.
|
195
|
+
*
|
196
|
+
* No false easting or northing is added. The value of \e lon returned is
|
197
|
+
* in the range [−180°, 180°).
|
198
|
+
**********************************************************************/
|
199
|
+
void Reverse(real lon0, real x, real y,
|
200
|
+
real& lat, real& lon, real& gamma, real& k) const;
|
201
|
+
|
202
|
+
/**
|
203
|
+
* TransverseMercatorExact::Forward without returning the convergence and
|
204
|
+
* scale.
|
205
|
+
**********************************************************************/
|
206
|
+
void Forward(real lon0, real lat, real lon,
|
207
|
+
real& x, real& y) const {
|
208
|
+
real gamma, k;
|
209
|
+
Forward(lon0, lat, lon, x, y, gamma, k);
|
210
|
+
}
|
211
|
+
|
212
|
+
/**
|
213
|
+
* TransverseMercatorExact::Reverse without returning the convergence and
|
214
|
+
* scale.
|
215
|
+
**********************************************************************/
|
216
|
+
void Reverse(real lon0, real x, real y,
|
217
|
+
real& lat, real& lon) const {
|
218
|
+
real gamma, k;
|
219
|
+
Reverse(lon0, x, y, lat, lon, gamma, k);
|
220
|
+
}
|
221
|
+
|
222
|
+
/** \name Inspector functions
|
223
|
+
**********************************************************************/
|
224
|
+
///@{
|
225
|
+
/**
|
226
|
+
* @return \e a the equatorial radius of the ellipsoid (meters). This is
|
227
|
+
* the value used in the constructor.
|
228
|
+
**********************************************************************/
|
229
|
+
Math::real MajorRadius() const { return _a; }
|
230
|
+
|
231
|
+
/**
|
232
|
+
* @return \e f the flattening of the ellipsoid. This is the value used in
|
233
|
+
* the constructor.
|
234
|
+
**********************************************************************/
|
235
|
+
Math::real Flattening() const { return _f; }
|
236
|
+
|
237
|
+
/**
|
238
|
+
* @return \e k0 central scale for the projection. This is the value of \e
|
239
|
+
* k0 used in the constructor and is the scale on the central meridian.
|
240
|
+
**********************************************************************/
|
241
|
+
Math::real CentralScale() const { return _k0; }
|
242
|
+
///@}
|
243
|
+
|
244
|
+
/**
|
245
|
+
* A global instantiation of TransverseMercatorExact with the WGS84
|
246
|
+
* ellipsoid and the UTM scale factor. However, unlike UTM, no false
|
247
|
+
* easting or northing is added.
|
248
|
+
**********************************************************************/
|
249
|
+
static const TransverseMercatorExact& UTM();
|
250
|
+
};
|
251
|
+
|
252
|
+
} // namespace GeographicLib
|
253
|
+
|
254
|
+
#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP
|
@@ -0,0 +1,421 @@
|
|
1
|
+
/**
|
2
|
+
* \file UTMUPS.hpp
|
3
|
+
* \brief Header for GeographicLib::UTMUPS class
|
4
|
+
*
|
5
|
+
* Copyright (c) Charles Karney (2008-2015) <charles@karney.com> and licensed
|
6
|
+
* under the MIT/X11 License. For more information, see
|
7
|
+
* http://geographiclib.sourceforge.net/
|
8
|
+
**********************************************************************/
|
9
|
+
|
10
|
+
#if !defined(GEOGRAPHICLIB_UTMUPS_HPP)
|
11
|
+
#define GEOGRAPHICLIB_UTMUPS_HPP 1
|
12
|
+
|
13
|
+
#include <GeographicLib/Constants.hpp>
|
14
|
+
|
15
|
+
namespace GeographicLib {
|
16
|
+
|
17
|
+
/**
|
18
|
+
* \brief Convert between geographic coordinates and UTM/UPS
|
19
|
+
*
|
20
|
+
* UTM and UPS are defined
|
21
|
+
* - J. W. Hager, J. F. Behensky, and B. W. Drew,
|
22
|
+
* <a href="http://earth-info.nga.mil/GandG/publications/tm8358.2/TM8358_2.pdf">
|
23
|
+
* The Universal Grids: Universal Transverse Mercator (UTM) and Universal
|
24
|
+
* Polar Stereographic (UPS)</a>, Defense Mapping Agency, Technical Manual
|
25
|
+
* TM8358.2 (1989).
|
26
|
+
* .
|
27
|
+
* Section 2-3 defines UTM and section 3-2.4 defines UPS. This document also
|
28
|
+
* includes approximate algorithms for the computation of the underlying
|
29
|
+
* transverse Mercator and polar stereographic projections. Here we
|
30
|
+
* substitute much more accurate algorithms given by
|
31
|
+
* GeographicLib:TransverseMercator and GeographicLib:PolarStereographic.
|
32
|
+
* These are the algorithms recommended by the NGA document
|
33
|
+
* - <a href="http://earth-info.nga.mil/GandG/publications/NGA_SIG_0012_2_0_0_UTMUPS/NGA.SIG.0012_2.0.0_UTMUPS.pdf">
|
34
|
+
* The Universal Grids and the Transverse Mercator and Polar Stereographic
|
35
|
+
* Map Projections</a>, NGA.SIG.0012_2.0.0_UTMUPS (2014).
|
36
|
+
*
|
37
|
+
* In this implementation, the conversions are closed, i.e., output from
|
38
|
+
* Forward is legal input for Reverse and vice versa. The error is about 5nm
|
39
|
+
* in each direction. However, the conversion from legal UTM/UPS coordinates
|
40
|
+
* to geographic coordinates and back might throw an error if the initial
|
41
|
+
* point is within 5nm of the edge of the allowed range for the UTM/UPS
|
42
|
+
* coordinates.
|
43
|
+
*
|
44
|
+
* The simplest way to guarantee the closed property is to define allowed
|
45
|
+
* ranges for the eastings and northings for UTM and UPS coordinates. The
|
46
|
+
* UTM boundaries are the same for all zones. (The only place the
|
47
|
+
* exceptional nature of the zone boundaries is evident is when converting to
|
48
|
+
* UTM/UPS coordinates requesting the standard zone.) The MGRS lettering
|
49
|
+
* scheme imposes natural limits on UTM/UPS coordinates which may be
|
50
|
+
* converted into MGRS coordinates. For the conversion to/from geographic
|
51
|
+
* coordinates these ranges have been extended by 100km in order to provide a
|
52
|
+
* generous overlap between UTM and UPS and between UTM zones.
|
53
|
+
*
|
54
|
+
* The <a href="http://www.nga.mil">NGA</a> software package
|
55
|
+
* <a href="http://earth-info.nga.mil/GandG/geotrans/index.html">geotrans</a>
|
56
|
+
* also provides conversions to and from UTM and UPS. Version 2.4.2 (and
|
57
|
+
* earlier) suffers from some drawbacks:
|
58
|
+
* - Inconsistent rules are used to determine the whether a particular UTM or
|
59
|
+
* UPS coordinate is legal. A more systematic approach is taken here.
|
60
|
+
* - The underlying projections are not very accurately implemented.
|
61
|
+
*
|
62
|
+
* The GeographicLib::UTMUPS::EncodeZone encodes the UTM zone and hemisphere
|
63
|
+
* to allow UTM/UPS coordinated to be displayed as, for example, "38N 444500
|
64
|
+
* 3688500". According to NGA.SIG.0012_2.0.0_UTMUPS the use of "N" to denote
|
65
|
+
* "north" in the context is not allowed (since a upper case letter in this
|
66
|
+
* context denotes the MGRS latitude band). Consequently, as of version
|
67
|
+
* 1.36, EncodeZone uses the lower case letters "n" and "s" to denote the
|
68
|
+
* hemisphere. In addition EncodeZone accepts an optional final argument \e
|
69
|
+
* abbrev, which, if false, results in the hemisphere being spelled out as in
|
70
|
+
* "38north".
|
71
|
+
*
|
72
|
+
* Example of use:
|
73
|
+
* \include example-UTMUPS.cpp
|
74
|
+
**********************************************************************/
|
75
|
+
class GEOGRAPHICLIB_EXPORT UTMUPS {
|
76
|
+
private:
|
77
|
+
typedef Math::real real;
|
78
|
+
static const int falseeasting_[4];
|
79
|
+
static const int falsenorthing_[4];
|
80
|
+
static const int mineasting_[4];
|
81
|
+
static const int maxeasting_[4];
|
82
|
+
static const int minnorthing_[4];
|
83
|
+
static const int maxnorthing_[4];
|
84
|
+
static const int epsg01N = 32601; // EPSG code for UTM 01N
|
85
|
+
static const int epsg60N = 32660; // EPSG code for UTM 60N
|
86
|
+
static const int epsgN = 32661; // EPSG code for UPS N
|
87
|
+
static const int epsg01S = 32701; // EPSG code for UTM 01S
|
88
|
+
static const int epsg60S = 32760; // EPSG code for UTM 60S
|
89
|
+
static const int epsgS = 32761; // EPSG code for UPS S
|
90
|
+
static real CentralMeridian(int zone)
|
91
|
+
{ return real(6 * zone - 183); }
|
92
|
+
// Throw an error if easting or northing are outside standard ranges. If
|
93
|
+
// throwp = false, return bool instead.
|
94
|
+
static bool CheckCoords(bool utmp, bool northp, real x, real y,
|
95
|
+
bool msgrlimits = false, bool throwp = true);
|
96
|
+
UTMUPS(); // Disable constructor
|
97
|
+
|
98
|
+
public:
|
99
|
+
|
100
|
+
/**
|
101
|
+
* In this class we bring together the UTM and UPS coordinates systems.
|
102
|
+
* The UTM divides the earth between latitudes −80° and 84°
|
103
|
+
* into 60 zones numbered 1 thru 60. Zone assign zone number 0 to the UPS
|
104
|
+
* regions, covering the two poles. Within UTMUPS, non-negative zone
|
105
|
+
* numbers refer to one of the "physical" zones, 0 for UPS and [1, 60] for
|
106
|
+
* UTM. Negative "pseudo-zone" numbers are used to select one of the
|
107
|
+
* physical zones.
|
108
|
+
**********************************************************************/
|
109
|
+
enum zonespec {
|
110
|
+
/**
|
111
|
+
* The smallest pseudo-zone number.
|
112
|
+
**********************************************************************/
|
113
|
+
MINPSEUDOZONE = -4,
|
114
|
+
/**
|
115
|
+
* A marker for an undefined or invalid zone. Equivalent to NaN.
|
116
|
+
**********************************************************************/
|
117
|
+
INVALID = -4,
|
118
|
+
/**
|
119
|
+
* If a coordinate already include zone information (e.g., it is an MGRS
|
120
|
+
* coordinate), use that, otherwise apply the UTMUPS::STANDARD rules.
|
121
|
+
**********************************************************************/
|
122
|
+
MATCH = -3,
|
123
|
+
/**
|
124
|
+
* Apply the standard rules for UTM zone assigment extending the UTM zone
|
125
|
+
* to each pole to give a zone number in [1, 60]. For example, use UTM
|
126
|
+
* zone 38 for longitude in [42°, 48°). The rules include the
|
127
|
+
* Norway and Svalbard exceptions.
|
128
|
+
**********************************************************************/
|
129
|
+
UTM = -2,
|
130
|
+
/**
|
131
|
+
* Apply the standard rules for zone assignment to give a zone number in
|
132
|
+
* [0, 60]. If the latitude is not in [−80°, 84°), then
|
133
|
+
* use UTMUPS::UPS = 0, otherwise apply the rules for UTMUPS::UTM. The
|
134
|
+
* tests on latitudes and longitudes are all closed on the lower end open
|
135
|
+
* on the upper. Thus for UTM zone 38, latitude is in [−80°,
|
136
|
+
* 84°) and longitude is in [42°, 48°).
|
137
|
+
**********************************************************************/
|
138
|
+
STANDARD = -1,
|
139
|
+
/**
|
140
|
+
* The largest pseudo-zone number.
|
141
|
+
**********************************************************************/
|
142
|
+
MAXPSEUDOZONE = -1,
|
143
|
+
/**
|
144
|
+
* The smallest physical zone number.
|
145
|
+
**********************************************************************/
|
146
|
+
MINZONE = 0,
|
147
|
+
/**
|
148
|
+
* The zone number used for UPS
|
149
|
+
**********************************************************************/
|
150
|
+
UPS = 0,
|
151
|
+
/**
|
152
|
+
* The smallest UTM zone number.
|
153
|
+
**********************************************************************/
|
154
|
+
MINUTMZONE = 1,
|
155
|
+
/**
|
156
|
+
* The largest UTM zone number.
|
157
|
+
**********************************************************************/
|
158
|
+
MAXUTMZONE = 60,
|
159
|
+
/**
|
160
|
+
* The largest physical zone number.
|
161
|
+
**********************************************************************/
|
162
|
+
MAXZONE = 60,
|
163
|
+
};
|
164
|
+
|
165
|
+
/**
|
166
|
+
* The standard zone.
|
167
|
+
*
|
168
|
+
* @param[in] lat latitude (degrees).
|
169
|
+
* @param[in] lon longitude (degrees).
|
170
|
+
* @param[in] setzone zone override (optional). If omitted, use the
|
171
|
+
* standard rules for picking the zone. If \e setzone is given then use
|
172
|
+
* that zone if it is non-negative, otherwise apply the rules given in
|
173
|
+
* UTMUPS::zonespec.
|
174
|
+
* @exception GeographicErr if \e setzone is outside the range
|
175
|
+
* [UTMUPS::MINPSEUDOZONE, UTMUPS::MAXZONE] = [−4, 60].
|
176
|
+
*
|
177
|
+
* This is exact.
|
178
|
+
**********************************************************************/
|
179
|
+
static int StandardZone(real lat, real lon, int setzone = STANDARD);
|
180
|
+
|
181
|
+
/**
|
182
|
+
* Forward projection, from geographic to UTM/UPS.
|
183
|
+
*
|
184
|
+
* @param[in] lat latitude of point (degrees).
|
185
|
+
* @param[in] lon longitude of point (degrees).
|
186
|
+
* @param[out] zone the UTM zone (zero means UPS).
|
187
|
+
* @param[out] northp hemisphere (true means north, false means south).
|
188
|
+
* @param[out] x easting of point (meters).
|
189
|
+
* @param[out] y northing of point (meters).
|
190
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
191
|
+
* @param[out] k scale of projection at point.
|
192
|
+
* @param[in] setzone zone override (optional).
|
193
|
+
* @param[in] mgrslimits if true enforce the stricter MGRS limits on the
|
194
|
+
* coordinates (default = false).
|
195
|
+
* @exception GeographicErr if \e lat is not in [−90°,
|
196
|
+
* 90°].
|
197
|
+
* @exception GeographicErr if the resulting \e x or \e y is out of allowed
|
198
|
+
* range (see Reverse); in this case, these arguments are unchanged.
|
199
|
+
*
|
200
|
+
* If \e setzone is omitted, use the standard rules for picking the zone.
|
201
|
+
* If \e setzone is given then use that zone if it is non-negative,
|
202
|
+
* otherwise apply the rules given in UTMUPS::zonespec. The accuracy of
|
203
|
+
* the conversion is about 5nm.
|
204
|
+
*
|
205
|
+
* The northing \e y jumps by UTMUPS::UTMShift() when crossing the equator
|
206
|
+
* in the southerly direction. Sometimes it is useful to remove this
|
207
|
+
* discontinuity in \e y by extending the "northern" hemisphere using
|
208
|
+
* UTMUPS::Transfer:
|
209
|
+
* \code
|
210
|
+
double lat = -1, lon = 123;
|
211
|
+
int zone;
|
212
|
+
bool northp;
|
213
|
+
double x, y, gamma, k;
|
214
|
+
GeographicLib::UTMUPS::Forward(lat, lon, zone, northp, x, y, gamma, k);
|
215
|
+
GeographicLib::UTMUPS::Transfer(zone, northp, x, y,
|
216
|
+
zone, true, x, y, zone);
|
217
|
+
northp = true;
|
218
|
+
\endcode
|
219
|
+
**********************************************************************/
|
220
|
+
static void Forward(real lat, real lon,
|
221
|
+
int& zone, bool& northp, real& x, real& y,
|
222
|
+
real& gamma, real& k,
|
223
|
+
int setzone = STANDARD, bool mgrslimits = false);
|
224
|
+
|
225
|
+
/**
|
226
|
+
* Reverse projection, from UTM/UPS to geographic.
|
227
|
+
*
|
228
|
+
* @param[in] zone the UTM zone (zero means UPS).
|
229
|
+
* @param[in] northp hemisphere (true means north, false means south).
|
230
|
+
* @param[in] x easting of point (meters).
|
231
|
+
* @param[in] y northing of point (meters).
|
232
|
+
* @param[out] lat latitude of point (degrees).
|
233
|
+
* @param[out] lon longitude of point (degrees).
|
234
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
235
|
+
* @param[out] k scale of projection at point.
|
236
|
+
* @param[in] mgrslimits if true enforce the stricter MGRS limits on the
|
237
|
+
* coordinates (default = false).
|
238
|
+
* @exception GeographicErr if \e zone, \e x, or \e y is out of allowed
|
239
|
+
* range; this this case the arguments are unchanged.
|
240
|
+
*
|
241
|
+
* The accuracy of the conversion is about 5nm.
|
242
|
+
*
|
243
|
+
* UTM eastings are allowed to be in the range [0km, 1000km], northings are
|
244
|
+
* allowed to be in in [0km, 9600km] for the northern hemisphere and in
|
245
|
+
* [900km, 10000km] for the southern hemisphere. However UTM northings
|
246
|
+
* can be continued across the equator. So the actual limits on the
|
247
|
+
* northings are [-9100km, 9600km] for the "northern" hemisphere and
|
248
|
+
* [900km, 19600km] for the "southern" hemisphere.
|
249
|
+
*
|
250
|
+
* UPS eastings and northings are allowed to be in the range [1200km,
|
251
|
+
* 2800km] in the northern hemisphere and in [700km, 3300km] in the
|
252
|
+
* southern hemisphere.
|
253
|
+
*
|
254
|
+
* These ranges are 100km larger than allowed for the conversions to MGRS.
|
255
|
+
* (100km is the maximum extra padding consistent with eastings remaining
|
256
|
+
* non-negative.) This allows generous overlaps between zones and UTM and
|
257
|
+
* UPS. If \e mgrslimits = true, then all the ranges are shrunk by 100km
|
258
|
+
* so that they agree with the stricter MGRS ranges. No checks are
|
259
|
+
* performed besides these (e.g., to limit the distance outside the
|
260
|
+
* standard zone boundaries).
|
261
|
+
**********************************************************************/
|
262
|
+
static void Reverse(int zone, bool northp, real x, real y,
|
263
|
+
real& lat, real& lon, real& gamma, real& k,
|
264
|
+
bool mgrslimits = false);
|
265
|
+
|
266
|
+
/**
|
267
|
+
* UTMUPS::Forward without returning convergence and scale.
|
268
|
+
**********************************************************************/
|
269
|
+
static void Forward(real lat, real lon,
|
270
|
+
int& zone, bool& northp, real& x, real& y,
|
271
|
+
int setzone = STANDARD, bool mgrslimits = false) {
|
272
|
+
real gamma, k;
|
273
|
+
Forward(lat, lon, zone, northp, x, y, gamma, k, setzone, mgrslimits);
|
274
|
+
}
|
275
|
+
|
276
|
+
/**
|
277
|
+
* UTMUPS::Reverse without returning convergence and scale.
|
278
|
+
**********************************************************************/
|
279
|
+
static void Reverse(int zone, bool northp, real x, real y,
|
280
|
+
real& lat, real& lon, bool mgrslimits = false) {
|
281
|
+
real gamma, k;
|
282
|
+
Reverse(zone, northp, x, y, lat, lon, gamma, k, mgrslimits);
|
283
|
+
}
|
284
|
+
|
285
|
+
/**
|
286
|
+
* Transfer UTM/UPS coordinated from one zone to another.
|
287
|
+
*
|
288
|
+
* @param[in] zonein the UTM zone for \e xin and \e yin (or zero for UPS).
|
289
|
+
* @param[in] northpin hemisphere for \e xin and \e yin (true means north,
|
290
|
+
* false means south).
|
291
|
+
* @param[in] xin easting of point (meters) in \e zonein.
|
292
|
+
* @param[in] yin northing of point (meters) in \e zonein.
|
293
|
+
* @param[in] zoneout the requested UTM zone for \e xout and \e yout (or
|
294
|
+
* zero for UPS).
|
295
|
+
* @param[in] northpout hemisphere for \e xout output and \e yout.
|
296
|
+
* @param[out] xout easting of point (meters) in \e zoneout.
|
297
|
+
* @param[out] yout northing of point (meters) in \e zoneout.
|
298
|
+
* @param[out] zone the actual UTM zone for \e xout and \e yout (or zero
|
299
|
+
* for UPS); this equals \e zoneout if \e zoneout ≥ 0.
|
300
|
+
* @exception GeographicErr if \e zonein is out of range (see below).
|
301
|
+
* @exception GeographicErr if \e zoneout is out of range (see below).
|
302
|
+
* @exception GeographicErr if \e xin or \e yin fall outside their allowed
|
303
|
+
* ranges (see UTMUPS::Reverse).
|
304
|
+
* @exception GeographicErr if \e xout or \e yout fall outside their
|
305
|
+
* allowed ranges (see UTMUPS::Reverse).
|
306
|
+
*
|
307
|
+
* \e zonein must be in the range [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0,
|
308
|
+
* 60] with \e zonein = UTMUPS::UPS, 0, indicating UPS. \e zonein may
|
309
|
+
* also be UTMUPS::INVALID.
|
310
|
+
*
|
311
|
+
* \e zoneout must be in the range [UTMUPS::MINPSEUDOZONE, UTMUPS::MAXZONE]
|
312
|
+
* = [-4, 60]. If \e zoneout < UTMUPS::MINZONE then the rules give in
|
313
|
+
* the documentation of UTMUPS::zonespec are applied, and \e zone is set to
|
314
|
+
* the actual zone used for output.
|
315
|
+
*
|
316
|
+
* (\e xout, \e yout) can overlap with (\e xin, \e yin).
|
317
|
+
**********************************************************************/
|
318
|
+
static void Transfer(int zonein, bool northpin, real xin, real yin,
|
319
|
+
int zoneout, bool northpout, real& xout, real& yout,
|
320
|
+
int& zone);
|
321
|
+
|
322
|
+
/**
|
323
|
+
* Decode a UTM/UPS zone string.
|
324
|
+
*
|
325
|
+
* @param[in] zonestr string representation of zone and hemisphere.
|
326
|
+
* @param[out] zone the UTM zone (zero means UPS).
|
327
|
+
* @param[out] northp hemisphere (true means north, false means south).
|
328
|
+
* @exception GeographicErr if \e zonestr is malformed.
|
329
|
+
*
|
330
|
+
* For UTM, \e zonestr has the form of a zone number in the range
|
331
|
+
* [UTMUPS::MINUTMZONE, UTMUPS::MAXUTMZONE] = [1, 60] followed by a
|
332
|
+
* hemisphere letter, n or s (or "north" or "south" spelled out). For UPS,
|
333
|
+
* it consists just of the hemisphere letter (or the spelled out
|
334
|
+
* hemisphere). The returned value of \e zone is UTMUPS::UPS = 0 for UPS.
|
335
|
+
* Note well that "38s" indicates the southern hemisphere of zone 38 and
|
336
|
+
* not latitude band S, 32° ≤ \e lat < 40°. n, 01s, 2n, 38s,
|
337
|
+
* south, 3north are legal. 0n, 001s, +3n, 61n, 38P are illegal. INV is a
|
338
|
+
* special value for which the returned value of \e is UTMUPS::INVALID.
|
339
|
+
**********************************************************************/
|
340
|
+
static void DecodeZone(const std::string& zonestr, int& zone, bool& northp);
|
341
|
+
|
342
|
+
/**
|
343
|
+
* Encode a UTM/UPS zone string.
|
344
|
+
*
|
345
|
+
* @param[in] zone the UTM zone (zero means UPS).
|
346
|
+
* @param[in] northp hemisphere (true means north, false means south).
|
347
|
+
* @param[in] abbrev if true (the default) use abbreviated (n/s) notation
|
348
|
+
* for hemisphere; otherwise spell out the hemisphere (north/south)
|
349
|
+
* @exception GeographicErr if \e zone is out of range (see below).
|
350
|
+
* @exception std::bad_alloc if memoy for the string can't be allocated.
|
351
|
+
* @return string representation of zone and hemisphere.
|
352
|
+
*
|
353
|
+
* \e zone must be in the range [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0,
|
354
|
+
* 60] with \e zone = UTMUPS::UPS, 0, indicating UPS (but the resulting
|
355
|
+
* string does not contain "0"). \e zone may also be UTMUPS::INVALID, in
|
356
|
+
* which case the returned string is "inv". This reverses
|
357
|
+
* UTMUPS::DecodeZone.
|
358
|
+
**********************************************************************/
|
359
|
+
static std::string EncodeZone(int zone, bool northp, bool abbrev = true);
|
360
|
+
|
361
|
+
/**
|
362
|
+
* Decode EPSG.
|
363
|
+
*
|
364
|
+
* @param[in] epsg the EPSG code.
|
365
|
+
* @param[out] zone the UTM zone (zero means UPS).
|
366
|
+
* @param[out] northp hemisphere (true means north, false means south).
|
367
|
+
*
|
368
|
+
* EPSG (European Petroleum Survery Group) codes are a way to refer to many
|
369
|
+
* different projections. DecodeEPSG decodes those refering to UTM or UPS
|
370
|
+
* projections for the WGS84 ellipsoid. If the code does not refer to one
|
371
|
+
* of these projections, \e zone is set to UTMUPS::INVALID. See
|
372
|
+
* http://spatialreference.org/ref/epsg/
|
373
|
+
**********************************************************************/
|
374
|
+
static void DecodeEPSG(int epsg, int& zone, bool& northp);
|
375
|
+
|
376
|
+
/**
|
377
|
+
* Encode zone as EPSG.
|
378
|
+
*
|
379
|
+
* @param[in] zone the UTM zone (zero means UPS).
|
380
|
+
* @param[in] northp hemisphere (true means north, false means south).
|
381
|
+
* @return EPSG code (or -1 if \e zone is not in the range
|
382
|
+
* [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0, 60])
|
383
|
+
*
|
384
|
+
* Convert \e zone and \e northp to the corresponding EPSG (European
|
385
|
+
* Petroleum Survery Group) codes
|
386
|
+
**********************************************************************/
|
387
|
+
static int EncodeEPSG(int zone, bool northp);
|
388
|
+
|
389
|
+
/**
|
390
|
+
* @return shift (meters) necessary to align north and south halves of a
|
391
|
+
* UTM zone (10<sup>7</sup>).
|
392
|
+
**********************************************************************/
|
393
|
+
static Math::real UTMShift();
|
394
|
+
|
395
|
+
/** \name Inspector functions
|
396
|
+
**********************************************************************/
|
397
|
+
///@{
|
398
|
+
/**
|
399
|
+
* @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
|
400
|
+
*
|
401
|
+
* (The WGS84 value is returned because the UTM and UPS projections are
|
402
|
+
* based on this ellipsoid.)
|
403
|
+
**********************************************************************/
|
404
|
+
static Math::real MajorRadius()
|
405
|
+
{ return Constants::WGS84_a(); }
|
406
|
+
|
407
|
+
/**
|
408
|
+
* @return \e f the flattening of the WGS84 ellipsoid.
|
409
|
+
*
|
410
|
+
* (The WGS84 value is returned because the UTM and UPS projections are
|
411
|
+
* based on this ellipsoid.)
|
412
|
+
**********************************************************************/
|
413
|
+
static Math::real Flattening()
|
414
|
+
{ return Constants::WGS84_f(); }
|
415
|
+
///@}
|
416
|
+
|
417
|
+
};
|
418
|
+
|
419
|
+
} // namespace GeographicLib
|
420
|
+
|
421
|
+
#endif // GEOGRAPHICLIB_UTMUPS_HPP
|