1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 03:35:53 +01:00

Limit the map bounds properly based on projection, not a magic height

This commit is contained in:
Martin Tůma 2020-04-21 23:26:35 +02:00
parent cbe312d9c8
commit c1584f30d2
27 changed files with 162 additions and 20 deletions

View File

@ -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<const AlbersEqual*>(&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);
}

View File

@ -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;

View File

@ -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

View File

@ -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);}

View File

@ -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;

View File

@ -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<Entry> _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

View File

@ -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();
}

View File

@ -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<const Krovak*>(&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<const KrovakNE*>(&ct);
return (other != 0 && _k == other->_k);
}

View File

@ -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());}

View File

@ -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<const LambertAzimuthal*>(&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);
}

View File

@ -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;

View File

@ -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<const LambertConic1*>(&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<const LambertConic2*>(&ct);
return (other != 0 && _lc1 == other->_lc1);
}

View File

@ -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;

View File

@ -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<const LatLon*>(&ct);
return (other != 0 && _au == other->_au);
}
virtual PointD ll2xy(const Coordinates &c) const
{return PointD(_au.fromDegrees(c.lon()), _au.fromDegrees(c.lat()));}

View File

@ -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

View File

@ -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<const Mercator*>(&ct);
return (other != 0 && _a == other->_a && _e == other->_e
&& _latitudeOrigin == other->_latitudeOrigin
&& _longitudeOrigin == other->_longitudeOrigin
&& _falseNorthing == other->_falseNorthing
&& _falseEasting == other->_falseEasting);
}

View File

@ -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;

View File

@ -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<const ObliqueStereographic*>(&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);
}

View File

@ -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;

View File

@ -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<const PolarStereographic*>(&ct);
return (other != 0 && _originLatitude == other->_originLatitude
&& _originLongitude == other->_originLongitude
&& _falseEasting == other->_falseEasting
&& _falseNorthing == other->_falseNorthing && _two_a == other->_two_a
&& _es == other->_es);
}

View File

@ -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;

View File

@ -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());

View File

@ -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());}

View File

@ -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<const TransverseMercator*>(&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);
}

View File

@ -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;

View File

@ -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<const WebMercator*>(&ct);
return (other != 0);
}

View File

@ -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;