From 4a612f12bb6ad3fd0970d3472984c9d1256613c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 15 Oct 2018 00:20:20 +0200 Subject: [PATCH] Properly handle WMTS TileMatrixLimits and default style --- src/map/wmts.cpp | 151 +++++++++++++++++++++++------------------------ src/map/wmts.h | 11 ++-- 2 files changed, 81 insertions(+), 81 deletions(-) diff --git a/src/map/wmts.cpp b/src/map/wmts.cpp index f7417421..525c693a 100644 --- a/src/map/wmts.cpp +++ b/src/map/wmts.cpp @@ -12,6 +12,12 @@ #include "wmts.h" +static void skipParentElement(QXmlStreamReader &reader) +{ + while (reader.readNextStartElement()) + reader.skipCurrentElement(); +} + WMTS::TileMatrix WMTS::tileMatrix(QXmlStreamReader &reader) { TileMatrix matrix; @@ -45,24 +51,19 @@ WMTS::TileMatrix WMTS::tileMatrix(QXmlStreamReader &reader) void WMTS::tileMatrixSet(QXmlStreamReader &reader, CTX &ctx) { - QString id, crs; - QSet matrixes; - while (reader.readNextStartElement()) { - if (reader.name() == "Identifier") - id = reader.readElementText(); - else if (reader.name() == "SupportedCRS") - crs = reader.readElementText(); + if (reader.name() == "Identifier") { + if (reader.readElementText() != ctx.setup.set()) { + skipParentElement(reader); + return; + } + } else if (reader.name() == "SupportedCRS") + ctx.crs = reader.readElementText(); else if (reader.name() == "TileMatrix") - matrixes.insert(tileMatrix(reader)); + ctx.matrixes.insert(tileMatrix(reader)); else reader.skipCurrentElement(); } - - if (id == ctx.setup.set()) { - ctx.crs = crs; - _matrixes = matrixes; - } } WMTS::MatrixLimits WMTS::tileMatrixLimits(QXmlStreamReader &reader) @@ -106,22 +107,19 @@ QSet WMTS::tileMatrixSetLimits(QXmlStreamReader &reader) void WMTS::tileMatrixSetLink(QXmlStreamReader &reader, CTX &ctx) { - QString id; - QSet limits; - while (reader.readNextStartElement()) { - if (reader.name() == "TileMatrixSet") - id = reader.readElementText(); - else if (reader.name() == "TileMatrixSetLimits") - limits = tileMatrixSetLimits(reader); + if (reader.name() == "TileMatrixSet") { + if (reader.readElementText() == ctx.setup.set()) + ctx.hasSet = true; + else { + skipParentElement(reader); + return; + } + } else if (reader.name() == "TileMatrixSetLimits") + ctx.limits = tileMatrixSetLimits(reader); else reader.skipCurrentElement(); } - - if (id == ctx.setup.set()) { - ctx.hasSet = true; - _limits = limits; - } } RectC WMTS::wgs84BoundingBox(QXmlStreamReader &reader) @@ -158,40 +156,37 @@ QString WMTS::style(QXmlStreamReader &reader) void WMTS::layer(QXmlStreamReader &reader, CTX &ctx) { - QString id, tpl; - RectC bounds; - QStringList formats, styles; - while (reader.readNextStartElement()) { - if (reader.name() == "Identifier") - id = reader.readElementText(); - else if (reader.name() == "TileMatrixSetLink") + if (reader.name() == "Identifier") { + if (reader.readElementText() == ctx.setup.layer()) + ctx.hasLayer = true; + else { + skipParentElement(reader); + return; + } + } else if (reader.name() == "TileMatrixSetLink") tileMatrixSetLink(reader, ctx); else if (reader.name() == "WGS84BoundingBox") - bounds = wgs84BoundingBox(reader); + _bounds = wgs84BoundingBox(reader); else if (reader.name() == "ResourceURL") { const QXmlStreamAttributes &attr = reader.attributes(); - if (attr.value("resourceType") == "tile") - tpl = attr.value("template").toString(); + if (attr.value("resourceType") == "tile" && ctx.setup.rest()) + _tileUrl = attr.value("template").toString(); reader.skipCurrentElement(); - } else if (reader.name() == "Style") - styles.append(style(reader)); - else if (reader.name() == "Format") - formats.append(reader.readElementText()); - else + } else if (reader.name() == "Style") { + const QXmlStreamAttributes &attr = reader.attributes(); + bool isDefault = (attr.value("isDefault") == "true"); + QString s = style(reader); + if (isDefault) + ctx.defaultStyle = s; + if (!s.isEmpty() && s == ctx.setup.style()) + ctx.hasStyle = true; + } else if (reader.name() == "Format") { + if (reader.readElementText() == ctx.setup.format()) + ctx.hasFormat = true; + } else reader.skipCurrentElement(); } - - if (id == ctx.setup.layer()) { - ctx.hasLayer = true; - _bounds = bounds; - if (ctx.setup.rest()) - _tileUrl = tpl; - if (styles.contains(ctx.setup.style()) || ctx.setup.style().isEmpty()) - ctx.hasStyle = true; - if (formats.contains(ctx.setup.format())) - ctx.hasFormat = true; - } } void WMTS::contents(QXmlStreamReader &reader, CTX &ctx) @@ -216,10 +211,24 @@ void WMTS::capabilities(QXmlStreamReader &reader, CTX &ctx) } } -bool WMTS::parseCapabilities(const QString &path, const Setup &setup) +void WMTS::createZooms(const CTX &ctx) +{ + for (QSet::const_iterator mi = ctx.matrixes.constBegin(); + mi != ctx.matrixes.constEnd(); ++mi) { + QSet::const_iterator li = ctx.limits.find( + MatrixLimits(mi->id)); + if (!ctx.limits.isEmpty() && li == ctx.limits.constEnd()) + continue; + _zooms.append(Zoom(mi->id, mi->scaleDenominator, mi->topLeft, mi->tile, + mi->matrix, li == ctx.limits.constEnd() ? QRect() : li->rect)); + } + + qSort(_zooms); +} + +bool WMTS::parseCapabilities(const QString &path, CTX &ctx) { QFile file(path); - CTX ctx(setup); QXmlStreamReader reader; if (!file.open(QFile::ReadOnly | QFile::Text)) { @@ -240,14 +249,20 @@ bool WMTS::parseCapabilities(const QString &path, const Setup &setup) return false; } + createZooms(ctx); + if (!ctx.hasLayer) { _errorString = ctx.setup.layer() + ": layer not provided"; return false; } - if (!ctx.hasStyle) { + if (!ctx.hasStyle && !ctx.setup.style().isEmpty()) { _errorString = ctx.setup.style() + ": style not provided"; return false; } + if (ctx.setup.style().isEmpty() && ctx.defaultStyle.isEmpty()) { + _errorString = "Default style not provided"; + return false; + } if (!ctx.setup.rest() && !ctx.hasFormat) { _errorString = ctx.setup.format() + ": format not provided"; return false; @@ -265,7 +280,7 @@ bool WMTS::parseCapabilities(const QString &path, const Setup &setup) _errorString = ctx.crs + ": unknown CRS"; return false; } - if (_matrixes.isEmpty()) { + if (ctx.matrixes.isEmpty()) { _errorString = "No usable tile matrix found"; return false; } @@ -307,10 +322,12 @@ WMTS::WMTS(const QString &file, const WMTS::Setup &setup) : _valid(false) if (!url.isLocalFile() && !QFileInfo(file).exists()) if (!downloadCapabilities(url.toString(), file, setup.authorization())) return; - if (!parseCapabilities(url.isLocalFile() ? url.toLocalFile() : file, setup)) + + CTX ctx(setup); + if (!parseCapabilities(url.isLocalFile() ? url.toLocalFile() : file, ctx)) return; - QString style = setup.style().isEmpty() ? "default" : setup.style(); + QString style = setup.style().isEmpty() ? ctx.defaultStyle : setup.style(); if (!setup.rest()) { _tileUrl = QString("%1%2service=WMTS&Version=1.0.0&request=GetTile" "&Format=%3&Layer=%4&Style=%5&TileMatrixSet=%6&TileMatrix=$z" @@ -337,26 +354,6 @@ WMTS::WMTS(const QString &file, const WMTS::Setup &setup) : _valid(false) _valid = true; } -QList WMTS::zooms() const -{ - QList zooms; - QSet::const_iterator mi; - QSet::const_iterator li; - - for (mi = _matrixes.constBegin(); mi != _matrixes.constEnd(); ++mi) { - if ((li = _limits.find(MatrixLimits(mi->id))) == _limits.constEnd()) - zooms.append(Zoom(mi->id, mi->scaleDenominator, mi->topLeft, - mi->tile, mi->matrix, QRect())); - else - zooms.append(Zoom(mi->id, mi->scaleDenominator, mi->topLeft, - mi->tile, mi->matrix, li->rect)); - } - - qSort(zooms); - - return zooms; -} - #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const WMTS::Setup &setup) { diff --git a/src/map/wmts.h b/src/map/wmts.h index 2032f3e5..76a29cb4 100644 --- a/src/map/wmts.h +++ b/src/map/wmts.h @@ -80,7 +80,7 @@ public: WMTS(const QString &path, const Setup &setup); const RectC &bounds() const {return _bounds;} - QList zooms() const; + const QList &zooms() const {return _zooms;} const Projection &projection() const {return _projection;} const QString &tileUrl() const {return _tileUrl;} @@ -117,7 +117,10 @@ private: struct CTX { const Setup &setup; + QSet matrixes; + QSet limits; QString crs; + QString defaultStyle; bool hasLayer; bool hasStyle; bool hasFormat; @@ -137,12 +140,12 @@ private: void layer(QXmlStreamReader &reader, CTX &ctx); void contents(QXmlStreamReader &reader, CTX &ctx); void capabilities(QXmlStreamReader &reader, CTX &ctx); - bool parseCapabilities(const QString &path, const Setup &setup); + bool parseCapabilities(const QString &path, CTX &ctx); bool downloadCapabilities(const QString &url, const QString &file, const Authorization &authorization); + void createZooms(const CTX &ctx); - QSet _matrixes; - QSet _limits; + QList _zooms; RectC _bounds; Projection _projection; QString _tileUrl;