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;
|
||||
}
|
||||
|
||||
void WMTS::tileMatrix(QXmlStreamReader &reader)
|
||||
WMTS::TileMatrix WMTS::tileMatrix(QXmlStreamReader &reader)
|
||||
{
|
||||
Zoom zoom;
|
||||
TileMatrix matrix;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "Identifier")
|
||||
zoom.id = reader.readElementText();
|
||||
matrix.id = reader.readElementText();
|
||||
else if (reader.name() == "ScaleDenominator")
|
||||
zoom.scaleDenominator = reader.readElementText().toDouble();
|
||||
matrix.scaleDenominator = reader.readElementText().toDouble();
|
||||
else if (reader.name() == "TopLeftCorner") {
|
||||
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")
|
||||
zoom.tile.setWidth(reader.readElementText().toInt());
|
||||
matrix.tile.setWidth(reader.readElementText().toInt());
|
||||
else if (reader.name() == "TileHeight")
|
||||
zoom.tile.setHeight(reader.readElementText().toInt());
|
||||
matrix.tile.setHeight(reader.readElementText().toInt());
|
||||
else if (reader.name() == "MatrixWidth")
|
||||
zoom.matrix.setWidth(reader.readElementText().toInt());
|
||||
matrix.matrix.setWidth(reader.readElementText().toInt());
|
||||
else if (reader.name() == "MatrixHeight")
|
||||
zoom.matrix.setHeight(reader.readElementText().toInt());
|
||||
matrix.matrix.setHeight(reader.readElementText().toInt());
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
Zoom &z = _zooms[zoom.id];
|
||||
z.id = zoom.id;
|
||||
z.matrix = zoom.matrix;
|
||||
z.scaleDenominator = zoom.scaleDenominator;
|
||||
z.tile = zoom.tile;
|
||||
z.topLeft = zoom.topLeft;
|
||||
if (!matrix.isValid())
|
||||
reader.raiseError("Invalid TileMatrix definition");
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
void WMTS::tileMatrixSet(QXmlStreamReader &reader, const QString &set)
|
||||
{
|
||||
QString id;
|
||||
QString id, crs;
|
||||
QSet<TileMatrix> matrixes;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "Identifier")
|
||||
id = reader.readElementText();
|
||||
else if (reader.name() == "SupportedCRS" && id == set) {
|
||||
if (!createProjection(reader.readElementText()))
|
||||
reader.raiseError("Invalid/unknown CRS");
|
||||
} else if (reader.name() == "TileMatrix" && id == set)
|
||||
tileMatrix(reader);
|
||||
else if (reader.name() == "SupportedCRS")
|
||||
crs = reader.readElementText();
|
||||
else if (reader.name() == "TileMatrix")
|
||||
matrixes.insert(tileMatrix(reader));
|
||||
else
|
||||
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;
|
||||
QRect limits;
|
||||
MatrixLimits limits;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "TileMatrix")
|
||||
id = reader.readElementText();
|
||||
limits.id = reader.readElementText();
|
||||
else if (reader.name() == "MinTileRow")
|
||||
limits.setTop(reader.readElementText().toInt());
|
||||
limits.rect.setTop(reader.readElementText().toInt());
|
||||
else if (reader.name() == "MaxTileRow")
|
||||
limits.setBottom(reader.readElementText().toInt());
|
||||
limits.rect.setBottom(reader.readElementText().toInt());
|
||||
else if (reader.name() == "MinTileCol")
|
||||
limits.setLeft(reader.readElementText().toInt());
|
||||
limits.rect.setLeft(reader.readElementText().toInt());
|
||||
else if (reader.name() == "MaxTileCol")
|
||||
limits.setRight(reader.readElementText().toInt());
|
||||
limits.rect.setRight(reader.readElementText().toInt());
|
||||
else
|
||||
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()) {
|
||||
if (reader.name() == "TileMatrixLimits")
|
||||
tileMatrixLimits(reader);
|
||||
limits.insert(tileMatrixLimits(reader));
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
return limits;
|
||||
}
|
||||
|
||||
void WMTS::tileMatrixSetLink(QXmlStreamReader &reader, const QString &set)
|
||||
{
|
||||
QString id;
|
||||
QSet<MatrixLimits> limits;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "TileMatrixSet")
|
||||
id = reader.readElementText();
|
||||
else if (reader.name() == "TileMatrixSetLimits" && id == set)
|
||||
tileMatrixSetLimits(reader);
|
||||
else if (reader.name() == "TileMatrixSetLimits")
|
||||
limits = tileMatrixSetLimits(reader);
|
||||
else
|
||||
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,
|
||||
const QString &set)
|
||||
{
|
||||
QString id;
|
||||
RectC bounds;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "Identifier")
|
||||
id = reader.readElementText();
|
||||
else if (reader.name() == "TileMatrixSetLink" && id == layer)
|
||||
else if (reader.name() == "TileMatrixSetLink")
|
||||
tileMatrixSetLink(reader, set);
|
||||
else if (reader.name() == "WGS84BoundingBox")
|
||||
bounds = wgs84BoundingBox(reader);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (id == layer)
|
||||
_bounds = bounds;
|
||||
}
|
||||
|
||||
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))
|
||||
return false;
|
||||
|
||||
if (_matrixes.isEmpty()) {
|
||||
_errorString = "No usable tile matrix found";
|
||||
return false;
|
||||
}
|
||||
if (_projection.isNull()) {
|
||||
_errorString = "Missing CRS definition";
|
||||
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;
|
||||
}
|
||||
|
||||
QList<WMTS::Zoom> WMTS::zooms() const
|
||||
{
|
||||
QList<Zoom> z(_zooms.values());
|
||||
qSort(z);
|
||||
return z;
|
||||
QList<Zoom> zooms;
|
||||
QSet<TileMatrix>::const_iterator mi;
|
||||
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
|
||||
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom)
|
||||
{
|
||||
dbg.nospace() << "Zoom(" << zoom.scaleDenominator << ", " << zoom.topLeft
|
||||
<< ", " << zoom.tile << ", " << zoom.matrix << ", " << zoom.limits << ")";
|
||||
dbg.nospace() << "Zoom(" << zoom.id << ", " << zoom.scaleDenominator << ", "
|
||||
<< zoom.topLeft << ", " << zoom.tile << ", " << zoom.matrix << ", "
|
||||
<< zoom.limits << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -2,8 +2,10 @@
|
||||
#define WMTS_H
|
||||
|
||||
#include <QSize>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include "common/rectc.h"
|
||||
#include "projection.h"
|
||||
|
||||
class QXmlStreamReader;
|
||||
@ -20,18 +22,20 @@ public:
|
||||
QSize matrix;
|
||||
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
|
||||
{return this->scaleDenominator > other.scaleDenominator;}
|
||||
bool isValid() const
|
||||
{return scaleDenominator > 0 && !id.isEmpty() && tile.isValid()
|
||||
&& matrix.isValid();}
|
||||
{return scaleDenominator > other.scaleDenominator;}
|
||||
};
|
||||
|
||||
bool load(const QString &path, const QString &url, const QString &layer,
|
||||
const QString &set);
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
||||
const RectC &bounds() const {return _bounds;}
|
||||
QList<Zoom> zooms() const;
|
||||
const Projection &projection() const {return _projection;}
|
||||
|
||||
@ -40,11 +44,39 @@ public:
|
||||
{_downloader = downloader;}
|
||||
|
||||
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);
|
||||
|
||||
void tileMatrixLimits(QXmlStreamReader &reader);
|
||||
void tileMatrix(QXmlStreamReader &reader);
|
||||
void tileMatrixSetLimits(QXmlStreamReader &reader);
|
||||
RectC wgs84BoundingBox(QXmlStreamReader &reader);
|
||||
MatrixLimits tileMatrixLimits(QXmlStreamReader &reader);
|
||||
TileMatrix tileMatrix(QXmlStreamReader &reader);
|
||||
QSet<MatrixLimits> tileMatrixSetLimits(QXmlStreamReader &reader);
|
||||
void tileMatrixSet(QXmlStreamReader &reader, const QString &set);
|
||||
void tileMatrixSetLink(QXmlStreamReader &reader, const QString &set);
|
||||
void layer(QXmlStreamReader &reader, const QString &layer,
|
||||
@ -57,14 +89,29 @@ private:
|
||||
const QString &set);
|
||||
bool getCapabilities(const QString &url, const QString &file);
|
||||
|
||||
QMap<QString, Zoom> _zooms;
|
||||
QSet<TileMatrix> _matrixes;
|
||||
QSet<MatrixLimits> _limits;
|
||||
RectC _bounds;
|
||||
Projection _projection;
|
||||
|
||||
QString _errorString;
|
||||
|
||||
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
|
||||
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -29,6 +29,7 @@ WMTSMap::WMTSMap(const QString &name, const QString &url, const QString &format,
|
||||
_errorString = wmts.errorString();
|
||||
return;
|
||||
}
|
||||
_bounds = wmts.bounds();
|
||||
_zooms = wmts.zooms();
|
||||
_projection = wmts.projection();
|
||||
|
||||
@ -108,14 +109,18 @@ void WMTSMap::emitLoaded()
|
||||
QRectF WMTSMap::bounds() const
|
||||
{
|
||||
const WMTS::Zoom &z = _zooms.at(_zoom);
|
||||
QRectF tileBounds, bounds;
|
||||
|
||||
if (z.limits.isNull())
|
||||
return QRectF(QPointF(0, 0), QSize(z.tile.width() * z.matrix.width(),
|
||||
z.tile.height() * z.matrix.height()));
|
||||
else
|
||||
return QRectF(QPointF(z.limits.left() * z.tile.width(), z.limits.top()
|
||||
* z.tile.height()), QSize(z.tile.width() * z.limits.width(),
|
||||
z.tile.height() * z.limits.height()));
|
||||
tileBounds = (z.limits.isNull()) ?
|
||||
QRectF(QPointF(0, 0), QSize(z.tile.width() * z.matrix.width(),
|
||||
z.tile.height() * z.matrix.height())) : QRectF(QPointF(z.limits.left()
|
||||
* z.tile.width(), z.limits.top() * 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)
|
||||
|
@ -56,6 +56,7 @@ private:
|
||||
|
||||
QString _name, _url, _layer, _set;
|
||||
TileLoader _tileLoader;
|
||||
RectC _bounds;
|
||||
QList<WMTS::Zoom> _zooms;
|
||||
bool _invertAxis;
|
||||
Projection _projection;
|
||||
|
Loading…
x
Reference in New Issue
Block a user