From c1584f30d2f261684a305b33bcd4b8b076b8f706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Tue, 21 Apr 2020 23:26:35 +0200 Subject: [PATCH] Limit the map bounds properly based on projection, not a magic height --- src/map/albersequal.cpp | 11 +++++++++++ src/map/albersequal.h | 1 + src/map/angularunits.h | 7 +++---- src/map/coordinatesystem.h | 3 +++ src/map/ct.h | 1 + src/map/gcs.h | 11 ++++++----- src/map/imgmap.cpp | 15 ++++++++++----- src/map/krovak.cpp | 15 +++++++++++++++ src/map/krovak.h | 2 ++ src/map/lambertazimuthal.cpp | 8 ++++++++ src/map/lambertazimuthal.h | 1 + src/map/lambertconic.cpp | 16 ++++++++++++++++ src/map/lambertconic.h | 2 ++ src/map/latlon.h | 5 +++++ src/map/linearunits.h | 7 +++---- src/map/mercator.cpp | 10 ++++++++++ src/map/mercator.h | 1 + src/map/obliquestereographic.cpp | 10 ++++++++++ src/map/obliquestereographic.h | 2 ++ src/map/polarstereographic.cpp | 11 +++++++++++ src/map/polarstereographic.h | 2 ++ src/map/projection.cpp | 21 +++++++++++++++++++-- src/map/projection.h | 1 + src/map/transversemercator.cpp | 11 +++++++++++ src/map/transversemercator.h | 1 + src/map/webmercator.cpp | 6 ++++++ src/map/webmercator.h | 1 + 27 files changed, 162 insertions(+), 20 deletions(-) diff --git a/src/map/albersequal.cpp b/src/map/albersequal.cpp index f93ad20a..ab3fe827 100644 --- a/src/map/albersequal.cpp +++ b/src/map/albersequal.cpp @@ -222,3 +222,14 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const return Coordinates(rad2deg(lon), rad2deg(lat)); } + +bool AlbersEqual::operator==(const CT &ct) const +{ + const AlbersEqual *other = dynamic_cast(&ct); + return (other != 0 && _latitudeOrigin == other->_latitudeOrigin + && _longitudeOrigin == other->_longitudeOrigin + && _falseEasting == other->_falseEasting + && _falseNorthing == other->_falseNorthing && _a2 == other->_a2 + && _es == other->_es && _rho0 == other->_rho0 && _c == other->_c + && _n == other->_n); +} diff --git a/src/map/albersequal.h b/src/map/albersequal.h index 2f3f10c9..63aefca7 100644 --- a/src/map/albersequal.h +++ b/src/map/albersequal.h @@ -13,6 +13,7 @@ public: double falseEasting, double falseNorthing); virtual CT *clone() const {return new AlbersEqual(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; diff --git a/src/map/angularunits.h b/src/map/angularunits.h index c484e09b..d605c341 100644 --- a/src/map/angularunits.h +++ b/src/map/angularunits.h @@ -10,13 +10,15 @@ public: AngularUnits() : _code(0), _f(NAN) {} AngularUnits(int code); + bool operator==(const AngularUnits &other) const + {return (_code == other._code && _f == other._f);} + bool isNull() const {return std::isnan(_f);} bool isValid() const {return !std::isnan(_f);} double toDegrees(double val) const; double fromDegrees(double val) const; - friend bool operator==(const AngularUnits &au1, const AngularUnits &au2); #ifndef QT_NO_DEBUG friend QDebug operator<<(QDebug dbg, const AngularUnits &au); #endif // QT_NO_DEBUG @@ -25,9 +27,6 @@ private: double _f; }; -inline bool operator==(const AngularUnits &au1, const AngularUnits &au2) - {return (au1._f == au2._f);} - #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const AngularUnits &au); #endif // QT_NO_DEBUG diff --git a/src/map/coordinatesystem.h b/src/map/coordinatesystem.h index f48788f3..030c0643 100644 --- a/src/map/coordinatesystem.h +++ b/src/map/coordinatesystem.h @@ -12,6 +12,9 @@ public: CoordinateSystem(AxisOrder axisOrder) : _axisOrder(axisOrder) {} CoordinateSystem(int code); + bool operator==(const CoordinateSystem &other) const + {return (_axisOrder == other._axisOrder);} + bool isNull() const {return (_axisOrder == Unknown);} bool isValid() const {return (_axisOrder != Unknown);} diff --git a/src/map/ct.h b/src/map/ct.h index 64b2ac65..a5bc8e0a 100644 --- a/src/map/ct.h +++ b/src/map/ct.h @@ -9,6 +9,7 @@ public: virtual ~CT() {} virtual CT *clone() const = 0; + virtual bool operator==(const CT &ct) const = 0; virtual PointD ll2xy(const Coordinates &c) const = 0; virtual Coordinates xy2ll(const PointD &p) const = 0; diff --git a/src/map/gcs.h b/src/map/gcs.h index 3834ea8e..f58ce882 100644 --- a/src/map/gcs.h +++ b/src/map/gcs.h @@ -14,6 +14,12 @@ public: const AngularUnits &angularUnits) : _datum(datum), _primeMeridian(primeMeridian), _angularUnits(angularUnits) {} + bool operator==(const GCS &other) const + { + return (_datum == other._datum && _primeMeridian == other._primeMeridian + && _angularUnits == other._angularUnits); + } + const PrimeMeridian &primeMeridian() const {return _primeMeridian;} const AngularUnits &angularUnits() const {return _angularUnits;} const Datum &datum() const {return _datum;} @@ -47,11 +53,6 @@ private: static QList _gcss; }; -inline bool operator==(const GCS &gcs1, const GCS &gcs2) - {return (gcs1.datum() == gcs2.datum() - && gcs1.primeMeridian() == gcs2.primeMeridian() - && gcs1.angularUnits() == gcs2.angularUnits());} - #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const GCS &gcs); #endif // QT_NO_DEBUG diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index c881474f..b3fd02d9 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -245,11 +245,7 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent) return; } - // Limit world maps bounds so that the maps can be projected using - // the default Web Mercator projection - _dataBounds = (_data->bounds().height() > 120) - ? _data->bounds() & OSM::BOUNDS : _data->bounds(); - + _dataBounds = _data->bounds() & OSM::BOUNDS; _zoom = _data->zooms().min(); updateTransform(); @@ -631,7 +627,16 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) void IMGMap::setProjection(const Projection &projection) { + if (projection == _projection) + return; + _projection = projection; + // Limit the bounds for some well known Mercator projections + // (GARMIN world maps have N/S bounds up to 90/-90!) + _dataBounds = (_projection == PCS::pcs(3857) + || _projection == PCS::pcs(3395)) + ? _data->bounds() & OSM::BOUNDS : _data->bounds(); + updateTransform(); QPixmapCache::clear(); } diff --git a/src/map/krovak.cpp b/src/map/krovak.cpp index 84d5b922..16e03116 100644 --- a/src/map/krovak.cpp +++ b/src/map/krovak.cpp @@ -68,3 +68,18 @@ Coordinates Krovak::xy2ll(const PointD &p) const return Coordinates(rad2deg(_lambda0 - V/_b), rad2deg(phi)); } + +bool Krovak::operator==(const CT &ct) const +{ + const Krovak *other = dynamic_cast(&ct); + return (other != 0 && _e == other->_e && _a == other->_a && _b == other->_b + && _t0 == other->_t0 && _r0 == other->_r0 && _phiP == other->_phiP + && _cosAlphaC == other->_cosAlphaC && _sinAlphaC == other->_sinAlphaC + && _lambda0 == other->_lambda0 && _fe == other->_fe && _fn == other->_fn); +} + +bool KrovakNE::operator==(const CT &ct) const +{ + const KrovakNE *other = dynamic_cast(&ct); + return (other != 0 && _k == other->_k); +} diff --git a/src/map/krovak.h b/src/map/krovak.h index 17bbb983..e66b2fdf 100644 --- a/src/map/krovak.h +++ b/src/map/krovak.h @@ -13,6 +13,7 @@ public: double longitudeOrigin, double falseEasting, double falseNorthing); virtual CT *clone() const {return new Krovak(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; @@ -32,6 +33,7 @@ public: longitudeOrigin, falseEasting, falseNorthing) {} virtual CT *clone() const {return new KrovakNE(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const {PointD p(_k.ll2xy(c)); return PointD(-p.x(), -p.y());} diff --git a/src/map/lambertazimuthal.cpp b/src/map/lambertazimuthal.cpp index da1ad89e..7a0cea44 100644 --- a/src/map/lambertazimuthal.cpp +++ b/src/map/lambertazimuthal.cpp @@ -68,3 +68,11 @@ Coordinates LambertAzimuthal::xy2ll(const PointD &p) const return Coordinates(rad2deg(lon), rad2deg(lat)); } + +bool LambertAzimuthal::operator==(const CT &ct) const +{ + const LambertAzimuthal *other = dynamic_cast(&ct); + return (other != 0 && _lon0 == other->_lon0 && _fn == other->_fn + && _fe == other->_fe && _a == other->_a && _es == other->_es + && _beta0 == other->_beta0 && _rq == other->_rq && _d == other->_d); +} diff --git a/src/map/lambertazimuthal.h b/src/map/lambertazimuthal.h index f7aab623..25a7cd75 100644 --- a/src/map/lambertazimuthal.h +++ b/src/map/lambertazimuthal.h @@ -12,6 +12,7 @@ public: double longitudeOrigin, double falseEasting, double falseNorthing); virtual CT *clone() const {return new LambertAzimuthal(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; diff --git a/src/map/lambertconic.cpp b/src/map/lambertconic.cpp index 30c4ba25..b10cb7fd 100644 --- a/src/map/lambertconic.cpp +++ b/src/map/lambertconic.cpp @@ -194,6 +194,16 @@ Coordinates LambertConic1::xy2ll(const PointD &p) const return Coordinates(rad2deg(lon), rad2deg(lat)); } +bool LambertConic1::operator==(const CT &ct) const +{ + const LambertConic1 *other = dynamic_cast(&ct); + return (other != 0 && _longitudeOrigin == other->_longitudeOrigin + && _falseEasting == other->_falseEasting + && _falseNorthing == other->_falseNorthing && _e == other->_e + && _n == other->_n && _rho0 == other->_rho0); +} + + LambertConic2::LambertConic2(const Ellipsoid *ellipsoid, double standardParallel1, double standardParallel2, double latitudeOrigin, double longitudeOrigin, double falseEasting, double falseNorthing) @@ -264,3 +274,9 @@ Coordinates LambertConic2::xy2ll(const PointD &p) const { return _lc1.xy2ll(p); } + +bool LambertConic2::operator==(const CT &ct) const +{ + const LambertConic2 *other = dynamic_cast(&ct); + return (other != 0 && _lc1 == other->_lc1); +} diff --git a/src/map/lambertconic.h b/src/map/lambertconic.h index de1e9685..e8c94d63 100644 --- a/src/map/lambertconic.h +++ b/src/map/lambertconic.h @@ -14,6 +14,7 @@ public: double falseNorthing); virtual CT *clone() const {return new LambertConic1(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; @@ -39,6 +40,7 @@ public: double falseEasting, double falseNorthing); virtual CT *clone() const {return new LambertConic2(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; diff --git a/src/map/latlon.h b/src/map/latlon.h index 06747276..0d4b94ef 100644 --- a/src/map/latlon.h +++ b/src/map/latlon.h @@ -10,6 +10,11 @@ public: LatLon(const AngularUnits &au) : _au(au) {} virtual CT *clone() const {return new LatLon(*this);} + virtual bool operator==(const CT &ct) const + { + const LatLon *other = dynamic_cast(&ct); + return (other != 0 && _au == other->_au); + } virtual PointD ll2xy(const Coordinates &c) const {return PointD(_au.fromDegrees(c.lon()), _au.fromDegrees(c.lat()));} diff --git a/src/map/linearunits.h b/src/map/linearunits.h index 04265f4b..c70d8e69 100644 --- a/src/map/linearunits.h +++ b/src/map/linearunits.h @@ -11,6 +11,9 @@ public: LinearUnits() : _f(NAN) {} LinearUnits(int code); + bool operator==(const LinearUnits &other) const + {return (_f == other._f);} + bool isNull() const {return std::isnan(_f);} bool isValid() const {return !std::isnan(_f);} @@ -21,7 +24,6 @@ public: PointD fromMeters(const PointD &p) const {return PointD(p.x() / _f, p.y() /_f);} - friend bool operator==(const LinearUnits &lu1, const LinearUnits &lu2); #ifndef QT_NO_DEBUG friend QDebug operator<<(QDebug dbg, const LinearUnits &lu); #endif // QT_NO_DEBUG @@ -30,9 +32,6 @@ private: double _f; }; -inline bool operator==(const LinearUnits &lu1, const LinearUnits &lu2) - {return (lu1._f == lu2._f);} - #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const LinearUnits &lu); #endif // QT_NO_DEBUG diff --git a/src/map/mercator.cpp b/src/map/mercator.cpp index dd891c72..6841da51 100644 --- a/src/map/mercator.cpp +++ b/src/map/mercator.cpp @@ -121,3 +121,13 @@ Coordinates Mercator::xy2ll(const PointD &p) const return Coordinates(rad2deg(lon), rad2deg(lat)); } + +bool Mercator::operator==(const CT &ct) const +{ + const Mercator *other = dynamic_cast(&ct); + return (other != 0 && _a == other->_a && _e == other->_e + && _latitudeOrigin == other->_latitudeOrigin + && _longitudeOrigin == other->_longitudeOrigin + && _falseNorthing == other->_falseNorthing + && _falseEasting == other->_falseEasting); +} diff --git a/src/map/mercator.h b/src/map/mercator.h index 39d0390b..81fd1178 100644 --- a/src/map/mercator.h +++ b/src/map/mercator.h @@ -12,6 +12,7 @@ public: double longitudeOrigin, double falseEasting, double falseNorthing); virtual CT *clone() const {return new Mercator(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; diff --git a/src/map/obliquestereographic.cpp b/src/map/obliquestereographic.cpp index b3add846..775476a0 100644 --- a/src/map/obliquestereographic.cpp +++ b/src/map/obliquestereographic.cpp @@ -80,3 +80,13 @@ Coordinates ObliqueStereographic::xy2ll(const PointD &p) const return Coordinates(rad2deg((lambda - _lambda0) / _n + _lambda0), rad2deg(phi)); } + +bool ObliqueStereographic::operator==(const CT &ct) const +{ + const ObliqueStereographic *other + = dynamic_cast(&ct); + return (other != 0 && _es == other->_es && _chi0 == other->_chi0 + && _sinChi0 == other->_sinChi0 && _cosChi0 == other->_cosChi0 + && _lambda0 == other->_lambda0 && _n == other->_n && _c == other->_c + && _fe == other->_fe && _fn == other->_fn && _twoRk0 == other->_twoRk0); +} diff --git a/src/map/obliquestereographic.h b/src/map/obliquestereographic.h index 429be7dc..9b335628 100644 --- a/src/map/obliquestereographic.h +++ b/src/map/obliquestereographic.h @@ -11,7 +11,9 @@ public: ObliqueStereographic(const Ellipsoid *ellipsoid, double latitudeOrigin, double longitudeOrigin, double scale, double falseEasting, double falseNorthing); + virtual CT *clone() const {return new ObliqueStereographic(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; diff --git a/src/map/polarstereographic.cpp b/src/map/polarstereographic.cpp index 6d790d84..e65933a4 100644 --- a/src/map/polarstereographic.cpp +++ b/src/map/polarstereographic.cpp @@ -190,3 +190,14 @@ Coordinates PolarStereographic::xy2ll(const PointD &p) const return Coordinates(rad2deg(Longitude), rad2deg(Latitude)); } + +bool PolarStereographic::operator==(const CT &ct) const +{ + const PolarStereographic *other + = dynamic_cast(&ct); + return (other != 0 && _originLatitude == other->_originLatitude + && _originLongitude == other->_originLongitude + && _falseEasting == other->_falseEasting + && _falseNorthing == other->_falseNorthing && _two_a == other->_two_a + && _es == other->_es); +} diff --git a/src/map/polarstereographic.h b/src/map/polarstereographic.h index 7ac606ff..eb25cb39 100644 --- a/src/map/polarstereographic.h +++ b/src/map/polarstereographic.h @@ -10,7 +10,9 @@ class PolarStereographic : public CT public: PolarStereographic(const Ellipsoid *ellipsoid, double latitudeOrigin, double longitudeOrigin, double falseEasting, double falseNorthing); + virtual CT *clone() const {return new PolarStereographic(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; diff --git a/src/map/projection.cpp b/src/map/projection.cpp index 1293c1ef..d0d022f8 100644 --- a/src/map/projection.cpp +++ b/src/map/projection.cpp @@ -36,9 +36,15 @@ Projection::Method::Method(int id) } } -Projection::Projection(const PCS *pcs) : _gcs(pcs->gcs()), _units(pcs->units()), - _cs(pcs->coordinateSystem()), _geographic(false) +Projection::Projection(const PCS *pcs) : _gcs(0), _ct(0), _geographic(false) { + if (!pcs) + return; + + _gcs = pcs->gcs(); + _units = pcs->units(); + _cs = pcs->coordinateSystem(); + const Ellipsoid *ellipsoid = _gcs->datum().ellipsoid(); const Projection::Setup &setup = pcs->setup(); @@ -109,6 +115,8 @@ Projection::Projection(const PCS *pcs) : _gcs(pcs->gcs()), _units(pcs->units()), Projection::Projection(const GCS *gcs, const CoordinateSystem &cs) : _gcs(gcs), _units(LinearUnits(9001)), _cs(cs), _geographic(true) { + if (!gcs) + return; _ct = new LatLon(gcs->angularUnits()); } @@ -141,6 +149,15 @@ Projection &Projection::operator=(const Projection &p) return *this; } +bool Projection::operator==(const Projection &p) const +{ + if (!isValid() || !p.isValid()) + return false; + + return (*_ct == *p._ct && *_gcs == *p._gcs && _units == p._units + && _cs == p._cs && _geographic == p._geographic); +} + PointD Projection::ll2xy(const Coordinates &c) const { Q_ASSERT(isValid()); diff --git a/src/map/projection.h b/src/map/projection.h index bcaf4c74..a13e248c 100644 --- a/src/map/projection.h +++ b/src/map/projection.h @@ -78,6 +78,7 @@ public: ~Projection(); Projection &operator=(const Projection &p); + bool operator==(const Projection &p) const; bool isNull() const {return (_gcs == 0 && _ct == 0 && _units.isNull());} bool isValid() const {return !(_gcs == 0 || _ct == 0 || _units.isNull());} diff --git a/src/map/transversemercator.cpp b/src/map/transversemercator.cpp index 4edd8944..5cdbbb9f 100644 --- a/src/map/transversemercator.cpp +++ b/src/map/transversemercator.cpp @@ -252,3 +252,14 @@ Coordinates TransverseMercator::xy2ll(const PointD &p) const return Coordinates(rad2deg(lon), rad2deg(lat)); } + +bool TransverseMercator::operator==(const CT &ct) const +{ + const TransverseMercator *other + = dynamic_cast(&ct); + return (other != 0 && _longitudeOrigin == other->_longitudeOrigin + && _latitudeOrigin == other->_latitudeOrigin && _scale == other->_scale + && _falseEasting == other->_falseEasting + && _falseNorthing == other->_falseNorthing && _a == other->_a + && _es == other->_es); +} diff --git a/src/map/transversemercator.h b/src/map/transversemercator.h index 9e9e2f18..f22ab444 100644 --- a/src/map/transversemercator.h +++ b/src/map/transversemercator.h @@ -13,6 +13,7 @@ public: double falseNorthing); virtual CT *clone() const {return new TransverseMercator(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const; diff --git a/src/map/webmercator.cpp b/src/map/webmercator.cpp index 66dd4978..e9e2e306 100644 --- a/src/map/webmercator.cpp +++ b/src/map/webmercator.cpp @@ -14,3 +14,9 @@ Coordinates WebMercator::xy2ll(const PointD &p) const return Coordinates(rad2deg(p.x() / WGS84_RADIUS), rad2deg(2.0 * atan(exp(p.y() / WGS84_RADIUS)) - M_PI_2)); } + +bool WebMercator::operator==(const CT &ct) const +{ + const WebMercator *other = dynamic_cast(&ct); + return (other != 0); +} diff --git a/src/map/webmercator.h b/src/map/webmercator.h index 3231bc77..7642e4fc 100644 --- a/src/map/webmercator.h +++ b/src/map/webmercator.h @@ -7,6 +7,7 @@ class WebMercator : public CT { public: virtual CT *clone() const {return new WebMercator(*this);} + virtual bool operator==(const CT &ct) const; virtual PointD ll2xy(const Coordinates &c) const; virtual Coordinates xy2ll(const PointD &p) const;