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,313 @@
|
|
1
|
+
/**
|
2
|
+
* \file LambertConformalConic.hpp
|
3
|
+
* \brief Header for GeographicLib::LambertConformalConic class
|
4
|
+
*
|
5
|
+
* Copyright (c) Charles Karney (2010-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_LAMBERTCONFORMALCONIC_HPP)
|
11
|
+
#define GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP 1
|
12
|
+
|
13
|
+
#include <GeographicLib/Constants.hpp>
|
14
|
+
|
15
|
+
namespace GeographicLib {
|
16
|
+
|
17
|
+
/**
|
18
|
+
* \brief Lambert conformal conic projection
|
19
|
+
*
|
20
|
+
* Implementation taken from the report,
|
21
|
+
* - J. P. Snyder,
|
22
|
+
* <a href="http://pubs.er.usgs.gov/usgspubs/pp/pp1395"> Map Projections: A
|
23
|
+
* Working Manual</a>, USGS Professional Paper 1395 (1987),
|
24
|
+
* pp. 107--109.
|
25
|
+
*
|
26
|
+
* This is a implementation of the equations in Snyder except that divided
|
27
|
+
* differences have been used to transform the expressions into ones which
|
28
|
+
* may be evaluated accurately and that Newton's method is used to invert the
|
29
|
+
* projection. In this implementation, the projection correctly becomes the
|
30
|
+
* Mercator projection or the polar stereographic projection when the
|
31
|
+
* standard latitude is the equator or a pole. The accuracy of the
|
32
|
+
* projections is about 10 nm (10 nanometers).
|
33
|
+
*
|
34
|
+
* The ellipsoid parameters, the standard parallels, and the scale on the
|
35
|
+
* standard parallels are set in the constructor. Internally, the case with
|
36
|
+
* two standard parallels is converted into a single standard parallel, the
|
37
|
+
* latitude of tangency (also the latitude of minimum scale), with a scale
|
38
|
+
* specified on this parallel. This latitude is also used as the latitude of
|
39
|
+
* origin which is returned by LambertConformalConic::OriginLatitude. The
|
40
|
+
* scale on the latitude of origin is given by
|
41
|
+
* LambertConformalConic::CentralScale. The case with two distinct standard
|
42
|
+
* parallels where one is a pole is singular and is disallowed. The central
|
43
|
+
* meridian (which is a trivial shift of the longitude) is specified as the
|
44
|
+
* \e lon0 argument of the LambertConformalConic::Forward and
|
45
|
+
* LambertConformalConic::Reverse functions. There is no provision in this
|
46
|
+
* class for specifying a false easting or false northing or a different
|
47
|
+
* latitude of origin. However these are can be simply included by the
|
48
|
+
* calling function. For example the Pennsylvania South state coordinate
|
49
|
+
* system (<a href="http://www.spatialreference.org/ref/epsg/3364/">
|
50
|
+
* EPSG:3364</a>) is obtained by:
|
51
|
+
* \include example-LambertConformalConic.cpp
|
52
|
+
*
|
53
|
+
* <a href="ConicProj.1.html">ConicProj</a> is a command-line utility
|
54
|
+
* providing access to the functionality of LambertConformalConic and
|
55
|
+
* AlbersEqualArea.
|
56
|
+
**********************************************************************/
|
57
|
+
class GEOGRAPHICLIB_EXPORT LambertConformalConic {
|
58
|
+
private:
|
59
|
+
typedef Math::real real;
|
60
|
+
real eps_, epsx_, ahypover_;
|
61
|
+
real _a, _f, _fm, _e2, _es;
|
62
|
+
real _sign, _n, _nc, _t0nm1, _scale, _lat0, _k0;
|
63
|
+
real _scbet0, _tchi0, _scchi0, _psi0, _nrho0, _drhomax;
|
64
|
+
static const int numit_ = 5;
|
65
|
+
static inline real hyp(real x) { return Math::hypot(real(1), x); }
|
66
|
+
// Divided differences
|
67
|
+
// Definition: Df(x,y) = (f(x)-f(y))/(x-y)
|
68
|
+
// See:
|
69
|
+
// W. M. Kahan and R. J. Fateman,
|
70
|
+
// Symbolic computation of divided differences,
|
71
|
+
// SIGSAM Bull. 33(3), 7-28 (1999)
|
72
|
+
// https://dx.doi.org/10.1145/334714.334716
|
73
|
+
// http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf
|
74
|
+
//
|
75
|
+
// General rules
|
76
|
+
// h(x) = f(g(x)): Dh(x,y) = Df(g(x),g(y))*Dg(x,y)
|
77
|
+
// h(x) = f(x)*g(x):
|
78
|
+
// Dh(x,y) = Df(x,y)*g(x) + Dg(x,y)*f(y)
|
79
|
+
// = Df(x,y)*g(y) + Dg(x,y)*f(x)
|
80
|
+
// = Df(x,y)*(g(x)+g(y))/2 + Dg(x,y)*(f(x)+f(y))/2
|
81
|
+
//
|
82
|
+
// hyp(x) = sqrt(1+x^2): Dhyp(x,y) = (x+y)/(hyp(x)+hyp(y))
|
83
|
+
static inline real Dhyp(real x, real y, real hx, real hy)
|
84
|
+
// hx = hyp(x)
|
85
|
+
{ return (x + y) / (hx + hy); }
|
86
|
+
// sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^2))
|
87
|
+
static inline real Dsn(real x, real y, real sx, real sy) {
|
88
|
+
// sx = x/hyp(x)
|
89
|
+
real t = x * y;
|
90
|
+
return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) :
|
91
|
+
(x - y != 0 ? (sx - sy) / (x - y) : 1);
|
92
|
+
}
|
93
|
+
// Dlog1p(x,y) = log1p((x-y)/(1+y))/(x-y)
|
94
|
+
static inline real Dlog1p(real x, real y) {
|
95
|
+
real t = x - y; if (t < 0) { t = -t; y = x; }
|
96
|
+
return t ? Math::log1p(t / (1 + y)) / t : 1 / (1 + x);
|
97
|
+
}
|
98
|
+
// Dexp(x,y) = exp((x+y)/2) * 2*sinh((x-y)/2)/(x-y)
|
99
|
+
static inline real Dexp(real x, real y) {
|
100
|
+
using std::sinh; using std::exp;
|
101
|
+
real t = (x - y)/2;
|
102
|
+
return (t ? sinh(t)/t : 1) * exp((x + y)/2);
|
103
|
+
}
|
104
|
+
// Dsinh(x,y) = 2*sinh((x-y)/2)/(x-y) * cosh((x+y)/2)
|
105
|
+
// cosh((x+y)/2) = (c+sinh(x)*sinh(y)/c)/2
|
106
|
+
// c=sqrt((1+cosh(x))*(1+cosh(y)))
|
107
|
+
// cosh((x+y)/2) = sqrt( (sinh(x)*sinh(y) + cosh(x)*cosh(y) + 1)/2 )
|
108
|
+
static inline real Dsinh(real x, real y, real sx, real sy, real cx, real cy)
|
109
|
+
// sx = sinh(x), cx = cosh(x)
|
110
|
+
{
|
111
|
+
// real t = (x - y)/2, c = sqrt((1 + cx) * (1 + cy));
|
112
|
+
// return (t ? sinh(t)/t : real(1)) * (c + sx * sy / c) /2;
|
113
|
+
using std::sinh; using std::sqrt;
|
114
|
+
real t = (x - y)/2;
|
115
|
+
return (t ? sinh(t)/t : 1) * sqrt((sx * sy + cx * cy + 1) /2);
|
116
|
+
}
|
117
|
+
// Dasinh(x,y) = asinh((x-y)*(x+y)/(x*sqrt(1+y^2)+y*sqrt(1+x^2)))/(x-y)
|
118
|
+
// = asinh((x*sqrt(1+y^2)-y*sqrt(1+x^2)))/(x-y)
|
119
|
+
static inline real Dasinh(real x, real y, real hx, real hy) {
|
120
|
+
// hx = hyp(x)
|
121
|
+
real t = x - y;
|
122
|
+
return t ?
|
123
|
+
Math::asinh(x*y > 0 ? t * (x+y) / (x*hy + y*hx) : x*hy - y*hx) / t :
|
124
|
+
1/hx;
|
125
|
+
}
|
126
|
+
// Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y)
|
127
|
+
inline real Deatanhe(real x, real y) const {
|
128
|
+
real t = x - y, d = 1 - _e2 * x * y;
|
129
|
+
return t ? Math::eatanhe(t / d, _es) / t : _e2 / d;
|
130
|
+
}
|
131
|
+
void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1);
|
132
|
+
public:
|
133
|
+
|
134
|
+
/**
|
135
|
+
* Constructor with a single standard parallel.
|
136
|
+
*
|
137
|
+
* @param[in] a equatorial radius of ellipsoid (meters).
|
138
|
+
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
|
139
|
+
* Negative \e f gives a prolate ellipsoid.
|
140
|
+
* @param[in] stdlat standard parallel (degrees), the circle of tangency.
|
141
|
+
* @param[in] k0 scale on the standard parallel.
|
142
|
+
* @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k0 is
|
143
|
+
* not positive.
|
144
|
+
* @exception GeographicErr if \e stdlat is not in [−90°,
|
145
|
+
* 90°].
|
146
|
+
**********************************************************************/
|
147
|
+
LambertConformalConic(real a, real f, real stdlat, real k0);
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Constructor with two standard parallels.
|
151
|
+
*
|
152
|
+
* @param[in] a equatorial radius of ellipsoid (meters).
|
153
|
+
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
|
154
|
+
* Negative \e f gives a prolate ellipsoid.
|
155
|
+
* @param[in] stdlat1 first standard parallel (degrees).
|
156
|
+
* @param[in] stdlat2 second standard parallel (degrees).
|
157
|
+
* @param[in] k1 scale on the standard parallels.
|
158
|
+
* @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k1 is
|
159
|
+
* not positive.
|
160
|
+
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
|
161
|
+
* [−90°, 90°], or if either \e stdlat1 or \e
|
162
|
+
* stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
|
163
|
+
**********************************************************************/
|
164
|
+
LambertConformalConic(real a, real f, real stdlat1, real stdlat2, real k1);
|
165
|
+
|
166
|
+
/**
|
167
|
+
* Constructor with two standard parallels specified by sines and cosines.
|
168
|
+
*
|
169
|
+
* @param[in] a equatorial radius of ellipsoid (meters).
|
170
|
+
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
|
171
|
+
* Negative \e f gives a prolate ellipsoid.
|
172
|
+
* @param[in] sinlat1 sine of first standard parallel.
|
173
|
+
* @param[in] coslat1 cosine of first standard parallel.
|
174
|
+
* @param[in] sinlat2 sine of second standard parallel.
|
175
|
+
* @param[in] coslat2 cosine of second standard parallel.
|
176
|
+
* @param[in] k1 scale on the standard parallels.
|
177
|
+
* @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k1 is
|
178
|
+
* not positive.
|
179
|
+
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
|
180
|
+
* [−90°, 90°], or if either \e stdlat1 or \e
|
181
|
+
* stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
|
182
|
+
*
|
183
|
+
* This allows parallels close to the poles to be specified accurately.
|
184
|
+
* This routine computes the latitude of origin and the scale at this
|
185
|
+
* latitude. In the case where \e lat1 and \e lat2 are different, the
|
186
|
+
* errors in this routines are as follows: if \e dlat = abs(\e lat2 −
|
187
|
+
* \e lat1) ≤ 160° and max(abs(\e lat1), abs(\e lat2)) ≤ 90
|
188
|
+
* − min(0.0002, 2.2 × 10<sup>−6</sup>(180 − \e
|
189
|
+
* dlat), 6 × 10<sup>−8</sup> <i>dlat</i><sup>2</sup>) (in
|
190
|
+
* degrees), then the error in the latitude of origin is less than 4.5
|
191
|
+
* × 10<sup>−14</sup>d and the relative error in the scale is
|
192
|
+
* less than 7 × 10<sup>−15</sup>.
|
193
|
+
**********************************************************************/
|
194
|
+
LambertConformalConic(real a, real f,
|
195
|
+
real sinlat1, real coslat1,
|
196
|
+
real sinlat2, real coslat2,
|
197
|
+
real k1);
|
198
|
+
|
199
|
+
/**
|
200
|
+
* Set the scale for the projection.
|
201
|
+
*
|
202
|
+
* @param[in] lat (degrees).
|
203
|
+
* @param[in] k scale at latitude \e lat (default 1).
|
204
|
+
* @exception GeographicErr \e k is not positive.
|
205
|
+
* @exception GeographicErr if \e lat is not in [−90°,
|
206
|
+
* 90°].
|
207
|
+
**********************************************************************/
|
208
|
+
void SetScale(real lat, real k = real(1));
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Forward projection, from geographic to Lambert conformal conic.
|
212
|
+
*
|
213
|
+
* @param[in] lon0 central meridian longitude (degrees).
|
214
|
+
* @param[in] lat latitude of point (degrees).
|
215
|
+
* @param[in] lon longitude of point (degrees).
|
216
|
+
* @param[out] x easting of point (meters).
|
217
|
+
* @param[out] y northing of point (meters).
|
218
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
219
|
+
* @param[out] k scale of projection at point.
|
220
|
+
*
|
221
|
+
* The latitude origin is given by LambertConformalConic::LatitudeOrigin().
|
222
|
+
* No false easting or northing is added and \e lat should be in the range
|
223
|
+
* [−90°, 90°]. The error in the projection is less than
|
224
|
+
* about 10 nm (10 nanometers), true distance, and the errors in the
|
225
|
+
* meridian convergence and scale are consistent with this. The values of
|
226
|
+
* \e x and \e y returned for points which project to infinity (i.e., one
|
227
|
+
* or both of the poles) will be large but finite.
|
228
|
+
**********************************************************************/
|
229
|
+
void Forward(real lon0, real lat, real lon,
|
230
|
+
real& x, real& y, real& gamma, real& k) const;
|
231
|
+
|
232
|
+
/**
|
233
|
+
* Reverse projection, from Lambert conformal conic to geographic.
|
234
|
+
*
|
235
|
+
* @param[in] lon0 central meridian longitude (degrees).
|
236
|
+
* @param[in] x easting of point (meters).
|
237
|
+
* @param[in] y northing of point (meters).
|
238
|
+
* @param[out] lat latitude of point (degrees).
|
239
|
+
* @param[out] lon longitude of point (degrees).
|
240
|
+
* @param[out] gamma meridian convergence at point (degrees).
|
241
|
+
* @param[out] k scale of projection at point.
|
242
|
+
*
|
243
|
+
* The latitude origin is given by LambertConformalConic::LatitudeOrigin().
|
244
|
+
* No false easting or northing is added. The value of \e lon returned is
|
245
|
+
* in the range [−180°, 180°). The error in the projection
|
246
|
+
* is less than about 10 nm (10 nanometers), true distance, and the errors
|
247
|
+
* in the meridian convergence and scale are consistent with this.
|
248
|
+
**********************************************************************/
|
249
|
+
void Reverse(real lon0, real x, real y,
|
250
|
+
real& lat, real& lon, real& gamma, real& k) const;
|
251
|
+
|
252
|
+
/**
|
253
|
+
* LambertConformalConic::Forward without returning the convergence and
|
254
|
+
* scale.
|
255
|
+
**********************************************************************/
|
256
|
+
void Forward(real lon0, real lat, real lon,
|
257
|
+
real& x, real& y) const {
|
258
|
+
real gamma, k;
|
259
|
+
Forward(lon0, lat, lon, x, y, gamma, k);
|
260
|
+
}
|
261
|
+
|
262
|
+
/**
|
263
|
+
* LambertConformalConic::Reverse without returning the convergence and
|
264
|
+
* scale.
|
265
|
+
**********************************************************************/
|
266
|
+
void Reverse(real lon0, real x, real y,
|
267
|
+
real& lat, real& lon) const {
|
268
|
+
real gamma, k;
|
269
|
+
Reverse(lon0, x, y, lat, lon, gamma, k);
|
270
|
+
}
|
271
|
+
|
272
|
+
/** \name Inspector functions
|
273
|
+
**********************************************************************/
|
274
|
+
///@{
|
275
|
+
/**
|
276
|
+
* @return \e a the equatorial radius of the ellipsoid (meters). This is
|
277
|
+
* the value used in the constructor.
|
278
|
+
**********************************************************************/
|
279
|
+
Math::real MajorRadius() const { return _a; }
|
280
|
+
|
281
|
+
/**
|
282
|
+
* @return \e f the flattening of the ellipsoid. This is the
|
283
|
+
* value used in the constructor.
|
284
|
+
**********************************************************************/
|
285
|
+
Math::real Flattening() const { return _f; }
|
286
|
+
|
287
|
+
/**
|
288
|
+
* @return latitude of the origin for the projection (degrees).
|
289
|
+
*
|
290
|
+
* This is the latitude of minimum scale and equals the \e stdlat in the
|
291
|
+
* 1-parallel constructor and lies between \e stdlat1 and \e stdlat2 in the
|
292
|
+
* 2-parallel constructors.
|
293
|
+
**********************************************************************/
|
294
|
+
Math::real OriginLatitude() const { return _lat0; }
|
295
|
+
|
296
|
+
/**
|
297
|
+
* @return central scale for the projection. This is the scale on the
|
298
|
+
* latitude of origin.
|
299
|
+
**********************************************************************/
|
300
|
+
Math::real CentralScale() const { return _k0; }
|
301
|
+
///@}
|
302
|
+
|
303
|
+
/**
|
304
|
+
* A global instantiation of LambertConformalConic with the WGS84
|
305
|
+
* ellipsoid, \e stdlat = 0, and \e k0 = 1. This degenerates to the
|
306
|
+
* Mercator projection.
|
307
|
+
**********************************************************************/
|
308
|
+
static const LambertConformalConic& Mercator();
|
309
|
+
};
|
310
|
+
|
311
|
+
} // namespace GeographicLib
|
312
|
+
|
313
|
+
#endif // GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP
|
@@ -0,0 +1,236 @@
|
|
1
|
+
/**
|
2
|
+
* \file LocalCartesian.hpp
|
3
|
+
* \brief Header for GeographicLib::LocalCartesian 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_LOCALCARTESIAN_HPP)
|
11
|
+
#define GEOGRAPHICLIB_LOCALCARTESIAN_HPP 1
|
12
|
+
|
13
|
+
#include <GeographicLib/Geocentric.hpp>
|
14
|
+
#include <GeographicLib/Constants.hpp>
|
15
|
+
|
16
|
+
namespace GeographicLib {
|
17
|
+
|
18
|
+
/**
|
19
|
+
* \brief Local cartesian coordinates
|
20
|
+
*
|
21
|
+
* Convert between geodetic coordinates latitude = \e lat, longitude = \e
|
22
|
+
* lon, height = \e h (measured vertically from the surface of the ellipsoid)
|
23
|
+
* to local cartesian coordinates (\e x, \e y, \e z). The origin of local
|
24
|
+
* cartesian coordinate system is at \e lat = \e lat0, \e lon = \e lon0, \e h
|
25
|
+
* = \e h0. The \e z axis is normal to the ellipsoid; the \e y axis points
|
26
|
+
* due north. The plane \e z = - \e h0 is tangent to the ellipsoid.
|
27
|
+
*
|
28
|
+
* The conversions all take place via geocentric coordinates using a
|
29
|
+
* Geocentric object (by default Geocentric::WGS84()).
|
30
|
+
*
|
31
|
+
* Example of use:
|
32
|
+
* \include example-LocalCartesian.cpp
|
33
|
+
*
|
34
|
+
* <a href="CartConvert.1.html">CartConvert</a> is a command-line utility
|
35
|
+
* providing access to the functionality of Geocentric and LocalCartesian.
|
36
|
+
**********************************************************************/
|
37
|
+
|
38
|
+
class GEOGRAPHICLIB_EXPORT LocalCartesian {
|
39
|
+
private:
|
40
|
+
typedef Math::real real;
|
41
|
+
static const size_t dim_ = 3;
|
42
|
+
static const size_t dim2_ = dim_ * dim_;
|
43
|
+
Geocentric _earth;
|
44
|
+
real _lat0, _lon0, _h0;
|
45
|
+
real _x0, _y0, _z0, _r[dim2_];
|
46
|
+
void IntForward(real lat, real lon, real h, real& x, real& y, real& z,
|
47
|
+
real M[dim2_]) const;
|
48
|
+
void IntReverse(real x, real y, real z, real& lat, real& lon, real& h,
|
49
|
+
real M[dim2_]) const;
|
50
|
+
void MatrixMultiply(real M[dim2_]) const;
|
51
|
+
public:
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Constructor setting the origin.
|
55
|
+
*
|
56
|
+
* @param[in] lat0 latitude at origin (degrees).
|
57
|
+
* @param[in] lon0 longitude at origin (degrees).
|
58
|
+
* @param[in] h0 height above ellipsoid at origin (meters); default 0.
|
59
|
+
* @param[in] earth Geocentric object for the transformation; default
|
60
|
+
* Geocentric::WGS84().
|
61
|
+
*
|
62
|
+
* \e lat0 should be in the range [−90°, 90°].
|
63
|
+
**********************************************************************/
|
64
|
+
LocalCartesian(real lat0, real lon0, real h0 = 0,
|
65
|
+
const Geocentric& earth = Geocentric::WGS84())
|
66
|
+
: _earth(earth)
|
67
|
+
{ Reset(lat0, lon0, h0); }
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Default constructor.
|
71
|
+
*
|
72
|
+
* @param[in] earth Geocentric object for the transformation; default
|
73
|
+
* Geocentric::WGS84().
|
74
|
+
*
|
75
|
+
* Sets \e lat0 = 0, \e lon0 = 0, \e h0 = 0.
|
76
|
+
**********************************************************************/
|
77
|
+
explicit LocalCartesian(const Geocentric& earth = Geocentric::WGS84())
|
78
|
+
: _earth(earth)
|
79
|
+
{ Reset(real(0), real(0), real(0)); }
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Reset the origin.
|
83
|
+
*
|
84
|
+
* @param[in] lat0 latitude at origin (degrees).
|
85
|
+
* @param[in] lon0 longitude at origin (degrees).
|
86
|
+
* @param[in] h0 height above ellipsoid at origin (meters); default 0.
|
87
|
+
*
|
88
|
+
* \e lat0 should be in the range [−90°, 90°].
|
89
|
+
**********************************************************************/
|
90
|
+
void Reset(real lat0, real lon0, real h0 = 0);
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Convert from geodetic to local cartesian coordinates.
|
94
|
+
*
|
95
|
+
* @param[in] lat latitude of point (degrees).
|
96
|
+
* @param[in] lon longitude of point (degrees).
|
97
|
+
* @param[in] h height of point above the ellipsoid (meters).
|
98
|
+
* @param[out] x local cartesian coordinate (meters).
|
99
|
+
* @param[out] y local cartesian coordinate (meters).
|
100
|
+
* @param[out] z local cartesian coordinate (meters).
|
101
|
+
*
|
102
|
+
* \e lat should be in the range [−90°, 90°].
|
103
|
+
**********************************************************************/
|
104
|
+
void Forward(real lat, real lon, real h, real& x, real& y, real& z)
|
105
|
+
const {
|
106
|
+
IntForward(lat, lon, h, x, y, z, NULL);
|
107
|
+
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Convert from geodetic to local cartesian coordinates and return rotation
|
111
|
+
* matrix.
|
112
|
+
*
|
113
|
+
* @param[in] lat latitude of point (degrees).
|
114
|
+
* @param[in] lon longitude of point (degrees).
|
115
|
+
* @param[in] h height of point above the ellipsoid (meters).
|
116
|
+
* @param[out] x local cartesian coordinate (meters).
|
117
|
+
* @param[out] y local cartesian coordinate (meters).
|
118
|
+
* @param[out] z local cartesian coordinate (meters).
|
119
|
+
* @param[out] M if the length of the vector is 9, fill with the rotation
|
120
|
+
* matrix in row-major order.
|
121
|
+
*
|
122
|
+
* \e lat should be in the range [−90°, 90°].
|
123
|
+
*
|
124
|
+
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
|
125
|
+
* express \e v as \e column vectors in one of two ways
|
126
|
+
* - in east, north, up coordinates (where the components are relative to a
|
127
|
+
* local coordinate system at (\e lat, \e lon, \e h)); call this
|
128
|
+
* representation \e v1.
|
129
|
+
* - in \e x, \e y, \e z coordinates (where the components are relative to
|
130
|
+
* the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
|
131
|
+
* representation \e v0.
|
132
|
+
* .
|
133
|
+
* Then we have \e v0 = \e M ⋅ \e v1.
|
134
|
+
**********************************************************************/
|
135
|
+
void Forward(real lat, real lon, real h, real& x, real& y, real& z,
|
136
|
+
std::vector<real>& M)
|
137
|
+
const {
|
138
|
+
if (M.end() == M.begin() + dim2_) {
|
139
|
+
real t[dim2_];
|
140
|
+
IntForward(lat, lon, h, x, y, z, t);
|
141
|
+
std::copy(t, t + dim2_, M.begin());
|
142
|
+
} else
|
143
|
+
IntForward(lat, lon, h, x, y, z, NULL);
|
144
|
+
}
|
145
|
+
|
146
|
+
/**
|
147
|
+
* Convert from local cartesian to geodetic coordinates.
|
148
|
+
*
|
149
|
+
* @param[in] x local cartesian coordinate (meters).
|
150
|
+
* @param[in] y local cartesian coordinate (meters).
|
151
|
+
* @param[in] z local cartesian coordinate (meters).
|
152
|
+
* @param[out] lat latitude of point (degrees).
|
153
|
+
* @param[out] lon longitude of point (degrees).
|
154
|
+
* @param[out] h height of point above the ellipsoid (meters).
|
155
|
+
*
|
156
|
+
* The value of \e lon returned is in the range [−180°,
|
157
|
+
* 180°).
|
158
|
+
**********************************************************************/
|
159
|
+
void Reverse(real x, real y, real z, real& lat, real& lon, real& h)
|
160
|
+
const {
|
161
|
+
IntReverse(x, y, z, lat, lon, h, NULL);
|
162
|
+
}
|
163
|
+
|
164
|
+
/**
|
165
|
+
* Convert from local cartesian to geodetic coordinates and return rotation
|
166
|
+
* matrix.
|
167
|
+
*
|
168
|
+
* @param[in] x local cartesian coordinate (meters).
|
169
|
+
* @param[in] y local cartesian coordinate (meters).
|
170
|
+
* @param[in] z local cartesian coordinate (meters).
|
171
|
+
* @param[out] lat latitude of point (degrees).
|
172
|
+
* @param[out] lon longitude of point (degrees).
|
173
|
+
* @param[out] h height of point above the ellipsoid (meters).
|
174
|
+
* @param[out] M if the length of the vector is 9, fill with the rotation
|
175
|
+
* matrix in row-major order.
|
176
|
+
*
|
177
|
+
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
|
178
|
+
* express \e v as \e column vectors in one of two ways
|
179
|
+
* - in east, north, up coordinates (where the components are relative to a
|
180
|
+
* local coordinate system at (\e lat, \e lon, \e h)); call this
|
181
|
+
* representation \e v1.
|
182
|
+
* - in \e x, \e y, \e z coordinates (where the components are relative to
|
183
|
+
* the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
|
184
|
+
* representation \e v0.
|
185
|
+
* .
|
186
|
+
* Then we have \e v1 = <i>M</i><sup>T</sup> ⋅ \e v0, where
|
187
|
+
* <i>M</i><sup>T</sup> is the transpose of \e M.
|
188
|
+
**********************************************************************/
|
189
|
+
void Reverse(real x, real y, real z, real& lat, real& lon, real& h,
|
190
|
+
std::vector<real>& M)
|
191
|
+
const {
|
192
|
+
if (M.end() == M.begin() + dim2_) {
|
193
|
+
real t[dim2_];
|
194
|
+
IntReverse(x, y, z, lat, lon, h, t);
|
195
|
+
std::copy(t, t + dim2_, M.begin());
|
196
|
+
} else
|
197
|
+
IntReverse(x, y, z, lat, lon, h, NULL);
|
198
|
+
}
|
199
|
+
|
200
|
+
/** \name Inspector functions
|
201
|
+
**********************************************************************/
|
202
|
+
///@{
|
203
|
+
/**
|
204
|
+
* @return latitude of the origin (degrees).
|
205
|
+
**********************************************************************/
|
206
|
+
Math::real LatitudeOrigin() const { return _lat0; }
|
207
|
+
|
208
|
+
/**
|
209
|
+
* @return longitude of the origin (degrees).
|
210
|
+
**********************************************************************/
|
211
|
+
Math::real LongitudeOrigin() const { return _lon0; }
|
212
|
+
|
213
|
+
/**
|
214
|
+
* @return height of the origin (meters).
|
215
|
+
**********************************************************************/
|
216
|
+
Math::real HeightOrigin() const { return _h0; }
|
217
|
+
|
218
|
+
/**
|
219
|
+
* @return \e a the equatorial radius of the ellipsoid (meters). This is
|
220
|
+
* the value of \e a inherited from the Geocentric object used in the
|
221
|
+
* constructor.
|
222
|
+
**********************************************************************/
|
223
|
+
Math::real MajorRadius() const { return _earth.MajorRadius(); }
|
224
|
+
|
225
|
+
/**
|
226
|
+
* @return \e f the flattening of the ellipsoid. This is the value
|
227
|
+
* inherited from the Geocentric object used in the constructor.
|
228
|
+
**********************************************************************/
|
229
|
+
Math::real Flattening() const { return _earth.Flattening(); }
|
230
|
+
///@}
|
231
|
+
|
232
|
+
};
|
233
|
+
|
234
|
+
} // namespace GeographicLib
|
235
|
+
|
236
|
+
#endif // GEOGRAPHICLIB_LOCALCARTESIAN_HPP
|