diff --git a/src/data/gpsdumpparser.cpp b/src/data/gpsdumpparser.cpp index c5545c94..a6283d12 100644 --- a/src/data/gpsdumpparser.cpp +++ b/src/data/gpsdumpparser.cpp @@ -2,6 +2,7 @@ #include "map/pcs.h" #include "map/gcs.h" #include "map/utm.h" +#include "map/projection.h" #include "gpsdumpparser.h" static double dms2dd(const QStringList &dms) diff --git a/src/map/bsbmap.cpp b/src/map/bsbmap.cpp index eeb44742..be72de54 100644 --- a/src/map/bsbmap.cpp +++ b/src/map/bsbmap.cpp @@ -303,20 +303,20 @@ bool BSBMap::createProjection(const QString &datum, const QString &proj, } if (!proj.compare("MERCATOR", Qt::CaseInsensitive)) { - Projection::Setup setup(0, c.lon(), NAN, 0, 0, NAN, NAN); + Conversion::Setup setup(0, c.lon(), NAN, 0, 0, NAN, NAN); pcs = PCS(gcs, Conversion(9804, setup, 9001)); } else if (!proj.compare("TRANSVERSE MERCATOR", Qt::CaseInsensitive)) { - Projection::Setup setup(0, params[1], params[2], 0, 0, NAN, NAN); + Conversion::Setup setup(0, params[1], params[2], 0, 0, NAN, NAN); pcs = PCS(gcs, Conversion(9807, setup, 9001)); } else if (!proj.compare("UNIVERSAL TRANSVERSE MERCATOR", Qt::CaseInsensitive)) { - Projection::Setup setup(0, params[0], 0.9996, 500000, 0, NAN, NAN); + Conversion::Setup setup(0, params[0], 0.9996, 500000, 0, NAN, NAN); pcs = PCS(gcs, Conversion(9807, setup, 9001)); } else if (!proj.compare("LAMBERT CONFORMAL CONIC", Qt::CaseInsensitive)) { - Projection::Setup setup(0, params[0], NAN, 0, 0, params[2], params[3]); + Conversion::Setup setup(0, params[0], NAN, 0, 0, params[2], params[3]); pcs = PCS(gcs, Conversion(9802, setup, 9001)); } else if (!proj.compare("POLYCONIC", Qt::CaseInsensitive)) { - Projection::Setup setup(0, params[0], NAN, 0, 0, NAN, NAN); + Conversion::Setup setup(0, params[0], NAN, 0, 0, NAN, NAN); pcs = PCS(gcs, Conversion(9818, setup, 9001)); } else { _errorString = proj + ": Unknown/missing projection"; diff --git a/src/map/conversion.cpp b/src/map/conversion.cpp index ce177c22..02e4e39b 100644 --- a/src/map/conversion.cpp +++ b/src/map/conversion.cpp @@ -1,71 +1,72 @@ #include #include "common/csv.h" +#include "angularunits.h" #include "conversion.h" -static bool parameter(int key, double val, int units, Projection::Setup &setup) +static bool parameter(int key, double val, int units, Conversion::Setup &setup) { switch (key) { - case 8801: - case 8811: - case 8821: - case 8832: - {AngularUnits au(units); - if (au.isNull()) + 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; - 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 QByteArrayList &list, Projection::Setup &setup) +static int projectionSetup(const QByteArrayList &list, Conversion::Setup &setup) { bool r1, r2, r3; @@ -87,13 +88,36 @@ static int projectionSetup(const QByteArrayList &list, Projection::Setup &setup) return 0; } +Conversion::Method::Method(int id) +{ + switch (id) { + case 1024: + case 1041: + case 9801: + case 9802: + case 9804: + case 9807: + case 9809: + case 9815: + case 9818: + case 9819: + case 9820: + case 9822: + case 9829: + _id = id; + break; + default: + _id = 0; + } +} + QMap Conversion::_conversions = defaults(); QMap Conversion::defaults() { QMap map; map.insert(3856, Entry("Popular Visualisation Pseudo-Mercator", 1024, - Projection::Setup(), 9001, 4400)); + Setup(), 9001, 4400)); return map; } @@ -159,7 +183,7 @@ bool Conversion::loadList(const QString &path) csv.line()); continue; } - if (!Projection::Method(transform).isValid()) { + if (!Method(transform).isValid()) { qWarning("%s:%d: Unknown coordinate transformation code", qPrintable(path), csv.line()); continue; @@ -170,7 +194,7 @@ bool Conversion::loadList(const QString &path) continue; } - Projection::Setup setup; + Setup setup; int pn = projectionSetup(entry, setup); if (pn) { qWarning("%s: %d: Invalid projection parameter #%d", @@ -196,6 +220,21 @@ QList > Conversion::list() } #ifndef QT_NO_DEBUG +QDebug operator<<(QDebug dbg, const Conversion::Setup &setup) +{ + dbg.nospace() << "Setup(" << setup.latitudeOrigin() << ", " + << setup.longitudeOrigin() << ", " << setup.scale() << ", " + << setup.falseEasting() << ", " << setup.falseNorthing() << ", " + << setup.standardParallel1() << ", " << setup.standardParallel2() << ")"; + return dbg.space(); +} + +QDebug operator<<(QDebug dbg, const Conversion::Method &method) +{ + dbg.nospace() << "Method(" << method.id() << ")"; + return dbg.space(); +} + QDebug operator<<(QDebug dbg, const Conversion &conversion) { dbg.nospace() << "Conversion(" << conversion.method() << ", " diff --git a/src/map/conversion.h b/src/map/conversion.h index 51057812..e5ff820a 100644 --- a/src/map/conversion.h +++ b/src/map/conversion.h @@ -1,18 +1,81 @@ #ifndef CONVERSION_H #define CONVERSION_H -#include "projection.h" +#include +#include +#include +#include "coordinatesystem.h" +#include "linearunits.h" class Conversion { public: - Conversion() {} - Conversion(const Projection::Method &method, - const Projection::Setup &setup, const LinearUnits &units, - const CoordinateSystem &cs = CoordinateSystem()) : _method(method), - _setup(setup), _units(units), _cs(cs) {} + class Setup { + public: + Setup() : _latitudeOrigin(NAN), _longitudeOrigin(NAN), _scale(NAN), + _falseEasting(NAN), _falseNorthing(NAN), _standardParallel1(NAN), + _standardParallel2(NAN) {} + Setup(double latitudeOrigin, double longitudeOrigin, double scale, + double falseEasting, double falseNorthing, double standardParallel1, + double standardParallel2) : _latitudeOrigin(latitudeOrigin), + _longitudeOrigin(longitudeOrigin), _scale(scale), + _falseEasting(falseEasting), _falseNorthing(falseNorthing), + _standardParallel1(standardParallel1), + _standardParallel2(standardParallel2) {} - const Projection::Method &method() const {return _method;} - const Projection::Setup &setup() const {return _setup;} + double latitudeOrigin() const {return _latitudeOrigin;} + double longitudeOrigin() const {return _longitudeOrigin;} + double scale() const {return _scale;} + double falseEasting() const {return _falseEasting;} + double falseNorthing() const {return _falseNorthing;} + double standardParallel1() const {return _standardParallel1;} + double standardParallel2() const {return _standardParallel2;} + + void setLatitudeOrigin(double val) {_latitudeOrigin = val;} + void setLongitudeOrigin(double val) {_longitudeOrigin = val;} + void setScale(double val) {_scale = val;} + void setFalseEasting(double val) {_falseEasting = val;} + void setFalseNorthing(double val) {_falseNorthing = val;} + void setStandardParallel1(double val) {_standardParallel1 = val;} + void setStandardParallel2(double val) {_standardParallel2 = val;} + + bool isNull() const + { + return std::isnan(_latitudeOrigin) + && std::isnan(_longitudeOrigin) && std::isnan(_scale) + && std::isnan(_falseEasting) && std::isnan(_falseNorthing) + && std::isnan(_standardParallel1) + && std::isnan(_standardParallel2); + } + + private: + double _latitudeOrigin; + double _longitudeOrigin; + double _scale; + double _falseEasting; + double _falseNorthing; + double _standardParallel1; + double _standardParallel2; + }; + + class Method { + public: + Method() : _id(0) {} + Method(int id); + + int id() const {return _id;} + bool isNull() const {return (_id == 0);} + bool isValid() const {return !isNull();} + private: + int _id; + }; + + Conversion() {} + Conversion(const Method &method, const Setup &setup, + const LinearUnits &units, const CoordinateSystem &cs = CoordinateSystem()) + : _method(method), _setup(setup), _units(units), _cs(cs) {} + + const Method &method() const {return _method;} + const Setup &setup() const {return _setup;} const LinearUnits &units() const {return _units;} const CoordinateSystem &cs() const {return _cs;} @@ -34,30 +97,28 @@ public: private: class Entry { public: - Entry(const QString &name, const Projection::Method &method, - const Projection::Setup &setup, const LinearUnits &units, - const CoordinateSystem &cs = CoordinateSystem()) - : _name(name), _method(method), _setup(setup), _units(units), - _cs(cs) {} + Entry(const QString &name, const Method &method, const Setup &setup, + const LinearUnits &units, const CoordinateSystem &cs = CoordinateSystem()) + : _name(name), _method(method), _setup(setup), _units(units), _cs(cs) {} const QString &name() const {return _name;} - const Projection::Method &method() const {return _method;} - const Projection::Setup &setup() const {return _setup;} + const Method &method() const {return _method;} + const Setup &setup() const {return _setup;} const LinearUnits &units() const {return _units;} const CoordinateSystem &cs() const {return _cs;} private: QString _name; - Projection::Method _method; - Projection::Setup _setup; + Method _method; + Setup _setup; LinearUnits _units; CoordinateSystem _cs; }; static QMap defaults(); - Projection::Method _method; - Projection::Setup _setup; + Method _method; + Setup _setup; LinearUnits _units; CoordinateSystem _cs; @@ -65,6 +126,8 @@ private: }; #ifndef QT_NO_DEBUG +QDebug operator<<(QDebug dbg, const Conversion::Setup &setup); +QDebug operator<<(QDebug dbg, const Conversion::Method &method); QDebug operator<<(QDebug dbg, const Conversion &conversion); #endif // QT_NO_DEBUG diff --git a/src/map/geotiff.cpp b/src/map/geotiff.cpp index c6c44738..4aa1343c 100644 --- a/src/map/geotiff.cpp +++ b/src/map/geotiff.cpp @@ -321,38 +321,38 @@ GCS GeoTIFF::geographicCS(QMap &kv) return gcs; } -Projection::Method GeoTIFF::coordinateTransformation(QMap &kv) +Conversion::Method GeoTIFF::coordinateTransformation(QMap &kv) { if (!IS_SET(kv, ProjCoordTransGeoKey)) { _errorString = "Missing coordinate transformation method"; - return Projection::Method(); + return Conversion::Method(); } switch (kv.value(ProjCoordTransGeoKey).SHORT) { case CT_TransverseMercator: - return Projection::Method(9807); + return Conversion::Method(9807); case CT_ObliqueMercator: - return Projection::Method(9815); + return Conversion::Method(9815); case CT_Mercator: - return Projection::Method(9804); + return Conversion::Method(9804); case CT_LambertConfConic_2SP: - return Projection::Method(9802); + return Conversion::Method(9802); case CT_LambertConfConic_1SP: - return Projection::Method(9801); + return Conversion::Method(9801); case CT_LambertAzimEqualArea: - return Projection::Method(9820); + return Conversion::Method(9820); case CT_AlbersEqualArea: - return Projection::Method(9822); + return Conversion::Method(9822); case CT_PolarStereographic: - return Projection::Method(9829); + return Conversion::Method(9829); case CT_ObliqueStereographic: - return Projection::Method(9809); + return Conversion::Method(9809); case CT_Polyconic: - return Projection::Method(9818); + return Conversion::Method(9818); default: _errorString = QString("%1: unknown coordinate transformation method") .arg(kv.value(ProjCoordTransGeoKey).SHORT); - return Projection::Method(); + return Conversion::Method(); } } @@ -383,7 +383,7 @@ bool GeoTIFF::projectedModel(QMap &kv) GCS gcs(geographicCS(kv)); if (gcs.isNull()) return false; - Projection::Method method(coordinateTransformation(kv)); + Conversion::Method method(coordinateTransformation(kv)); if (method.isNull()) return false; @@ -452,7 +452,7 @@ bool GeoTIFF::projectedModel(QMap &kv) else fe = NAN; - Projection::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2); + Conversion::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2); _projection = Projection(PCS(gcs, Conversion(method, setup, lu))); } diff --git a/src/map/geotiff.h b/src/map/geotiff.h index ed1e510b..494ef876 100644 --- a/src/map/geotiff.h +++ b/src/map/geotiff.h @@ -5,6 +5,7 @@ #include #include "transform.h" #include "projection.h" +#include "conversion.h" class TIFFFile; class GCS; @@ -49,7 +50,7 @@ private: double &val) const; GCS geographicCS(QMap &kv); - Projection::Method coordinateTransformation(QMap &kv); + Conversion::Method coordinateTransformation(QMap &kv); bool geographicModel(QMap &kv); bool projectedModel(QMap &kv); diff --git a/src/map/mapfile.cpp b/src/map/mapfile.cpp index d1be7f55..58ddd708 100644 --- a/src/map/mapfile.cpp +++ b/src/map/mapfile.cpp @@ -17,7 +17,7 @@ static double parameter(const QString &str, bool *res, double dflt = 0.0) } int MapFile::parse(QIODevice &device, QList &points, - QString &projection, Projection::Setup &setup, QString &datum) + QString &projection, Conversion::Setup &setup, QString &datum) { bool res, utm = false; int ln = 1, zone = 0; @@ -123,7 +123,7 @@ int MapFile::parse(QIODevice &device, QList &points, setup = UTM::setup(zone); else { bool r[8]; - setup = Projection::Setup( + setup = Conversion::Setup( parameter(list[1], &r[1]), parameter(list[2], &r[2]), parameter(list[3], &r[3], 1.0), parameter(list[4], &r[4]), parameter(list[5], &r[5]), parameter(list[6], &r[6]), @@ -143,7 +143,7 @@ int MapFile::parse(QIODevice &device, QList &points, } bool MapFile::parseMapFile(QIODevice &device, QList &points, - QString &projection, Projection::Setup &setup, QString &datum) + QString &projection, Conversion::Setup &setup, QString &datum) { int el; @@ -161,7 +161,7 @@ bool MapFile::parseMapFile(QIODevice &device, QList &points, } bool MapFile::createProjection(const QString &datum, const QString &name, - const Projection::Setup &setup) + const Conversion::Setup &setup) { PCS pcs; @@ -188,37 +188,37 @@ bool MapFile::createProjection(const QString &datum, const QString &name, else if (name == "Polyconic (American)") pcs = PCS(gcs, Conversion(9818, setup, 9001)); else if (name == "(NZTM2) New Zealand TM 2000") - pcs = PCS(gcs, Conversion(9807, Projection::Setup(0, 173.0, 0.9996, + pcs = PCS(gcs, Conversion(9807, Conversion::Setup(0, 173.0, 0.9996, 1600000, 10000000, NAN, NAN), 9001)); else if (name == "(BNG) British National Grid") - pcs = PCS(gcs, Conversion(9807, Projection::Setup(49, -2, 0.999601, + pcs = PCS(gcs, Conversion(9807, Conversion::Setup(49, -2, 0.999601, 400000, -100000, NAN, NAN), 9001)); else if (name == "(IG) Irish Grid") - pcs = PCS(gcs, Conversion(9807, Projection::Setup(53.5, -8, 1.000035, + pcs = PCS(gcs, Conversion(9807, Conversion::Setup(53.5, -8, 1.000035, 200000, 250000, NAN, NAN), 9001)); else if (name == "(SG) Swedish Grid") - pcs = PCS(gcs, Conversion(9807, Projection::Setup(0, 15.808278, 1, + pcs = PCS(gcs, Conversion(9807, Conversion::Setup(0, 15.808278, 1, 1500000, 0, NAN, NAN), 9001)); else if (name == "(I) France Zone I") - pcs = PCS(gcs, Conversion(9802, Projection::Setup(49.5, 2.337229, NAN, + pcs = PCS(gcs, Conversion(9802, Conversion::Setup(49.5, 2.337229, NAN, 600000, 1200000, 48.598523, 50.395912), 9001)); else if (name == "(II) France Zone II") - pcs = PCS(gcs, Conversion(9802, Projection::Setup(46.8, 2.337229, NAN, + pcs = PCS(gcs, Conversion(9802, Conversion::Setup(46.8, 2.337229, NAN, 600000, 2200000, 45.898919, 47.696014), 9001)); else if (name == "(III) France Zone III") - pcs = PCS(gcs, Conversion(9802, Projection::Setup(44.1, 2.337229, NAN, + pcs = PCS(gcs, Conversion(9802, Conversion::Setup(44.1, 2.337229, NAN, 600000, 3200000, 43.199291, 44.996094), 9001)); else if (name == "(IV) France Zone IV") - pcs = PCS(gcs, Conversion(9802, Projection::Setup(42.165, 2.337229, NAN, + pcs = PCS(gcs, Conversion(9802, Conversion::Setup(42.165, 2.337229, NAN, 234.358, 4185861.369, 41.560388, 42.767663), 9001)); else if (name == "(VICGRID) Victoria Australia") - pcs = PCS(gcs, Conversion(9802, Projection::Setup(-37, 145, NAN, + pcs = PCS(gcs, Conversion(9802, Conversion::Setup(-37, 145, NAN, 2500000, 4500000, -36, -38), 9001)); else if (name == "(VG94) VICGRID94 Victoria Australia") - pcs = PCS(gcs, Conversion(9802, Projection::Setup(-37, 145, NAN, + pcs = PCS(gcs, Conversion(9802, Conversion::Setup(-37, 145, NAN, 2500000, 2500000, -36, -38), 9001)); else if (name == "(SUI) Swiss Grid") - pcs = PCS(gcs, Conversion(9815, Projection::Setup(46.570866, 7.26225, + pcs = PCS(gcs, Conversion(9815, Conversion::Setup(46.570866, 7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001)); else { _errorString = QString("%1: Unknown map projection").arg(name); @@ -250,7 +250,7 @@ MapFile::MapFile(QIODevice &file) { QList points; QString ct, datum; - Projection::Setup setup; + Conversion::Setup setup; if (!parseMapFile(file, points, ct, setup, datum)) return; diff --git a/src/map/mapfile.h b/src/map/mapfile.h index 53d9c257..d7ccdb79 100644 --- a/src/map/mapfile.h +++ b/src/map/mapfile.h @@ -3,6 +3,7 @@ #include "transform.h" #include "projection.h" +#include "conversion.h" #include "calibrationpoint.h" class QIODevice; @@ -26,11 +27,11 @@ public: private: int parse(QIODevice &device, QList &points, - QString &projection, Projection::Setup &setup, QString &datum); + QString &projection, Conversion::Setup &setup, QString &datum); bool parseMapFile(QIODevice &device, QList &points, - QString &projection, Projection::Setup &setup, QString &datum); + QString &projection, Conversion::Setup &setup, QString &datum); bool createProjection(const QString &datum, const QString &projection, - const Projection::Setup &setup); + const Conversion::Setup &setup); bool computeTransformation(const QList &points); QString _name; diff --git a/src/map/oruxmap.cpp b/src/map/oruxmap.cpp index bb0ffdca..0ed99c8c 100644 --- a/src/map/oruxmap.cpp +++ b/src/map/oruxmap.cpp @@ -75,93 +75,93 @@ static PointD corner2point(const QString &name, const QSize &size) return PointD(); } -static Projection::Setup lcc2setup(const QStringList &list) +static Conversion::Setup lcc2setup(const QStringList &list) { double params[6]; bool ok; if (list.size() < 7) - return Projection::Setup(); + return Conversion::Setup(); for (int i = 1; i < 7; i++) { params[i - 1] = list.at(i).toDouble(&ok); if (!ok) - return Projection::Setup(); + return Conversion::Setup(); } - return Projection::Setup(params[0], params[1], NAN, params[4], + return Conversion::Setup(params[0], params[1], NAN, params[4], params[5], params[2], params[3]); } -static Projection::Setup laea2setup(const QStringList &list) +static Conversion::Setup laea2setup(const QStringList &list) { double params[2]; bool ok; if (list.size() < 3) - return Projection::Setup(); + return Conversion::Setup(); for (int i = 1; i < 3; i++) { params[i - 1] = list.at(i).toDouble(&ok); if (!ok) - return Projection::Setup(); + return Conversion::Setup(); } - return Projection::Setup(params[1], params[0], NAN, 0, 0, NAN, NAN); + return Conversion::Setup(params[1], params[0], NAN, 0, 0, NAN, NAN); } -static Projection::Setup polyconic2setup(const QStringList &list) +static Conversion::Setup polyconic2setup(const QStringList &list) { double params[3]; bool ok; if (list.size() < 4) - return Projection::Setup(); + return Conversion::Setup(); for (int i = 1; i < 4; i++) { params[i - 1] = list.at(i).toDouble(&ok); if (!ok) - return Projection::Setup(); + return Conversion::Setup(); } - return Projection::Setup(NAN, params[0], NAN, params[1], params[2], NAN, + return Conversion::Setup(NAN, params[0], NAN, params[1], params[2], NAN, NAN); } -static Projection::Setup tm2setup(const QStringList &list) +static Conversion::Setup tm2setup(const QStringList &list) { double params[5]; bool ok; if (list.size() < 6) - return Projection::Setup(); + return Conversion::Setup(); for (int i = 1; i < 6; i++) { params[i - 1] = list.at(i).toDouble(&ok); if (!ok) - return Projection::Setup(); + return Conversion::Setup(); } - return Projection::Setup(params[1], params[0], params[2], params[3], + return Conversion::Setup(params[1], params[0], params[2], params[3], params[4], NAN, NAN); } -static Projection::Setup utm2setup(const QStringList &list) +static Conversion::Setup utm2setup(const QStringList &list) { bool ok; if (list.size() < 2) - return Projection::Setup(); + return Conversion::Setup(); int zone = list.at(1).toInt(&ok); - return ok ? UTM::setup(zone) : Projection::Setup(); + return ok ? UTM::setup(zone) : Conversion::Setup(); } -static Projection::Setup mercator2setup(const QStringList &list) +static Conversion::Setup mercator2setup(const QStringList &list) { double lon; bool ok; if (list.size() < 2) - return Projection::Setup(0, 0, NAN, 0, 0, NAN, NAN); + return Conversion::Setup(0, 0, NAN, 0, 0, NAN, NAN); lon = list.at(1).toDouble(&ok); - return ok ? Projection::Setup(0, lon, NAN, 0, 0, NAN, NAN) - : Projection::Setup(); + return ok ? Conversion::Setup(0, lon, NAN, 0, 0, NAN, NAN) + : Conversion::Setup(); } static GCS createGCS(const QString &datum) @@ -180,7 +180,7 @@ static Projection createProjection(const GCS &gcs, const QString &name) else if (pl.first() == "UTM") pcs = PCS(gcs, Conversion(9807, utm2setup(pl), 9001)); else if (pl.first() == "Mercator") - pcs = PCS(gcs, Conversion(1024, Projection::Setup(), 9001)); + pcs = PCS(gcs, Conversion(1024, Conversion::Setup(), 9001)); else if (pl.first() == "Mercator Ellipsoidal") pcs = PCS(gcs, Conversion(9804, mercator2setup(pl), 9001)); else if (pl.first() == "Transverse Mercator") @@ -192,13 +192,13 @@ static Projection createProjection(const GCS &gcs, const QString &name) else if (pl.first() == "Polyconic (American)") pcs = PCS(gcs, Conversion(9818, polyconic2setup(pl), 9001)); else if (pl.first() == "(IG) Irish Grid") - pcs = PCS(gcs, Conversion(9807, Projection::Setup(53.5, -8, 1.000035, + pcs = PCS(gcs, Conversion(9807, Conversion::Setup(53.5, -8, 1.000035, 200000, 250000, NAN, NAN), 9001)); else if (pl.first() == "(SUI) Swiss Grid") - pcs = PCS(gcs, Conversion(9815, Projection::Setup(46.570866, 7.26225, + pcs = PCS(gcs, Conversion(9815, Conversion::Setup(46.570866, 7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001)); else if (pl.first() == "Rijksdriehoeksmeting") - pcs = PCS(gcs, Conversion(9809, Projection::Setup(52.1561605555556, + pcs = PCS(gcs, Conversion(9809, Conversion::Setup(52.1561605555556, 5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001)); else return Projection(); diff --git a/src/map/prjfile.cpp b/src/map/prjfile.cpp index db9a4b37..4b7b380c 100644 --- a/src/map/prjfile.cpp +++ b/src/map/prjfile.cpp @@ -4,7 +4,7 @@ #include "pcs.h" #include "prjfile.h" -static Projection::Method projectionMethod(const QString &name) +static Conversion::Method projectionMethod(const QString &name) { static const struct { int id; @@ -30,10 +30,10 @@ static Projection::Method projectionMethod(const QString &name) qWarning("%s: unknown projection", qPrintable(name)); - return Projection::Method(); + return Conversion::Method(); } -static void setParameter(Projection::Setup *setup, const QString &name, +static void setParameter(Conversion::Setup *setup, const QString &name, double val) { // latitude origin @@ -460,7 +460,7 @@ void PRJFile::primeMeridian(CTX &ctx, PrimeMeridian *pm, int *epsg) *pm = PrimeMeridian(lon); } -void PRJFile::parameter(CTX &ctx, Projection::Setup *setup) +void PRJFile::parameter(CTX &ctx, Conversion::Setup *setup) { QString name; @@ -478,7 +478,7 @@ void PRJFile::parameter(CTX &ctx, Projection::Setup *setup) } } -void PRJFile::projection(CTX &ctx, Projection::Method *method) +void PRJFile::projection(CTX &ctx, Conversion::Method *method) { int epsg = -1; QString proj; @@ -490,7 +490,7 @@ void PRJFile::projection(CTX &ctx, Projection::Method *method) optAuthority(ctx, &epsg); compare(ctx, RBRK); - *method = (epsg > 0) ? Projection::Method(epsg) : projectionMethod(proj); + *method = (epsg > 0) ? Conversion::Method(epsg) : projectionMethod(proj); } void PRJFile::optProjectedCS2(CTX &ctx, int *epsg) @@ -521,8 +521,8 @@ void PRJFile::projectedCS(CTX &ctx, PCS *pcs) int epsg = -1; GCS gcs; LinearUnits lu; - Projection::Method method; - Projection::Setup setup; + Conversion::Method method; + Conversion::Setup setup; compare(ctx, PROJCS); compare(ctx, LBRK); diff --git a/src/map/prjfile.h b/src/map/prjfile.h index 4a117783..e9686c89 100644 --- a/src/map/prjfile.h +++ b/src/map/prjfile.h @@ -2,6 +2,7 @@ #define PRJFILE_H #include +#include "conversion.h" #include "projection.h" class Datum; @@ -57,8 +58,8 @@ private: void geographicCS(CTX &ctx, GCS *gcs); void projectedCS(CTX &ctx, PCS *pcs); void compdCS(CTX &ctx); - void projection(CTX &ctx, Projection::Method *method); - void parameter(CTX &ctx, Projection::Setup *setup); + void projection(CTX &ctx, Conversion::Method *method); + void parameter(CTX &ctx, Conversion::Setup *setup); void datum(CTX &ctx, Datum *dtm, int *epsg); void verticalDatum(CTX &ctx); void unit(CTX &ctx, double *val, int *epsg); diff --git a/src/map/projection.cpp b/src/map/projection.cpp index 1cdb0d5a..079083fd 100644 --- a/src/map/projection.cpp +++ b/src/map/projection.cpp @@ -9,40 +9,16 @@ #include "proj/obliquestereographic.h" #include "proj/polyconic.h" #include "datum.h" -#include "gcs.h" #include "pcs.h" #include "projection.h" -Projection::Method::Method(int id) -{ - switch (id) { - case 1024: - case 1041: - case 9801: - case 9802: - case 9804: - case 9807: - case 9809: - case 9815: - case 9818: - case 9819: - case 9820: - case 9822: - case 9829: - _id = id; - break; - default: - _id = 0; - } -} - Projection::Projection(const PCS &pcs) : _gcs(pcs.gcs()), _ct(0), _units(pcs.conversion().units()), _cs(pcs.conversion().cs()) { const Ellipsoid &ellipsoid = _gcs.datum().ellipsoid(); - const Projection::Setup &setup = pcs.conversion().setup(); + const Conversion::Setup &setup = pcs.conversion().setup(); switch (pcs.conversion().method().id()) { case 1024: @@ -154,32 +130,3 @@ bool Projection::operator==(const Projection &p) const return (*_ct == *p._ct && _gcs == p._gcs && _units == p._units && _cs == p._cs); } - -PointD Projection::ll2xy(const Coordinates &c) const -{ - Q_ASSERT(isValid()); - return _units.fromMeters(_ct->ll2xy(_gcs.fromWGS84(c))); -} - -Coordinates Projection::xy2ll(const PointD &p) const -{ - Q_ASSERT(isValid()); - return _gcs.toWGS84(_ct->xy2ll(_units.toMeters(p))); -} - -#ifndef QT_NO_DEBUG -QDebug operator<<(QDebug dbg, const Projection::Setup &setup) -{ - dbg.nospace() << "Setup(" << setup.latitudeOrigin() << ", " - << setup.longitudeOrigin() << ", " << setup.scale() << ", " - << setup.falseEasting() << ", " << setup.falseNorthing() << ", " - << setup.standardParallel1() << ", " << setup.standardParallel2() << ")"; - return dbg.space(); -} - -QDebug operator<<(QDebug dbg, const Projection::Method &method) -{ - dbg.nospace() << "Method(" << method.id() << ")"; - return dbg.space(); -} -#endif // QT_NO_DEBUG diff --git a/src/map/projection.h b/src/map/projection.h index f5ad35ce..0f4c696e 100644 --- a/src/map/projection.h +++ b/src/map/projection.h @@ -1,76 +1,19 @@ #ifndef PROJECTION_H #define PROJECTION_H -#include +#include #include "common/coordinates.h" #include "pointd.h" #include "linearunits.h" #include "coordinatesystem.h" #include "gcs.h" +#include "ct.h" #include "proj/latlon.h" class PCS; -class CT; -class AngularUnits; class Projection { public: - class Setup { - public: - Setup() : _latitudeOrigin(NAN), _longitudeOrigin(NAN), _scale(NAN), - _falseEasting(NAN), _falseNorthing(NAN), _standardParallel1(NAN), - _standardParallel2(NAN) {} - Setup(double latitudeOrigin, double longitudeOrigin, double scale, - double falseEasting, double falseNorthing, double standardParallel1, - double standardParallel2) : _latitudeOrigin(latitudeOrigin), - _longitudeOrigin(longitudeOrigin), _scale(scale), - _falseEasting(falseEasting), _falseNorthing(falseNorthing), - _standardParallel1(standardParallel1), - _standardParallel2(standardParallel2) {} - - double latitudeOrigin() const {return _latitudeOrigin;} - double longitudeOrigin() const {return _longitudeOrigin;} - double scale() const {return _scale;} - double falseEasting() const {return _falseEasting;} - double falseNorthing() const {return _falseNorthing;} - double standardParallel1() const {return _standardParallel1;} - double standardParallel2() const {return _standardParallel2;} - - void setLatitudeOrigin(double val) {_latitudeOrigin = val;} - void setLongitudeOrigin(double val) {_longitudeOrigin = val;} - void setScale(double val) {_scale = val;} - void setFalseEasting(double val) {_falseEasting = val;} - void setFalseNorthing(double val) {_falseNorthing = val;} - void setStandardParallel1(double val) {_standardParallel1 = val;} - void setStandardParallel2(double val) {_standardParallel2 = val;} - - bool isNull() const {return std::isnan(_latitudeOrigin) - && std::isnan(_longitudeOrigin) && std::isnan(_scale) - && std::isnan(_falseEasting) && std::isnan(_falseNorthing) - && std::isnan(_standardParallel1) && std::isnan(_standardParallel2);} - - private: - double _latitudeOrigin; - double _longitudeOrigin; - double _scale; - double _falseEasting; - double _falseNorthing; - double _standardParallel1; - double _standardParallel2; - }; - - class Method { - public: - Method() : _id(0) {} - Method(int id); - - int id() const {return _id;} - bool isNull() const {return (_id == 0);} - bool isValid() const {return !isNull();} - private: - int _id; - }; - Projection() : _ct(0) {} Projection(const Projection &p); Projection(const PCS &pcs); @@ -87,8 +30,8 @@ public: } bool isValid() const { - // We do not check the CoordinateSystem here as it is not always defined - // and except of WMTS/WMS it is not needed. + /* We do not check the CoordinateSystem here as it is not always defined + and except of WMTS/WMS it is not needed. */ return (_gcs.isValid() && _ct != 0 && _units.isValid()); } bool isGeographic() const @@ -96,8 +39,16 @@ public: return (dynamic_cast(_ct) != 0); } - PointD ll2xy(const Coordinates &c) const; - Coordinates xy2ll(const PointD &p) const; + PointD ll2xy(const Coordinates &c) const + { + Q_ASSERT(isValid()); + return _units.fromMeters(_ct->ll2xy(_gcs.fromWGS84(c))); + } + Coordinates xy2ll(const PointD &p) const + { + Q_ASSERT(isValid()); + return _gcs.toWGS84(_ct->xy2ll(_units.toMeters(p))); + } const LinearUnits &units() const {return _units;} const CoordinateSystem &coordinateSystem() const {return _cs;} @@ -109,9 +60,4 @@ private: CoordinateSystem _cs; }; -#ifndef QT_NO_DEBUG -QDebug operator<<(QDebug dbg, const Projection::Setup &setup); -QDebug operator<<(QDebug dbg, const Projection::Method &method); -#endif // QT_NO_DEBUG - #endif // PROJECTION_H diff --git a/src/map/rmap.cpp b/src/map/rmap.cpp index 86a12b26..90380df6 100644 --- a/src/map/rmap.cpp +++ b/src/map/rmap.cpp @@ -58,37 +58,37 @@ static Projection parseProjection(const QString &str, const GCS &gcs) case 1: // LatLon return Projection(gcs); case 2: // Mercator - return Projection(PCS(gcs, Conversion(1024, Projection::Setup(), + return Projection(PCS(gcs, Conversion(1024, Conversion::Setup(), 9001))); case 3: // Transversal Mercator if (fields.size() < 7) return Projection(); - return Projection(PCS(gcs, Conversion(9807, Projection::Setup( + return Projection(PCS(gcs, Conversion(9807, Conversion::Setup( fields.at(3).toDouble(), fields.at(2).toDouble(), fields.at(6).toDouble(), fields.at(5).toDouble(), fields.at(4).toDouble(), NAN, NAN), 9001))); case 4: // Lambert 2SP if (fields.size() < 8) return Projection(); - return Projection(PCS(gcs, Conversion(9802, Projection::Setup( + return Projection(PCS(gcs, Conversion(9802, Conversion::Setup( fields.at(4).toDouble(), fields.at(5).toDouble(), NAN, fields.at(6).toDouble(), fields.at(7).toDouble(), fields.at(3).toDouble(), fields.at(2).toDouble()), 9001))); case 6: // BGN (British National Grid) - return Projection(PCS(gcs, Conversion(9807, Projection::Setup(49, + return Projection(PCS(gcs, Conversion(9807, Conversion::Setup(49, -2, 0.999601, 400000, -100000, NAN, NAN), 9001))); case 12: // France Lambert II etendu - return Projection(PCS(gcs, Conversion(9801, Projection::Setup(52, 0, + return Projection(PCS(gcs, Conversion(9801, Conversion::Setup(52, 0, 0.99987742, 600000, 2200000, NAN, NAN), 9001))); case 14: // Swiss Grid - return Projection(PCS(gcs, Conversion(9815, Projection::Setup( + return Projection(PCS(gcs, Conversion(9815, Conversion::Setup( 46.570866, 7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001))); case 108: // Dutch RD grid - return Projection(PCS(gcs, Conversion(9809, Projection::Setup( + return Projection(PCS(gcs, Conversion(9809, Conversion::Setup( 52.15616055555555, 5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001))); case 184: // Swedish Grid - return Projection(PCS(gcs, Conversion(9807, Projection::Setup(0, + return Projection(PCS(gcs, Conversion(9807, Conversion::Setup(0, 15.808278, 1, 1500000, 0, NAN, NAN), 9001))); default: return Projection(); diff --git a/src/map/utm.cpp b/src/map/utm.cpp index 4f72198f..d16098c4 100644 --- a/src/map/utm.cpp +++ b/src/map/utm.cpp @@ -1,9 +1,10 @@ +#include "common/coordinates.h" #include "ellipsoid.h" #include "utm.h" -Projection::Setup UTM::setup(int zone) +Conversion::Setup UTM::setup(int zone) { - return Projection::Setup(0, (qAbs(zone) - 1)*6 - 180 + 3, 0.9996, 500000, + return Conversion::Setup(0, (qAbs(zone) - 1)*6 - 180 + 3, 0.9996, 500000, zone < 0 ? 10000000 : 0, 0, 0); } diff --git a/src/map/utm.h b/src/map/utm.h index cb345431..98cf10e4 100644 --- a/src/map/utm.h +++ b/src/map/utm.h @@ -1,12 +1,14 @@ #ifndef UTM_H #define UTM_H -#include "projection.h" +#include "conversion.h" + +class Coordinates; namespace UTM { int zone(const Coordinates &c); - Projection::Setup setup(int zone); + Conversion::Setup setup(int zone); } #endif // UTM_H