1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-14 19:04:23 +02:00

Compare commits

...

15 Commits
7.23 ... 7.25

Author SHA1 Message Date
bf0dd1b24a Version++ 2020-03-04 19:49:11 +01:00
9859608115 Added missing support for URLs defined in OnlineResources 2020-03-04 19:47:23 +01:00
9f62b7114e The service parameter is expected in the GetMap request by some servers
(The WMS specification is not 100% clear here)
2020-03-03 09:38:18 +01:00
c85f404d28 Enable specifiing of format parameters 2020-03-03 09:29:16 +01:00
bb6d6a4044 Version++ 2020-03-01 14:39:40 +01:00
521369a6ec Make the WMS tile size configurable 2020-03-01 13:59:15 +01:00
45a6cdeda0 Strip the format parameters for format comparsion 2020-03-01 13:26:19 +01:00
12827edcb2 Removed obsolete include 2020-03-01 11:46:44 +01:00
ee24bd54f1 Fixed tile cache reload issues 2020-03-01 11:43:08 +01:00
cc22df3bf2 Cosmetics 2020-03-01 10:30:00 +01:00
d7f0cda4b2 Properly parse the ScaleHint tag 2020-02-29 21:40:13 +01:00
a898ff2807 Use 72dpi in the ScaleHint to scaleDenominator transformation 2020-02-29 20:11:49 +01:00
9dd4e117f6 Added missing WMS 1.1 ScaleHint handling 2020-02-29 13:47:27 +01:00
92deaaaf2b Use the latest xmlns 2020-02-23 12:45:36 +01:00
015a9187a0 Fixed memory leak
(formal only, the data is allocated during the whole application life anyway)
2020-02-20 09:02:01 +01:00
21 changed files with 118 additions and 37 deletions

View File

@ -1,4 +1,4 @@
version: 7.23.{build}
version: 7.25.{build}
configuration:
- Release

View File

@ -3,7 +3,7 @@ unix:!macx {
} else {
TARGET = GPXSee
}
VERSION = 7.23
VERSION = 7.25
QT += core \
gui \

View File

@ -7,7 +7,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "7.23"
!define VERSION "7.25"
; The file to write
OutFile "GPXSee-${VERSION}.exe"

View File

@ -7,7 +7,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "7.23"
!define VERSION "7.25"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.gpxsee.org/map/1.3">
<map xmlns="http://www.gpxsee.org/map/1.4">
<name>4UMaps</name>
<url>https://tileserver.4umaps.com/$z/$x/$y.png</url>
<zoom min="2" max="15"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.gpxsee.org/map/1.3" type="WMTS">
<map xmlns="http://www.gpxsee.org/map/1.4" type="WMTS">
<name>Antarctica</name>
<url type="REST">https://gis.ngdc.noaa.gov/arcgis/rest/services/antarctic/antarctic_basemap/MapServer/WMTS/1.0.0/WMTSCapabilities.xml</url>
<copyright>NOAA National Centers for Environmental Information (NCEI); International Bathymetric Chart of the Southern Ocean (IBCSO); General Bathymetric Chart of the Oceans (GEBCO); Natural Earth</copyright>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.gpxsee.org/map/1.3">
<map xmlns="http://www.gpxsee.org/map/1.4">
<name>Open Street Map</name>
<url>https://tile.openstreetmap.org/$z/$x/$y.png</url>
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © OpenStreetMap (CC-BY-SA)</copyright>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.gpxsee.org/map/1.3">
<map xmlns="http://www.gpxsee.org/map/1.4">
<name>Open Topo Map</name>
<url>https://a.tile.opentopomap.org/$z/$x/$y.png</url>
<zoom max="17"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.gpxsee.org/map/1.3">
<map xmlns="http://www.gpxsee.org/map/1.4">
<name>USGS Imagery</name>
<url>https://basemap.nationalmap.gov/ArcGIS/rest/services/USGSImageryOnly/MapServer/tile/$z/$y/$x</url>
<zoom min="2" max="15"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.gpxsee.org/map/1.3">
<map xmlns="http://www.gpxsee.org/map/1.4">
<name>USGS Topo</name>
<url>https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/$z/$y/$x</url>
<zoom min="2" max="15"/>

