geographiclib 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|