Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "GeographicLib/PolarStereographic.hpp"
00010 #include "GeographicLib/Constants.hpp"
00011 #include <limits>
00012
00013 namespace {
00014 char RCSID[] = "$Id: PolarStereographic.cpp 6568 2009-03-01 17:58:41Z ckarney $";
00015 char RCSID_H[] = POLARSTEREOGRAPHIC_HPP;
00016 }
00017
00018 namespace GeographicLib {
00019
00020 using namespace std;
00021
00022 PolarStereographic::PolarStereographic(double a, double invf, double k0)
00023 throw()
00024 : _a(a)
00025 , _f(invf > 0 ? 1 / invf : 0)
00026 , _k0(k0)
00027 , _e(sqrt(_f * (2 - _f)))
00028 , _e2m(1 - sq(_e))
00029 , _c(sqrt( pow(1 + _e, 1 + _e) * pow(1 - _e, 1 - _e) ))
00030 , _tol(0.1*sqrt(numeric_limits<double>::epsilon()))
00031 , _numit(5)
00032 {}
00033
00034 const PolarStereographic
00035 PolarStereographic::UPS(Constants::WGS84_a(), Constants::WGS84_invf(),
00036 Constants::UPS_k0());
00037
00038 void PolarStereographic::Forward(bool northp, double lat, double lon,
00039 double& x, double& y,
00040 double& gamma, double& k) const throw() {
00041 double theta = 90 - (northp ? lat : -lat);
00042 double rho;
00043 theta *= Constants::degree();
00044 double
00045 ecos = _e * cos(theta),
00046 f = pow((1 + ecos)/(1 - ecos), _e/2),
00047 t2 = 2 * tan(theta/2) * f,
00048 m = sin(theta) / sqrt(1 - sq(ecos));
00049 rho = _a * _k0 * t2 / _c;
00050 k = m < numeric_limits<double>::epsilon() ? _k0 : rho / (_a * m);
00051 double
00052 lam = lon * Constants::degree();
00053 x = rho * sin(lam);
00054 y = (northp ? -rho : rho) * cos(lam);
00055 gamma = northp ? lon : -lon;
00056 }
00057
00058 void PolarStereographic::Reverse(bool northp, double x, double y,
00059 double& lat, double& lon,
00060 double& gamma, double& k) const throw() {
00061 double
00062 rho = hypot(x, y),
00063 t2 = rho * _c / (_a * _k0),
00064 theta = Constants::pi()/2,
00065 ecos = _e * cos(theta);
00066
00067
00068
00069
00070 for (int i = 0; i < _numit; ++i) {
00071 double
00072 f = pow((1 + ecos)/(1 - ecos), _e/2),
00073 c2 = cos(theta/2),
00074 v = 2 * tan(theta/2) * f - t2,
00075 dv = _e2m * f / ((1 - sq(ecos)) * sq(c2)),
00076 dtheta = -v/dv;
00077 theta += dtheta;
00078 ecos = _e * cos(theta);
00079 if (abs(dtheta) < _tol)
00080 break;
00081 }
00082 lat = (northp ? 1 : -1) * (90 - theta / Constants::degree());
00083
00084 lon = -atan2( -x, northp ? -y : y ) / Constants::degree();
00085 double m = sin(theta) / sqrt(1 - sq(ecos));
00086 k = m == 0 ? _k0 : rho / (_a * m);
00087 gamma = northp ? lon : -lon;
00088 }
00089
00090 }