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
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
|