1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00

Added support for limiting the maximal zoom level of online map sources

This commit is contained in:
Martin Tůma 2017-09-09 12:33:43 +02:00
parent ba856d7eb6
commit cc694971be
8 changed files with 95 additions and 57 deletions

View File

@ -1,5 +1,5 @@
Open Topo Map https://a.tile.opentopomap.org/$z/$x/$y.png Open Topo Map https://a.tile.opentopomap.org/$z/$x/$y.png 16
4UMaps http://4umaps.eu/$z/$x/$y.png 4UMaps http://4umaps.eu/$z/$x/$y.png 15
Open Street Map http://tile.openstreetmap.org/$z/$x/$y.png 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 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 USGS Imagery https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y 15

View File

@ -696,10 +696,11 @@ void GUI::dataSources()
"following file:") "following file:")
+ "</p><p><code>" + USER_MAP_FILE + "</code></p><p>" + "</p><p><code>" + USER_MAP_FILE + "</code></p><p>"
+ tr("The file format is one map entry per line, consisting of the map " + 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 " "name, tiles URL and an optional maximal zoom level delimited by "
"coordinates are replaced with $x and $y in the URL and the zoom " "a TAB character. The tile X and Y coordinates are replaced with $x "
"level is replaced with $z. An example map file could look like:") "and $y in the URL and the zoom level is replaced with $z. An example "
+ "</p><p><code>Map1 http://tile.server.com/map/$z/$x/$y.png" "map file could look like:")
+ "</p><p><code>Map1 http://tile.server.com/map/$z/$x/$y.png 15"
"<br/>Map2 http://mapserver.org/map/$z-$x-$y</code></p>" "<br/>Map2 http://mapserver.org/map/$z-$x-$y</code></p>"
+ "<h4>" + tr("Offline maps") + "</h4><p>" + "<h4>" + tr("Offline maps") + "</h4><p>"

View File

@ -1,24 +1,38 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include "range.h"
#include "atlas.h" #include "atlas.h"
#include "offlinemap.h" #include "offlinemap.h"
#include "onlinemap.h" #include "onlinemap.h"
#include "maplist.h" #include "maplist.h"
#define ZOOM_MAX 18
#define ZOOM_MIN 2
Map *MapList::loadListEntry(const QByteArray &line) Map *MapList::loadListEntry(const QByteArray &line)
{ {
int max;
QList<QByteArray> list = line.split('\t'); QList<QByteArray> list = line.split('\t');
if (list.size() != 2) if (list.size() < 2)
return 0; return 0;
QByteArray ba1 = list[0].trimmed(); QByteArray ba1 = list.at(0).trimmed();
QByteArray ba2 = list[1].trimmed(); QByteArray ba2 = list.at(1).trimmed();
if (ba1.isEmpty() || ba2.isEmpty()) if (ba1.isEmpty() || ba2.isEmpty())
return 0; 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()), 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) bool MapList::loadList(const QString &path)

View File

