#include #include "angularunits.h" #include "pcs.h" class PCS::Entry { public: Entry(const QString &name, int id, int proj, const PCS &pcs) : _name(name), _id(id), _proj(proj), _pcs(pcs) {} const QString &name() const {return _name;} int id() const {return _id;} int proj() const {return _proj;} const PCS &pcs() const {return _pcs;} private: QString _name; int _id, _proj; PCS _pcs; }; QList PCS::_pcss = defaults(); QList PCS::defaults() { QList list; list.append(PCS::Entry("WGS 84 / Pseudo-Mercator", 3857, 3856, PCS(GCS::WGS84(), 1024, Projection::Setup(0, 0, NAN, 0, 0, NAN, NAN), 9001, 4499))); return list; } static bool parameter(int key, double val, int units, Projection::Setup &setup) { switch (key) { case 8801: case 8811: case 8821: case 8832: {AngularUnits au(units); if (au.isNull()) return false; setup.setLatitudeOrigin(au.toDegrees(val));} return true; case 8802: case 8812: case 8822: case 8833: {AngularUnits au(units); if (au.isNull()) return false; setup.setLongitudeOrigin(au.toDegrees(val));} return true; case 8805: case 8815: case 8819: setup.setScale(val); return true; case 8806: case 8816: case 8826: {LinearUnits lu(units); if (lu.isNull()) return false; setup.setFalseEasting(lu.toMeters(val));} return true; case 8807: case 8817: case 8827: {LinearUnits lu(units); if (lu.isNull()) return false; setup.setFalseNorthing(lu.toMeters(val));} return true; case 8813: case 8818: case 8823: {AngularUnits au(units); if (au.isNull()) return false; setup.setStandardParallel1(au.toDegrees(val));} return true; case 1036: case 8814: case 8824: {AngularUnits au(units); if (au.isNull()) return false; setup.setStandardParallel2(au.toDegrees(val));} return true; default: return false; } } static int projectionSetup(const QList &list, Projection::Setup &setup) { bool r1, r2, r3; for (int i = 7; i < 28; i += 3) { QString ks = list[i].trimmed(); if (ks.isEmpty()) break; int key = ks.toInt(&r1); double val = list[i+1].trimmed().toDouble(&r2); int un = list[i+2].trimmed().toInt(&r3); if (!r1 || !r2 || !r3) return (i - 7)/3 + 1; if (!parameter(key, val, un, setup)) return (i - 7)/3 + 1; } return 0; } const PCS &PCS::pcs(int id) { static const PCS null; for (int i = 0; i < _pcss.size(); i++) if (_pcss.at(i).id() == id) return _pcss.at(i).pcs(); return null; } const PCS &PCS::pcs(const GCS &gcs, int proj) { static const PCS null; for (int i = 0; i < _pcss.size(); i++) if (_pcss.at(i).proj() == proj && _pcss.at(i).pcs().gcs() == gcs) return _pcss.at(i).pcs(); return null; } void PCS::loadList(const QString &path) { QFile file(path); bool res; int ln = 0, pn; 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() != 28) { qWarning("%s:%d: Format error", qPrintable(path), ln); continue; } QString name(list.at(0).trimmed()); int id = list.at(1).trimmed().toInt(&res); if (!res) { qWarning("%s:%d: Invalid PCS code", qPrintable(path), ln); continue; } int gcsid = list.at(2).trimmed().toInt(&res); if (!res) { qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln); continue; } int proj = list.at(3).trimmed().toInt(&res); if (!res) { qWarning("%s:%d: Invalid projection code", qPrintable(path), ln); continue; } int units = list.at(4).trimmed().toInt(&res); if (!res) { qWarning("%s:%d: Invalid linear units code", qPrintable(path), ln); continue; } int transform = list.at(5).trimmed().toInt(&res); if (!res) { qWarning("%s:%d: Invalid coordinate transformation code", qPrintable(path), ln); continue; } int cs = list[6].trimmed().toInt(&res); if (!res) { qWarning("%s:%d: Invalid coordinate system code", qPrintable(path), ln); continue; } if (!LinearUnits(units).isValid()) { qWarning("%s:%d: Unknown linear units code", qPrintable(path), ln); continue; } if (!Projection::Method(transform).isValid()) { qWarning("%s:%d: Unknown coordinate transformation code", qPrintable(path), ln); continue; } if (!CoordinateSystem(cs).isValid()) { qWarning("%s:%d: Unknown coordinate system code", qPrintable(path), ln); continue; } const GCS &gcs = GCS::gcs(gcsid); if (gcs.isNull()) { qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln); continue; } Projection::Setup setup; if ((pn = projectionSetup(list, setup))) { qWarning("%s: %d: Invalid projection parameter #%d", qPrintable(path), ln, pn); continue; } PCS pcs(gcs, transform, setup, units, cs); _pcss.append(Entry(name, id, proj, pcs)); } } QList > PCS::list() { QList > list; for (int i = 0; i < _pcss.size(); i++) list.append(KV(_pcss.at(i).id(), _pcss.at(i).name())); return list; } #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const PCS &pcs) { dbg.nospace() << "PCS(" << pcs.gcs() << ", " << pcs.method() << ", " << pcs.units() << ", " << pcs.setup() << ")"; return dbg.space(); } #endif // QT_NO_DEBUG