2017-11-26 18:54:03 +01:00
|
|
|
#include "common/wgs84.h"
|
2017-04-17 18:03:04 +02:00
|
|
|
#include "datum.h"
|
|
|
|
|
2018-05-11 19:54:12 +02:00
|
|
|
|
2018-05-11 20:06:16 +02:00
|
|
|
#define as2rad(x) ((x) * (M_PI/648000.0))
|
|
|
|
#define rad2as(x) ((x) * (648000.0/M_PI))
|
2018-05-19 22:36:11 +02:00
|
|
|
#define ds2scale(x) (1.0 + (x) * 1e-6)
|
|
|
|
#define scale2ds(x) (((x) - 1.0) / 1e-6)
|
2018-05-11 19:54:12 +02:00
|
|
|
|
2018-01-08 23:47:45 +01:00
|
|
|
static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
|
|
|
const Datum &to)
|
2017-04-17 18:03:04 +02:00
|
|
|
{
|
2018-01-08 23:47:45 +01:00
|
|
|
double rlat = deg2rad(c.lat());
|
|
|
|
double rlon = deg2rad(c.lon());
|
|
|
|
|
|
|
|
double slat = sin(rlat);
|
|
|
|
double clat = cos(rlat);
|
|
|
|
double slon = sin(rlon);
|
|
|
|
double clon = cos(rlon);
|
|
|
|
double ssqlat = slat * slat;
|
|
|
|
|
|
|
|
double dx = from.dx() - to.dx();
|
|
|
|
double dy = from.dy() - to.dy();
|
|
|
|
double dz = from.dz() - to.dz();
|
|
|
|
|
2018-01-20 20:13:56 +01:00
|
|
|
double from_f = from.ellipsoid()->flattening();
|
|
|
|
double to_f = to.ellipsoid()->flattening();
|
2018-01-08 23:47:45 +01:00
|
|
|
double df = to_f - from_f;
|
2018-01-20 20:13:56 +01:00
|
|
|
double from_a = from.ellipsoid()->radius();
|
|
|
|
double to_a = to.ellipsoid()->radius();
|
2018-01-08 23:47:45 +01:00
|
|
|
double da = to_a - from_a;
|
|
|
|
double from_esq = from_f * (2.0 - from_f);
|
|
|
|
double adb = 1.0 / (1.0 - from_f);
|
|
|
|
double rn = from_a / sqrt(1 - from_esq * ssqlat);
|
|
|
|
double rm = from_a * (1 - from_esq) / pow((1 - from_esq * ssqlat), 1.5);
|
|
|
|
|
|
|
|
double dlat = (-dx * slat * clon - dy * slat * slon + dz * clat + da
|
|
|
|
* rn * from_esq * slat * clat / from_a + df * (rm * adb + rn / adb) * slat
|
2018-05-18 22:22:36 +02:00
|
|
|
* clat) / rm;
|
2018-01-08 23:47:45 +01:00
|
|
|
|
2018-05-18 22:22:36 +02:00
|
|
|
double dlon = (-dx * slon + dy * clon) / (rn * clat);
|
2018-01-08 23:47:45 +01:00
|
|
|
|
|
|
|
return Coordinates(c.lon() + rad2deg(dlon), c.lat() + rad2deg(dlat));
|
2017-04-17 18:03:04 +02:00
|
|
|
}
|
|
|
|
|
2018-07-26 23:51:11 +02:00
|
|
|
const Datum &Datum::WGS84()
|
|
|
|
{
|
|
|
|
static Datum d(&Ellipsoid::WGS84(), 0.0, 0.0, 0.0);
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2018-05-11 19:54:12 +02:00
|
|
|
Point3D Datum::helmert(const Point3D &p) const
|
|
|
|
{
|
2018-05-19 22:36:11 +02:00
|
|
|
return Point3D(_scale * (p.x() + _rz * p.y() -_ry * p.z()) + _dx,
|
|
|
|
_scale * (-_rz * p.x() + p.y() + _rx * p.z()) + _dy,
|
|
|
|
_scale * (_ry * p.x() -_rx * p.y() + p.z()) + _dz);
|
2018-05-11 19:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Point3D Datum::helmertr(const Point3D &p) const
|
|
|
|
{
|
2018-05-19 20:55:43 +02:00
|
|
|
double x = (p.x() - _dx) / _scale;
|
|
|
|
double y = (p.y() - _dy) / _scale;
|
|
|
|
double z = (p.z() - _dz) / _scale;
|
2018-05-11 19:54:12 +02:00
|
|
|
|
2018-05-19 22:36:11 +02:00
|
|
|
return Point3D(x -_rz * y + _ry * z, _rz * x + y + -_rx * z, -_ry * x + _rx
|
|
|
|
* y + z);
|
2018-05-11 19:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
|
|
|
|
double rx, double ry, double rz, double ds)
|
|
|
|
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(as2rad(rx)),
|
2018-05-19 22:36:11 +02:00
|
|
|
_ry(as2rad(ry)), _rz(as2rad(rz)), _scale(ds2scale(ds))
|
2018-05-11 19:54:12 +02:00
|
|
|
{
|
|
|
|
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
|
|
|
|
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0
|
2018-05-19 20:55:43 +02:00
|
|
|
&& _rx == 0.0 && _ry == 0.0 && _rz == 0.0 && ds == 0.0)
|
2018-05-12 13:13:35 +02:00
|
|
|
_transformation = None;
|
2018-05-11 19:54:12 +02:00
|
|
|
else
|
2018-05-12 13:13:35 +02:00
|
|
|
_transformation = Helmert;
|
2018-05-11 19:54:12 +02:00
|
|
|
}
|
|
|
|
|
2018-02-12 01:20:21 +01:00
|
|
|
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz)
|
2018-05-11 19:54:12 +02:00
|
|
|
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(0.0), _ry(0.0),
|
2018-05-19 20:55:43 +02:00
|
|
|
_rz(0.0), _scale(1.0)
|
2018-01-08 23:47:45 +01:00
|
|
|
{
|
2018-05-11 19:54:12 +02:00
|
|
|
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
|
|
|
|
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0)
|
2018-05-12 13:13:35 +02:00
|
|
|
_transformation = None;
|
2018-05-11 19:54:12 +02:00
|
|
|
else
|
2018-05-12 13:13:35 +02:00
|
|
|
_transformation = Molodensky;
|
2017-04-17 18:03:04 +02:00
|
|
|
}
|
2017-06-29 19:53:42 +02:00
|
|
|
|
|
|
|
Coordinates Datum::toWGS84(const Coordinates &c) const
|
|
|
|
{
|
2018-05-12 13:13:35 +02:00
|
|
|
switch (_transformation) {
|
2018-05-11 19:54:12 +02:00
|
|
|
case Helmert:
|
|
|
|
return Geocentric::toGeodetic(helmert(Geocentric::fromGeodetic(c,
|
2018-07-26 23:51:11 +02:00
|
|
|
ellipsoid())), WGS84().ellipsoid());
|
2018-05-11 19:54:12 +02:00
|
|
|
case Molodensky:
|
2018-07-26 23:51:11 +02:00
|
|
|
return molodensky(c, *this, WGS84());
|
2018-05-11 19:54:12 +02:00
|
|
|
default:
|
|
|
|
return c;
|
|
|
|
}
|
2018-01-08 23:47:45 +01:00
|
|
|
}
|
2017-06-29 19:53:42 +02:00
|
|
|
|
2018-01-08 23:47:45 +01:00
|
|
|
Coordinates Datum::fromWGS84(const Coordinates &c) const
|
|
|
|
{
|
2018-05-12 13:13:35 +02:00
|
|
|
switch (_transformation) {
|
2018-05-11 19:54:12 +02:00
|
|
|
case Helmert:
|
|
|
|
return Geocentric::toGeodetic(helmertr(Geocentric::fromGeodetic(c,
|
2018-07-26 23:51:11 +02:00
|
|
|
WGS84().ellipsoid())), ellipsoid());
|
2018-05-11 19:54:12 +02:00
|
|
|
case Molodensky:
|
2018-07-26 23:51:11 +02:00
|
|
|
return molodensky(c, WGS84(), *this);
|
2018-05-11 19:54:12 +02:00
|
|
|
default:
|
|
|
|
return c;
|
|
|
|
}
|
2018-01-08 23:47:45 +01:00
|
|
|
}
|
2017-06-29 19:53:42 +02:00
|
|
|
|
2018-02-13 23:03:18 +01:00
|
|
|
#ifndef QT_NO_DEBUG
|
2018-01-08 23:47:45 +01:00
|
|
|
QDebug operator<<(QDebug dbg, const Datum &datum)
|
|
|
|
{
|
2018-01-21 11:19:46 +01:00
|
|
|
dbg.nospace() << "Datum(" << *datum.ellipsoid() << ", " << datum.dx()
|
2018-05-11 19:54:12 +02:00
|
|
|
<< ", " << datum.dy() << ", " << datum.dz() << ", " << rad2as(datum.rx())
|
|
|
|
<< ", " << rad2as(datum.ry()) << ", " << rad2as(datum.rz()) << ", "
|
2018-05-19 22:36:11 +02:00
|
|
|
<< scale2ds(datum.scale()) << ")";
|
2018-01-21 11:19:46 +01:00
|
|
|
return dbg.space();
|
2017-06-29 19:53:42 +02:00
|
|
|
}
|
2018-02-13 23:03:18 +01:00
|
|
|
#endif // QT_NO_DEBUG
|