1 #include <QXmlStreamReader>
7 #include <QtAlgorithms>
8 #include <QXmlStreamReader>
9 #include "downloader.h"
15 WMTS::TileMatrix
WMTS::tileMatrix(QXmlStreamReader
&reader
)
19 while (reader
.readNextStartElement()) {
20 if (reader
.name() == "Identifier")
21 matrix
.id
= reader
.readElementText();
22 else if (reader
.name() == "ScaleDenominator")
23 matrix
.scaleDenominator
= reader
.readElementText().toDouble();
24 else if (reader
.name() == "TopLeftCorner") {
25 QString str
= reader
.readElementText();
27 ts
>> matrix
.topLeft
.rx() >> matrix
.topLeft
.ry();
28 } else if (reader
.name() == "TileWidth")
29 matrix
.tile
.setWidth(reader
.readElementText().toInt());
30 else if (reader
.name() == "TileHeight")
31 matrix
.tile
.setHeight(reader
.readElementText().toInt());
32 else if (reader
.name() == "MatrixWidth")
33 matrix
.matrix
.setWidth(reader
.readElementText().toInt());
34 else if (reader
.name() == "MatrixHeight")
35 matrix
.matrix
.setHeight(reader
.readElementText().toInt());
37 reader
.skipCurrentElement();
40 if (!matrix
.isValid())
41 reader
.raiseError("Invalid TileMatrix definition");
46 void WMTS::tileMatrixSet(QXmlStreamReader
&reader
, CTX
&ctx
)
49 QSet
<TileMatrix
> matrixes
;
51 while (reader
.readNextStartElement()) {
52 if (reader
.name() == "Identifier")
53 id
= reader
.readElementText();
54 else if (reader
.name() == "SupportedCRS")
55 crs
= reader
.readElementText();
56 else if (reader
.name() == "TileMatrix")
57 matrixes
.insert(tileMatrix(reader
));
59 reader
.skipCurrentElement();
62 if (id
== ctx
.setup
.set()) {
68 WMTS::MatrixLimits
WMTS::tileMatrixLimits(QXmlStreamReader
&reader
)
72 while (reader
.readNextStartElement()) {
73 if (reader
.name() == "TileMatrix")
74 limits
.id
= reader
.readElementText();
75 else if (reader
.name() == "MinTileRow")
76 limits
.rect
.setTop(reader
.readElementText().toInt());
77 else if (reader
.name() == "MaxTileRow")
78 limits
.rect
.setBottom(reader
.readElementText().toInt());
79 else if (reader
.name() == "MinTileCol")
80 limits
.rect
.setLeft(reader
.readElementText().toInt());
81 else if (reader
.name() == "MaxTileCol")
82 limits
.rect
.setRight(reader
.readElementText().toInt());
84 reader
.skipCurrentElement();
87 if (!limits
.isValid())
88 reader
.raiseError("Invalid TileMatrixLimits definition");
93 QSet
<WMTS::MatrixLimits
> WMTS::tileMatrixSetLimits(QXmlStreamReader
&reader
)
95 QSet
<MatrixLimits
> limits
;
97 while (reader
.readNextStartElement()) {
98 if (reader
.name() == "TileMatrixLimits")
99 limits
.insert(tileMatrixLimits(reader
));
101 reader
.skipCurrentElement();
107 void WMTS::tileMatrixSetLink(QXmlStreamReader
&reader
, CTX
&ctx
)
110 QSet
<MatrixLimits
> limits
;
112 while (reader
.readNextStartElement()) {
113 if (reader
.name() == "TileMatrixSet")
114 id
= reader
.readElementText();
115 else if (reader
.name() == "TileMatrixSetLimits")
116 limits
= tileMatrixSetLimits(reader
);
118 reader
.skipCurrentElement();
121 if (id
== ctx
.setup
.set()) {
127 RectC
WMTS::wgs84BoundingBox(QXmlStreamReader
&reader
)
129 Coordinates topLeft
, bottomRight
;
131 while (reader
.readNextStartElement()) {
132 if (reader
.name() == "LowerCorner") {
133 QString str
= reader
.readElementText();
134 QTextStream(&str
) >> topLeft
.rlon() >> bottomRight
.rlat();
135 } else if (reader
.name() == "UpperCorner") {
136 QString str
= reader
.readElementText();
137 QTextStream(&str
) >> bottomRight
.rlon() >> topLeft
.rlat();
139 reader
.skipCurrentElement();
142 return RectC(topLeft
, bottomRight
);
145 QString
WMTS::style(QXmlStreamReader
&reader
)
149 while (reader
.readNextStartElement()) {
150 if (reader
.name() == "Identifier")
151 id
= reader
.readElementText();
153 reader
.skipCurrentElement();
159 void WMTS::layer(QXmlStreamReader
&reader
, CTX
&ctx
)
163 QStringList formats
, styles
;
165 while (reader
.readNextStartElement()) {
166 if (reader
.name() == "Identifier")
167 id
= reader
.readElementText();
168 else if (reader
.name() == "TileMatrixSetLink")
169 tileMatrixSetLink(reader
, ctx
);
170 else if (reader
.name() == "WGS84BoundingBox")
171 bounds
= wgs84BoundingBox(reader
);
172 else if (reader
.name() == "ResourceURL") {
173 const QXmlStreamAttributes
&attr
= reader
.attributes();
174 if (attr
.value("resourceType") == "tile")
175 tpl
= attr
.value("template").toString();
176 reader
.skipCurrentElement();
177 } else if (reader
.name() == "Style")
178 styles
.append(style(reader
));
179 else if (reader
.name() == "Format")
180 formats
.append(reader
.readElementText());
182 reader
.skipCurrentElement();
185 if (id
== ctx
.setup
.layer()) {
188 if (ctx
.setup
.rest())
190 if (styles
.contains(ctx
.setup
.style()) || ctx
.setup
.style().isEmpty())
192 if (formats
.contains(ctx
.setup
.format()))
193 ctx
.hasFormat
= true;
197 void WMTS::contents(QXmlStreamReader
&reader
, CTX
&ctx
)
199 while (reader
.readNextStartElement()) {
200 if (reader
.name() == "TileMatrixSet")
201 tileMatrixSet(reader
, ctx
);
202 else if (reader
.name() == "Layer")
205 reader
.skipCurrentElement();
209 void WMTS::capabilities(QXmlStreamReader
&reader
, CTX
&ctx
)
211 while (reader
.readNextStartElement()) {
212 if (reader
.name() == "Contents")
213 contents(reader
, ctx
);
215 reader
.skipCurrentElement();
219 bool WMTS::parseCapabilities(const QString
&path
, const Setup
&setup
)
223 QXmlStreamReader reader
;
225 if (!file
.open(QFile::ReadOnly
| QFile::Text
)) {
226 _errorString
= file
.errorString();
230 reader
.setDevice(&file
);
231 if (reader
.readNextStartElement()) {
232 if (reader
.name() == "Capabilities")
233 capabilities(reader
, ctx
);
235 reader
.raiseError("Not a Capabilities XML file");
237 if (reader
.error()) {
238 _errorString
= QString("%1:%2: %3").arg(path
).arg(reader
.lineNumber())
239 .arg(reader
.errorString());
244 _errorString
= ctx
.setup
.layer() + ": layer not provided";
248 _errorString
= ctx
.setup
.style() + ": style not provided";
251 if (!ctx
.setup
.rest() && !ctx
.hasFormat
) {
252 _errorString
= ctx
.setup
.format() + ": format not provided";
256 _errorString
= ctx
.setup
.set() + ": set not provided";
259 if (ctx
.crs
.isNull()) {
260 _errorString
= "Missing CRS definition";
263 _projection
= CRS::projection(ctx
.crs
);
264 if (!_projection
.isValid()) {
265 _errorString
= ctx
.crs
+ ": unknown CRS";
268 if (_matrixes
.isEmpty()) {
269 _errorString
= "No usable tile matrix found";
272 if (ctx
.setup
.rest() && _tileUrl
.isNull()) {
273 _errorString
= "Missing tile URL template";
280 bool WMTS::getCapabilities(const QString
&url
, const QString
&file
,
281 const Authorization
&authorization
)
286 dl
.append(Download(url
, file
));
289 QObject::connect(&d
, SIGNAL(finished()), &wait
, SLOT(quit()));
290 if (d
.get(dl
, authorization
))
293 if (QFileInfo(file
).exists())
296 _errorString
= "Error downloading capabilities XML file";
301 WMTS::WMTS(const QString
&file
, const WMTS::Setup
&setup
) : _valid(false)
303 QString capaUrl
= setup
.rest() ? setup
.url() :
304 QString("%1%2service=WMTS&Version=1.0.0&request=GetCapabilities")
305 .arg(setup
.url(), setup
.url().contains('?') ? "&" : "?");
307 if (!QFileInfo(file
).exists())
308 if (!getCapabilities(capaUrl
, file
, setup
.authorization()))
310 if (!parseCapabilities(file
, setup
))
313 QString style
= setup
.style().isEmpty() ? "default" : setup
.style();
315 _tileUrl
= QString("%1%2service=WMTS&Version=1.0.0&request=GetTile"
316 "&Format=%3&Layer=%4&Style=%5&TileMatrixSet=%6&TileMatrix=$z"
317 "&TileRow=$y&TileCol=$x").arg(setup
.url(),
318 setup
.url().contains('?') ? "&" : "?" , setup
.format(),
319 setup
.layer(), style
, setup
.set());
320 for (int i
= 0; i
< setup
.dimensions().size(); i
++) {
321 const QPair
<QString
, QString
> &dim
= setup
.dimensions().at(i
);
322 _tileUrl
.append(QString("&%1=%2").arg(dim
.first
, dim
.second
));
325 _tileUrl
.replace("{Style}", style
, Qt::CaseInsensitive
);
326 _tileUrl
.replace("{TileMatrixSet}", setup
.set(), Qt::CaseInsensitive
);
327 _tileUrl
.replace("{TileMatrix}", "$z", Qt::CaseInsensitive
);
328 _tileUrl
.replace("{TileRow}", "$y", Qt::CaseInsensitive
);
329 _tileUrl
.replace("{TileCol}", "$x", Qt::CaseInsensitive
);
330 for (int i
= 0; i
< setup
.dimensions().size(); i
++) {
331 const QPair
<QString
, QString
> &dim
= setup
.dimensions().at(i
);
332 _tileUrl
.replace(QString("{%1}").arg(dim
.first
), dim
.second
,
333 Qt::CaseInsensitive
);
340 QList
<WMTS::Zoom
> WMTS::zooms() const
343 QSet
<TileMatrix
>::const_iterator mi
;
344 QSet
<MatrixLimits
>::const_iterator li
;
346 for (mi
= _matrixes
.constBegin(); mi
!= _matrixes
.constEnd(); ++mi
) {
347 if ((li
= _limits
.find(MatrixLimits(mi
->id
))) == _limits
.constEnd())
348 zooms
.append(Zoom(mi
->id
, mi
->scaleDenominator
, mi
->topLeft
,
349 mi
->tile
, mi
->matrix
, QRect()));
351 zooms
.append(Zoom(mi
->id
, mi
->scaleDenominator
, mi
->topLeft
,
352 mi
->tile
, mi
->matrix
, li
->rect
));
361 QDebug
operator<<(QDebug dbg
, const WMTS::Setup
&setup
)
363 dbg
.nospace() << "Setup(" << setup
.url() << ", " << setup
.layer() << ", "
364 << setup
.set() << ", " << setup
.style() << ", " << setup
.format() << ", "
365 << setup
.rest() << ")";
369 QDebug
operator<<(QDebug dbg
, const WMTS::Zoom
&zoom
)
371 dbg
.nospace() << "Zoom(" << zoom
.id() << ", " << zoom
.scaleDenominator()
372 << ", " << zoom
.topLeft() << ", " << zoom
.tile() << ", " << zoom
.matrix()
373 << ", " << zoom
.limits() << ")";
376 #endif // QT_NO_DEBUG