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