14# pragma warning (disable: 4127 5055)
22 : eps_(numeric_limits<real>::epsilon())
23 , epsx_(
Math::sq(eps_))
24 , epsx2_(
Math::sq(epsx_))
26 , tol0_(tol_ * sqrt(sqrt(eps_)))
33 , _qZ(1 + _e2m * atanhee(real(1)))
34 , _qx(_qZ / ( 2 * _e2m ))
36 if (!(isfinite(_a) && _a > 0))
38 if (!(isfinite(_f) && _f < 1))
40 if (!(isfinite(k0) && k0 > 0))
44 +
"d, " + to_string(
Math::qd) +
"d]");
47 Init(sphi, cphi, sphi, cphi, k0);
52 : eps_(numeric_limits<real>::epsilon())
53 , epsx_(
Math::sq(eps_))
54 , epsx2_(
Math::sq(epsx_))
56 , tol0_(tol_ * sqrt(sqrt(eps_)))
63 , _qZ(1 + _e2m * atanhee(real(1)))
64 , _qx(_qZ / ( 2 * _e2m ))
66 if (!(isfinite(_a) && _a > 0))
68 if (!(isfinite(_f) && _f < 1))
70 if (!(isfinite(k1) && k1 > 0))
80 real sphi1, cphi1, sphi2, cphi2;
83 Init(sphi1, cphi1, sphi2, cphi2, k1);
87 real sinlat1, real coslat1,
88 real sinlat2, real coslat2,
90 : eps_(numeric_limits<real>::epsilon())
91 , epsx_(
Math::sq(eps_))
92 , epsx2_(
Math::sq(epsx_))
94 , tol0_(tol_ * sqrt(sqrt(eps_)))
101 , _qZ(1 + _e2m * atanhee(real(1)))
102 , _qx(_qZ / ( 2 * _e2m ))
104 if (!(isfinite(_a) && _a > 0))
106 if (!(isfinite(_f) && _f < 1))
108 if (!(isfinite(k1) && k1 > 0))
110 if (signbit(coslat1))
114 if (signbit(coslat2))
118 if (!(fabs(sinlat1) <= 1 && coslat1 <= 1) || (coslat1 == 0 && sinlat1 == 0))
119 throw GeographicErr(
"Bad sine/cosine of standard latitude 1");
120 if (!(fabs(sinlat2) <= 1 && coslat2 <= 1) || (coslat2 == 0 && sinlat2 == 0))
121 throw GeographicErr(
"Bad sine/cosine of standard latitude 2");
122 if (coslat1 == 0 && coslat2 == 0 && sinlat1 * sinlat2 <= 0)
124 (
"Standard latitudes cannot be opposite poles");
125 Init(sinlat1, coslat1, sinlat2, coslat2, k1);
128 void AlbersEqualArea::Init(
real sphi1,
real cphi1,
132 r = hypot(sphi1, cphi1);
133 sphi1 /= r; cphi1 /= r;
134 r = hypot(sphi2, cphi2);
135 sphi2 /= r; cphi2 /= r;
137 bool polar = (cphi1 == 0);
138 cphi1 = fmax(epsx_, cphi1);
139 cphi2 = fmax(epsx_, cphi2);
141 _sign = sphi1 + sphi2 >= 0 ? 1 : -1;
143 sphi1 *= _sign; sphi2 *= _sign;
145 swap(sphi1, sphi2);
swap(cphi1, cphi2);
148 tphi1 = sphi1/cphi1, tphi2 = sphi2/cphi2;
173 if (polar || tphi1 == tphi2) {
178 tbet1 = _fm * tphi1, scbet12 = 1 +
Math::sq(tbet1),
179 tbet2 = _fm * tphi2, scbet22 = 1 +
Math::sq(tbet2),
180 txi1 = txif(tphi1), cxi1 = 1/hyp(txi1), sxi1 = txi1 * cxi1,
181 txi2 = txif(tphi2), cxi2 = 1/hyp(txi2), sxi2 = txi2 * cxi2,
182 dtbet2 = _fm * (tbet1 + tbet2),
189 dsxi = ( (1 + _e2 * sphi1 * sphi2) / (es2 * es1) +
190 Datanhee(sphi2, sphi1) ) * Dsn(tphi2, tphi1, sphi2, sphi1) /
192 den = (sxi2 + sxi1) * dtbet2 + (scbet22 + scbet12) * dsxi,
194 s = 2 * dtbet2 / den,
199 sm1 = -Dsn(tphi2, tphi1, sphi2, sphi1) *
200 ( -( ((sphi2 <= 0 ? (1 - sxi2) / (1 - sphi2) :
201 Math::sq(cxi2/cphi2) * (1 + sphi2) / (1 + sxi2)) +
202 (sphi1 <= 0 ? (1 - sxi1) / (1 - sphi1) :
203 Math::sq(cxi1/cphi1) * (1 + sphi1) / (1 + sxi1))) ) *
204 (1 + _e2 * (sphi1 + sphi2 + sphi1 * sphi2)) /
205 (1 + (sphi1 + sphi2 + sphi1 * sphi2)) +
206 (scbet22 * (sphi2 <= 0 ? 1 - sphi2 :
208 scbet12 * (sphi1 <= 0 ? 1 - sphi1 :
Math::sq(cphi1) / ( 1 + sphi1)))
209 * (_e2 * (1 + sphi1 + sphi2 + _e2 * sphi1 * sphi2)/(es1 * es2)
210 +_e2m * DDatanhee(sphi1, sphi2) ) / _qZ ) / den;
212 C = den / (2 * scbet12 * scbet22 * dsxi);
213 tphi0 = (tphi2 + tphi1)/2;
214 real stol = tol0_ * fmax(
real(1), fabs(tphi0));
249 scphi02 = 1 +
Math::sq(tphi0), scphi0 = sqrt(scphi02),
251 sphi0 = tphi0 / scphi0, sphi0m = 1/(scphi0 * (tphi0 + scphi0)),
253 g = (1 +
Math::sq( _fm * tphi0 )) * sphi0,
255 dg = _e2m * scphi02 * (1 + 2 *
Math::sq(tphi0)) + _e2,
256 D = sphi0m * (1 - _e2*(1 + 2*sphi0*(1+sphi0))) / (_e2m * (1+sphi0)),
258 dD = -2 * (1 - _e2*
Math::sq(sphi0) * (2*sphi0+3)) /
260 A = -_e2 *
Math::sq(sphi0m) * (2+(1+_e2)*sphi0) /
262 B = (sphi0m * _e2m / (1 - _e2*sphi0) *
264 Math::sq(sphi0m / (1-_e2*sphi0))) - _e2*sphi0m/_e2m)),
266 dAB = (2 * _e2 * (2 - _e2 * (1 +
Math::sq(sphi0))) /
268 u = sm1 * g - s/_qZ * ( D - g * (A + B) ),
270 du = sm1 * dg - s/_qZ * (dD - dg * (A + B) - g * dAB),
271 dtu = -u/du * (scphi0 * scphi02);
273 if (!(fabs(dtu) >= stol))
277 _txi0 = txif(tphi0); _scxi0 = hyp(_txi0); _sxi0 = _txi0 / _scxi0;
278 _n0 = tphi0/hyp(tphi0);
279 _m02 = 1 / (1 +
Math::sq(_fm * tphi0));
280 _nrho0 = polar ? 0 : _a * sqrt(_m02);
281 _k0 = sqrt(tphi1 == tphi2 ? 1 : C / (_m02 + _n0 * _qZ * _sxi0)) * k1;
289 real(0), real(1), real(0), real(1), real(1));
290 return cylindricalequalarea;
296 real(1), real(0), real(1), real(0), real(1));
297 return azimuthalequalareanorth;
303 real(-1), real(0), real(-1), real(0), real(1));
304 return azimuthalequalareasouth;
323 cphi = 1 / sqrt(1 +
Math::sq(tphi)),
326 es2m1 = 1 - es1 * sphi,
327 es2m1a = _e2m * es2m1;
328 return ( tphi / es2m1 + atanhee(sphi) / cphi ) /
329 sqrt( ( (1 + es1) / es2m1a + Datanhee(1, sphi) ) *
330 ( (1 - es1) / es2m1a + Datanhee(1, -sphi) ) );
336 stol = tol_ * fmax(
real(1), fabs(txi));
344 scterm = scphi2/(1 +
Math::sq(txia)),
345 dtphi = (txi - txia) * scterm * sqrt(scterm) *
346 _qx *
Math::sq(1 - _e2 * tphi2 / scphi2);
348 if (!(fabs(dtphi) >= stol))
358 if (fabs(x) <
real(0.5)) {
359 static const real lg2eps_ = -log2(numeric_limits<real>::epsilon() / 2);
368 int n = x == 0 ? 1 : int(ceil(lg2eps_ / e)) + 1;
372 real xs = sqrt(fabs(x));
373 s = (x > 0 ? atanh(xs) : atan(xs)) / xs - 1;
382 if (y < x)
swap(x, y);
384 q2 = fabs(2 * _e / _e2m * (1 - x));
386 x <= 0 || !(fmin(q1, q2) <
real(0.75)) ? DDatanhee0(x, y) :
387 (q1 < q2 ? DDatanhee1(x, y) : DDatanhee2(x, y));
393 return (Datanhee(1, y) - Datanhee(x, y))/(1 - x);
412 real z = 1, k = 1, t = 0, c = 0, en = 1;
414 t = y * t + z; c += t; z *= x;
415 t = y * t + z; c += t; z *= x;
421 real ds = en * c / k;
423 if (!(fabs(ds) > fabs(s) * eps_/2))
466 real s, dx = 1 - x, dy = 1 - y, xy = 1, yy = 1, ee = _e2 /
Math::sq(_e2m);
468 for (
int m = 1; ; ++m) {
469 real c = m + 2, t = c;
476 if (m % 2 == 0) ee *= _e2;
479 for (
int k = kmax - 1; k >= 0; --k) {
481 c *= (k + 1) * (2 * (k + m - 2*kmax) + 3);
482 c /= (kmax - k) * (2 * (kmax - k) + 1);
487 real ds = t * ee * xy / (m + 2);
489 if (!(fabs(ds) > fabs(s) * eps_/2))
496 real& x, real& y, real& gamma, real& k)
const {
501 cphi = fmax(epsx_, cphi);
504 tphi = sphi/cphi, txi = txif(tphi), sxi = txi/hyp(txi),
505 dq = _qZ * Dsn(txi, _txi0, sxi, _sxi0) * (txi - _txi0),
506 drho = - _a * dq / (sqrt(_m02 - _n0 * dq) + _nrho0 / _a),
507 theta = _k2 * _n0 * lam, stheta = sin(theta), ctheta = cos(theta),
508 t = _nrho0 + _n0 * drho;
509 x = t * (_n0 != 0 ? stheta / _n0 : _k2 * lam) / _k0;
512 (ctheta < 0 ? 1 - ctheta :
Math::sq(stheta)/(1 + ctheta)) / _n0 :
514 - drho * ctheta) / _k0;
515 k = _k0 * (t != 0 ? t * hyp(_fm * tphi) / _a : 1);
521 real& lat, real& lon,
522 real& gamma, real& k)
const {
525 nx = _k0 * _n0 * x, ny = _k0 * _n0 * y, y1 = _nrho0 - ny,
526 den = hypot(nx, y1) + _nrho0,
527 drho = den != 0 ? (_k0*x*nx - 2*_k0*y*_nrho0 + _k0*y*ny) / den : 0,
529 dsxia = - _scxi0 * (2 * _nrho0 + _n0 * drho) * drho /
531 txi = (_txi0 + dsxia) / sqrt(fmax(1 - dsxia * (2*_txi0 + dsxia), epsx2_)),
533 theta = atan2(nx, y1),
534 lam = _n0 != 0 ? theta / (_k2 * _n0) : x / (y1 * _k0);
539 k = _k0 * (den != 0 ? (_nrho0 + _n0 * drho) * hyp(_fm * tphi) / _a : 1);
543 if (!(isfinite(k) && k > 0))
549 real x, y, gamma, kold;
550 Forward(0, lat, 0, x, y, gamma, kold);
Header for GeographicLib::AlbersEqualArea class.
GeographicLib::Math::real real
#define GEOGRAPHICLIB_PANIC
Albers equal area conic projection.
void Reverse(real lon0, real x, real y, real &lat, real &lon, real &gamma, real &k) const
AlbersEqualArea(real a, real f, real stdlat, real k0)
void SetScale(real lat, real k=real(1))
static const AlbersEqualArea & CylindricalEqualArea()
static const AlbersEqualArea & AzimuthalEqualAreaNorth()
static const AlbersEqualArea & AzimuthalEqualAreaSouth()
void Forward(real lon0, real lat, real lon, real &x, real &y, real &gamma, real &k) const
Exception handling for GeographicLib.
Mathematical functions needed by GeographicLib.
static void sincosd(T x, T &sinx, T &cosx)
static T AngNormalize(T x)
static T AngDiff(T x, T y, T &e)
@ qd
degrees per quarter turn
Namespace for GeographicLib.
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)