1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 23:03:22 +02:00
GPXSee/src/map/wmts.cpp

287 lines
6.8 KiB
C++
Raw Normal View History

2018-02-20 23:37:19 +01:00
#include <QXmlStreamReader>
#include <QFile>
#include <QFileInfo>
#include <QEventLoop>
#include <QTextStream>
2018-02-21 00:13:11 +01:00
#include <QStringList>
#include <QtAlgorithms>
2018-02-20 23:37:19 +01:00
#include "downloader.h"
#include "pcs.h"
#include "wmts.h"
Downloader *WMTS::_downloader = 0;
bool WMTS::createProjection(const QString &crs)
{
QStringList list(crs.split(':'));
QString authority, code;
bool res;
int epsg;
2018-02-20 23:37:19 +01:00
const PCS *pcs;
const GCS *gcs;
2018-02-20 23:37:19 +01:00
switch (list.size()) {
case 2:
authority = list.at(0);
code = list.at(1);
break;
case 7:
authority = list.at(4);
code = list.at(6);
break;
default:
return false;
}
if (authority == "EPSG") {
epsg = code.toInt(&res);
if (!res)
return false;
2018-02-20 23:37:19 +01:00
if ((pcs = PCS::pcs(epsg))) {
_projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(),
pcs->units());
return true;
} else if ((gcs = GCS::gcs(epsg))) {
_projection = Projection(gcs);
return true;
} else
return false;
} else if (authority == "OGC") {
if (code == "CRS84") {
_projection = Projection(GCS::gcs(4326));
return true;
} else
return false;
} else
return false;
2018-02-20 23:37:19 +01:00
}
void WMTS::tileMatrix(QXmlStreamReader &reader)
{
Zoom zoom;
while (reader.readNextStartElement()) {
if (reader.name() == "Identifier")
zoom.id = reader.readElementText();
else if (reader.name() == "ScaleDenominator")
2018-02-20 23:37:19 +01:00
zoom.scaleDenominator = reader.readElementText().toDouble();
else if (reader.name() == "TopLeftCorner") {
QString str = reader.readElementText();
QTextStream(&str) >> zoom.topLeft.rx() >> zoom.topLeft.ry();
} else if (reader.name() == "TileWidth")
zoom.tile.setWidth(reader.readElementText().toInt());
else if (reader.name() == "TileHeight")
zoom.tile.setHeight(reader.readElementText().toInt());
else if (reader.name() == "MatrixWidth")
zoom.matrix.setWidth(reader.readElementText().toInt());
else if (reader.name() == "MatrixHeight")
zoom.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;
2018-02-20 23:37:19 +01:00
}
void WMTS::tileMatrixSet(QXmlStreamReader &reader, const QString &set)
{
QString id;
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
reader.skipCurrentElement();
}
}
void WMTS::tileMatrixLimits(QXmlStreamReader &reader)
{
QString id;
QRect limits;
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrix")
id = reader.readElementText();
else if (reader.name() == "MinTileRow")
limits.setTop(reader.readElementText().toInt());
else if (reader.name() == "MaxTileRow")
limits.setBottom(reader.readElementText().toInt());
else if (reader.name() == "MinTileCol")
limits.setLeft(reader.readElementText().toInt());
else if (reader.name() == "MaxTileCol")
limits.setRight(reader.readElementText().toInt());
else
reader.skipCurrentElement();
}
_zooms[id].limits = limits;
}
void WMTS::tileMatrixSetLimits(QXmlStreamReader &reader)
{
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrixLimits")
tileMatrixLimits(reader);
else
reader.skipCurrentElement();
}
}
void WMTS::tileMatrixSetLink(QXmlStreamReader &reader, const QString &set)
{
QString id;
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrixSet")
id = reader.readElementText();
else if (reader.name() == "TileMatrixSetLimits" && id == set)
tileMatrixSetLimits(reader);
else
reader.skipCurrentElement();
}
}
void WMTS::layer(QXmlStreamReader &reader, const QString &layer,
const QString &set)
{
QString id;
while (reader.readNextStartElement()) {
if (reader.name() == "Identifier")
id = reader.readElementText();
else if (reader.name() == "TileMatrixSetLink" && id == layer)
tileMatrixSetLink(reader, set);
else
reader.skipCurrentElement();
}
}
void WMTS::contents(QXmlStreamReader &reader, const QString &layer,
const QString &set)
2018-02-20 23:37:19 +01:00
{
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrixSet")
tileMatrixSet(reader, set);
else if (reader.name() == "Layer")
WMTS::layer(reader, layer, set);
2018-02-20 23:37:19 +01:00
else
reader.skipCurrentElement();
}
}
void WMTS::capabilities(QXmlStreamReader &reader, const QString &layer,
const QString &set)
2018-02-20 23:37:19 +01:00
{
while (reader.readNextStartElement()) {
if (reader.name() == "Contents")
contents(reader, layer, set);
2018-02-20 23:37:19 +01:00
else
reader.skipCurrentElement();
}
}
bool WMTS::parseCapabilities(const QString &path, const QString &layer,
const QString &set)
2018-02-20 23:37:19 +01:00
{
QFile file(path);
QXmlStreamReader reader;
if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString();
return false;
}
reader.setDevice(&file);
if (reader.readNextStartElement()) {
if (reader.name() == "Capabilities")
capabilities(reader, layer, set);
2018-02-20 23:37:19 +01:00
else
reader.raiseError("Not a Capabilities XML file");
}
_errorString = reader.error() ? QString("%1:%2: %3").arg(path)
.arg(reader.lineNumber()).arg(reader.errorString()) : QString();
return reader.error() ? false : true;
}
bool WMTS::getCapabilities(const QString &url, const QString &file)
{
QList<Download> dl;
QString capabilitiesUrl = QString("%1?service=WMTS&Version=1.0.0"
"&request=GetCapabilities").arg(url);
dl.append(Download(capabilitiesUrl, file));
QEventLoop wait;
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
if (_downloader->get(dl))
wait.exec();
if (QFileInfo(file).exists())
return true;
else {
_errorString = "Error downloading capabilities XML file";
return false;
}
}
bool WMTS::load(const QString &file, const QString &url, const QString &layer,
const QString &set)
2018-02-20 23:37:19 +01:00
{
2018-02-24 11:40:54 +01:00
QMap<QString, Zoom>::const_iterator it;
2018-02-20 23:37:19 +01:00
if (!QFileInfo(file).exists())
if (!getCapabilities(url, file))
return false;
if (!parseCapabilities(file, layer, set))
2018-02-20 23:37:19 +01:00
return false;
if (_projection.isNull()) {
_errorString = "Missing CRS definition";
return false;
}
if (_zooms.isEmpty()) {
_errorString = "No tile matrix found";
return false;
}
2018-02-24 11:40:54 +01:00
for (it = _zooms.constBegin(); it != _zooms.constEnd(); ++it) {
if (!it->isValid()) {
_errorString = it->id + ": invalid tile matrix definition";
return false;
}
}
2018-02-20 23:37:19 +01:00
return true;
}
QList<WMTS::Zoom> WMTS::zooms() const
{
QList<Zoom> z(_zooms.values());
qSort(z);
return z;
}
#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 << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG