diff --git a/gpxsee.pro b/gpxsee.pro index e094c499..40b65ac6 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -94,7 +94,8 @@ HEADERS += src/config.h \ src/datum.h \ src/maplist.h \ src/albersequal.h \ - src/oddspinbox.h + src/oddspinbox.h \ + src/rectc.h SOURCES += src/main.cpp \ src/gui.cpp \ src/poi.cpp \ @@ -162,7 +163,8 @@ SOURCES += src/main.cpp \ src/datum.cpp \ src/maplist.cpp \ src/albersequal.cpp \ - src/oddspinbox.cpp + src/oddspinbox.cpp \ + src/rectc.cpp RESOURCES += gpxsee.qrc TRANSLATIONS = lang/gpxsee_cs.ts \ lang/gpxsee_sv.ts \ diff --git a/src/atlas.cpp b/src/atlas.cpp index b2848e1f..6611da0d 100644 --- a/src/atlas.cpp +++ b/src/atlas.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "rectc.h" #include "tar.h" #include "atlas.h" @@ -198,7 +199,7 @@ qreal Atlas::zoom() const return _zoom; } -qreal Atlas::zoomFit(const QSize &size, const QRectF &br) +qreal Atlas::zoomFit(const QSize &size, const RectC &br) { _zoom = 0; diff --git a/src/atlas.h b/src/atlas.h index ac3ab464..ea52d85e 100644 --- a/src/atlas.h +++ b/src/atlas.h @@ -20,7 +20,7 @@ public: qreal resolution(const QPointF &p) const; qreal zoom() const; - qreal zoomFit(const QSize &size, const QRectF &br); + qreal zoomFit(const QSize &size, const RectC &br); qreal zoomFit(qreal resolution, const Coordinates &c); qreal zoomIn(); qreal zoomOut(); diff --git a/src/coordinates.cpp b/src/coordinates.cpp index 436afea4..0cfab3e3 100644 --- a/src/coordinates.cpp +++ b/src/coordinates.cpp @@ -22,7 +22,7 @@ QDebug operator<<(QDebug dbg, const Coordinates &coordinates) dbg.nospace() << "Coordinates(" << coordinates.lon() << ", " << coordinates.lat() << ")"; - return dbg.space(); + return dbg.maybeSpace(); } QPair Coordinates::boundingRect(qreal distance) const diff --git a/src/coordinates.h b/src/coordinates.h index 3a7db43e..7ea64c29 100644 --- a/src/coordinates.h +++ b/src/coordinates.h @@ -2,7 +2,7 @@ #define COORDINATES_H #include -#include +#include #include class Coordinates @@ -12,9 +12,6 @@ public: Coordinates(const Coordinates &c) {_lon = c._lon; _lat = c._lat;} Coordinates(qreal lon, qreal lat) {_lon = lon; _lat = lat;} - Coordinates(const QPointF &p) {_lon = p.x(), _lat = p.y();} - QPointF toPointF() const {return QPointF(_lon, _lat);} - qreal &rlon() {return _lon;} qreal &rlat() {return _lat;} void setLon(qreal lon) {_lon = lon;} @@ -39,6 +36,7 @@ inline bool operator==(const Coordinates &c1, const Coordinates &c2) {return (c1.lat() == c2.lat() && c1.lon() == c2.lon());} inline bool operator!=(const Coordinates &c1, const Coordinates &c2) {return !(c1 == c2);} + QDebug operator<<(QDebug dbg, const Coordinates &trackpoint); #endif // COORDINATES_H diff --git a/src/emptymap.cpp b/src/emptymap.cpp index 2fcf4ec4..329f5cab 100644 --- a/src/emptymap.cpp +++ b/src/emptymap.cpp @@ -1,5 +1,6 @@ #include #include +#include "rectc.h" #include "misc.h" #include "rd.h" #include "wgs84.h" @@ -21,17 +22,14 @@ QRectF EmptyMap::bounds() const return scaled(QRectF(QPointF(-180, -180), QSizeF(360, 360)), 1.0/_scale); } -qreal EmptyMap::zoomFit(const QSize &size, const QRectF &br) +qreal EmptyMap::zoomFit(const QSize &size, const RectC &br) { if (br.isNull()) _scale = SCALE_MAX; else { - Coordinates topLeft(br.topLeft()); - Coordinates bottomRight(br.bottomRight()); - QRectF tbr(Mercator().ll2xy(topLeft), Mercator().ll2xy(bottomRight)); - + QRectF tbr(Mercator().ll2xy(br.topLeft()), + Mercator().ll2xy(br.bottomRight())); QPointF sc(tbr.width() / size.width(), tbr.height() / size.height()); - _scale = qMax(sc.x(), sc.y()); } diff --git a/src/emptymap.h b/src/emptymap.h index ddf644bd..65a0d905 100644 --- a/src/emptymap.h +++ b/src/emptymap.h @@ -16,7 +16,7 @@ public: qreal resolution(const QPointF &p) const; qreal zoom() const {return _scale;} - qreal zoomFit(const QSize &size, const QRectF &br); + qreal zoomFit(const QSize &size, const RectC &br); qreal zoomFit(qreal resolution, const Coordinates &c); qreal zoomIn(); qreal zoomOut(); diff --git a/src/latlon.h b/src/latlon.h index 28202854..a99491cb 100644 --- a/src/latlon.h +++ b/src/latlon.h @@ -7,9 +7,9 @@ class LatLon : public Projection { public: virtual QPointF ll2xy(const Coordinates &c) const - {return c.toPointF();} + {return QPointF(c.lon(), c.lat());} virtual Coordinates xy2ll(const QPointF &p) const - {return Coordinates(p);} + {return Coordinates(p.x(), p.y());} }; #endif // LATLON_H diff --git a/src/map.h b/src/map.h index 479b04d2..3945a5ad 100644 --- a/src/map.h +++ b/src/map.h @@ -7,6 +7,7 @@ class QPainter; class Coordinates; +class RectC; class Map : public QObject { @@ -21,7 +22,7 @@ public: virtual qreal resolution(const QPointF &p) const = 0; virtual qreal zoom() const = 0; - virtual qreal zoomFit(const QSize &size, const QRectF &br) = 0; + virtual qreal zoomFit(const QSize &size, const RectC &br) = 0; virtual qreal zoomFit(qreal resolution, const Coordinates &c) = 0; virtual qreal zoomIn() = 0; virtual qreal zoomOut() = 0; diff --git a/src/offlinemap.h b/src/offlinemap.h index 81b965b4..30f40ffa 100644 --- a/src/offlinemap.h +++ b/src/offlinemap.h @@ -27,7 +27,7 @@ public: qreal resolution(const QPointF &) const {return _resolution;} qreal zoom() const {return 0;} - qreal zoomFit(const QSize &, const QRectF &) {return 0;} + qreal zoomFit(const QSize &, const RectC &) {return 0;} qreal zoomFit(qreal, const Coordinates &) {return 0;} qreal zoomIn() {return 0;} qreal zoomOut() {return 0;} diff --git a/src/onlinemap.cpp b/src/onlinemap.cpp index 173d3b62..762d8fe1 100644 --- a/src/onlinemap.cpp +++ b/src/onlinemap.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "rectc.h" #include "downloader.h" #include "config.h" #include "rd.h" @@ -165,14 +166,13 @@ QRectF OnlineMap::bounds() const 1.0/zoom2scale(_zoom)); } -qreal OnlineMap::zoomFit(const QSize &size, const QRectF &br) +qreal OnlineMap::zoomFit(const QSize &size, const RectC &br) { if (br.isNull()) _zoom = ZOOM_MAX; else { - Coordinates topLeft(br.topLeft()); - Coordinates bottomRight(br.bottomRight()); - QRectF tbr(Mercator().ll2xy(topLeft), Mercator().ll2xy(bottomRight)); + QRectF tbr(Mercator().ll2xy(br.topLeft()), + Mercator().ll2xy(br.bottomRight())); QPointF sc(tbr.width() / size.width(), tbr.height() / size.height()); _zoom = scale2zoom(qMax(sc.x(), sc.y())); diff --git a/src/onlinemap.h b/src/onlinemap.h index 6809fee7..5ddde8e9 100644 --- a/src/onlinemap.h +++ b/src/onlinemap.h @@ -19,7 +19,7 @@ public: qreal resolution(const QPointF &p) const; qreal zoom() const {return _zoom;} - qreal zoomFit(const QSize &size, const QRectF &br); + qreal zoomFit(const QSize &size, const RectC &br); qreal zoomFit(qreal resolution, const Coordinates &c); qreal zoomIn(); qreal zoomOut(); diff --git a/src/path.cpp b/src/path.cpp index 8fb14ad7..957ca655 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -1,27 +1,15 @@ #include "path.h" -QRectF Path::boundingRect() const +RectC Path::boundingRect() const { if (size() < 2) - return QRectF(); + return RectC(); - QPointF topLeft(at(0).coordinates().lon(), at(0).coordinates().lat()); - QPointF bottomRight(topLeft); + RectC ret(first().coordinates(), first().coordinates()); + for (int i = 1; i < size(); i++) + ret.unite(at(i).coordinates()); - for (int i = 1; i < size(); i++) { - qreal x = at(i).coordinates().lon(); - qreal y = at(i).coordinates().lat(); - - if (x < topLeft.x()) - topLeft.setX(x); - if (y < topLeft.y()) - topLeft.setY(y); - if (x > bottomRight.x()) - bottomRight.setX(x); - if (y > bottomRight.y()) - bottomRight.setY(y); - } - return QRectF(topLeft, bottomRight); + return ret; } QDebug operator<<(QDebug dbg, const PathPoint &point) diff --git a/src/path.h b/src/path.h index b0cff53b..4e506f99 100644 --- a/src/path.h +++ b/src/path.h @@ -4,6 +4,7 @@ #include #include #include "coordinates.h" +#include "rectc.h" class PathPoint { @@ -28,7 +29,7 @@ QDebug operator<<(QDebug dbg, const PathPoint &point); class Path : public QVector { public: - QRectF boundingRect() const; + RectC boundingRect() const; }; #endif // PATH_H diff --git a/src/pathview.cpp b/src/pathview.cpp index 146b75e1..226eab8d 100644 --- a/src/pathview.cpp +++ b/src/pathview.cpp @@ -21,18 +21,6 @@ #define MARGIN 10.0 #define SCALE_OFFSET 7 -static void unite(QRectF &rect, const QPointF &p) -{ - if (p.x() < rect.left()) - rect.setLeft(p.x()); - if (p.x() > rect.right()) - rect.setRight(p.x()); - if (p.y() > rect.bottom()) - rect.setBottom(p.y()); - if (p.y() < rect.top()) - rect.setTop(p.y()); -} - PathView::PathView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent) { @@ -141,8 +129,7 @@ void PathView::addWaypoints(const QList &waypoints) WaypointItem *wi = new WaypointItem(w, _map); _waypoints.append(wi); - Coordinates c = wi->waypoint().coordinates(); - updateWaypointsBoundingRect(QPointF(c.lon(), c.lat())); + updateWaypointsBoundingRect(wi->waypoint().coordinates()); wi->setZValue(1); wi->showLabel(_showWaypointLabels); wi->setUnits(_units); @@ -184,33 +171,33 @@ QList PathView::loadData(const Data &data) return paths; } -void PathView::updateWaypointsBoundingRect(const QPointF &wp) +void PathView::updateWaypointsBoundingRect(const Coordinates &wp) { if (_wr.isNull()) { if (_wp.isNull()) _wp = wp; else { - _wr = QRectF(_wp, wp).normalized(); - _wp = QPointF(); + _wr = RectC(_wp, wp).normalized(); + _wp = Coordinates(); } } else - unite(_wr, wp); + _wr.unite(wp); } qreal PathView::mapScale() const { - QRectF br = _tr | _rr | _wr; + RectC br = _tr | _rr | _wr; if (!br.isNull() && !_wp.isNull()) - unite(br, _wp); + br.unite(_wp); return _map->zoomFit(viewport()->size() - QSize(MARGIN/2, MARGIN/2), br); } QPointF PathView::contentCenter() const { - QRectF br = _tr | _rr | _wr; + RectC br = _tr | _rr | _wr; if (!br.isNull() && !_wp.isNull()) - unite(br, _wp); + br.unite(_wp); if (br.isNull()) return _map->ll2xy(_wp); @@ -543,8 +530,8 @@ void PathView::clear() _scene->clear(); _palette.reset(); - _tr = QRectF(); _rr = QRectF(); _wr = QRectF(); - _wp = QPointF(); + _tr = RectC(); _rr = RectC(); _wr = RectC(); + _wp = Coordinates(); resetDigitalZoom(); resetCachedContent(); diff --git a/src/pathview.h b/src/pathview.h index 3e3ee14b..e45bdb59 100644 --- a/src/pathview.h +++ b/src/pathview.h @@ -8,6 +8,7 @@ #include "units.h" #include "palette.h" #include "waypoint.h" +#include "rectc.h" class Data; class POI; @@ -80,7 +81,7 @@ private: void digitalZoom(int zoom); void resetDigitalZoom(); void updatePOIVisibility(); - void updateWaypointsBoundingRect(const QPointF &wp); + void updateWaypointsBoundingRect(const Coordinates &wp); void mouseDoubleClickEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); @@ -97,8 +98,8 @@ private: QList _waypoints; QHash _pois; - QRectF _tr, _rr, _wr; - QPointF _wp; + RectC _tr, _rr, _wr; + Coordinates _wp; qreal _res; Map *_map; diff --git a/src/rectc.cpp b/src/rectc.cpp new file mode 100644 index 00000000..a5bce4be --- /dev/null +++ b/src/rectc.cpp @@ -0,0 +1,86 @@ +#include "rectc.h" + +RectC RectC::normalized() const +{ + RectC r; + + if (_br.lon() < _tl.lon()) { + r._tl.setLon(_br.lon()); + r._br.setLon(_tl.lon()); + } else { + r._tl.setLon(_tl.lon()); + r._br.setLon(_br.lon()); + } + + if (_br.lat() < _tl.lat()) { + r._tl.setLat(_br.lat()); + r._br.setLat(_tl.lat()); + } else { + r._tl.setLat(_tl.lat()); + r._br.setLat(_br.lat()); + } + + return r; +} + +RectC RectC::operator|(const RectC &r) const +{ + if (isNull()) + return r; + if (r.isNull()) + return *this; + + qreal l1 = _tl.lon(); + qreal r1 = _tl.lon(); + if (_br.lon() - _tl.lon() < 0) + l1 = _br.lon(); + else + r1 = _br.lon(); + + qreal l2 = r._tl.lon(); + qreal r2 = r._tl.lon(); + if (r._br.lon() - r._tl.lon() < 0) + l2 = r._br.lon(); + else + r2 = r._br.lon(); + + qreal t1 = _tl.lat(); + qreal b1 = _tl.lat(); + if (_br.lat() - _tl.lat() < 0) + t1 = _br.lat(); + else + b1 = _br.lat(); + + qreal t2 = r._tl.lat(); + qreal b2 = r._tl.lat(); + if (r._br.lat() - r._tl.lat() < 0) + t2 = r._br.lat(); + else + b2 = r._br.lat(); + + RectC tmp; + tmp._tl.setLon(qMin(l1, l2)); + tmp._br.setLon(qMax(r1, r2)); + tmp._tl.setLat(qMin(t1, t2)); + tmp._br.setLat(qMax(b1, b2)); + + return tmp; +} + +void RectC::unite(const Coordinates &c) +{ + if (c.lon() < _tl.lon()) + _tl.setLon(c.lon()); + if (c.lon() > _br.lon()) + _br.setLon(c.lon()); + if (c.lat() > _br.lat()) + _br.setLat(c.lat()); + if (c.lat() < _tl.lat()) + _tl.setLat(c.lat()); +} + +QDebug operator<<(QDebug dbg, const RectC &rect) +{ + dbg.nospace() << "RectC(" << rect.topLeft() << ", " << rect.size() << ")"; + return dbg.maybeSpace(); +} diff --git a/src/rectc.h b/src/rectc.h new file mode 100644 index 00000000..e174727f --- /dev/null +++ b/src/rectc.h @@ -0,0 +1,42 @@ +#ifndef RECTC_H +#define RECTC_H + +#include +#include +#include "coordinates.h" + +class RectC +{ +public: + RectC() {} + RectC(const Coordinates &topLeft, const Coordinates &bottomRight) + : _tl(topLeft), _br(bottomRight) {} + + bool isNull() const + {return _tl.isNull() || _br.isNull() || _tl == _br;} + + Coordinates topLeft() const {return _tl;} + Coordinates bottomRight() const {return _br;} + + Coordinates center() const + {return Coordinates((_tl.lon() + _br.lon()) / 2.0, + (_tl.lat() + _br.lat()) / 2.0);} + qreal width() const {return _br.lon() - _tl.lon();} + qreal height() const {return _br.lat() - _tl.lat();} + + QSizeF size() const {return QSizeF(width(), height());} + + RectC normalized() const; + + RectC operator|(const RectC &r) const; + RectC &operator|=(const RectC &r) {*this = *this | r; return *this;} + + void unite(const Coordinates &c); + +private: + Coordinates _tl, _br; +}; + +QDebug operator<<(QDebug dbg, const RectC &rect); + +#endif // RECTC_H