mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-01-31 09:05:14 +01:00
Improved capabilities xml parsing
Improved bounds handling
This commit is contained in:
parent
fa3e6d8550
commit
ee80260e46
149
src/map/wmts.cpp
149
src/map/wmts.cpp
@ -58,115 +58,156 @@ bool WMTS::createProjection(const QString &crs)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMTS::tileMatrix(QXmlStreamReader &reader)
|
WMTS::TileMatrix WMTS::tileMatrix(QXmlStreamReader &reader)
|
||||||
{
|
{
|
||||||
Zoom zoom;
|
TileMatrix matrix;
|
||||||
|
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == "Identifier")
|
if (reader.name() == "Identifier")
|
||||||
zoom.id = reader.readElementText();
|
matrix.id = reader.readElementText();
|
||||||
else if (reader.name() == "ScaleDenominator")
|
else if (reader.name() == "ScaleDenominator")
|
||||||
zoom.scaleDenominator = reader.readElementText().toDouble();
|
matrix.scaleDenominator = reader.readElementText().toDouble();
|
||||||
else if (reader.name() == "TopLeftCorner") {
|
else if (reader.name() == "TopLeftCorner") {
|
||||||
QString str = reader.readElementText();
|
QString str = reader.readElementText();
|
||||||
QTextStream(&str) >> zoom.topLeft.rx() >> zoom.topLeft.ry();
|
QTextStream(&str) >> matrix.topLeft.rx() >> matrix.topLeft.ry();
|
||||||
} else if (reader.name() == "TileWidth")
|
} else if (reader.name() == "TileWidth")
|
||||||
zoom.tile.setWidth(reader.readElementText().toInt());
|
matrix.tile.setWidth(reader.readElementText().toInt());
|
||||||
else if (reader.name() == "TileHeight")
|
else if (reader.name() == "TileHeight")
|
||||||
zoom.tile.setHeight(reader.readElementText().toInt());
|
matrix.tile.setHeight(reader.readElementText().toInt());
|
||||||
else if (reader.name() == "MatrixWidth")
|
else if (reader.name() == "MatrixWidth")
|
||||||
zoom.matrix.setWidth(reader.readElementText().toInt());
|
matrix.matrix.setWidth(reader.readElementText().toInt());
|
||||||
else if (reader.name() == "MatrixHeight")
|
else if (reader.name() == "MatrixHeight")
|
||||||
zoom.matrix.setHeight(reader.readElementText().toInt());
|
matrix.matrix.setHeight(reader.readElementText().toInt());
|
||||||
else
|
else
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
Zoom &z = _zooms[zoom.id];
|
if (!matrix.isValid())
|
||||||
z.id = zoom.id;
|
reader.raiseError("Invalid TileMatrix definition");
|
||||||
z.matrix = zoom.matrix;
|
|
||||||
z.scaleDenominator = zoom.scaleDenominator;
|
return matrix;
|
||||||
z.tile = zoom.tile;
|
|
||||||
z.topLeft = zoom.topLeft;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMTS::tileMatrixSet(QXmlStreamReader &reader, const QString &set)
|
void WMTS::tileMatrixSet(QXmlStreamReader &reader, const QString &set)
|
||||||
{
|
{
|
||||||
QString id;
|
QString id, crs;
|
||||||
|
QSet<TileMatrix> matrixes;
|
||||||
|
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == "Identifier")
|
if (reader.name() == "Identifier")
|
||||||
id = reader.readElementText();
|
id = reader.readElementText();
|
||||||
else if (reader.name() == "SupportedCRS" && id == set) {
|
else if (reader.name() == "SupportedCRS")
|
||||||
if (!createProjection(reader.readElementText()))
|
crs = reader.readElementText();
|
||||||
reader.raiseError("Invalid/unknown CRS");
|
else if (reader.name() == "TileMatrix")
|
||||||
} else if (reader.name() == "TileMatrix" && id == set)
|
matrixes.insert(tileMatrix(reader));
|
||||||
tileMatrix(reader);
|
|
||||||
else
|
else
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id == set) {
|
||||||
|
if (!createProjection(crs)) {
|
||||||
|
reader.raiseError("Invalid/unknown CRS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_matrixes.unite(matrixes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMTS::tileMatrixLimits(QXmlStreamReader &reader)
|
WMTS::MatrixLimits WMTS::tileMatrixLimits(QXmlStreamReader &reader)
|
||||||
{
|
{
|
||||||
QString id;
|
MatrixLimits limits;
|
||||||
QRect limits;
|
|
||||||
|
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == "TileMatrix")
|
if (reader.name() == "TileMatrix")
|
||||||
id = reader.readElementText();
|
limits.id = reader.readElementText();
|
||||||
else if (reader.name() == "MinTileRow")
|
else if (reader.name() == "MinTileRow")
|
||||||
limits.setTop(reader.readElementText().toInt());
|
limits.rect.setTop(reader.readElementText().toInt());
|
||||||
else if (reader.name() == "MaxTileRow")
|
else if (reader.name() == "MaxTileRow")
|
||||||
limits.setBottom(reader.readElementText().toInt());
|
limits.rect.setBottom(reader.readElementText().toInt());
|
||||||
else if (reader.name() == "MinTileCol")
|
else if (reader.name() == "MinTileCol")
|
||||||
limits.setLeft(reader.readElementText().toInt());
|
limits.rect.setLeft(reader.readElementText().toInt());
|
||||||
else if (reader.name() == "MaxTileCol")
|
else if (reader.name() == "MaxTileCol")
|
||||||
limits.setRight(reader.readElementText().toInt());
|
limits.rect.setRight(reader.readElementText().toInt());
|
||||||
else
|
else
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
_zooms[id].limits = limits;
|
if (!limits.isValid())
|
||||||
|
reader.raiseError("Invalid TileMatrixLimits definition");
|
||||||
|
|
||||||
|
return limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMTS::tileMatrixSetLimits(QXmlStreamReader &reader)
|
QSet<WMTS::MatrixLimits> WMTS::tileMatrixSetLimits(QXmlStreamReader &reader)
|
||||||
{
|
{
|
||||||
|
QSet<MatrixLimits> limits;
|
||||||
|
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == "TileMatrixLimits")
|
if (reader.name() == "TileMatrixLimits")
|
||||||
tileMatrixLimits(reader);
|
limits.insert(tileMatrixLimits(reader));
|
||||||
else
|
else
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMTS::tileMatrixSetLink(QXmlStreamReader &reader, const QString &set)
|
void WMTS::tileMatrixSetLink(QXmlStreamReader &reader, const QString &set)
|
||||||
{
|
{
|
||||||
QString id;
|
QString id;
|
||||||
|
QSet<MatrixLimits> limits;
|
||||||
|
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == "TileMatrixSet")
|
if (reader.name() == "TileMatrixSet")
|
||||||
id = reader.readElementText();
|
id = reader.readElementText();
|
||||||
else if (reader.name() == "TileMatrixSetLimits" && id == set)
|
else if (reader.name() == "TileMatrixSetLimits")
|
||||||
tileMatrixSetLimits(reader);
|
limits = tileMatrixSetLimits(reader);
|
||||||
else
|
else
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id == set)
|
||||||
|
_limits.unite(limits);
|
||||||
|
}
|
||||||
|
|
||||||
|
RectC WMTS::wgs84BoundingBox(QXmlStreamReader &reader)
|
||||||
|
{
|
||||||
|
Coordinates topLeft, bottomRight;
|
||||||
|
|
||||||
|
while (reader.readNextStartElement()) {
|
||||||
|
if (reader.name() == "LowerCorner") {
|
||||||
|
QString str = reader.readElementText();
|
||||||
|
QTextStream(&str) >> topLeft.rlon() >> bottomRight.rlat();
|
||||||
|
} else if (reader.name() == "UpperCorner") {
|
||||||
|
QString str = reader.readElementText();
|
||||||
|
QTextStream(&str) >> bottomRight.rlon() >> topLeft.rlat();
|
||||||
|
} else
|
||||||
|
reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
return RectC(topLeft, bottomRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMTS::layer(QXmlStreamReader &reader, const QString &layer,
|
void WMTS::layer(QXmlStreamReader &reader, const QString &layer,
|
||||||
const QString &set)
|
const QString &set)
|
||||||
{
|
{
|
||||||
QString id;
|
QString id;
|
||||||
|
RectC bounds;
|
||||||
|
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == "Identifier")
|
if (reader.name() == "Identifier")
|
||||||
id = reader.readElementText();
|
id = reader.readElementText();
|
||||||
else if (reader.name() == "TileMatrixSetLink" && id == layer)
|
else if (reader.name() == "TileMatrixSetLink")
|
||||||
tileMatrixSetLink(reader, set);
|
tileMatrixSetLink(reader, set);
|
||||||
|
else if (reader.name() == "WGS84BoundingBox")
|
||||||
|
bounds = wgs84BoundingBox(reader);
|
||||||
else
|
else
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id == layer)
|
||||||
|
_bounds = bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMTS::contents(QXmlStreamReader &reader, const QString &layer,
|
void WMTS::contents(QXmlStreamReader &reader, const QString &layer,
|
||||||
@ -251,36 +292,44 @@ bool WMTS::load(const QString &file, const QString &url, const QString &layer,
|
|||||||
if (!parseCapabilities(file, layer, set))
|
if (!parseCapabilities(file, layer, set))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (_matrixes.isEmpty()) {
|
||||||
|
_errorString = "No usable tile matrix found";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (_projection.isNull()) {
|
if (_projection.isNull()) {
|
||||||
_errorString = "Missing CRS definition";
|
_errorString = "Missing CRS definition";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_zooms.isEmpty()) {
|
|
||||||
_errorString = "No tile matrix found";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (it = _zooms.constBegin(); it != _zooms.constEnd(); ++it) {
|
|
||||||
if (!it->isValid()) {
|
|
||||||
_errorString = it->id + ": invalid tile matrix definition";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<WMTS::Zoom> WMTS::zooms() const
|
QList<WMTS::Zoom> WMTS::zooms() const
|
||||||
{
|
{
|
||||||
QList<Zoom> z(_zooms.values());
|
QList<Zoom> zooms;
|
||||||
qSort(z);
|
QSet<TileMatrix>::const_iterator mi;
|
||||||
return z;
|
QSet<MatrixLimits>::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(Zoom(mi->id, mi->scaleDenominator, mi->topLeft,
|
||||||
|
mi->tile, mi->matrix, li->rect)));
|
||||||
|
}
|
||||||
|
|
||||||
|
qSort(zooms);
|
||||||
|
|
||||||
|
return zooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom)
|
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "Zoom(" << zoom.scaleDenominator << ", " << zoom.topLeft
|
dbg.nospace() << "Zoom(" << zoom.id << ", " << zoom.scaleDenominator << ", "
|
||||||
<< ", " << zoom.tile << ", " << zoom.matrix << ", " << zoom.limits << ")";
|
<< zoom.topLeft << ", " << zoom.tile << ", " << zoom.matrix << ", "
|
||||||
|
<< zoom.limits << ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
#endif // QT_NO_DEBUG
|
#endif // QT_NO_DEBUG
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
#define WMTS_H
|
#define WMTS_H
|
||||||
|
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QMap>
|
#include <QSet>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QHash>
|
||||||
|
#include "common/rectc.h"
|
||||||
#include "projection.h"
|
#include "projection.h"
|
||||||
|
|
||||||
class QXmlStreamReader;
|
class QXmlStreamReader;
|
||||||
@ -20,18 +22,20 @@ public:
|
|||||||
QSize matrix;
|
QSize matrix;
|
||||||
QRect limits;
|
QRect limits;
|
||||||
|
|
||||||
Zoom() : scaleDenominator(0) {}
|
Zoom() {}
|
||||||
|
Zoom(const QString &id, qreal scaleDenominator, const QPointF &topLeft,
|
||||||
|
const QSize &tile, const QSize &matrix, const QRect &limits) :
|
||||||
|
id(id), scaleDenominator(scaleDenominator), topLeft(topLeft),
|
||||||
|
tile(tile), matrix(matrix), limits(limits) {}
|
||||||
bool operator<(const Zoom &other) const
|
bool operator<(const Zoom &other) const
|
||||||
{return this->scaleDenominator > other.scaleDenominator;}
|
{return scaleDenominator > other.scaleDenominator;}
|
||||||
bool isValid() const
|
|
||||||
{return scaleDenominator > 0 && !id.isEmpty() && tile.isValid()
|
|
||||||
&& matrix.isValid();}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool load(const QString &path, const QString &url, const QString &layer,
|
bool load(const QString &path, const QString &url, const QString &layer,
|
||||||
const QString &set);
|
const QString &set);
|
||||||
const QString &errorString() const {return _errorString;}
|
const QString &errorString() const {return _errorString;}
|
||||||
|
|
||||||
|
const RectC &bounds() const {return _bounds;}
|
||||||
QList<Zoom> zooms() const;
|
QList<Zoom> zooms() const;
|
||||||
const Projection &projection() const {return _projection;}
|
const Projection &projection() const {return _projection;}
|
||||||
|
|
||||||
@ -40,11 +44,39 @@ public:
|
|||||||
{_downloader = downloader;}
|
{_downloader = downloader;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct TileMatrix {
|
||||||
|
QString id;
|
||||||
|
qreal scaleDenominator;
|
||||||
|
QPointF topLeft;
|
||||||
|
QSize tile;
|
||||||
|
QSize matrix;
|
||||||
|
|
||||||
|
TileMatrix() : scaleDenominator(0) {}
|
||||||
|
bool operator==(const TileMatrix &other) const
|
||||||
|
{return this->id == other.id;}
|
||||||
|
bool isValid() const
|
||||||
|
{return !id.isEmpty() && scaleDenominator > 0 && tile.isValid()
|
||||||
|
&& matrix.isValid();}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MatrixLimits {
|
||||||
|
QString id;
|
||||||
|
QRect rect;
|
||||||
|
|
||||||
|
MatrixLimits() {}
|
||||||
|
MatrixLimits(const QString &id) : id(id) {}
|
||||||
|
bool operator==(const MatrixLimits &other) const
|
||||||
|
{return this->id == other.id;}
|
||||||
|
bool isValid() const
|
||||||
|
{return !id.isEmpty() && rect.isValid();}
|
||||||
|
};
|
||||||
|
|
||||||
bool createProjection(const QString &crs);
|
bool createProjection(const QString &crs);
|
||||||
|
|
||||||
void tileMatrixLimits(QXmlStreamReader &reader);
|
RectC wgs84BoundingBox(QXmlStreamReader &reader);
|
||||||
void tileMatrix(QXmlStreamReader &reader);
|
MatrixLimits tileMatrixLimits(QXmlStreamReader &reader);
|
||||||
void tileMatrixSetLimits(QXmlStreamReader &reader);
|
TileMatrix tileMatrix(QXmlStreamReader &reader);
|
||||||
|
QSet<MatrixLimits> tileMatrixSetLimits(QXmlStreamReader &reader);
|
||||||
void tileMatrixSet(QXmlStreamReader &reader, const QString &set);
|
void tileMatrixSet(QXmlStreamReader &reader, const QString &set);
|
||||||
void tileMatrixSetLink(QXmlStreamReader &reader, const QString &set);
|
void tileMatrixSetLink(QXmlStreamReader &reader, const QString &set);
|
||||||
void layer(QXmlStreamReader &reader, const QString &layer,
|
void layer(QXmlStreamReader &reader, const QString &layer,
|
||||||
@ -57,14 +89,29 @@ private:
|
|||||||
const QString &set);
|
const QString &set);
|
||||||
bool getCapabilities(const QString &url, const QString &file);
|
bool getCapabilities(const QString &url, const QString &file);
|
||||||
|
|
||||||
QMap<QString, Zoom> _zooms;
|
QSet<TileMatrix> _matrixes;
|
||||||
|
QSet<MatrixLimits> _limits;
|
||||||
|
RectC _bounds;
|
||||||
Projection _projection;
|
Projection _projection;
|
||||||
|
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
|
|
||||||
static Downloader *_downloader;
|
static Downloader *_downloader;
|
||||||
|
|
||||||
|
friend uint qHash(const WMTS::TileMatrix &key);
|
||||||
|
friend uint qHash(const WMTS::MatrixLimits &key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline uint qHash(const WMTS::TileMatrix &key)
|
||||||
|
{
|
||||||
|
return ::qHash(key.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint qHash(const WMTS::MatrixLimits &key)
|
||||||
|
{
|
||||||
|
return ::qHash(key.id);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom);
|
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom);
|
||||||
#endif // QT_NO_DEBUG
|
#endif // QT_NO_DEBUG
|
||||||
|
@ -29,6 +29,7 @@ WMTSMap::WMTSMap(const QString &name, const QString &url, const QString &format,
|
|||||||
_errorString = wmts.errorString();
|
_errorString = wmts.errorString();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_bounds = wmts.bounds();
|
||||||
_zooms = wmts.zooms();
|
_zooms = wmts.zooms();
|
||||||
_projection = wmts.projection();
|
_projection = wmts.projection();
|
||||||
|
|
||||||
@ -108,14 +109,18 @@ void WMTSMap::emitLoaded()
|
|||||||
QRectF WMTSMap::bounds() const
|
QRectF WMTSMap::bounds() const
|
||||||
{
|
{
|
||||||
const WMTS::Zoom &z = _zooms.at(_zoom);
|
const WMTS::Zoom &z = _zooms.at(_zoom);
|
||||||
|
QRectF tileBounds, bounds;
|
||||||
|
|
||||||
if (z.limits.isNull())
|
tileBounds = (z.limits.isNull()) ?
|
||||||
return QRectF(QPointF(0, 0), QSize(z.tile.width() * z.matrix.width(),
|
QRectF(QPointF(0, 0), QSize(z.tile.width() * z.matrix.width(),
|
||||||
z.tile.height() * z.matrix.height()));
|
z.tile.height() * z.matrix.height())) : QRectF(QPointF(z.limits.left()
|
||||||
else
|
* z.tile.width(), z.limits.top() * z.tile.height()), QSize(z.tile.width()
|
||||||
return QRectF(QPointF(z.limits.left() * z.tile.width(), z.limits.top()
|
* z.limits.width(), z.tile.height() * z.limits.height()));
|
||||||
* z.tile.height()), QSize(z.tile.width() * z.limits.width(),
|
|
||||||
z.tile.height() * z.limits.height()));
|
bounds = _bounds.isValid() ? QRectF(ll2xy(_bounds.topLeft()),
|
||||||
|
ll2xy(_bounds.bottomRight())) : QRectF();
|
||||||
|
|
||||||
|
return _bounds.isValid() ? tileBounds.intersected(bounds) : tileBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal WMTSMap::zoomFit(const QSize &size, const RectC &br)
|
qreal WMTSMap::zoomFit(const QSize &size, const RectC &br)
|
||||||
|
@ -56,6 +56,7 @@ private:
|
|||||||
|
|
||||||
QString _name, _url, _layer, _set;
|
QString _name, _url, _layer, _set;
|
||||||
TileLoader _tileLoader;
|
TileLoader _tileLoader;
|
||||||
|
RectC _bounds;
|
||||||
QList<WMTS::Zoom> _zooms;
|
QList<WMTS::Zoom> _zooms;
|
||||||
bool _invertAxis;
|
bool _invertAxis;
|
||||||
Projection _projection;
|
Projection _projection;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user