From 5698b4c9b0d1f8ec21e920134856f2783b74b3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 25 Jan 2018 00:19:11 +0100 Subject: [PATCH] Fixed another bunch of GeoTIFF handling bugs --- gpxsee.pro | 3 +- src/map/albersequal.h | 6 ++- src/map/angularunits.cpp | 8 ++-- src/map/ct.h | 17 +++++++ src/map/datum.cpp | 3 +- src/map/geotiff.cpp | 29 ++++++------ src/map/geotiff.h | 14 +++--- src/map/lambertazimuthal.h | 6 ++- src/map/lambertconic.h | 10 +++-- src/map/latlon.h | 6 ++- src/map/linearunits.h | 5 +++ src/map/mapfile.cpp | 87 +++++++++++++++++------------------- src/map/mapfile.h | 13 +++--- src/map/mercator.h | 6 ++- src/map/offlinemap.cpp | 21 +++------ src/map/offlinemap.h | 10 ++--- src/map/projection.cpp | 65 ++++++++++++++++++++++----- src/map/projection.h | 24 +++++++--- src/map/transversemercator.h | 6 ++- 19 files changed, 208 insertions(+), 131 deletions(-) create mode 100644 src/map/ct.h diff --git a/gpxsee.pro b/gpxsee.pro index 73f1ee43..71fa0adc 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -115,7 +115,8 @@ HEADERS += src/config.h \ src/map/gcs.h \ src/map/angularunits.h \ src/map/primemeridian.h \ - src/map/linearunits.h + src/map/linearunits.h \ + src/map/ct.h SOURCES += src/main.cpp \ src/common/coordinates.cpp \ src/common/rectc.cpp \ diff --git a/src/map/albersequal.h b/src/map/albersequal.h index 52de73c4..11b9a63a 100644 --- a/src/map/albersequal.h +++ b/src/map/albersequal.h @@ -2,15 +2,17 @@ #define ALBERSEQUAL_H #include "ellipsoid.h" -#include "projection.h" +#include "ct.h" -class AlbersEqual : public Projection +class AlbersEqual : public CT { public: AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1, double standardParallel2, double latitudeOrigin, double longitudeOrigin, double falseEasting, double falseNorthing); + virtual CT *clone() const {return new AlbersEqual(*this);} + virtual QPointF ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const QPointF &p) const; diff --git a/src/map/angularunits.cpp b/src/map/angularunits.cpp index 0718fc4f..f1898f09 100644 --- a/src/map/angularunits.cpp +++ b/src/map/angularunits.cpp @@ -5,14 +5,14 @@ static double sDMS2deg(double val) { double angle; - char *decimal; - char str[13]; + const char *decimal; if (val < -999.9 || val > 999.9) return NAN; - sprintf(str, "%.7f", qAbs(val)); - decimal = strchr(str,'.'); + QString qstr(QString::number(qAbs(val), 'f', 7)); + const char *str = qstr.toLatin1().constData(); + decimal = strrchr(str, '.'); int deg = str2int(str, decimal - str); int min = str2int(decimal + 1, 2); int sec = str2int(decimal + 3, 2); diff --git a/src/map/ct.h b/src/map/ct.h new file mode 100644 index 00000000..1c750efa --- /dev/null +++ b/src/map/ct.h @@ -0,0 +1,17 @@ +#ifndef CT_H +#define CT_H + +#include +#include "common/coordinates.h" + +class CT { +public: + virtual ~CT() {} + + virtual CT *clone() const = 0; + + virtual QPointF ll2xy(const Coordinates &c) const = 0; + virtual Coordinates xy2ll(const QPointF &p) const = 0; +}; + +#endif // CT_H diff --git a/src/map/datum.cpp b/src/map/datum.cpp index 5f6a6f41..c2b89303 100644 --- a/src/map/datum.cpp +++ b/src/map/datum.cpp @@ -46,7 +46,8 @@ static Coordinates molodensky(const Coordinates &c, const Datum &from, Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz) : _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz) { - _WGS84 = (*this == WGS84) ? true : false; + _WGS84 = (*_ellipsoid == *WGS84.ellipsoid() && _dx == WGS84.dx() + && _dy == WGS84.dy() && _dz == WGS84.dz()) ? true : false; } Coordinates Datum::toWGS84(const Coordinates &c) const diff --git a/src/map/geotiff.cpp b/src/map/geotiff.cpp index d185076b..66d527dc 100644 --- a/src/map/geotiff.cpp +++ b/src/map/geotiff.cpp @@ -325,25 +325,26 @@ bool GeoTIFF::projectedModel(QMap &kv) .arg(kv.value(ProjectedCSTypeGeoKey).SHORT); return false; } - _gcs = pcs->gcs(); - _projection = Projection::projection(_gcs->datum(), pcs->method(), - pcs->setup()); + _projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(), + pcs->units()); } else if (IS_SET(kv, ProjectionGeoKey)) { - if (!(_gcs = gcs(kv))) + const GCS *g = gcs(kv); + if (!g) return false; - const PCS *pcs; - if (!(pcs = PCS::pcs(_gcs, kv.value(ProjectionGeoKey).SHORT))) { + const PCS *pcs = PCS::pcs(g, kv.value(ProjectionGeoKey).SHORT); + if (!pcs) { _errorString = QString("%1: unknown projection code") .arg(kv.value(GeographicTypeGeoKey).SHORT) .arg(kv.value(ProjectionGeoKey).SHORT); return false; } - _projection = Projection::projection(_gcs->datum(), pcs->method(), - pcs->setup()); + _projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(), + pcs->units()); } else { - if (!(_gcs = gcs(kv))) + const GCS *g = gcs(kv); + if (!g) return false; - Projection::Method m = method(kv); + Projection::Method m(method(kv)); if (m.isNull()) return false; @@ -366,7 +367,8 @@ bool GeoTIFF::projectedModel(QMap &kv) au.toDegrees(kv.value(ProjStdParallel1GeoKey).DOUBLE), au.toDegrees(kv.value(ProjStdParallel2GeoKey).DOUBLE) ); - _projection = Projection::projection(_gcs->datum(), m, setup); + + _projection = Projection(g, m, setup, lu); } return true; @@ -374,10 +376,11 @@ bool GeoTIFF::projectedModel(QMap &kv) bool GeoTIFF::geographicModel(QMap &kv) { - if (!(_gcs = gcs(kv))) + const GCS *g = gcs(kv); + if (!g) return false; - _projection = new LatLon(_gcs->angularUnits()); + _projection = Projection(g); return true; } diff --git a/src/map/geotiff.h b/src/map/geotiff.h index 1d4c3f4b..06d3b136 100644 --- a/src/map/geotiff.h +++ b/src/map/geotiff.h @@ -8,20 +8,17 @@ #include "projection.h" #include "tifffile.h" #include "transform.h" +#include "linearunits.h" class GeoTIFF { public: - GeoTIFF() : _projection(0) {} - bool load(const QString &path); - - const GCS *gcs() const {return _gcs;} - Projection *projection() const {return _projection;} - const QTransform &transform() const {return _transform;} - const QString &errorString() const {return _errorString;} + const Projection &projection() const {return _projection;} + const QTransform &transform() const {return _transform;} + private: union Value { quint16 SHORT; @@ -56,8 +53,7 @@ private: bool projectedModel(QMap &kv); QTransform _transform; - const GCS *_gcs; - Projection *_projection; + Projection _projection; QString _errorString; }; diff --git a/src/map/lambertazimuthal.h b/src/map/lambertazimuthal.h index 7dc3b88b..1f45b020 100644 --- a/src/map/lambertazimuthal.h +++ b/src/map/lambertazimuthal.h @@ -2,14 +2,16 @@ #define LAMBERTAZIMUTHAL_H #include "ellipsoid.h" -#include "projection.h" +#include "ct.h" -class LambertAzimuthal : public Projection +class LambertAzimuthal : public CT { public: LambertAzimuthal(const Ellipsoid *ellipsoid, double latitudeOrigin, double longitudeOrigin, double falseEasting, double falseNorthing); + virtual CT *clone() const {return new LambertAzimuthal(*this);} + virtual QPointF ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const QPointF &p) const; diff --git a/src/map/lambertconic.h b/src/map/lambertconic.h index 17260493..25aa8b93 100644 --- a/src/map/lambertconic.h +++ b/src/map/lambertconic.h @@ -2,9 +2,9 @@ #define LAMBERTCONIC_H #include "ellipsoid.h" -#include "projection.h" +#include "ct.h" -class LambertConic1 : public Projection +class LambertConic1 : public CT { public: LambertConic1() {} @@ -12,6 +12,8 @@ public: double longitudeOrigin, double scale, double falseEasting, double falseNorthing); + virtual CT *clone() const {return new LambertConic1(*this);} + virtual QPointF ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const QPointF &p) const; @@ -28,13 +30,15 @@ private: double _rho_olat; }; -class LambertConic2 : public Projection +class LambertConic2 : public CT { public: LambertConic2(const Ellipsoid *ellipsoid, double standardParallel1, double standardParallel2, double latitudeOrigin, double longitudeOrigin, double falseEasting, double falseNorthing); + virtual CT *clone() const {return new LambertConic2(*this);} + virtual QPointF ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const QPointF &p) const; diff --git a/src/map/latlon.h b/src/map/latlon.h index 9c6bf565..d327f02d 100644 --- a/src/map/latlon.h +++ b/src/map/latlon.h @@ -1,14 +1,16 @@ #ifndef LATLON_H #define LATLON_H -#include "projection.h" +#include "ct.h" #include "angularunits.h" -class LatLon : public Projection +class LatLon : public CT { public: LatLon(const AngularUnits &au) : _au(au) {} + virtual CT *clone() const {return new LatLon(*this);} + virtual QPointF ll2xy(const Coordinates &c) const {return QPointF(_au.fromDegrees(c.lon()), _au.fromDegrees(c.lat()));} virtual Coordinates xy2ll(const QPointF &p) const diff --git a/src/map/linearunits.h b/src/map/linearunits.h index 308b0248..376e1cd7 100644 --- a/src/map/linearunits.h +++ b/src/map/linearunits.h @@ -3,6 +3,7 @@ #include #include +#include class LinearUnits { @@ -14,7 +15,11 @@ public: bool isValid() const {return !std::isnan(_f);} double toMeters(double val) const {return val * _f;} + QPointF toMeters(const QPointF &p) const + {return QPointF(p.x() * _f, p.y() * _f);} double fromMeters(double val) const {return val / _f;} + QPointF fromMeters(const QPointF &p) const + {return QPointF(p.x() / _f, p.y() /_f);} friend bool operator==(const LinearUnits &lu1, const LinearUnits &lu2); friend QDebug operator<<(QDebug dbg, const LinearUnits &lu); diff --git a/src/map/mapfile.cpp b/src/map/mapfile.cpp index 2c9e9f7a..0b5fef5b 100644 --- a/src/map/mapfile.cpp +++ b/src/map/mapfile.cpp @@ -1,4 +1,3 @@ -#include "latlon.h" #include "utm.h" #include "gcs.h" #include "mapfile.h" @@ -150,31 +149,31 @@ bool MapFile::parseMapFile(QIODevice &device, QList &points, return true; } -bool MapFile::createDatum(const QString &datum) +const GCS *MapFile::createGCS(const QString &datum) { - if (!(_gcs = GCS::gcs(datum))) { - _errorString = QString("%1: Unknown datum").arg(datum); - return false; - } + const GCS *gcs; - return true; + if (!(gcs = GCS::gcs(datum))) + _errorString = QString("%1: Unknown datum").arg(datum); + + return gcs; } -bool MapFile::createProjection(const QString &name, +bool MapFile::createProjection(const GCS *gcs, const QString &name, const Projection::Setup &setup, QList &points) { if (name == "Mercator") - _projection = Projection::projection(_gcs->datum(), 1024, setup); + _projection = Projection(gcs, 1024, setup, 9001); else if (name == "Transverse Mercator") - _projection = Projection::projection(_gcs->datum(), 9807, setup); + _projection = Projection(gcs, 9807, setup, 9001); else if (name == "Latitude/Longitude") - _projection = new LatLon(9102); + _projection = Projection(gcs); else if (name == "Lambert Conformal Conic") - _projection = Projection::projection(_gcs->datum(), 9802, setup); + _projection = Projection(gcs, 9802, setup, 9001); else if (name == "Albers Equal Area") - _projection = Projection::projection(_gcs->datum(), 9822, setup); + _projection = Projection(gcs, 9822, setup, 9001); else if (name == "(A)Lambert Azimuthual Equal Area") - _projection = Projection::projection(_gcs->datum(), 9820, setup); + _projection = Projection(gcs, 9820, setup, 9001); else if (name == "(UTM) Universal Transverse Mercator") { int zone; if (points.first().zone) @@ -183,44 +182,39 @@ bool MapFile::createProjection(const QString &name, zone = UTM::zone(points.first().ll); else { _errorString = "Can not determine UTM zone"; - return 0; + return false; } - _projection = Projection::projection(_gcs->datum(), 9807, - UTM::setup(zone)); + _projection = Projection(gcs, 9807, UTM::setup(zone), 9001); } else if (name == "(NZTM2) New Zealand TM 2000") - _projection = Projection::projection(_gcs->datum(), 9807, - Projection::Setup(0, 173.0, 0.9996, 1600000, 10000000, NAN, NAN)); + _projection = Projection(gcs, 9807, Projection::Setup(0, 173.0, 0.9996, + 1600000, 10000000, NAN, NAN), 9001); else if (name == "(BNG) British National Grid") - _projection = Projection::projection(_gcs->datum(), 9807, - Projection::Setup(49, -2, 0.999601, 400000, -100000, NAN, NAN)); + _projection = Projection(gcs, 9807, Projection::Setup(49, -2, 0.999601, + 400000, -100000, NAN, NAN), 9001); else if (name == "(IG) Irish Grid") - _projection = Projection::projection(_gcs->datum(), 9807, - Projection::Setup(53.5, -8, 1.000035, 200000, 250000, NAN, NAN)); + _projection = Projection(gcs, 9807, Projection::Setup(53.5, -8, + 1.000035, 200000, 250000, NAN, NAN), 9001); else if (name == "(SG) Swedish Grid") - _projection = Projection::projection(_gcs->datum(), 9807, - Projection::Setup(0, 15.808278, 1, 1500000, 0, NAN, NAN)); + _projection = Projection(gcs, 9807, Projection::Setup(0, 15.808278, 1, + 1500000, 0, NAN, NAN), 9001); else if (name == "(I) France Zone I") - _projection = Projection::projection(_gcs->datum(), 9802, - Projection::Setup(49.5, 2.337229, NAN, 600000, 1200000, 48.598523, - 50.395912)); + _projection = Projection(gcs, 9802, Projection::Setup(49.5, 2.337229, + NAN, 600000, 1200000, 48.598523, 50.395912), 9001); else if (name == "(II) France Zone II") - _projection = Projection::projection(_gcs->datum(), 9802, - Projection::Setup(46.8, 2.337229, NAN, 600000, 2200000, 45.898919, - 47.696014)); + _projection = Projection(gcs, 9802, Projection::Setup(46.8, 2.337229, + NAN, 600000, 2200000, 45.898919, 47.696014), 9001); else if (name == "(III) France Zone III") - _projection = Projection::projection(_gcs->datum(), 9802, - Projection::Setup(44.1, 2.337229, NAN, 600000, 3200000, 43.199291, - 44.996094)); + _projection = Projection(gcs, 9802, Projection::Setup(44.1, 2.337229, + NAN, 600000, 3200000, 43.199291, 44.996094), 9001); else if (name == "(IV) France Zone IV") - _projection = Projection::projection(_gcs->datum(), 9802, - Projection::Setup(42.165, 2.337229, NAN, 234.358, 4185861.369, - 41.560388, 42.767663)); + _projection = Projection(gcs, 9802, Projection::Setup(42.165, 2.337229, + NAN, 234.358, 4185861.369, 41.560388, 42.767663), 9001); else if (name == "(VICGRID) Victoria Australia") - _projection = Projection::projection(_gcs->datum(), 9802, - Projection::Setup(-37, 145, NAN, 2500000, 4500000, -36, -38)); + _projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN, + 2500000, 4500000, -36, -38), 9001); else if (name == "(VG94) VICGRID94 Victoria Australia") - _projection = Projection::projection(_gcs->datum(), 9802, - Projection::Setup(-37, 145, NAN, 2500000, 2500000, -36, -38)); + _projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN, + 2500000, 2500000, -36, -38), 9001); else { _errorString = QString("%1: Unknown map projection").arg(name); return false; @@ -235,7 +229,7 @@ bool MapFile::computeTransformation(QList &points) for (int i = 0; i < points.size(); i++) { if (points.at(i).rp.pp.isNull()) - points[i].rp.pp = _projection->ll2xy(points.at(i).ll); + points[i].rp.pp = _projection.ll2xy(points.at(i).ll); rp.append(points.at(i).rp); } @@ -254,14 +248,15 @@ bool MapFile::computeTransformation(QList &points) bool MapFile::load(QIODevice &file) { QList points; - QString projection, datum; + QString ct, datum; Projection::Setup setup; + const GCS *gcs; - if (!parseMapFile(file, points, projection, setup, datum)) + if (!parseMapFile(file, points, ct, setup, datum)) return false; - if (!createDatum(datum)) + if (!(gcs = createGCS(datum))) return false; - if (!createProjection(projection, setup, points)) + if (!createProjection(gcs, ct, setup, points)) return false; if (!computeTransformation(points)) return false; diff --git a/src/map/mapfile.h b/src/map/mapfile.h index de433ab3..c09b0e73 100644 --- a/src/map/mapfile.h +++ b/src/map/mapfile.h @@ -11,17 +11,15 @@ class MapFile { public: bool load(QIODevice &file); + const QString &errorString() const {return _errorString;} - const GCS *gcs() const {return _gcs;} - Projection *projection() const {return _projection;} + const Projection &projection() const {return _projection;} const QTransform &transform() const {return _transform;} const QString &name() const {return _name;} const QString &image() const {return _image;} const QSize &size() const {return _size;} - const QString &errorString() const {return _errorString;} - private: struct CalibrationPoint { ReferencePoint rp; @@ -33,8 +31,8 @@ private: QString &projection, Projection::Setup &setup, QString &datum); bool parseMapFile(QIODevice &device, QList &points, QString &projection, Projection::Setup &setup, QString &datum); - bool createDatum(const QString &datum); - bool createProjection(const QString &projection, + const GCS *createGCS(const QString &datum); + bool createProjection(const GCS *gcs, const QString &projection, const Projection::Setup &setup, QList &points); bool computeTransformation(QList &points); @@ -42,8 +40,7 @@ private: QString _image; QSize _size; - const GCS *_gcs; - Projection *_projection; + Projection _projection; QTransform _transform; QString _errorString; diff --git a/src/map/mercator.h b/src/map/mercator.h index 0ec7ca96..0068bef7 100644 --- a/src/map/mercator.h +++ b/src/map/mercator.h @@ -1,11 +1,13 @@ #ifndef MERCATOR_H #define MERCATOR_H -#include "projection.h" +#include "ct.h" -class Mercator : public Projection +class Mercator : public CT { public: + virtual CT *clone() const {return new Mercator(*this);} + virtual QPointF ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const QPointF &p) const; }; diff --git a/src/map/offlinemap.cpp b/src/map/offlinemap.cpp index 2642ff8b..6529b5be 100644 --- a/src/map/offlinemap.cpp +++ b/src/map/offlinemap.cpp @@ -112,7 +112,6 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent) _valid = false; _img = 0; - _projection = 0; _resolution = 0.0; _zoom = 0; _scale = QPointF(1.0, 1.0); @@ -138,7 +137,6 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent) _name = mf.name(); _size = mf.size(); _imgPath = mf.image(); - _gcs = mf.gcs(); _projection = mf.projection(); _transform = mf.transform(); } @@ -152,7 +150,6 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent) _name = mf.name(); _size = mf.size(); _imgPath = mf.image(); - _gcs = mf.gcs(); _projection = mf.projection(); _transform = mf.transform(); } @@ -164,7 +161,6 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent) } else { _name = fi.fileName(); _imgPath = fileName; - _gcs = gt.gcs(); _projection = gt.projection(); _transform = gt.transform(); } @@ -207,7 +203,6 @@ OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent) _valid = false; _img = 0; - _projection = 0; _resolution = 0.0; _zoom = 0; _scale = QPointF(1.0, 1.0); @@ -230,7 +225,6 @@ OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent) _name = mf.name(); _size = mf.size(); - _gcs = mf.gcs(); _projection = mf.projection(); _transform = mf.transform(); @@ -244,7 +238,6 @@ OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent) OfflineMap::~OfflineMap() { delete _img; - delete _projection; } void OfflineMap::load() @@ -363,19 +356,19 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect) QPointF OfflineMap::ll2xy(const Coordinates &c) { if (_ozf.isOpen()) { - QPointF p(_transform.map(_projection->ll2xy(_gcs->fromWGS84(c)))); + QPointF p(_transform.map(_projection.ll2xy(c))); return QPointF(p.x() * _scale.x(), p.y() * _scale.y()); } else - return _transform.map(_projection->ll2xy(_gcs->fromWGS84(c))); + return _transform.map(_projection.ll2xy(c)); } Coordinates OfflineMap::xy2ll(const QPointF &p) { if (_ozf.isOpen()) { - return _gcs->toWGS84(_projection->xy2ll(_inverted.map(QPointF(p.x() - / _scale.x(), p.y() / _scale.y())))); + return _projection.xy2ll(_inverted.map(QPointF(p.x() / _scale.x(), + p.y() / _scale.y()))); } else - return _gcs->toWGS84(_projection->xy2ll(_inverted.map(p))); + return _projection.xy2ll(_inverted.map(p)); } QRectF OfflineMap::bounds() const @@ -402,8 +395,8 @@ qreal OfflineMap::zoomFit(const QSize &size, const RectC &br) if (!br.isValid()) rescale(0); else { - QRect sbr(QRectF(_transform.map(_projection->ll2xy(br.topLeft())), - _transform.map(_projection->ll2xy(br.bottomRight()))) + QRect sbr(QRectF(_transform.map(_projection.ll2xy(br.topLeft())), + _transform.map(_projection.ll2xy(br.bottomRight()))) .toRect().normalized()); for (int i = 0; i < _ozf.zooms(); i++) { diff --git a/src/map/offlinemap.h b/src/map/offlinemap.h index dd750e96..73c81dac 100644 --- a/src/map/offlinemap.h +++ b/src/map/offlinemap.h @@ -2,10 +2,9 @@ #define OFFLINEMAP_H #include -#include "common/coordinates.h" -#include "gcs.h" #include "projection.h" #include "transform.h" +#include "linearunits.h" #include "map.h" #include "tar.h" #include "ozf.h" @@ -45,7 +44,7 @@ public: const QString &errorString() const {return _errorString;} QPointF ll2pp(const Coordinates &c) const - {return _projection->ll2xy(c);} + {return _projection.ll2xy(c);} QPointF xy2pp(const QPointF &p) const {return _inverted.map(p);} QPointF pp2xy(const QPointF &p) const @@ -65,9 +64,7 @@ private: QString _name; - QSize _size; - const GCS *_gcs; - Projection *_projection; + Projection _projection; QTransform _transform, _inverted; OZF _ozf; @@ -77,6 +74,7 @@ private: QString _imgPath; QSize _tileSize; QString _tileName; + QSize _size; int _zoom; qreal _resolution; diff --git a/src/map/projection.cpp b/src/map/projection.cpp index 537d48a5..82e31560 100644 --- a/src/map/projection.cpp +++ b/src/map/projection.cpp @@ -4,6 +4,8 @@ #include "lambertconic.h" #include "albersequal.h" #include "lambertazimuthal.h" +#include "latlon.h" +#include "gcs.h" #include "projection.h" @@ -24,42 +26,85 @@ Projection::Method::Method(int id) } } -Projection *Projection::projection(const Datum &datum, const Method &method, - const Setup &setup) +Projection::Projection(const GCS *gcs, const Method &method, const Setup &setup, + const LinearUnits &units) : _gcs(gcs), _units(units) { - const Ellipsoid *ellipsoid = datum.ellipsoid(); + const Ellipsoid *ellipsoid = _gcs->datum().ellipsoid(); switch (method.id()) { case 9807: - return new TransverseMercator(ellipsoid, setup.latitudeOrigin(), + _ct = new TransverseMercator(ellipsoid, setup.latitudeOrigin(), setup.longitudeOrigin(), setup.scale(), setup.falseEasting(), setup.falseNorthing()); + break; case 1024: case 9841: - return new Mercator(); + _ct = new Mercator(); + break; case 9802: - return new LambertConic2(ellipsoid, setup.standardParallel1(), + _ct = new LambertConic2(ellipsoid, setup.standardParallel1(), setup.standardParallel2(), setup.latitudeOrigin(), setup.longitudeOrigin(), setup.falseEasting(), setup.falseNorthing()); + break; case 9801: - return new LambertConic1(ellipsoid, setup.latitudeOrigin(), + _ct = new LambertConic1(ellipsoid, setup.latitudeOrigin(), setup.longitudeOrigin(), setup.scale(), setup.falseEasting(), setup.falseNorthing()); + break; case 9820: - return new LambertAzimuthal(ellipsoid, setup.latitudeOrigin(), + _ct = new LambertAzimuthal(ellipsoid, setup.latitudeOrigin(), setup.longitudeOrigin(), setup.falseEasting(), setup.falseNorthing()); + break; case 9822: - return new AlbersEqual(ellipsoid, setup.standardParallel1(), + _ct = new AlbersEqual(ellipsoid, setup.standardParallel1(), setup.standardParallel2(), setup.latitudeOrigin(), setup.longitudeOrigin(), setup.falseEasting(), setup.falseNorthing()); + break; default: - return 0; + _ct = 0; } } +Projection::Projection(const GCS *gcs) : _gcs(gcs) +{ + _ct = new LatLon(gcs->angularUnits()); + _units = LinearUnits(9001); +} + +Projection::Projection(const Projection &p) +{ + _gcs = p._gcs; + _units = p._units; + _ct = p._ct->clone(); +} + +Projection::~Projection() +{ + delete _ct; +} + +Projection &Projection::operator=(const Projection &p) +{ + _gcs = p._gcs; + _units = p._units; + _ct = p._ct->clone(); + + return *this; +} + +QPointF Projection::ll2xy(const Coordinates &c) const +{ + return _units.fromMeters(_ct->ll2xy(_gcs->fromWGS84(c))); +} + +Coordinates Projection::xy2ll(const QPointF &p) const +{ + return _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p))); +} + QDebug operator<<(QDebug dbg, const Projection::Setup &setup) { dbg.nospace() << "Setup(" << setup.latitudeOrigin() << ", " diff --git a/src/map/projection.h b/src/map/projection.h index bb664d9b..9c9bb2e0 100644 --- a/src/map/projection.h +++ b/src/map/projection.h @@ -4,8 +4,11 @@ #include #include #include "common/coordinates.h" +#include "linearunits.h" -class Datum; +class GCS; +class CT; +class AngularUnits; class Projection { public: @@ -65,13 +68,22 @@ public: int _id; }; - virtual ~Projection() {} + Projection() : _gcs(0), _ct(0) {} + Projection(const Projection &p); + Projection(const GCS *gcs, const Method &method, const Setup &setup, + const LinearUnits &units); + Projection(const GCS *gcs); + ~Projection(); - virtual QPointF ll2xy(const Coordinates &c) const = 0; - virtual Coordinates xy2ll(const QPointF &p) const = 0; + Projection &operator=(const Projection &p); - static Projection *projection(const Datum &datum, const Method &method, - const Setup &setup); + QPointF ll2xy(const Coordinates &c) const; + Coordinates xy2ll(const QPointF &p) const; + +private: + const GCS * _gcs; + CT *_ct; + LinearUnits _units; }; QDebug operator<<(QDebug dbg, const Projection::Setup &setup); diff --git a/src/map/transversemercator.h b/src/map/transversemercator.h index a8e086ab..13c78bd4 100644 --- a/src/map/transversemercator.h +++ b/src/map/transversemercator.h @@ -1,16 +1,18 @@ #ifndef TRANSVERSEMERCATOR_H #define TRANSVERSEMERCATOR_H -#include "projection.h" +#include "ct.h" #include "ellipsoid.h" -class TransverseMercator : public Projection +class TransverseMercator : public CT { public: TransverseMercator(const Ellipsoid *ellipsoid, double latitudeOrigin, double longitudeOrigin, double scale, double falseEasting, double falseNorthing); + virtual CT *clone() const {return new TransverseMercator(*this);} + virtual QPointF ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const QPointF &p) const;