From 27194d3d36879fde1598c08bda6a668edd1329b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 24 Oct 2016 00:21:40 +0200 Subject: [PATCH] Added coordinates checking to file parsers Refactoring --- gpxsee.pro | 11 +++--- src/coordinates.cpp | 42 ++++++++++++++++++++++ src/coordinates.h | 35 ++++++++++++++++++ src/csvparser.cpp | 2 +- src/data.cpp | 3 +- src/gpxparser.cpp | 31 +++++++++++----- src/gpxparser.h | 2 ++ src/ll.cpp | 86 -------------------------------------------- src/ll.h | 18 ---------- src/map.cpp | 3 +- src/map.h | 19 +--------- src/misc.cpp | 10 +++--- src/misc.h | 3 +- src/pathview.cpp | 60 +++++++++++++++++++++++++------ src/poi.cpp | 43 +++++++++++----------- src/rd.h | 13 +++++++ src/route.cpp | 3 +- src/routeitem.cpp | 10 +++--- src/scaleitem.cpp | 20 +++++++---- src/tcxparser.cpp | 24 +++++++++---- src/tcxparser.h | 2 +- src/tile.h | 25 +++++++++++++ src/track.cpp | 3 +- src/trackitem.cpp | 10 +++--- src/trackpoint.h | 10 +++--- src/waypoint.h | 10 +++--- src/waypointitem.cpp | 5 ++- src/wgs84.h | 6 ++++ 28 files changed, 288 insertions(+), 221 deletions(-) create mode 100644 src/coordinates.cpp create mode 100644 src/coordinates.h delete mode 100644 src/ll.cpp delete mode 100644 src/ll.h create mode 100644 src/rd.h create mode 100644 src/tile.h create mode 100644 src/wgs84.h diff --git a/gpxsee.pro b/gpxsee.pro index 78529daf..40c00b92 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -10,7 +10,6 @@ HEADERS += src/config.h \ src/gui.h \ src/poi.h \ src/rtree.h \ - src/ll.h \ src/axisitem.h \ src/keys.h \ src/slideritem.h \ @@ -56,11 +55,14 @@ HEADERS += src/config.h \ src/gpxparser.h \ src/tcxparser.h \ src/parser.h \ - src/csvparser.h + src/csvparser.h \ + src/coordinates.h \ + src/tile.h \ + src/rd.h \ + src/wgs84.h SOURCES += src/main.cpp \ src/gui.cpp \ src/poi.cpp \ - src/ll.cpp \ src/axisitem.cpp \ src/slideritem.cpp \ src/markeritem.cpp \ @@ -98,7 +100,8 @@ SOURCES += src/main.cpp \ src/data.cpp \ src/gpxparser.cpp \ src/tcxparser.cpp \ - src/csvparser.cpp + src/csvparser.cpp \ + src/coordinates.cpp RESOURCES += gpxsee.qrc TRANSLATIONS = lang/gpxsee_cs.ts macx { diff --git a/src/coordinates.cpp b/src/coordinates.cpp new file mode 100644 index 00000000..200ac03b --- /dev/null +++ b/src/coordinates.cpp @@ -0,0 +1,42 @@ +#include "rd.h" +#include "wgs84.h" +#include "coordinates.h" + +bool Coordinates::isValid() const +{ + return (_lon >= -180.0 && _lon <= 180.0 && _lat >= -90.0 && _lat <= 90.0) + ? true : false; +} + +qreal Coordinates::distanceTo(const Coordinates &c) const +{ + qreal dLat = deg2rad(c.lat() - _lat); + qreal dLon = deg2rad(c.lon() - _lon); + qreal a = pow(sin(dLat / 2.0), 2.0) + + cos(deg2rad(_lat)) * cos(deg2rad(c.lat())) * pow(sin(dLon / 2.0), 2.0); + + return (WGS84_RADIUS * (2.0 * atan2(sqrt(a), sqrt(1.0 - a)))); +} + +QPointF Coordinates::toMercator() const +{ + return QPointF(_lon, rad2deg(log(tan(M_PI/4.0 + deg2rad(_lat)/2.0)))); +} + +Coordinates Coordinates::fromMercator(const QPointF &m) +{ + return Coordinates(m.x(), rad2deg(2 * atan(exp(deg2rad(m.y()))) - M_PI/2)); +} + +bool operator==(const Coordinates &c1, const Coordinates &c2) +{ + return (c1.lat() == c2.lat() && c1.lon() == c2.lon()); +} + +QDebug operator<<(QDebug dbg, const Coordinates &coordinates) +{ + dbg.nospace() << "Coordinates(" << coordinates.lon() << ", " + << coordinates.lat() << ")"; + + return dbg.maybeSpace(); +} diff --git a/src/coordinates.h b/src/coordinates.h new file mode 100644 index 00000000..d979d5c8 --- /dev/null +++ b/src/coordinates.h @@ -0,0 +1,35 @@ +#ifndef COORDINATES_H +#define COORDINATES_H + +#include +#include +#include + +class Coordinates +{ +public: + Coordinates() {_lon = NAN; _lat = NAN;} + Coordinates(const Coordinates &c) {_lon = c._lon; _lat = c._lat;} + Coordinates(qreal lon, qreal lat) {_lon = lon; _lat = lat;} + + qreal &rLon() {return _lon;} + qreal &rLat() {return _lat;} + void setLon(qreal lon) {_lon = lon;} + void setLat(qreal lat) {_lat = lat;} + qreal lon() const {return _lon;} + qreal lat() const {return _lat;} + + bool isValid() const; + qreal distanceTo(const Coordinates &c) const; + + QPointF toMercator() const; + static Coordinates fromMercator(const QPointF &m); + +private: + qreal _lat, _lon; +}; + +bool operator==(const Coordinates &c1, const Coordinates &c2); +QDebug operator<<(QDebug dbg, const Coordinates &trackpoint); + +#endif // COORDINATES_H diff --git a/src/csvparser.cpp b/src/csvparser.cpp index 132b3d18..b9179a22 100644 --- a/src/csvparser.cpp +++ b/src/csvparser.cpp @@ -29,7 +29,7 @@ bool CSVParser::loadFile(QIODevice *device) _errorLine = ln; return false; } - Waypoint wp(QPointF(lon, lat)); + Waypoint wp(Coordinates(lon, lat)); QByteArray ba = list[2].trimmed(); QString name = QString::fromUtf8(ba.data(), ba.size()); diff --git a/src/data.cpp b/src/data.cpp index cb1c3165..3cf218cd 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -1,6 +1,5 @@ -#include +#include #include -#include "ll.h" #include "gpxparser.h" #include "tcxparser.h" #include "csvparser.h" diff --git a/src/gpxparser.cpp b/src/gpxparser.cpp index 6a17db70..52418249 100644 --- a/src/gpxparser.cpp +++ b/src/gpxparser.cpp @@ -76,25 +76,38 @@ void GPXParser::handleRoutepointData(DataType type, const QString &value) } } +Coordinates GPXParser::coordinates(const QXmlStreamAttributes &attr) +{ + bool res; + qreal lon, lat; + + lon = attr.value("lon").toDouble(&res); + if (!res || (lon < -180.0 || lon > 180.0)) { + _reader.raiseError("Invalid longitude."); + return Coordinates(); + } + lat = attr.value("lat").toDouble(&res); + if (!res || (lat < -90.0 || lat > 90.0)) { + _reader.raiseError("Invalid latitude."); + return Coordinates(); + } + + return Coordinates(lon, lat); +} + void GPXParser::handleTrackpointAttributes(const QXmlStreamAttributes &attr) { - _track->last().setCoordinates(QPointF( - attr.value("lon").toDouble(), - attr.value("lat").toDouble())); + _track->last().setCoordinates(coordinates(attr)); } void GPXParser::handleRoutepointAttributes(const QXmlStreamAttributes &attr) { - _route->last().setCoordinates(QPointF( - attr.value("lon").toDouble(), - attr.value("lat").toDouble())); + _route->last().setCoordinates(coordinates(attr)); } void GPXParser::handleWaypointAttributes(const QXmlStreamAttributes &attr) { - _waypoints.last().setCoordinates(QPointF( - attr.value("lon").toDouble(), - attr.value("lat").toDouble())); + _waypoints.last().setCoordinates(coordinates(attr)); } void GPXParser::tpExtension() diff --git a/src/gpxparser.h b/src/gpxparser.h index c6c7a437..3121d3e3 100644 --- a/src/gpxparser.h +++ b/src/gpxparser.h @@ -36,6 +36,8 @@ private: void routepointData(); void waypointData(); + Coordinates coordinates(const QXmlStreamAttributes &attr); + void handleWaypointAttributes(const QXmlStreamAttributes &attr); void handleWaypointData(DataType type, const QString &value); void handleTrackpointAttributes(const QXmlStreamAttributes &attr); diff --git a/src/ll.cpp b/src/ll.cpp deleted file mode 100644 index f4e39039..00000000 --- a/src/ll.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include "ll.h" - -// MSVC workarounds -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif // M_PI -#if defined(_MSC_VER) && (_MSC_VER < 1800) - #define log2(n) (log(n)/log(2.0)) -#endif - - -#define WGS84_RADIUS 6378137.0 -#define deg2rad(d) (((d)*M_PI)/180.0) -#define rad2deg(d) (((d)*180.0)/M_PI) - -qreal llDistance(const QPointF &p1, const QPointF &p2) -{ - qreal dLat = deg2rad(p2.y() - p1.y()); - qreal dLon = deg2rad(p2.x() - p1.x()); - qreal a = pow(sin(dLat / 2.0), 2.0) - + cos(deg2rad(p1.y())) * cos(deg2rad(p2.y())) * pow(sin(dLon / 2.0), 2.0); - qreal c = 2.0 * atan2(sqrt(a), sqrt(1.0 - a)); - - return (WGS84_RADIUS * c); -} - -QPointF ll2mercator(const QPointF &ll) -{ - QPointF m; - - m.setX(ll.x()); - m.setY(rad2deg(log(tan(M_PI/4.0 + deg2rad(ll.y())/2.0)))); - - return m; -} - -QPointF mercator2ll(const QPointF &m) -{ - QPointF ll; - - ll.setX(m.x()); - ll.setY(rad2deg(2 * atan(exp(deg2rad(m.y()))) - M_PI/2)); - - return ll; -} - -QPoint mercator2tile(const QPointF &m, int z) -{ - QPoint tile; - - tile.setX((int)(floor((m.x() + 180.0) / 360.0 * pow(2.0, z)))); - tile.setY((int)(floor((1.0 - (m.y() / 180.0)) / 2.0 * pow(2.0, z)))); - - return tile; -} - -QPointF tile2mercator(const QPoint &tile, int z) -{ - QPointF m; - - m.setX(tile.x() / pow(2.0, z) * 360.0 - 180); - qreal n = M_PI - 2.0 * M_PI * tile.y() / pow(2.0, z); - m.setY(rad2deg(atan(0.5 * (exp(n) - exp(-n))))); - - return ll2mercator(m); -} - -int scale2zoom(qreal scale) -{ - int zoom; - - zoom = (int)log2(360.0/(scale * (qreal)TILE_SIZE)); - - if (zoom < ZOOM_MIN) - return ZOOM_MIN; - if (zoom > ZOOM_MAX) - return ZOOM_MAX; - return zoom; -} - -qreal zoom2resolution(int zoom, qreal y) -{ - return (WGS84_RADIUS * 2 * M_PI / 256 * cos(2 * atan(exp(deg2rad(y))) - - M_PI/2)) / pow(2.0, zoom); -} diff --git a/src/ll.h b/src/ll.h deleted file mode 100644 index e84575d2..00000000 --- a/src/ll.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef LL_H -#define LL_H - -#include - -#define TILE_SIZE 256 -#define ZOOM_MAX 18 -#define ZOOM_MIN 3 - -QPointF ll2mercator(const QPointF &ll); -QPointF mercator2ll(const QPointF &m); -qreal llDistance(const QPointF &p1, const QPointF &p2); -QPoint mercator2tile(const QPointF &m, int zoom); -QPointF tile2mercator(const QPoint &tile, int zoom); -int scale2zoom(qreal scale); -qreal zoom2resolution(int zoom, qreal y); - -#endif // LL_H diff --git a/src/map.cpp b/src/map.cpp index 52883390..f86ad550 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1,7 +1,6 @@ #include #include #include "downloader.h" -#include "ll.h" #include "config.h" #include "map.h" @@ -91,7 +90,7 @@ void Map::loadTilesSync(QList &list) void Map::fillTile(Tile &tile) { - tile.pixmap() = QPixmap(TILE_SIZE, TILE_SIZE); + tile.pixmap() = QPixmap(Tile::size(), Tile::size()); tile.pixmap().fill(); } diff --git a/src/map.h b/src/map.h index 63300832..cbd84333 100644 --- a/src/map.h +++ b/src/map.h @@ -1,24 +1,7 @@ #ifndef MAP_H #define MAP_H -#include - -class Tile -{ -public: - Tile(const QPoint &xy, int zoom) - {_xy = xy; _zoom = zoom;} - - int zoom() const {return _zoom;} - const QPoint& xy() const {return _xy;} - QPixmap& pixmap() {return _pixmap;} - -private: - int _zoom; - QPoint _xy; - QPixmap _pixmap; -}; - +#include "tile.h" class Map : public QObject { diff --git a/src/misc.cpp b/src/misc.cpp index f3a68376..6b0bfafe 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -76,11 +76,11 @@ QString elevation(qreal value, Units units) + qApp->translate("Misc", "ft"); } -QString coordinates(const QPointF &value) +QString coordinates(const Coordinates &value) { - QChar yH = (value.y() < 0) ? 'S' : 'N'; - QChar xH = (value.x() < 0) ? 'W' : 'E'; + QChar yH = (value.lat() < 0) ? 'S' : 'N'; + QChar xH = (value.lon() < 0) ? 'W' : 'E'; - return QString::number(qAbs(value.y()), 'f', 5) + yH + "," + QChar(0x00A0) - + QString::number(qAbs(value.x()), 'f', 5) + xH; + return QString::number(qAbs(value.lat()), 'f', 5) + yH + "," + QChar(0x00A0) + + QString::number(qAbs(value.lon()), 'f', 5) + xH; } diff --git a/src/misc.h b/src/misc.h index c07cb191..0de66ddf 100644 --- a/src/misc.h +++ b/src/misc.h @@ -3,6 +3,7 @@ #include #include +#include "coordinates.h" #include "units.h" double niceNum(double x, int round); @@ -10,6 +11,6 @@ double niceNum(double x, int round); QString timeSpan(qreal time); QString distance(qreal value, Units units); QString elevation(qreal value, Units units); -QString coordinates(const QPointF &value); +QString coordinates(const Coordinates &value); #endif // MISC_H diff --git a/src/pathview.cpp b/src/pathview.cpp index f7acbc0b..b63da690 100644 --- a/src/pathview.cpp +++ b/src/pathview.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "ll.h" +#include "rd.h" #include "poi.h" #include "data.h" #include "map.h" @@ -12,8 +12,43 @@ #include "pathview.h" -#define MARGIN 10.0 -#define SCALE_OFFSET 7 +#define ZOOM_MAX 18 +#define ZOOM_MIN 3 +#define MARGIN 10.0 +#define SCALE_OFFSET 7 + +static QPoint mercator2tile(const QPointF &m, int z) +{ + QPoint tile; + + tile.setX((int)(floor((m.x() + 180.0) / 360.0 * pow(2.0, z)))); + tile.setY((int)(floor((1.0 - (m.y() / 180.0)) / 2.0 * pow(2.0, z)))); + + return tile; +} + +static QPointF tile2mercator(const QPoint &tile, int z) +{ + Coordinates m; + + m.setLon(tile.x() / pow(2.0, z) * 360.0 - 180); + qreal n = M_PI - 2.0 * M_PI * tile.y() / pow(2.0, z); + m.setLat(rad2deg(atan(0.5 * (exp(n) - exp(-n))))); + + return m.toMercator(); +} + +static int scale2zoom(qreal scale) +{ + int zoom = (int)log2(360.0/(scale * (qreal)Tile::size())); + + if (zoom < ZOOM_MIN) + return ZOOM_MIN; + if (zoom > ZOOM_MAX) + return ZOOM_MAX; + + return zoom; +} PathView::PathView(QWidget *parent) : QGraphicsView(parent) @@ -147,7 +182,8 @@ QList PathView::loadData(const Data &data) QRectF br = trackBoundingRect() | routeBoundingRect() | waypointBoundingRect(); - QRectF ba = br.adjusted(-TILE_SIZE, -TILE_SIZE, TILE_SIZE, TILE_SIZE); + QRectF ba = br.adjusted(-Tile::size(), -Tile::size(), Tile::size(), + Tile::size()); _scene->setSceneRect(ba); centerOn(ba.center()); @@ -268,7 +304,7 @@ qreal PathView::waypointScale() const qreal PathView::mapScale(int zoom) const { - return ((360.0/(qreal)(1<setSceneRect(ba); if (br.width() < viewport()->size().width() @@ -603,8 +640,8 @@ void PathView::drawBackground(QPainter *painter, const QRectF &rect) -tm.y() / _scale))).toPoint(); QList tiles; - for (int i = 0; i <= rr.size().width() / TILE_SIZE + 1; i++) { - for (int j = 0; j <= rr.size().height() / TILE_SIZE + 1; j++) { + for (int i = 0; i <= rr.size().width() / Tile::size() + 1; i++) { + for (int j = 0; j <= rr.size().height() / Tile::size() + 1; j++) { tiles.append(Tile(QPoint(tile.x() + i, tile.y() + j), _zoom)); } } @@ -613,8 +650,8 @@ void PathView::drawBackground(QPainter *painter, const QRectF &rect) for (int i = 0; i < tiles.count(); i++) { Tile &t = tiles[i]; - QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE, - tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE); + QPoint tp(tl.x() + (t.xy().x() - tile.x()) * Tile::size(), + tl.y() + (t.xy().y() - tile.y()) * Tile::size()); painter->drawPixmap(tp, t.pixmap()); } } @@ -628,7 +665,8 @@ void PathView::resizeEvent(QResizeEvent *e) QRectF br = trackBoundingRect() | routeBoundingRect() | waypointBoundingRect(); - QRectF ba = br.adjusted(-TILE_SIZE, -TILE_SIZE, TILE_SIZE, TILE_SIZE); + QRectF ba = br.adjusted(-Tile::size(), -Tile::size(), Tile::size(), + Tile::size()); if (ba.width() < e->size().width()) { qreal diff = e->size().width() - ba.width(); diff --git a/src/poi.cpp b/src/poi.cpp index 3665c514..603ef56d 100644 --- a/src/poi.cpp +++ b/src/poi.cpp @@ -3,7 +3,6 @@ #include #include "pathitem.h" #include "waypointitem.h" -#include "ll.h" #include "data.h" #include "poi.h" @@ -36,10 +35,10 @@ bool POI::loadFile(const QString &fileName) index.end = _data.size() - 1; for (int i = index.start; i <= index.end; i++) { - const QPointF &p = _data.at(i).coordinates(); + const Coordinates &p = _data.at(i).coordinates(); qreal c[2]; - c[0] = p.x(); - c[1] = p.y(); + c[0] = p.lon(); + c[1] = p.lat(); _tree.Insert(c, c, i); } @@ -67,11 +66,11 @@ QVector POI::points(const PathItem *path) const const QPainterPath &pp = path->path(); for (int i = 0; i < pp.elementCount(); i++) { - QPointF p = mercator2ll(pp.elementAt(i)); - min[0] = p.x() - _radius; - min[1] = -p.y() - _radius; - max[0] = p.x() + _radius; - max[1] = -p.y() + _radius; + Coordinates p = Coordinates::fromMercator(pp.elementAt(i)); + min[0] = p.lon() - _radius; + min[1] = -p.lat() - _radius; + max[0] = p.lon() + _radius; + max[1] = -p.lat() + _radius; _tree.Search(min, max, cb, &set); } @@ -92,11 +91,11 @@ QVector POI::points(const QList &list) qreal min[2], max[2]; for (int i = 0; i < list.count(); i++) { - const QPointF &p = list.at(i)->waypoint().coordinates(); - min[0] = p.x() - _radius; - min[1] = p.y() - _radius; - max[0] = p.x() + _radius; - max[1] = p.y() + _radius; + const Coordinates &p = list.at(i)->waypoint().coordinates(); + min[0] = p.lon() - _radius; + min[1] = p.lat() - _radius; + max[0] = p.lon() + _radius; + max[1] = p.lat() + _radius; _tree.Search(min, max, cb, &set); } @@ -116,11 +115,11 @@ QVector POI::points(const QList &list) const qreal min[2], max[2]; for (int i = 0; i < list.count(); i++) { - const QPointF &p = list.at(i).coordinates(); - min[0] = p.x() - _radius; - min[1] = p.y() - _radius; - max[0] = p.x() + _radius; - max[1] = p.y() + _radius; + const Coordinates &p = list.at(i).coordinates(); + min[0] = p.lon() - _radius; + min[1] = p.lat() - _radius; + max[0] = p.lon() + _radius; + max[1] = p.lat() + _radius; _tree.Search(min, max, cb, &set); } @@ -148,10 +147,10 @@ void POI::enableFile(const QString &fileName, bool enable) continue; for (int j = idx.start; j <= idx.end; j++) { - const QPointF &p = _data.at(j).coordinates(); + const Coordinates &p = _data.at(j).coordinates(); qreal c[2]; - c[0] = p.x(); - c[1] = p.y(); + c[0] = p.lon(); + c[1] = p.lat(); _tree.Insert(c, c, j); } } diff --git a/src/rd.h b/src/rd.h new file mode 100644 index 00000000..fc746d46 --- /dev/null +++ b/src/rd.h @@ -0,0 +1,13 @@ +#ifndef RD_H +#define RD_H + +#include + +#ifndef M_PI + #define M_PI 3.14159265358979323846 +#endif // M_PI + +#define deg2rad(d) (((d)*M_PI)/180.0) +#define rad2deg(d) (((d)*180.0)/M_PI) + +#endif // RD_H diff --git a/src/route.cpp b/src/route.cpp index f145e21d..f2b0c4fc 100644 --- a/src/route.cpp +++ b/src/route.cpp @@ -1,4 +1,3 @@ -#include "ll.h" #include "route.h" Route::Route(const QVector &data) : _data(data) @@ -7,7 +6,7 @@ Route::Route(const QVector &data) : _data(data) _distance.append(dist); for (int i = 1; i < data.count(); i++) { - dist += llDistance(data.at(i).coordinates(), data.at(i-1).coordinates()); + dist += data.at(i).coordinates().distanceTo(data.at(i-1).coordinates()); _distance.append(dist); } } diff --git a/src/routeitem.cpp b/src/routeitem.cpp index 7cea8dae..1a07e4e1 100644 --- a/src/routeitem.cpp +++ b/src/routeitem.cpp @@ -1,6 +1,5 @@ #include #include -#include "ll.h" #include "misc.h" #include "waypoint.h" #include "waypointitem.h" @@ -23,13 +22,14 @@ RouteItem::RouteItem(const Route &route, QGraphicsItem *parent) { QVector r = route.route(); Q_ASSERT(r.count() >= 2); + QPointF p; new WaypointItem(r.at(0), this); - const QPointF &p = r.at(0).coordinates(); - _path.moveTo(ll2mercator(QPointF(p.x(), -p.y()))); + p = r.at(0).coordinates().toMercator(); + _path.moveTo(QPointF(p.x(), -p.y())); for (int i = 1; i < r.size(); i++) { - const QPointF &p = r.at(i).coordinates(); - _path.lineTo(ll2mercator(QPointF(p.x(), -p.y()))); + p = r.at(i).coordinates().toMercator(); + _path.lineTo(QPointF(p.x(), -p.y())); new WaypointItem(r.at(i), this); } diff --git a/src/scaleitem.cpp b/src/scaleitem.cpp index c93e9982..46dde63e 100644 --- a/src/scaleitem.cpp +++ b/src/scaleitem.cpp @@ -1,22 +1,28 @@ #include #include "config.h" -#include "ll.h" +#include "rd.h" +#include "wgs84.h" +#include "tile.h" #include "misc.h" #include "scaleitem.h" #define BORDER_WIDTH 1 -#define SCALE_WIDTH 132 -#define SCALE_HEIGHT 5 -#define SEGMENTS 3 - -#define PADDING 4 +#define SCALE_WIDTH 132 +#define SCALE_HEIGHT 5 +#define SEGMENTS 3 +#define PADDING 4 +static qreal zoom2resolution(int zoom, qreal y) +{ + return (WGS84_RADIUS * 2 * M_PI / Tile::size() + * cos(2 * atan(exp(deg2rad(y))) - M_PI/2)) / pow(2.0, zoom); +} ScaleItem::ScaleItem(QGraphicsItem *parent) : QGraphicsItem(parent) { _units = Metric; - _zoom = ZOOM_MIN; + _zoom = 0; _lat = 0; #ifndef Q_OS_MAC diff --git a/src/tcxparser.cpp b/src/tcxparser.cpp index 0a13c273..96ab1f8b 100644 --- a/src/tcxparser.cpp +++ b/src/tcxparser.cpp @@ -1,16 +1,26 @@ #include "tcxparser.h" -QPointF TCXParser::position() +Coordinates TCXParser::position() { - QPointF pos; + Coordinates pos; + qreal val; + bool res; while (_reader.readNextStartElement()) { - if (_reader.name() == "LatitudeDegrees") - pos.setY(_reader.readElementText().toDouble()); - else if (_reader.name() == "LongitudeDegrees") - pos.setX(_reader.readElementText().toDouble()); - else + if (_reader.name() == "LatitudeDegrees") { + val = _reader.readElementText().toDouble(&res); + if (!res || (val < -90.0 || val > 90.0)) + _reader.raiseError("Invalid latitude."); + else + pos.setLat(_reader.readElementText().toDouble(&res)); + } else if (_reader.name() == "LongitudeDegrees") { + val = _reader.readElementText().toDouble(&res); + if (!res || (val < -180.0 || val > 180.0)) + _reader.raiseError("Invalid longitude."); + else + pos.setLon(_reader.readElementText().toDouble(&res)); + } else _reader.skipCurrentElement(); } diff --git a/src/tcxparser.h b/src/tcxparser.h index 3dc0f846..7ea54a3d 100644 --- a/src/tcxparser.h +++ b/src/tcxparser.h @@ -32,7 +32,7 @@ private: void trackpointData(); void routepointData(); void waypointData(); - QPointF position(); + Coordinates position(); QXmlStreamReader _reader; QVector *_track; diff --git a/src/tile.h b/src/tile.h new file mode 100644 index 00000000..3cf5082c --- /dev/null +++ b/src/tile.h @@ -0,0 +1,25 @@ +#ifndef TILE_H +#define TILE_H + +#include +#include + +class Tile +{ +public: + Tile(const QPoint &xy, int zoom) + {_xy = xy; _zoom = zoom;} + + int zoom() const {return _zoom;} + const QPoint& xy() const {return _xy;} + QPixmap& pixmap() {return _pixmap;} + + static int size() {return 256;} + +private: + int _zoom; + QPoint _xy; + QPixmap _pixmap; +}; + +#endif // TILE_H diff --git a/src/track.cpp b/src/track.cpp index ff58c41c..a48b2c7a 100644 --- a/src/track.cpp +++ b/src/track.cpp @@ -1,4 +1,3 @@ -#include "ll.h" #include "track.h" @@ -87,7 +86,7 @@ Track::Track(const QVector &data) : _data(data) _distance.append(0); _time.append(0); for (int i = 1; i < data.count(); i++) { - dist += llDistance(data.at(i).coordinates(), data.at(i-1).coordinates()); + dist += data.at(i).coordinates().distanceTo(data.at(i-1).coordinates()); _distance.append(dist); if (data.first().hasTimestamp() && data.at(i).hasTimestamp()) diff --git a/src/trackitem.cpp b/src/trackitem.cpp index cc065f4d..831ee124 100644 --- a/src/trackitem.cpp +++ b/src/trackitem.cpp @@ -1,7 +1,6 @@ #include #include #include -#include "ll.h" #include "misc.h" #include "tooltip.h" #include "trackitem.h" @@ -25,14 +24,15 @@ QString TrackItem::toolTip() TrackItem::TrackItem(const Track &track, QGraphicsItem *parent) : PathItem(parent) { + QPointF p; const QVector &t = track.track(); Q_ASSERT(t.count() >= 2); - const QPointF &p = t.at(0).coordinates(); - _path.moveTo(ll2mercator(QPointF(p.x(), -p.y()))); + p = t.first().coordinates().toMercator(); + _path.moveTo(QPointF(p.x(), -p.y())); for (int i = 1; i < t.size(); i++) { - const QPointF &p = t.at(i).coordinates(); - _path.lineTo(ll2mercator(QPointF(p.x(), -p.y()))); + p = t.at(i).coordinates().toMercator(); + _path.lineTo(QPointF(p.x(), -p.y())); } updateShape(); diff --git a/src/trackpoint.h b/src/trackpoint.h index 909bb5de..f65a0fa8 100644 --- a/src/trackpoint.h +++ b/src/trackpoint.h @@ -1,10 +1,10 @@ #ifndef TRACKPOINT_H #define TRACKPOINT_H -#include #include #include #include +#include "coordinates.h" class Trackpoint { @@ -13,9 +13,9 @@ public: _elevation = NAN; _geoidHeight = 0; _speed = NAN; _heartRate = NAN; _temperature = NAN; } - Trackpoint(const QPointF &coordinates) {_coordinates = coordinates;} + Trackpoint(const Coordinates &coordinates) {_coordinates = coordinates;} - const QPointF &coordinates() const {return _coordinates;} + const Coordinates &coordinates() const {return _coordinates;} const QDateTime ×tamp() const {return _timestamp;} qreal elevation() const {return _elevation;} qreal geoidHeight() const {return _geoidHeight;} @@ -23,7 +23,7 @@ public: qreal heartRate() const {return _heartRate;} qreal temperature() const {return _temperature;} - void setCoordinates(const QPointF &coordinates) + void setCoordinates(const Coordinates &coordinates) {_coordinates = coordinates;} void setTimestamp(const QDateTime ×tamp) {_timestamp = timestamp;} void setElevation(qreal elevation) {_elevation = elevation;} @@ -39,7 +39,7 @@ public: bool hasTemperature() const {return !std::isnan(_temperature);} private: - QPointF _coordinates; + Coordinates _coordinates; QDateTime _timestamp; qreal _elevation; qreal _geoidHeight; diff --git a/src/waypoint.h b/src/waypoint.h index 561ed0eb..0d373ab7 100644 --- a/src/waypoint.h +++ b/src/waypoint.h @@ -1,28 +1,28 @@ #ifndef WAYPOINT_H #define WAYPOINT_H -#include #include #include #include #include #include +#include "coordinates.h" class Waypoint { public: Waypoint() {_elevation = NAN; _geoidHeight = 0;} - Waypoint(const QPointF &coordinates) + Waypoint(const Coordinates &coordinates) : _coordinates(coordinates) {_elevation = NAN; _geoidHeight = 0;} - const QPointF &coordinates() const {return _coordinates;} + const Coordinates &coordinates() const {return _coordinates;} const QString &name() const {return _name;} const QString &description() const {return _description;} const QDateTime ×tamp() const {return _timestamp;} qreal elevation() const {return _elevation;} qreal geoidHeight() const {return _geoidHeight;} - void setCoordinates(const QPointF &coordinates) + void setCoordinates(const Coordinates &coordinates) {_coordinates = coordinates;} void setName(const QString &name) {_name = name;} void setDescription(const QString &description) @@ -38,7 +38,7 @@ public: && this->_coordinates == other._coordinates;} private: - QPointF _coordinates; + Coordinates _coordinates; QString _name; QString _description; QDateTime _timestamp; diff --git a/src/waypointitem.cpp b/src/waypointitem.cpp index 065a3dbd..5a6b4dce 100644 --- a/src/waypointitem.cpp +++ b/src/waypointitem.cpp @@ -1,7 +1,6 @@ #include #include #include "config.h" -#include "ll.h" #include "misc.h" #include "tooltip.h" #include "waypointitem.h" @@ -39,8 +38,8 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, QGraphicsItem *parent) _hover = false; _waypoint = waypoint; - _coordinates = ll2mercator(QPointF(waypoint.coordinates().x(), - -waypoint.coordinates().y())); + QPointF p = waypoint.coordinates().toMercator(); + _coordinates = QPointF(p.x(), -p.y()); updateShape(); diff --git a/src/wgs84.h b/src/wgs84.h new file mode 100644 index 00000000..766f3440 --- /dev/null +++ b/src/wgs84.h @@ -0,0 +1,6 @@ +#ifndef WGS84_H +#define WGS84_H + +#define WGS84_RADIUS 6378137.0 + +#endif // WGS84_H