1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-28 05:34:47 +01:00
GPXSee/src/map/gcs.cpp

253 lines
5.5 KiB
C++

#include <QFile>
#include "common/wgs84.h"
#include "gcs.h"
class GCS::Entry {
public:
Entry(int id, int gd, const QString &name, const GCS &gcs)
: _id(id), _gd(gd), _name(name), _gcs(gcs) {}
int id() const {return _id;}
int gd() const {return _gd;}
const QString &name() const {return _name;}
const GCS &gcs() const {return _gcs;}
private:
int _id, _gd;
QString _name;
GCS _gcs;
};
static int parameter(const QString &str, bool *res)
{
QString field = str.trimmed();
if (field.isEmpty()) {
*res = true;
return 0;
}
return field.toInt(res);
}
static double parameterd(const QString &str, bool *res)
{
QString field = str.trimmed();
if (field.isEmpty()) {
*res = true;
return NAN;
}
return field.toDouble(res);
}
QList<GCS::Entry> GCS::_gcss = defaults();
const GCS &GCS::WGS84()
{
static GCS g(Datum::WGS84(), 8901, 9122);
return g;
}
QList<GCS::Entry> GCS::defaults()
{
QList<GCS::Entry> list;
list.append(GCS::Entry(4326, 6326, "WGS 84", WGS84()));
list.append(GCS::Entry(4326, 6326, "WGS84", WGS84()));
return list;
}
GCS GCS::gcs(int id)
{
for (int i = 0; i < _gcss.size(); i++)
if (_gcss.at(i).id() == id)
return _gcss.at(i).gcs();
return GCS();
}
GCS GCS::gcs(int geodeticDatum, int primeMeridian, int angularUnits)
{
for (int i = 0; i < _gcss.size(); i++) {
const Entry &e = _gcss.at(i);
if (e.gd() == geodeticDatum && e.gcs().primeMeridian() == primeMeridian
&& e.gcs().angularUnits() == angularUnits)
return e.gcs();
}
return GCS();
}
GCS GCS::gcs(const QString &name)
{
for (int i = 0; i < _gcss.size(); i++)
if (_gcss.at(i).name() == name)
return _gcss.at(i).gcs();
return GCS();
}
void GCS::loadList(const QString &path)
{
QFile file(path);
bool res;
int ln = 0;
if (!file.open(QFile::ReadOnly)) {
qWarning("Error opening PCS file: %s: %s", qPrintable(path),
qPrintable(file.errorString()));
return;
}
while (!file.atEnd()) {
ln++;
QByteArray line = file.readLine();
QList<QByteArray> list = line.split(',');
if (list.size() != 14) {
qWarning("%s:%d: Format error", qPrintable(path), ln);
continue;
}
int id = parameter(list[1], &res);
if (!res) {
qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln);
continue;
}
int gd = parameter(list[2], &res);
if (!res) {
qWarning("%s:%d: Invalid geodetic datum code", qPrintable(path),
ln);
continue;
}
int au = list[3].trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid angular units code", qPrintable(path),
ln);
continue;
}
int el = list[4].trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid ellipsoid code", qPrintable(path), ln);
continue;
}
int pm = list[5].trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid prime meridian code", qPrintable(path),
ln);
continue;
}
int ct = list[6].trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid coordinates transformation code",
qPrintable(path), ln);
continue;
}
double dx = list[7].trimmed().toDouble(&res);
if (!res) {
qWarning("%s:%d: Invalid dx", qPrintable(path), ln);
continue;
}
double dy = list[8].trimmed().toDouble(&res);
if (!res) {
qWarning("%s:%d: Invalid dy", qPrintable(path), ln);
continue;
}
double dz = list[9].trimmed().toDouble(&res);
if (!res) {
qWarning("%s:%d: Invalid dz", qPrintable(path), ln);
continue;
}
double rx = parameterd(list[10], &res);
if (!res) {
qWarning("%s:%d: Invalid rx", qPrintable(path), ln);
continue;
}
double ry = parameterd(list[11], &res);
if (!res) {
qWarning("%s:%d: Invalid ry", qPrintable(path), ln);
continue;
}
double rz = parameterd(list[12], &res);
if (!res) {
qWarning("%s:%d: Invalid rz", qPrintable(path), ln);
continue;
}
double ds = parameterd(list[13], &res);
if (!res) {
qWarning("%s:%d: Invalid ds", qPrintable(path), ln);
continue;
}
const Ellipsoid &e = Ellipsoid::ellipsoid(el);
if (e.isNull()) {
qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln);
continue;
}
Datum datum;
switch (ct) {
case 9603:
datum = Datum(e, dx, dy, dz);
break;
case 9606:
datum = Datum(e, dx, dy, dz, -rx, -ry, -rz, ds);
break;
case 9607:
datum = Datum(e, dx, dy, dz, rx, ry, rz, ds);
break;
default:
qWarning("%s:%d: Unknown coordinates transformation method",
qPrintable(path), ln);
continue;
}
if (!datum.isValid()) {
qWarning("%s:%d: Invalid coordinates transformation parameters",
qPrintable(path), ln);
continue;
}
GCS gcs(datum, pm, au);
if (gcs.isValid())
_gcss.append(Entry(id, gd, list[0].trimmed(), gcs));
else
qWarning("%s:%d: Unknown prime meridian/angular units code",
qPrintable(path), ln);
}
}
Coordinates GCS::toWGS84(const Coordinates &c) const
{
return datum().toWGS84(Coordinates(_primeMeridian.toGreenwich(c.lon()),
c.lat()));
}
Coordinates GCS::fromWGS84(const Coordinates &c) const
{
Coordinates ds(datum().fromWGS84(c));
return Coordinates(_primeMeridian.fromGreenwich(ds.lon()), ds.lat());
}
QList<KV<int, QString> > GCS::list()
{
QList<KV<int, QString> > list;
for (int i = 0; i < _gcss.size(); i++)
if (_gcss.at(i).id())
list.append(KV<int, QString>(_gcss.at(i).id(), _gcss.at(i).name()
+ " / Geographic 2D"));
return list;
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const GCS &gcs)
{
dbg.nospace() << "GCS(" << gcs.datum() << ", " << gcs.primeMeridian()
<< ", " << gcs.angularUnits() << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG