From cc694971bea330a93eb4078a90a4b7d0d4ced8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Sat, 9 Sep 2017 12:33:43 +0200 Subject: [PATCH] Added support for limiting the maximal zoom level of online map sources --- pkg/maps.txt | 10 +++---- src/gui.cpp | 9 +++--- src/maplist.cpp | 22 +++++++++++--- src/onlinemap.cpp | 76 +++++++++++++++++++++++------------------------ src/onlinemap.h | 12 ++++---- src/pathview.cpp | 2 +- src/range.cpp | 6 ++++ src/range.h | 15 ++++++++++ 8 files changed, 95 insertions(+), 57 deletions(-) diff --git a/pkg/maps.txt b/pkg/maps.txt index 3f3ec451..87b1b502 100644 --- a/pkg/maps.txt +++ b/pkg/maps.txt @@ -1,5 +1,5 @@ -Open Topo Map https://a.tile.opentopomap.org/$z/$x/$y.png -4UMaps http://4umaps.eu/$z/$x/$y.png -Open Street Map http://tile.openstreetmap.org/$z/$x/$y.png -USGS Topo https://navigator.er.usgs.gov/tiles/tcr.cgi/$z/$x/$y.png -USGS Imagery https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y +Open Topo Map https://a.tile.opentopomap.org/$z/$x/$y.png 16 +4UMaps http://4umaps.eu/$z/$x/$y.png 15 +Open Street Map http://tile.openstreetmap.org/$z/$x/$y.png 19 +USGS Topo https://navigator.er.usgs.gov/tiles/tcr.cgi/$z/$x/$y.png 15 +USGS Imagery https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y 15 diff --git a/src/gui.cpp b/src/gui.cpp index 5df1ddf4..03b93b13 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -696,10 +696,11 @@ void GUI::dataSources() "following file:") + "

" + USER_MAP_FILE + "

" + tr("The file format is one map entry per line, consisting of the map " - "name and tiles URL delimited by a TAB character. The tile X and Y " - "coordinates are replaced with $x and $y in the URL and the zoom " - "level is replaced with $z. An example map file could look like:") - + "

Map1 http://tile.server.com/map/$z/$x/$y.png" + "name, tiles URL and an optional maximal zoom level delimited by " + "a TAB character. The tile X and Y coordinates are replaced with $x " + "and $y in the URL and the zoom level is replaced with $z. An example " + "map file could look like:") + + "

Map1 http://tile.server.com/map/$z/$x/$y.png 15" "
Map2 http://mapserver.org/map/$z-$x-$y

" + "

" + tr("Offline maps") + "

" diff --git a/src/maplist.cpp b/src/maplist.cpp index a81090da..404ea41f 100644 --- a/src/maplist.cpp +++ b/src/maplist.cpp @@ -1,24 +1,38 @@ #include #include +#include "range.h" #include "atlas.h" #include "offlinemap.h" #include "onlinemap.h" #include "maplist.h" +#define ZOOM_MAX 18 +#define ZOOM_MIN 2 + Map *MapList::loadListEntry(const QByteArray &line) { + int max; + QList list = line.split('\t'); - if (list.size() != 2) + if (list.size() < 2) return 0; - QByteArray ba1 = list[0].trimmed(); - QByteArray ba2 = list[1].trimmed(); + QByteArray ba1 = list.at(0).trimmed(); + QByteArray ba2 = list.at(1).trimmed(); if (ba1.isEmpty() || ba2.isEmpty()) return 0; + if (list.size() == 3) { + bool ok; + max = QString(list.at(2).trimmed()).toInt(&ok); + if (!ok) + return 0; + } else + max = ZOOM_MAX; + return new OnlineMap(QString::fromUtf8(ba1.data(), ba1.size()), - QString::fromLatin1(ba2.data(), ba2.size()), this); + QString::fromLatin1(ba2.data(), ba2.size()), Range(ZOOM_MIN, max), this); } bool MapList::loadList(const QString &path) diff --git a/src/onlinemap.cpp b/src/onlinemap.cpp index 803c3d03..ae9f7077 100644 --- a/src/onlinemap.cpp +++ b/src/onlinemap.cpp @@ -12,8 +12,6 @@ #include "onlinemap.h" -#define ZOOM_MAX 18 -#define ZOOM_MIN 3 #define TILE_SIZE 256 static QPoint mercator2tile(const QPointF &m, int z) @@ -36,16 +34,33 @@ static int scale2zoom(qreal scale) return (int)log2(360.0/(scale * (qreal)TILE_SIZE)); } +static void fillTile(Tile &tile) +{ + tile.pixmap() = QPixmap(TILE_SIZE, TILE_SIZE); + tile.pixmap().fill(); +} + +static bool loadTileFile(Tile &tile, const QString &file) +{ + if (!tile.pixmap().load(file)) { + qWarning("%s: error loading tile file\n", qPrintable(file)); + return false; + } + + return true; +} + Downloader *OnlineMap::downloader; -OnlineMap::OnlineMap(const QString &name, const QString &url, QObject *parent) - : Map(parent) +OnlineMap::OnlineMap(const QString &name, const QString &url, + const Range &zooms, QObject *parent) : Map(parent) { _name = name; _url = url; _block = false; - _zoom = ZOOM_MAX; + _zooms = zooms; + _zoom = zooms.max(); connect(downloader, SIGNAL(finished()), this, SLOT(emitLoaded())); @@ -115,23 +130,7 @@ void OnlineMap::loadTilesSync(QList &list) } } -void OnlineMap::fillTile(Tile &tile) -{ - tile.pixmap() = QPixmap(TILE_SIZE, TILE_SIZE); - tile.pixmap().fill(); -} - -bool OnlineMap::loadTileFile(Tile &tile, const QString &file) -{ - if (!tile.pixmap().load(file)) { - qWarning("%s: error loading tile file\n", qPrintable(file)); - return false; - } - - return true; -} - -QString OnlineMap::tileUrl(const Tile &tile) +QString OnlineMap::tileUrl(const Tile &tile) const { QString url(_url); @@ -142,7 +141,7 @@ QString OnlineMap::tileUrl(const Tile &tile) return url; } -QString OnlineMap::tileFile(const Tile &tile) +QString OnlineMap::tileFile(const Tile &tile) const { QString file = TILES_DIR + QString("/%1/%2-%3-%4").arg(name()) .arg(tile.zoom()).arg(tile.xy().x()).arg(tile.xy().y()); @@ -166,20 +165,26 @@ QRectF OnlineMap::bounds() const 1.0/zoom2scale(_zoom)); } +int OnlineMap::limitZoom(int zoom) const +{ + if (zoom < _zooms.min()) + return _zooms.min(); + if (zoom > _zooms.max()) + return _zooms.max(); + + return zoom; +} + qreal OnlineMap::zoomFit(const QSize &size, const RectC &br) { if (!br.isValid()) - _zoom = ZOOM_MAX; + _zoom = _zooms.max(); else { 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())); - if (_zoom < ZOOM_MIN) - _zoom = ZOOM_MIN; - if (_zoom > ZOOM_MAX) - _zoom = ZOOM_MAX; + _zoom = limitZoom(scale2zoom(qMax(sc.x(), sc.y()))); } return _zoom; @@ -187,13 +192,8 @@ qreal OnlineMap::zoomFit(const QSize &size, const RectC &br) qreal OnlineMap::zoomFit(qreal resolution, const Coordinates &c) { - _zoom = (int)(log2((WGS84_RADIUS * 2 * M_PI * cos(deg2rad(c.lat()))) - / resolution) - log2(TILE_SIZE)); - - if (_zoom < ZOOM_MIN) - _zoom = ZOOM_MIN; - if (_zoom > ZOOM_MAX) - _zoom = ZOOM_MAX; + _zoom = limitZoom((int)(log2((WGS84_RADIUS * 2 * M_PI + * cos(deg2rad(c.lat()))) / resolution) - log2(TILE_SIZE))); return _zoom; } @@ -208,13 +208,13 @@ qreal OnlineMap::resolution(const QPointF &p) const qreal OnlineMap::zoomIn() { - _zoom = qMin(_zoom + 1, ZOOM_MAX); + _zoom = qMin(_zoom + 1, _zooms.max()); return _zoom; } qreal OnlineMap::zoomOut() { - _zoom = qMax(_zoom - 1, ZOOM_MIN); + _zoom = qMax(_zoom - 1, _zooms.min()); return _zoom; } diff --git a/src/onlinemap.h b/src/onlinemap.h index 5ddde8e9..6c4e3c87 100644 --- a/src/onlinemap.h +++ b/src/onlinemap.h @@ -3,6 +3,7 @@ #include "map.h" #include "tile.h" +#include "range.h" class Downloader; @@ -11,7 +12,8 @@ class OnlineMap : public Map Q_OBJECT public: - OnlineMap(const QString &name, const QString &url, QObject *parent = 0); + OnlineMap(const QString &name, const QString &url, const Range &zooms, + QObject *parent = 0); const QString &name() const {return _name;} @@ -39,13 +41,13 @@ private slots: void emitLoaded(); private: - QString tileUrl(const Tile &tile); - QString tileFile(const Tile &tile); - bool loadTileFile(Tile &tile, const QString &file); - void fillTile(Tile &tile); + QString tileUrl(const Tile &tile) const; + QString tileFile(const Tile &tile) const; void loadTilesAsync(QList &list); void loadTilesSync(QList &list); + int limitZoom(int zoom) const; + Range _zooms; int _zoom; QString _name; QString _url; diff --git a/src/pathview.cpp b/src/pathview.cpp index 140f5dac..3ca703b3 100644 --- a/src/pathview.cpp +++ b/src/pathview.cpp @@ -16,7 +16,7 @@ #include "pathview.h" -#define MAX_DIGITAL_ZOOM 1 +#define MAX_DIGITAL_ZOOM 2 #define MIN_DIGITAL_ZOOM -3 #define MARGIN 10.0 #define SCALE_OFFSET 7 diff --git a/src/range.cpp b/src/range.cpp index 5e38d231..0a3072c6 100644 --- a/src/range.cpp +++ b/src/range.cpp @@ -8,6 +8,12 @@ void RangeF::resize(qreal size) _max += adj; } +QDebug operator<<(QDebug dbg, const Range &range) +{ + dbg.nospace() << "Range(" << range.min() << ", " << range.max() << ")"; + return dbg.space(); +} + QDebug operator<<(QDebug dbg, const RangeF &range) { dbg.nospace() << "RangeF(" << range.min() << ", " << range.max() << ")"; diff --git a/src/range.h b/src/range.h index ed5718b0..41a5f405 100644 --- a/src/range.h +++ b/src/range.h @@ -4,6 +4,20 @@ #include #include +class Range +{ +public: + Range() {_min = 0; _max = 0;} + Range(int min, int max) {_min = min, _max = max;} + + int min() const {return _min;} + int max() const {return _max;} + int size() const {return (_max - _min);} + +private: + int _min, _max; +}; + class RangeF { public: @@ -20,6 +34,7 @@ private: qreal _min, _max; }; +QDebug operator<<(QDebug dbg, const Range &range); QDebug operator<<(QDebug dbg, const RangeF &range); #endif // RANGE_H