#include #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::_gcss = defaults(); const GCS &GCS::WGS84() { static GCS g(Datum::WGS84(), 8901, 9122); return g; } QList GCS::defaults() { QList list; list.append(GCS::Entry(4326, 6326, "WGS 84", WGS84())); list.append(GCS::Entry(4326, 6326, "WGS84", WGS84())); return list; } const GCS &GCS::gcs(int id) { static const GCS null; for (int i = 0; i < _gcss.size(); i++) if (_gcss.at(i).id() == id) return _gcss.at(i).gcs(); return null; } const GCS &GCS::gcs(int geodeticDatum, int primeMeridian, int angularUnits) { static const GCS null; 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 null; } const GCS &GCS::gcs(const QString &name) { static const GCS null; for (int i = 0; i < _gcss.size(); i++) if (_gcss.at(i).name() == name) return _gcss.at(i).gcs(); return null; } 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 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 > GCS::list() { QList > list; for (int i = 0; i < _gcss.size(); i++) if (_gcss.at(i).id()) list.append(KV(_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