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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa8370a9028f271543b408485a76114b2d7f396f
|
4
|
+
data.tar.gz: 21443c4c505ce041d24155701c38e4a5a3ffa420
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3c0efaf0dbadca39751487f1626cb3124b6554fb66e367455e9431316944bcbe5dfb19af4517009349730d306dd59e8c5e07a1bb5c693598cb7dcf3232c9a4ad
|
7
|
+
data.tar.gz: 6b4e08090d147a0e4ebaf5adf219485b4f20c7b1b749facbffe63193706b3b5ec4eec4f74bf3049365e4e22f1ce5e45bdcd33a4a2d7ac520be9569b17ab4ad8a
|
data/AUTHORS
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Charles Karney <charles@karney.com>
|
2
|
+
Francesco Paolo Lovergine <frankie@debian.org> (autoconfiscation)
|
3
|
+
Mathieu Peyréga <mathieu.peyrega@gmail.com> (help with gravity models)
|
4
|
+
Andrew MacIntyre <Andrew.MacIntyre@acma.gov.au> (python/setup.py)
|
5
|
+
Skip Breidbach <skip@waywally.com> (maven support for Java)
|
6
|
+
Scott Heiman <mrmtdew2@outlook.com> (.NET wrappers + C# examples)
|
7
|
+
Chris Bennight <chris@bennight.com> (deploying Java library)
|
8
|
+
Sebastian Mattheis <Sebastian.Mattheis@bmw.de> (gnomonic projection in Java)
|
9
|
+
Yurij Mikhalevich <0@39.yt> (node.js port)
|
10
|
+
Phil Miller <phillip.miller@sri.com> (putting tests into python/setup.py)
|
11
|
+
Jonathan Takahashi <jtakahashi@gmail.com> (boost-python sample)
|
12
|
+
Lukas Joeressen <lukas@joeressen.net> (Ruby wrapper)
|
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
The MIT License (MIT); this license applies to GeographicLib,
|
2
|
+
versions 1.12 and later.
|
3
|
+
|
4
|
+
Copyright (c) 2008-2016, Charles Karney
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person
|
7
|
+
obtaining a copy of this software and associated documentation
|
8
|
+
files (the "Software"), to deal in the Software without
|
9
|
+
restriction, including without limitation the rights to use, copy,
|
10
|
+
modify, merge, publish, distribute, sublicense, and/or sell copies
|
11
|
+
of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
21
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
22
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
24
|
+
DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
/**
|
2
|
+
* \file Accumulator.cpp
|
3
|
+
* \brief Implementation for GeographicLib::Accumulator class
|
4
|
+
*
|
5
|
+
* Copyright (c) Charles Karney (2013) <charles@karney.com> and licensed under
|
6
|
+
* the MIT/X11 License. For more information, see
|
7
|
+
* http://geographiclib.sourceforge.net/
|
8
|
+
**********************************************************************/
|
9
|
+
|
10
|
+
#include <GeographicLib/Accumulator.hpp>
|
11
|
+
|
12
|
+
namespace GeographicLib {
|
13
|
+
|
14
|
+
/// \cond SKIP
|
15
|
+
|
16
|
+
// Need to instantiate Accumulator to get the code into the shared library
|
17
|
+
// (without this, NETGeographic complains about not finding the == and !=
|
18
|
+
// operators).
|
19
|
+
template class GEOGRAPHICLIB_EXPORT Accumulator<Math::real>;
|
20
|
+
|
21
|
+
/// \endcond
|
22
|
+
|
23
|
+
} // namespace GeographicLib
|
@@ -0,0 +1,445 @@
|
|
1
|
+
/**
|
2
|
+
* \file AlbersEqualArea.cpp
|
3
|
+
* \brief Implementation for GeographicLib::AlbersEqualArea 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
|
+
#include <GeographicLib/AlbersEqualArea.hpp>
|
11
|
+
|
12
|
+
#if defined(_MSC_VER)
|
13
|
+
// Squelch warnings about constant conditional expressions
|
14
|
+
# pragma warning (disable: 4127)
|
15
|
+
#endif
|
16
|
+
|
17
|
+
namespace GeographicLib {
|
18
|
+
|
19
|
+
using namespace std;
|
20
|
+
|
21
|
+
AlbersEqualArea::AlbersEqualArea(real a, real f, real stdlat, real k0)
|
22
|
+
: eps_(numeric_limits<real>::epsilon())
|
23
|
+
, epsx_(Math::sq(eps_))
|
24
|
+
, epsx2_(Math::sq(epsx_))
|
25
|
+
, tol_(sqrt(eps_))
|
26
|
+
, tol0_(tol_ * sqrt(sqrt(eps_)))
|
27
|
+
, _a(a)
|
28
|
+
, _f(f)
|
29
|
+
, _fm(1 - _f)
|
30
|
+
, _e2(_f * (2 - _f))
|
31
|
+
, _e(sqrt(abs(_e2)))
|
32
|
+
, _e2m(1 - _e2)
|
33
|
+
, _qZ(1 + _e2m * atanhee(real(1)))
|
34
|
+
, _qx(_qZ / ( 2 * _e2m ))
|
35
|
+
{
|
36
|
+
if (!(Math::isfinite(_a) && _a > 0))
|
37
|
+
throw GeographicErr("Major radius is not positive");
|
38
|
+
if (!(Math::isfinite(_f) && _f < 1))
|
39
|
+
throw GeographicErr("Minor radius is not positive");
|
40
|
+
if (!(Math::isfinite(k0) && k0 > 0))
|
41
|
+
throw GeographicErr("Scale is not positive");
|
42
|
+
if (!(abs(stdlat) <= 90))
|
43
|
+
throw GeographicErr("Standard latitude not in [-90d, 90d]");
|
44
|
+
real sphi, cphi;
|
45
|
+
Math::sincosd(stdlat, sphi, cphi);
|
46
|
+
Init(sphi, cphi, sphi, cphi, k0);
|
47
|
+
}
|
48
|
+
|
49
|
+
AlbersEqualArea::AlbersEqualArea(real a, real f, real stdlat1, real stdlat2,
|
50
|
+
real k1)
|
51
|
+
: eps_(numeric_limits<real>::epsilon())
|
52
|
+
, epsx_(Math::sq(eps_))
|
53
|
+
, epsx2_(Math::sq(epsx_))
|
54
|
+
, tol_(sqrt(eps_))
|
55
|
+
, tol0_(tol_ * sqrt(sqrt(eps_)))
|
56
|
+
, _a(a)
|
57
|
+
, _f(f)
|
58
|
+
, _fm(1 - _f)
|
59
|
+
, _e2(_f * (2 - _f))
|
60
|
+
, _e(sqrt(abs(_e2)))
|
61
|
+
, _e2m(1 - _e2)
|
62
|
+
, _qZ(1 + _e2m * atanhee(real(1)))
|
63
|
+
, _qx(_qZ / ( 2 * _e2m ))
|
64
|
+
{
|
65
|
+
if (!(Math::isfinite(_a) && _a > 0))
|
66
|
+
throw GeographicErr("Major radius is not positive");
|
67
|
+
if (!(Math::isfinite(_f) && _f < 1))
|
68
|
+
throw GeographicErr("Minor radius is not positive");
|
69
|
+
if (!(Math::isfinite(k1) && k1 > 0))
|
70
|
+
throw GeographicErr("Scale is not positive");
|
71
|
+
if (!(abs(stdlat1) <= 90))
|
72
|
+
throw GeographicErr("Standard latitude 1 not in [-90d, 90d]");
|
73
|
+
if (!(abs(stdlat2) <= 90))
|
74
|
+
throw GeographicErr("Standard latitude 2 not in [-90d, 90d]");
|
75
|
+
real sphi1, cphi1, sphi2, cphi2;
|
76
|
+
Math::sincosd(stdlat1, sphi1, cphi1);
|
77
|
+
Math::sincosd(stdlat2, sphi2, cphi2);
|
78
|
+
Init(sphi1, cphi1, sphi2, cphi2, k1);
|
79
|
+
}
|
80
|
+
|
81
|
+
AlbersEqualArea::AlbersEqualArea(real a, real f,
|
82
|
+
real sinlat1, real coslat1,
|
83
|
+
real sinlat2, real coslat2,
|
84
|
+
real k1)
|
85
|
+
: eps_(numeric_limits<real>::epsilon())
|
86
|
+
, epsx_(Math::sq(eps_))
|
87
|
+
, epsx2_(Math::sq(epsx_))
|
88
|
+
, tol_(sqrt(eps_))
|
89
|
+
, tol0_(tol_ * sqrt(sqrt(eps_)))
|
90
|
+
, _a(a)
|
91
|
+
, _f(f)
|
92
|
+
, _fm(1 - _f)
|
93
|
+
, _e2(_f * (2 - _f))
|
94
|
+
, _e(sqrt(abs(_e2)))
|
95
|
+
, _e2m(1 - _e2)
|
96
|
+
, _qZ(1 + _e2m * atanhee(real(1)))
|
97
|
+
, _qx(_qZ / ( 2 * _e2m ))
|
98
|
+
{
|
99
|
+
if (!(Math::isfinite(_a) && _a > 0))
|
100
|
+
throw GeographicErr("Major radius is not positive");
|
101
|
+
if (!(Math::isfinite(_f) && _f < 1))
|
102
|
+
throw GeographicErr("Minor radius is not positive");
|
103
|
+
if (!(Math::isfinite(k1) && k1 > 0))
|
104
|
+
throw GeographicErr("Scale is not positive");
|
105
|
+
if (!(coslat1 >= 0))
|
106
|
+
throw GeographicErr("Standard latitude 1 not in [-90d, 90d]");
|
107
|
+
if (!(coslat2 >= 0))
|
108
|
+
throw GeographicErr("Standard latitude 2 not in [-90d, 90d]");
|
109
|
+
if (!(abs(sinlat1) <= 1 && coslat1 <= 1) || (coslat1 == 0 && sinlat1 == 0))
|
110
|
+
throw GeographicErr("Bad sine/cosine of standard latitude 1");
|
111
|
+
if (!(abs(sinlat2) <= 1 && coslat2 <= 1) || (coslat2 == 0 && sinlat2 == 0))
|
112
|
+
throw GeographicErr("Bad sine/cosine of standard latitude 2");
|
113
|
+
if (coslat1 == 0 && coslat2 == 0 && sinlat1 * sinlat2 <= 0)
|
114
|
+
throw GeographicErr
|
115
|
+
("Standard latitudes cannot be opposite poles");
|
116
|
+
Init(sinlat1, coslat1, sinlat2, coslat2, k1);
|
117
|
+
}
|
118
|
+
|
119
|
+
void AlbersEqualArea::Init(real sphi1, real cphi1,
|
120
|
+
real sphi2, real cphi2, real k1) {
|
121
|
+
{
|
122
|
+
real r;
|
123
|
+
r = Math::hypot(sphi1, cphi1);
|
124
|
+
sphi1 /= r; cphi1 /= r;
|
125
|
+
r = Math::hypot(sphi2, cphi2);
|
126
|
+
sphi2 /= r; cphi2 /= r;
|
127
|
+
}
|
128
|
+
bool polar = (cphi1 == 0);
|
129
|
+
cphi1 = max(epsx_, cphi1); // Avoid singularities at poles
|
130
|
+
cphi2 = max(epsx_, cphi2);
|
131
|
+
// Determine hemisphere of tangent latitude
|
132
|
+
_sign = sphi1 + sphi2 >= 0 ? 1 : -1;
|
133
|
+
// Internally work with tangent latitude positive
|
134
|
+
sphi1 *= _sign; sphi2 *= _sign;
|
135
|
+
if (sphi1 > sphi2) {
|
136
|
+
swap(sphi1, sphi2); swap(cphi1, cphi2); // Make phi1 < phi2
|
137
|
+
}
|
138
|
+
real
|
139
|
+
tphi1 = sphi1/cphi1, tphi2 = sphi2/cphi2;
|
140
|
+
|
141
|
+
// q = (1-e^2)*(sphi/(1-e^2*sphi^2) - atanhee(sphi))
|
142
|
+
// qZ = q(pi/2) = (1 + (1-e^2)*atanhee(1))
|
143
|
+
// atanhee(x) = atanh(e*x)/e
|
144
|
+
// q = sxi * qZ
|
145
|
+
// dq/dphi = 2*(1-e^2)*cphi/(1-e^2*sphi^2)^2
|
146
|
+
//
|
147
|
+
// n = (m1^2-m2^2)/(q2-q1) -> sin(phi0) for phi1, phi2 -> phi0
|
148
|
+
// C = m1^2 + n*q1 = (m1^2*q2-m2^2*q1)/(q2-q1)
|
149
|
+
// let
|
150
|
+
// rho(pi/2)/rho(-pi/2) = (1-s)/(1+s)
|
151
|
+
// s = n*qZ/C
|
152
|
+
// = qZ * (m1^2-m2^2)/(m1^2*q2-m2^2*q1)
|
153
|
+
// = qZ * (scbet2^2 - scbet1^2)/(scbet2^2*q2 - scbet1^2*q1)
|
154
|
+
// = (scbet2^2 - scbet1^2)/(scbet2^2*sxi2 - scbet1^2*sxi1)
|
155
|
+
// = (tbet2^2 - tbet1^2)/(scbet2^2*sxi2 - scbet1^2*sxi1)
|
156
|
+
// 1-s = -((1-sxi2)*scbet2^2 - (1-sxi1)*scbet1^2)/
|
157
|
+
// (scbet2^2*sxi2 - scbet1^2*sxi1)
|
158
|
+
//
|
159
|
+
// Define phi0 to give same value of s, i.e.,
|
160
|
+
// s = sphi0 * qZ / (m0^2 + sphi0*q0)
|
161
|
+
// = sphi0 * scbet0^2 / (1/qZ + sphi0 * scbet0^2 * sxi0)
|
162
|
+
|
163
|
+
real tphi0, C;
|
164
|
+
if (polar || tphi1 == tphi2) {
|
165
|
+
tphi0 = tphi2;
|
166
|
+
C = 1; // ignored
|
167
|
+
} else {
|
168
|
+
real
|
169
|
+
tbet1 = _fm * tphi1, scbet12 = 1 + Math::sq(tbet1),
|
170
|
+
tbet2 = _fm * tphi2, scbet22 = 1 + Math::sq(tbet2),
|
171
|
+
txi1 = txif(tphi1), cxi1 = 1/hyp(txi1), sxi1 = txi1 * cxi1,
|
172
|
+
txi2 = txif(tphi2), cxi2 = 1/hyp(txi2), sxi2 = txi2 * cxi2,
|
173
|
+
dtbet2 = _fm * (tbet1 + tbet2),
|
174
|
+
es1 = 1 - _e2 * Math::sq(sphi1), es2 = 1 - _e2 * Math::sq(sphi2),
|
175
|
+
/*
|
176
|
+
dsxi = ( (_e2 * sq(sphi2 + sphi1) + es2 + es1) / (2 * es2 * es1) +
|
177
|
+
Datanhee(sphi2, sphi1) ) * Dsn(tphi2, tphi1, sphi2, sphi1) /
|
178
|
+
( 2 * _qx ),
|
179
|
+
*/
|
180
|
+
dsxi = ( (1 + _e2 * sphi1 * sphi2) / (es2 * es1) +
|
181
|
+
Datanhee(sphi2, sphi1) ) * Dsn(tphi2, tphi1, sphi2, sphi1) /
|
182
|
+
( 2 * _qx ),
|
183
|
+
den = (sxi2 + sxi1) * dtbet2 + (scbet22 + scbet12) * dsxi,
|
184
|
+
// s = (sq(tbet2) - sq(tbet1)) / (scbet22*sxi2 - scbet12*sxi1)
|
185
|
+
s = 2 * dtbet2 / den,
|
186
|
+
// 1-s = -(sq(scbet2)*(1-sxi2) - sq(scbet1)*(1-sxi1)) /
|
187
|
+
// (scbet22*sxi2 - scbet12*sxi1)
|
188
|
+
// Write
|
189
|
+
// sq(scbet)*(1-sxi) = sq(scbet)*(1-sphi) * (1-sxi)/(1-sphi)
|
190
|
+
sm1 = -Dsn(tphi2, tphi1, sphi2, sphi1) *
|
191
|
+
( -( ((sphi2 <= 0 ? (1 - sxi2) / (1 - sphi2) :
|
192
|
+
Math::sq(cxi2/cphi2) * (1 + sphi2) / (1 + sxi2)) +
|
193
|
+
(sphi1 <= 0 ? (1 - sxi1) / (1 - sphi1) :
|
194
|
+
Math::sq(cxi1/cphi1) * (1 + sphi1) / (1 + sxi1))) ) *
|
195
|
+
(1 + _e2 * (sphi1 + sphi2 + sphi1 * sphi2)) /
|
196
|
+
(1 + (sphi1 + sphi2 + sphi1 * sphi2)) +
|
197
|
+
(scbet22 * (sphi2 <= 0 ? 1 - sphi2 : Math::sq(cphi2) / ( 1 + sphi2)) +
|
198
|
+
scbet12 * (sphi1 <= 0 ? 1 - sphi1 : Math::sq(cphi1) / ( 1 + sphi1)))
|
199
|
+
* (_e2 * (1 + sphi1 + sphi2 + _e2 * sphi1 * sphi2)/(es1 * es2)
|
200
|
+
+_e2m * DDatanhee(sphi1, sphi2) ) / _qZ ) / den;
|
201
|
+
// C = (scbet22*sxi2 - scbet12*sxi1) / (scbet22 * scbet12 * (sx2 - sx1))
|
202
|
+
C = den / (2 * scbet12 * scbet22 * dsxi);
|
203
|
+
tphi0 = (tphi2 + tphi1)/2;
|
204
|
+
real stol = tol0_ * max(real(1), abs(tphi0));
|
205
|
+
for (int i = 0; i < 2*numit0_ || GEOGRAPHICLIB_PANIC; ++i) {
|
206
|
+
// Solve (scbet0^2 * sphi0) / (1/qZ + scbet0^2 * sphi0 * sxi0) = s
|
207
|
+
// for tphi0 by Newton's method on
|
208
|
+
// v(tphi0) = (scbet0^2 * sphi0) - s * (1/qZ + scbet0^2 * sphi0 * sxi0)
|
209
|
+
// = 0
|
210
|
+
// Alt:
|
211
|
+
// (scbet0^2 * sphi0) / (1/qZ - scbet0^2 * sphi0 * (1-sxi0)) = s / (1-s)
|
212
|
+
// w(tphi0) = (1-s) * (scbet0^2 * sphi0)
|
213
|
+
// - s * (1/qZ - scbet0^2 * sphi0 * (1-sxi0))
|
214
|
+
// = (1-s) * (scbet0^2 * sphi0)
|
215
|
+
// - S/qZ * (1 - scbet0^2 * sphi0 * (qZ-q0))
|
216
|
+
// Now
|
217
|
+
// qZ-q0 = (1+e2*sphi0)*(1-sphi0)/(1-e2*sphi0^2) +
|
218
|
+
// (1-e2)*atanhee((1-sphi0)/(1-e2*sphi0))
|
219
|
+
// In limit sphi0 -> 1, qZ-q0 -> 2*(1-sphi0)/(1-e2), so wrte
|
220
|
+
// qZ-q0 = 2*(1-sphi0)/(1-e2) + A + B
|
221
|
+
// A = (1-sphi0)*( (1+e2*sphi0)/(1-e2*sphi0^2) - (1+e2)/(1-e2) )
|
222
|
+
// = -e2 *(1-sphi0)^2 * (2+(1+e2)*sphi0) / ((1-e2)*(1-e2*sphi0^2))
|
223
|
+
// B = (1-e2)*atanhee((1-sphi0)/(1-e2*sphi0)) - (1-sphi0)
|
224
|
+
// = (1-sphi0)*(1-e2)/(1-e2*sphi0)*
|
225
|
+
// ((atanhee(x)/x-1) - e2*(1-sphi0)/(1-e2))
|
226
|
+
// x = (1-sphi0)/(1-e2*sphi0), atanhee(x)/x = atanh(e*x)/(e*x)
|
227
|
+
//
|
228
|
+
// 1 - scbet0^2 * sphi0 * (qZ-q0)
|
229
|
+
// = 1 - scbet0^2 * sphi0 * (2*(1-sphi0)/(1-e2) + A + B)
|
230
|
+
// = D - scbet0^2 * sphi0 * (A + B)
|
231
|
+
// D = 1 - scbet0^2 * sphi0 * 2*(1-sphi0)/(1-e2)
|
232
|
+
// = (1-sphi0)*(1-e2*(1+2*sphi0*(1+sphi0)))/((1-e2)*(1+sphi0))
|
233
|
+
// dD/dsphi0 = -2*(1-e2*sphi0^2*(2*sphi0+3))/((1-e2)*(1+sphi0)^2)
|
234
|
+
// d(A+B)/dsphi0 = 2*(1-sphi0^2)*e2*(2-e2*(1+sphi0^2))/
|
235
|
+
// ((1-e2)*(1-e2*sphi0^2)^2)
|
236
|
+
|
237
|
+
real
|
238
|
+
scphi02 = 1 + Math::sq(tphi0), scphi0 = sqrt(scphi02),
|
239
|
+
// sphi0m = 1-sin(phi0) = 1/( sec(phi0) * (tan(phi0) + sec(phi0)) )
|
240
|
+
sphi0 = tphi0 / scphi0, sphi0m = 1/(scphi0 * (tphi0 + scphi0)),
|
241
|
+
// scbet0^2 * sphi0
|
242
|
+
g = (1 + Math::sq( _fm * tphi0 )) * sphi0,
|
243
|
+
// dg/dsphi0 = dg/dtphi0 * scphi0^3
|
244
|
+
dg = _e2m * scphi02 * (1 + 2 * Math::sq(tphi0)) + _e2,
|
245
|
+
D = sphi0m * (1 - _e2*(1 + 2*sphi0*(1+sphi0))) / (_e2m * (1+sphi0)),
|
246
|
+
// dD/dsphi0
|
247
|
+
dD = -2 * (1 - _e2*Math::sq(sphi0) * (2*sphi0+3)) /
|
248
|
+
(_e2m * Math::sq(1+sphi0)),
|
249
|
+
A = -_e2 * Math::sq(sphi0m) * (2+(1+_e2)*sphi0) /
|
250
|
+
(_e2m*(1-_e2*Math::sq(sphi0))),
|
251
|
+
B = (sphi0m * _e2m / (1 - _e2*sphi0) *
|
252
|
+
(atanhxm1(_e2 *
|
253
|
+
Math::sq(sphi0m / (1-_e2*sphi0))) - _e2*sphi0m/_e2m)),
|
254
|
+
// d(A+B)/dsphi0
|
255
|
+
dAB = (2 * _e2 * (2 - _e2 * (1 + Math::sq(sphi0))) /
|
256
|
+
(_e2m * Math::sq(1 - _e2*Math::sq(sphi0)) * scphi02)),
|
257
|
+
u = sm1 * g - s/_qZ * ( D - g * (A + B) ),
|
258
|
+
// du/dsphi0
|
259
|
+
du = sm1 * dg - s/_qZ * (dD - dg * (A + B) - g * dAB),
|
260
|
+
dtu = -u/du * (scphi0 * scphi02);
|
261
|
+
tphi0 += dtu;
|
262
|
+
if (!(abs(dtu) >= stol))
|
263
|
+
break;
|
264
|
+
}
|
265
|
+
}
|
266
|
+
_txi0 = txif(tphi0); _scxi0 = hyp(_txi0); _sxi0 = _txi0 / _scxi0;
|
267
|
+
_n0 = tphi0/hyp(tphi0);
|
268
|
+
_m02 = 1 / (1 + Math::sq(_fm * tphi0));
|
269
|
+
_nrho0 = polar ? 0 : _a * sqrt(_m02);
|
270
|
+
_k0 = sqrt(tphi1 == tphi2 ? 1 : C / (_m02 + _n0 * _qZ * _sxi0)) * k1;
|
271
|
+
_k2 = Math::sq(_k0);
|
272
|
+
_lat0 = _sign * atan(tphi0)/Math::degree();
|
273
|
+
}
|
274
|
+
|
275
|
+
const AlbersEqualArea& AlbersEqualArea::CylindricalEqualArea() {
|
276
|
+
static const AlbersEqualArea
|
277
|
+
cylindricalequalarea(Constants::WGS84_a(), Constants::WGS84_f(),
|
278
|
+
real(0), real(1), real(0), real(1), real(1));
|
279
|
+
return cylindricalequalarea;
|
280
|
+
}
|
281
|
+
|
282
|
+
const AlbersEqualArea& AlbersEqualArea::AzimuthalEqualAreaNorth() {
|
283
|
+
static const AlbersEqualArea
|
284
|
+
azimuthalequalareanorth(Constants::WGS84_a(), Constants::WGS84_f(),
|
285
|
+
real(1), real(0), real(1), real(0), real(1));
|
286
|
+
return azimuthalequalareanorth;
|
287
|
+
}
|
288
|
+
|
289
|
+
const AlbersEqualArea& AlbersEqualArea::AzimuthalEqualAreaSouth() {
|
290
|
+
static const AlbersEqualArea
|
291
|
+
azimuthalequalareasouth(Constants::WGS84_a(), Constants::WGS84_f(),
|
292
|
+
real(-1), real(0), real(-1), real(0), real(1));
|
293
|
+
return azimuthalequalareasouth;
|
294
|
+
}
|
295
|
+
|
296
|
+
Math::real AlbersEqualArea::txif(real tphi) const {
|
297
|
+
// sxi = ( sphi/(1-e2*sphi^2) + atanhee(sphi) ) /
|
298
|
+
// ( 1/(1-e2) + atanhee(1) )
|
299
|
+
//
|
300
|
+
// txi = ( sphi/(1-e2*sphi^2) + atanhee(sphi) ) /
|
301
|
+
// sqrt( ( (1+e2*sphi)*(1-sphi)/( (1-e2*sphi^2) * (1-e2) ) +
|
302
|
+
// atanhee((1-sphi)/(1-e2*sphi)) ) *
|
303
|
+
// ( (1-e2*sphi)*(1+sphi)/( (1-e2*sphi^2) * (1-e2) ) +
|
304
|
+
// atanhee((1+sphi)/(1+e2*sphi)) ) )
|
305
|
+
//
|
306
|
+
// subst 1-sphi = cphi^2/(1+sphi)
|
307
|
+
int s = tphi < 0 ? -1 : 1; // Enforce odd parity
|
308
|
+
tphi *= s;
|
309
|
+
real
|
310
|
+
cphi2 = 1 / (1 + Math::sq(tphi)),
|
311
|
+
sphi = tphi * sqrt(cphi2),
|
312
|
+
es1 = _e2 * sphi,
|
313
|
+
es2m1 = 1 - es1 * sphi,
|
314
|
+
sp1 = 1 + sphi,
|
315
|
+
es1m1 = (1 - es1) * sp1,
|
316
|
+
es2m1a = _e2m * es2m1,
|
317
|
+
es1p1 = sp1 / (1 + es1);
|
318
|
+
return s * ( sphi / es2m1 + atanhee(sphi) ) /
|
319
|
+
sqrt( ( cphi2 / (es1p1 * es2m1a) + atanhee(cphi2 / es1m1) ) *
|
320
|
+
( es1m1 / es2m1a + atanhee(es1p1) ) );
|
321
|
+
}
|
322
|
+
|
323
|
+
Math::real AlbersEqualArea::tphif(real txi) const {
|
324
|
+
real
|
325
|
+
tphi = txi,
|
326
|
+
stol = tol_ * max(real(1), abs(txi));
|
327
|
+
// CHECK: min iterations = 1, max iterations = 2; mean = 1.99
|
328
|
+
for (int i = 0; i < numit_ || GEOGRAPHICLIB_PANIC; ++i) {
|
329
|
+
// dtxi/dtphi = (scxi/scphi)^3 * 2*(1-e^2)/(qZ*(1-e^2*sphi^2)^2)
|
330
|
+
real
|
331
|
+
txia = txif(tphi),
|
332
|
+
tphi2 = Math::sq(tphi),
|
333
|
+
scphi2 = 1 + tphi2,
|
334
|
+
scterm = scphi2/(1 + Math::sq(txia)),
|
335
|
+
dtphi = (txi - txia) * scterm * sqrt(scterm) *
|
336
|
+
_qx * Math::sq(1 - _e2 * tphi2 / scphi2);
|
337
|
+
tphi += dtphi;
|
338
|
+
if (!(abs(dtphi) >= stol))
|
339
|
+
break;
|
340
|
+
}
|
341
|
+
return tphi;
|
342
|
+
}
|
343
|
+
|
344
|
+
// return atanh(sqrt(x))/sqrt(x) - 1 = y/3 + y^2/5 + y^3/7 + ...
|
345
|
+
// typical x < e^2 = 2*f
|
346
|
+
Math::real AlbersEqualArea::atanhxm1(real x) {
|
347
|
+
real s = 0;
|
348
|
+
if (abs(x) < real(0.5)) {
|
349
|
+
real os = -1, y = 1, k = 1;
|
350
|
+
while (os != s) {
|
351
|
+
os = s;
|
352
|
+
y *= x; // y = x^n
|
353
|
+
k += 2; // k = 2*n + 1
|
354
|
+
s += y/k; // sum( x^n/(2*n + 1) )
|
355
|
+
}
|
356
|
+
} else {
|
357
|
+
real xs = sqrt(abs(x));
|
358
|
+
s = (x > 0 ? Math::atanh(xs) : atan(xs)) / xs - 1;
|
359
|
+
}
|
360
|
+
return s;
|
361
|
+
}
|
362
|
+
|
363
|
+
// return (Datanhee(1,y) - Datanhee(1,x))/(y-x)
|
364
|
+
Math::real AlbersEqualArea::DDatanhee(real x, real y) const {
|
365
|
+
real s = 0;
|
366
|
+
if (_e2 * (abs(x) + abs(y)) < real(0.5)) {
|
367
|
+
real os = -1, z = 1, k = 1, t = 0, c = 0, en = 1;
|
368
|
+
while (os != s) {
|
369
|
+
os = s;
|
370
|
+
t = y * t + z; c += t; z *= x;
|
371
|
+
t = y * t + z; c += t; z *= x;
|
372
|
+
k += 2; en *= _e2;
|
373
|
+
// Here en[l] = e2^l, k[l] = 2*l + 1,
|
374
|
+
// c[l] = sum( x^i * y^j; i >= 0, j >= 0, i+j < 2*l)
|
375
|
+
s += en * c / k;
|
376
|
+
}
|
377
|
+
// Taylor expansion is
|
378
|
+
// s = sum( c[l] * e2^l / (2*l + 1), l, 1, N)
|
379
|
+
} else
|
380
|
+
s = (Datanhee(1, y) - Datanhee(x, y))/(1 - x);
|
381
|
+
return s;
|
382
|
+
}
|
383
|
+
|
384
|
+
void AlbersEqualArea::Forward(real lon0, real lat, real lon,
|
385
|
+
real& x, real& y, real& gamma, real& k)
|
386
|
+
const {
|
387
|
+
lon = Math::AngDiff(lon0, lon);
|
388
|
+
lat *= _sign;
|
389
|
+
real sphi, cphi;
|
390
|
+
Math::sincosd(Math::LatFix(lat) * _sign, sphi, cphi);
|
391
|
+
cphi = max(epsx_, cphi);
|
392
|
+
real
|
393
|
+
lam = lon * Math::degree(),
|
394
|
+
tphi = sphi/cphi, txi = txif(tphi), sxi = txi/hyp(txi),
|
395
|
+
dq = _qZ * Dsn(txi, _txi0, sxi, _sxi0) * (txi - _txi0),
|
396
|
+
drho = - _a * dq / (sqrt(_m02 - _n0 * dq) + _nrho0 / _a),
|
397
|
+
theta = _k2 * _n0 * lam, stheta = sin(theta), ctheta = cos(theta),
|
398
|
+
t = _nrho0 + _n0 * drho;
|
399
|
+
x = t * (_n0 ? stheta / _n0 : _k2 * lam) / _k0;
|
400
|
+
y = (_nrho0 *
|
401
|
+
(_n0 ?
|
402
|
+
(ctheta < 0 ? 1 - ctheta : Math::sq(stheta)/(1 + ctheta)) / _n0 :
|
403
|
+
0)
|
404
|
+
- drho * ctheta) / _k0;
|
405
|
+
k = _k0 * (t ? t * hyp(_fm * tphi) / _a : 1);
|
406
|
+
y *= _sign;
|
407
|
+
gamma = _sign * theta / Math::degree();
|
408
|
+
}
|
409
|
+
|
410
|
+
void AlbersEqualArea::Reverse(real lon0, real x, real y,
|
411
|
+
real& lat, real& lon,
|
412
|
+
real& gamma, real& k)
|
413
|
+
const {
|
414
|
+
y *= _sign;
|
415
|
+
real
|
416
|
+
nx = _k0 * _n0 * x, ny = _k0 * _n0 * y, y1 = _nrho0 - ny,
|
417
|
+
den = Math::hypot(nx, y1) + _nrho0, // 0 implies origin with polar aspect
|
418
|
+
drho = den ? (_k0*x*nx - 2*_k0*y*_nrho0 + _k0*y*ny) / den : 0,
|
419
|
+
// dsxia = scxi0 * dsxi
|
420
|
+
dsxia = - _scxi0 * (2 * _nrho0 + _n0 * drho) * drho /
|
421
|
+
(Math::sq(_a) * _qZ),
|
422
|
+
txi = (_txi0 + dsxia) / sqrt(max(1 - dsxia * (2*_txi0 + dsxia), epsx2_)),
|
423
|
+
tphi = tphif(txi),
|
424
|
+
theta = atan2(nx, y1),
|
425
|
+
lam = _n0 ? theta / (_k2 * _n0) : x / (y1 * _k0);
|
426
|
+
gamma = _sign * theta / Math::degree();
|
427
|
+
lat = Math::atand(_sign * tphi);
|
428
|
+
lon = lam / Math::degree();
|
429
|
+
lon = Math::AngNormalize(lon + Math::AngNormalize(lon0));
|
430
|
+
k = _k0 * (den ? (_nrho0 + _n0 * drho) * hyp(_fm * tphi) / _a : 1);
|
431
|
+
}
|
432
|
+
|
433
|
+
void AlbersEqualArea::SetScale(real lat, real k) {
|
434
|
+
if (!(Math::isfinite(k) && k > 0))
|
435
|
+
throw GeographicErr("Scale is not positive");
|
436
|
+
if (!(abs(lat) < 90))
|
437
|
+
throw GeographicErr("Latitude for SetScale not in (-90d, 90d)");
|
438
|
+
real x, y, gamma, kold;
|
439
|
+
Forward(0, lat, 0, x, y, gamma, kold);
|
440
|
+
k /= kold;
|
441
|
+
_k0 *= k;
|
442
|
+
_k2 = Math::sq(_k0);
|
443
|
+
}
|
444
|
+
|
445
|
+
} // namespace GeographicLib
|