1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 14:53:21 +02:00

Using the correct projection for Lambert azimuthal equal area

This commit is contained in:
Martin Tůma 2018-02-22 00:46:05 +01:00
parent 9c5153f89a
commit b054cf9046
2 changed files with 48 additions and 172 deletions

View File

@ -1,193 +1,74 @@
/*
* Based on libgeotrans with the following Source Code Disclaimer:
1. The GEOTRANS source code ("the software") is provided free of charge by
the National Imagery and Mapping Agency (NIMA) of the United States
Department of Defense. Although NIMA makes no copyright claim under Title 17
U.S.C., NIMA claims copyrights in the source code under other legal regimes.
NIMA hereby grants to each user of the software a license to use and
distribute the software, and develop derivative works.
2. Warranty Disclaimer: The software was developed to meet only the internal
requirements of the U.S. National Imagery and Mapping Agency. The software
is provided "as is," and no warranty, express or implied, including but not
limited to the implied warranties of merchantability and fitness for
particular purpose or arising by statute or otherwise in law or from a
course of dealing or usage in trade, is made by NIMA as to the accuracy and
functioning of the software.
3. NIMA and its personnel are not required to provide technical support or
general assistance with respect to the software.
4. Neither NIMA nor its personnel will be liable for any claims, losses, or
damages arising from or connected with the use of the software. The user
agrees to hold harmless the United States National Imagery and Mapping
Agency. The user's sole and exclusive remedy is to stop using the software.
5. NIMA requests that products developed using the software credit the
source of the software with the following statement, "The product was
developed using GEOTRANS, a product of the National Imagery and Mapping
Agency and U.S. Army Engineering Research and Development Center."
6. For any products developed using the software, NIMA requires a disclaimer
that use of the software does not indicate endorsement or approval of the
product by the Secretary of Defense or the National Imagery and Mapping
Agency. Pursuant to the United States Code, 10 U.S.C. Sec. 2797, the name of
the National Imagery and Mapping Agency, the initials "NIMA", the seal of
the National Imagery and Mapping Agency, or any colorable imitation thereof
shall not be used to imply approval, endorsement, or authorization of a
product without prior written permission from United States Secretary of
Defense.
*/
#include "lambertazimuthal.h"
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
#define sin2(x) (sin(x) * sin(x))
#define sqr(x) ((x) * (x))
LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
double latitudeOrigin, double longitudeOrigin, double falseEasting,
double falseNorthing)
{
double es2, es4, es6;
double lat0 = deg2rad(latitudeOrigin);
es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
es4 = es2 * es2;
es6 = es4 * es2;
_ra = ellipsoid->radius() * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0
* es6 / 3024.0);
_latOrigin = deg2rad(latitudeOrigin);
_sinLatOrigin = sin(_latOrigin);
_cosLatOrigin = cos(_latOrigin);
_absLatOrigin = fabs(_latOrigin);
_lonOrigin = deg2rad(longitudeOrigin);
if (_lonOrigin > M_PI)
_lonOrigin -= 2.0 * M_PI;
_falseNorthing = falseNorthing;
_falseEasting = falseEasting;
_falseNorthing = falseNorthing;
_lon0 = deg2rad(longitudeOrigin);
_a = ellipsoid->radius();
_es2 = 2.0 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = sqrt(_es2);
double q0 = (1.0 - _es2) * ((sin(lat0) / (1.0 - _es2 * sin2(lat0)))
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat0)) / (1.0 + _es
* sin(lat0)))));
_qP = (1.0 - _es2) * ((1.0 / (1.0 - _es2)) - ((1.0/(2.0*_es))
* log((1.0 - _es) / (1.0 + _es))));
_beta0 = asin(q0 / _qP);
_Rq = _a * sqrt(_qP / 2.0);
_D = _a * (cos(lat0) / sqrt(1.0 - _es2 * sin2(lat0))) / (_Rq * cos(_beta0));
}
QPointF LambertAzimuthal::ll2xy(const Coordinates &c) const
{
double dlam;
double k_prime;
double cd;
double rlat = deg2rad(c.lat());
double slat = sin(rlat);
double clat = cos(rlat);
double cos_c;
double sin_dlam, cos_dlam;
double Ra_kprime;
double Ra_PI_OVER_2_Lat;
QPointF p;
double lon = deg2rad(c.lon());
double lat = deg2rad(c.lat());
double q = (1.0 - _es2) * ((sin(lat) / (1.0 - _es2 * sin2(lat)))
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat)) / (1.0 + _es
* sin(lat)))));
double beta = asin(q / _qP);
double B = _Rq * sqrt(2.0 / (1.0 + sin(_beta0) * sin(beta) + (cos(_beta0)
* cos(beta) * cos(lon - _lon0))));
dlam = deg2rad(c.lon()) - _lonOrigin;
if (dlam > M_PI)
dlam -= 2.0 * M_PI;
if (dlam < -M_PI)
dlam += 2.0 * M_PI;
double x = _falseEasting + ((B * _D) * (cos(beta) * sin(lon - _lon0)));
double y = _falseNorthing + (B / _D) * ((cos(_beta0) * sin(beta))
- (sin(_beta0) * cos(beta) * cos(lon - _lon0)));
sin_dlam = sin(dlam);
cos_dlam = cos(dlam);
if (fabs(_absLatOrigin - M_PI_2) < 1.0e-10) {
if (_latOrigin >= 0.0) {
Ra_PI_OVER_2_Lat = _ra * (M_PI_2 - rlat);
p.rx() = Ra_PI_OVER_2_Lat * sin_dlam + _falseEasting;
p.ry() = -1.0 * (Ra_PI_OVER_2_Lat * cos_dlam) + _falseNorthing;
} else {
Ra_PI_OVER_2_Lat = _ra * (M_PI_2 + rlat);
p.rx() = Ra_PI_OVER_2_Lat * sin_dlam + _falseEasting;
p.ry() = Ra_PI_OVER_2_Lat * cos_dlam + _falseNorthing;
}
} else if (_absLatOrigin <= 1.0e-10) {
cos_c = clat * cos_dlam;
if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) {
if (cos_c >= 0.0) {
p.rx() = _falseEasting;
p.ry() = _falseNorthing;
} else
return QPointF(NAN, NAN);
} else {
cd = acos(cos_c);
k_prime = cd / sin(cd);
Ra_kprime = _ra * k_prime;
p.rx() = Ra_kprime * clat * sin_dlam + _falseEasting;
p.ry() = Ra_kprime * slat + _falseNorthing;
}
} else {
cos_c = (_sinLatOrigin * slat) + (_cosLatOrigin * clat * cos_dlam);
if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) {
if (cos_c >= 0.0) {
p.rx() = _falseEasting;
p.ry() = _falseNorthing;
} else
return QPointF(NAN, NAN);
} else {
cd = acos(cos_c);
k_prime = cd / sin(cd);
Ra_kprime = _ra * k_prime;
p.rx() = Ra_kprime * clat * sin_dlam + _falseEasting;
p.ry() = Ra_kprime * (_cosLatOrigin * slat - _sinLatOrigin * clat
* cos_dlam) + _falseNorthing;
}
}
return p;
return QPointF(x, y);
}
Coordinates LambertAzimuthal::xy2ll(const QPointF &p) const
{
double dx, dy;
double rho;
double cd;
double sin_c, cos_c, dy_sinc;
double lat, lon;
double e4 = _es2 * _es2;
double e6 = _es2 * e4;
double rho = sqrt(sqr((p.x() - _falseEasting) / _D) + sqr(_D * (p.y()
- _falseNorthing)));
double C = 2.0 * asin(rho / (2.0*_Rq));
double betaS = asin((cos(C) * sin(_beta0)) + ((_D * (p.y() -_falseNorthing)
* sin(C) * cos(_beta0)) / rho));
dy = p.y() - _falseNorthing;
dx = p.x() - _falseEasting;
rho = sqrt(dx * dx + dy * dy);
if (fabs(rho) <= 1.0e-10) {
lat = _latOrigin;
lon = _lonOrigin;
} else {
cd = rho / _ra;
sin_c = sin(cd);
cos_c = cos(cd);
dy_sinc = dy * sin_c;
lat = asin((cos_c * _sinLatOrigin) + ((dy_sinc * _cosLatOrigin) / rho));
if (fabs(_absLatOrigin - M_PI_2) < 1.0e-10) {
if (_latOrigin >= 0.0)
lon = _lonOrigin + atan2(dx, -dy);
else
lon = _lonOrigin + atan2(dx, dy);
}
else
lon = _lonOrigin + atan2((dx * sin_c), ((rho * _cosLatOrigin
* cos_c) - (dy_sinc * _sinLatOrigin)));
}
if (lat > M_PI_2)
lat = M_PI_2;
else if (lat < -M_PI_2)
lat = -M_PI_2;
if (lon > M_PI)
lon -= 2.0 * M_PI;
if (lon < -M_PI)
lon += 2.0 * M_PI;
if (lon > M_PI)
lon = M_PI;
else if (lon < -M_PI)
lon = -M_PI;
double lon = _lon0 + atan((p.x() - _falseEasting) * sin(C) / (_D * rho
* cos(_beta0) * cos(C) - sqr(_D) * (p.y() - _falseNorthing) * sin(_beta0)
* sin(C)));
double lat = betaS + ((_es2/3.0 + 31.0*e4/180.0 + 517.0*e6/5040.0)
* sin(2.0*betaS)) + ((23.0*e4/360.0 + 251.0*e6/3780.0) * sin(4.0*betaS))
+ ((761.0*e6/45360.0)*sin(6.0*betaS));
return Coordinates(rad2deg(lon), rad2deg(lat));
}

View File

@ -16,15 +16,10 @@ public:
virtual Coordinates xy2ll(const QPointF &p) const;
private:
double _ra;
double _sinLatOrigin;
double _cosLatOrigin;
double _absLatOrigin;
double _latOrigin;
double _lonOrigin;
double _lon0;
double _falseNorthing;
double _falseEasting;
double _a, _es, _es2, _qP, _beta0, _Rq, _D;
};
#endif // LAMBERTAZIMUTHAL_H