@ -12,8 +12,6 @@
#include "onlinemap.h" #include "onlinemap.h"
#define ZOOM_MAX 18
#define ZOOM_MIN 3
#define TILE_SIZE 256 #define TILE_SIZE 256
static QPoint mercator2tile(const QPointF &m, int z) 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)); 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; Downloader *OnlineMap::downloader;
OnlineMap::OnlineMap(const QString &name, const QString &url, QObject *parent) OnlineMap::OnlineMap(const QString &name, const QString &url,
: Map(parent) const Range &zooms, QObject *parent) : Map(parent)
{ {
_name = name; _name = name;
_url = url; _url = url;
_block = false; _block = false;
_zoom = ZOOM_MAX; _zooms = zooms;
_zoom = zooms.max();
connect(downloader, SIGNAL(finished()), this, SLOT(emitLoaded())); connect(downloader, SIGNAL(finished()), this, SLOT(emitLoaded()));
@ -115,23 +130,7 @@ void OnlineMap::loadTilesSync(QList<Tile> &list)
} }
} }
void OnlineMap::fillTile(Tile &tile) QString OnlineMap::tileUrl(const Tile &tile) const
{
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 url(_url); QString url(_url);
@ -142,7 +141,7 @@ QString OnlineMap::tileUrl(const Tile &tile)
return url; 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()) QString file = TILES_DIR + QString("/%1/%2-%3-%4").arg(name())
.arg(tile.zoom()).arg(tile.xy().x()).arg(tile.xy().y()); .arg(tile.zoom()).arg(tile.xy().x()).arg(tile.xy().y());
@ -166,20 +165,26 @@ QRectF OnlineMap::bounds() const
1.0/zoom2scale(_zoom)); 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) qreal OnlineMap::zoomFit(const QSize &size, const RectC &br)
{ {
if (!br.isValid()) if (!br.isValid())
_zoom = ZOOM_MAX; _zoom = _zooms.max();
else { else {
QRectF tbr(Mercator().ll2xy(br.topLeft()), QRectF tbr(Mercator().ll2xy(br.topLeft()),
Mercator().ll2xy(br.bottomRight())); Mercator().ll2xy(br.bottomRight()));
QPointF sc(tbr.width() / size.width(), tbr.height() / size.height()); QPointF sc(tbr.width() / size.width(), tbr.height() / size.height());
_zoom = scale2zoom(qMax(sc.x(), sc.y())); _zoom = limitZoom(scale2zoom(qMax(sc.x(), sc.y())));
if (_zoom < ZOOM_MIN)
_zoom = ZOOM_MIN;
if (_zoom > ZOOM_MAX)
_zoom = ZOOM_MAX;
} }
return _zoom; return _zoom;
@ -187,13 +192,8 @@ qreal OnlineMap::zoomFit(const QSize &size, const RectC &br)
qreal OnlineMap::zoomFit(qreal resolution, const Coordinates &c) qreal OnlineMap::zoomFit(qreal resolution, const Coordinates &c)
{ {
_zoom = (int)(log2((WGS84_RADIUS * 2 * M_PI * cos(deg2rad(c.lat()))) _zoom = limitZoom((int)(log2((WGS84_RADIUS * 2 * M_PI
/ resolution) - log2(TILE_SIZE)); * cos(deg2rad(c.lat()))) / resolution) - log2(TILE_SIZE)));
if (_zoom < ZOOM_MIN)
_zoom = ZOOM_MIN;
if (_zoom > ZOOM_MAX)
_zoom = ZOOM_MAX;
return _zoom; return _zoom;
} }
@ -208,13 +208,13 @@ qreal OnlineMap::resolution(const QPointF &p) const
qreal OnlineMap::zoomIn() qreal OnlineMap::zoomIn()
{ {
_zoom = qMin(_zoom + 1, ZOOM_MAX); _zoom = qMin(_zoom + 1, _zooms.max());
return _zoom; return _zoom;
} }
qreal OnlineMap::zoomOut() qreal OnlineMap::zoomOut()
{ {
_zoom = qMax(_zoom - 1, ZOOM_MIN); _zoom = qMax(_zoom - 1, _zooms.min());
return _zoom; return _zoom;
} }

View File

@ -3,6 +3,7 @@
#include "map.h" #include "map.h"
#include "tile.h" #include "tile.h"
#include "range.h"
class Downloader; class Downloader;
@ -11,7 +12,8 @@ class OnlineMap : public Map
Q_OBJECT Q_OBJECT
public: 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;} const QString &name() const {return _name;}
@ -39,13 +41,13 @@ private slots:
void emitLoaded(); void emitLoaded();
private: private:
QString tileUrl(const Tile &tile); QString tileUrl(const Tile &tile) const;
QString tileFile(const Tile &tile); QString tileFile(const Tile &tile) const;
bool loadTileFile(Tile &tile, const QString &file);
void fillTile(Tile &tile);
void loadTilesAsync(QList<Tile> &list); void loadTilesAsync(QList<Tile> &list);
void loadTilesSync(QList<Tile> &list); void loadTilesSync(QList<Tile> &list);
int limitZoom(int zoom) const;
Range _zooms;
int _zoom; int _zoom;
QString _name; QString _name;
QString _url; QString _url;

View File

@ -16,7 +16,7 @@
#include "pathview.h" #include "pathview.h"
#define MAX_DIGITAL_ZOOM 1 #define MAX_DIGITAL_ZOOM 2
#define MIN_DIGITAL_ZOOM -3 #define MIN_DIGITAL_ZOOM -3
#define MARGIN 10.0 #define MARGIN 10.0
#define SCALE_OFFSET 7 #define SCALE_OFFSET 7

View File

@ -8,6 +8,12 @@ void RangeF::resize(qreal size)
_max += adj; _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) QDebug operator<<(QDebug dbg, const RangeF &range)
{ {
dbg.nospace() << "RangeF(" << range.min() << ", " << range.max() << ")"; dbg.nospace() << "RangeF(" << range.min() << ", " << range.max() << ")";

View File

@ -4,6 +4,20 @@
#include <QtGlobal> #include <QtGlobal>
#include <QDebug> #include <QDebug>
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 class RangeF
{ {
public: public:
@ -20,6 +34,7 @@ private:
qreal _min, _max; qreal _min, _max;
}; };
QDebug operator<<(QDebug dbg, const Range &range);
QDebug operator<<(QDebug dbg, const RangeF &range); QDebug operator<<(QDebug dbg, const RangeF &range);
#endif // RANGE_H #endif // RANGE_H