View File

@ -2,7 +2,6 @@
#include <QGraphicsScene>
#include <QWheelEvent>
#include <QApplication>
#include <QPixmapCache>
#include <QScrollBar>
#include "data/poi.h"
#include "data/data.h"
@ -351,7 +350,6 @@ void MapView::setMap(Map *map)
centerOn(nc);
reloadMap();
QPixmapCache::clear();
}
void MapView::setPOI(POI *poi)
@ -982,7 +980,6 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
_deviceRatio = deviceRatio;
_mapRatio = mapRatio;
QPixmapCache::clear();
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
.intersected(_map->bounds()));

View File

@ -425,7 +425,7 @@ QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
quint32 ls = 0;
SegmentType lt = (SegmentType)0;
for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) {
for (quint8 mask = 0x1; mask <= 0x10; mask <<= 1) {
if (subdiv->objects() & mask) {
if (ls) {
quint16 po;

View File

@ -52,7 +52,7 @@ bool MapList::loadFile(const QString &path, bool *terminate)
else if (GMAP::isGMAP(path)) {
if (terminate)
*terminate = true;
map = new IMGMap(path);
map = new IMGMap(path, this);
}
} else if (suffix == "jnx")
map = new JNXMap(path, this);

View File

@ -300,7 +300,7 @@ Map *MapSource::loadMap(const QString &path, QString &errorString)
case WMS:
return new WMSMap(config.name, WMS::Setup(config.url, config.layer,
config.style, config.format, config.crs, config.coordinateSystem,
config.dimensions, config.authorization));
config.dimensions, config.authorization), config.tileSize);
case TMS:
return new OnlineMap(config.name, config.url, config.zooms,
config.bounds, config.tileRatio, config.authorization,

View File

@ -169,6 +169,17 @@ void TileLoader::clearCache()
dir.remove(list.at(i));
_downloader->clearErrors();
QPixmapCache::clear();
}
void TileLoader::setScaledSize(int size)
{
if (_scaledSize == size)
return;
_scaledSize = size;
QPixmapCache::clear();
}
QUrl TileLoader::tileUrl(const Tile &tile) const

View File

@ -16,7 +16,7 @@ public:
void setUrl(const QString &url) {_url = url;}
void setAuthorization(const Authorization &authorization)
{_authorization = authorization;}
void setScaledSize(int size) {_scaledSize = size;}
void setScaledSize(int size);
void setQuadTiles(bool quadTiles) {_quadTiles = quadTiles;}
void loadTilesAsync(QVector<Tile> &list);

View File

@ -1,3 +1,4 @@
#include <cmath>
#include <QFileInfo>
#include <QEventLoop>
#include <QXmlStreamReader>
@ -7,6 +8,19 @@
#include "wms.h"
static QString bareFormat(const QString &format)
{
return format.left(format.indexOf(';')).trimmed();
}
static inline double hint2denominator(double h)
{
/* Some WMS 1.1.1 servers use a 72dpi resolution by default. Using the usual
90dpi (0.28mm) resolution known from later standards (WMS 1.3, WMTS) does
make them return emty images in the "max" scale level. */
return h / (M_SQRT2 * 0.36e-3);
}
WMS::CTX::CTX(const Setup &setup) : setup(setup), formatSupported(false)
{
QStringList ll = setup.layer().split(',');
@ -24,13 +38,48 @@ WMS::CTX::CTX(const Setup &setup) : setup(setup), formatSupported(false)
}
}
void WMS::get(QXmlStreamReader &reader, CTX &ctx)
{
while (reader.readNextStartElement()) {
if (reader.name() == "OnlineResource") {
QXmlStreamAttributes attr = reader.attributes();
ctx.url = attr.value("xlink:href").toString();
reader.skipCurrentElement();
} else
reader.skipCurrentElement();
}
}
void WMS::http(QXmlStreamReader &reader, CTX &ctx)
{
while (reader.readNextStartElement()) {
if (reader.name() == "Get")
get(reader, ctx);
else
reader.skipCurrentElement();
}
}
void WMS::dcpType(QXmlStreamReader &reader, CTX &ctx)
{
while (reader.readNextStartElement()) {
if (reader.name() == "HTTP")
http(reader, ctx);
else
reader.skipCurrentElement();
}
}
void WMS::getMap(QXmlStreamReader &reader, CTX &ctx)
{
while (reader.readNextStartElement()) {
if (reader.name() == "Format") {
if (reader.readElementText() == ctx.setup.format())
QString format(reader.readElementText());
if (bareFormat(format) == bareFormat(ctx.setup.format()))
ctx.formatSupported = true;
} else
} else if (reader.name() == "DCPType")
dcpType(reader, ctx);
else
reader.skipCurrentElement();
}
}
@ -97,7 +146,16 @@ void WMS::layer(QXmlStreamReader &reader, CTX &ctx,
CRSs.append(reader.readElementText());
else if (reader.name() == "Style")
styles.append(style(reader));
else if (reader.name() == "MinScaleDenominator") {
else if (reader.name() == "ScaleHint") {
QXmlStreamAttributes attr = reader.attributes();
double minHint = attr.value("min").toString().toDouble();
double maxHint = attr.value("max").toString().toDouble();
if (minHint > 0)
scaleDenominator.setMin(hint2denominator(minHint));
if (maxHint > 0)
scaleDenominator.setMax(hint2denominator(maxHint));
reader.skipCurrentElement();
} else if (reader.name() == "MinScaleDenominator") {
double sd = reader.readElementText().toDouble();
if (sd > 0)
scaleDenominator.setMin(sd);
@ -248,6 +306,8 @@ bool WMS::parseCapabilities(const QString &path, const Setup &setup)
return false;
}
_tileUrl = ctx.url.isEmpty() ? setup.url() : ctx.url;
return true;
}

View File

@ -54,6 +54,7 @@ public:
const RangeF &scaleDenominator() const {return _scaleDenominator;}
const RectC &boundingBox() const {return _boundingBox;}
const QString &version() const {return _version;}
const QString &tileUrl() const {return _tileUrl;}
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
@ -79,12 +80,16 @@ private:
const Setup &setup;
QList<Layer> layers;
bool formatSupported;
QString url;
CTX(const Setup &setup);
};
RectC geographicBoundingBox(QXmlStreamReader &reader);
QString style(QXmlStreamReader &reader);
void get(QXmlStreamReader &reader, CTX &ctx);
void http(QXmlStreamReader &reader, CTX &ctx);
void dcpType(QXmlStreamReader &reader, CTX &ctx);
void getMap(QXmlStreamReader &reader, CTX &ctx);
void request(QXmlStreamReader &reader, CTX &ctx);
void layer(QXmlStreamReader &reader, CTX &ctx, const QList<QString> &pCRSs,
@ -100,6 +105,7 @@ private:
RangeF _scaleDenominator;
RectC _boundingBox;
QString _version;
QString _tileUrl;
bool _valid;
QString _errorString;

View File

@ -10,7 +10,6 @@
#define CAPABILITIES_FILE "capabilities.xml"
#define TILE_SIZE 256
#define EPSILON 1e-6
double WMSMap::sd2res(double scaleDenominator) const
@ -18,14 +17,14 @@ double WMSMap::sd2res(double scaleDenominator) const
return scaleDenominator * 0.28e-3 * _projection.units().fromMeters(1.0);
}
QString WMSMap::tileUrl(const QString &version) const
QString WMSMap::tileUrl(const QString &baseUrl, const QString &version) const
{
QString url;
url = QString("%1%2version=%3&request=GetMap&bbox=$bbox"
url = QString("%1%2service=WMS&version=%3&request=GetMap&bbox=$bbox"
"&width=%4&height=%5&layers=%6&styles=%7&format=%8&transparent=true")
.arg(_setup.url(), _setup.url().contains('?') ? "&" : "?", version,
QString::number(TILE_SIZE), QString::number(TILE_SIZE), _setup.layer(),
.arg(baseUrl, baseUrl.contains('?') ? "&" : "?", version,
QString::number(_tileSize), QString::number(_tileSize), _setup.layer(),
_setup.style(), _setup.format());
if (version >= "1.3.0")
@ -84,7 +83,7 @@ bool WMSMap::loadWMS()
_projection = wms.projection();
_bbox = wms.boundingBox();
_bounds = RectD(_bbox, _projection);
_tileLoader->setUrl(tileUrl(wms.version()));
_tileLoader->setUrl(tileUrl(wms.tileUrl(), wms.version()));
if (wms.version() >= "1.3.0") {
if (_setup.coordinateSystem().axisOrder() == CoordinateSystem::Unknown)
@ -100,9 +99,9 @@ bool WMSMap::loadWMS()
return true;
}
WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent)
: Map(parent), _name(name), _setup(setup), _tileLoader(0), _zoom(0),
_mapRatio(1.0), _valid(false)
WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, int tileSize,
QObject *parent) : Map(parent), _name(name), _setup(setup), _tileLoader(0),
_zoom(0), _tileSize(tileSize), _mapRatio(1.0), _valid(false)
{
_tileLoader = new TileLoader(tilesDir(), this);
_tileLoader->setAuthorization(_setup.authorization());
@ -180,7 +179,7 @@ Coordinates WMSMap::xy2ll(const QPointF &p)
qreal WMSMap::tileSize() const
{
return (TILE_SIZE / _mapRatio);
return (_tileSize / _mapRatio);
}
void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
@ -194,10 +193,10 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
tiles.reserve((br.x() - tl.x()) * (br.y() - tl.y()));
for (int i = tl.x(); i < br.x(); i++) {
for (int j = tl.y(); j < br.y(); j++) {
PointD ttl(_transform.img2proj(QPointF(i * TILE_SIZE,
j * TILE_SIZE)));
PointD tbr(_transform.img2proj(QPointF(i * TILE_SIZE + TILE_SIZE,
j * TILE_SIZE + TILE_SIZE)));
PointD ttl(_transform.img2proj(QPointF(i * _tileSize,
j * _tileSize)));
PointD tbr(_transform.img2proj(QPointF(i * _tileSize + _tileSize,
j * _tileSize + _tileSize)));
RectD bbox = (_cs.axisOrder() == CoordinateSystem::YX)
? RectD(PointD(tbr.y(), tbr.x()), PointD(ttl.y(), ttl.x()))
: RectD(ttl, tbr);

View File

@ -14,7 +14,8 @@ class WMSMap : public Map
Q_OBJECT
public:
WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent = 0);
WMSMap(const QString &name, const WMS::Setup &setup, int tileSize,
QObject *parent = 0);
QString name() const {return _name;}
@ -39,7 +40,7 @@ public:
QString errorString() const {return _errorString;}
private:
QString tileUrl(const QString &version) const;
QString tileUrl(const QString &baseUrl, const QString &version) const;
double sd2res(double scaleDenominator) const;
QString tilesDir() const;
void computeZooms(const RangeF &scaleDenominator);
@ -58,6 +59,7 @@ private:
RectC _bbox;
RectD _bounds;
int _zoom;
int _tileSize;
qreal _mapRatio;
bool _valid;

View File

@ -12,6 +12,11 @@
#include "wmts.h"
static QString bareFormat(const QString &format)
{
return format.left(format.indexOf(';')).trimmed();
}
static void skipParentElement(QXmlStreamReader &reader)
{
while (reader.readNextStartElement())
@ -182,7 +187,8 @@ void WMTS::layer(QXmlStreamReader &reader, CTX &ctx)
if (s == ctx.setup.style())
ctx.hasStyle = true;
} else if (reader.name() == "Format") {
if (reader.readElementText() == ctx.setup.format())
QString format(reader.readElementText());
if (bareFormat(format) == bareFormat(ctx.setup.format()))
ctx.hasFormat = true;
} else
reader.skipCurrentElement();