Marble

ServerLayout.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2010, 2011 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
4//
5
6// Own
7#include "ServerLayout.h"
8
9#include "GeoDataLatLonBox.h"
10#include "GeoSceneTileDataset.h"
11#include "MarbleGlobal.h"
12#include "TileId.h"
13
14#include <QUrlQuery>
15
16#include <cmath>
17
18namespace Marble
19{
20
21ServerLayout::ServerLayout(GeoSceneTileDataset *textureLayer)
22 : m_textureLayer(textureLayer)
23{
24}
25
26ServerLayout::~ServerLayout() = default;
27
28MarbleServerLayout::MarbleServerLayout(GeoSceneTileDataset *textureLayer)
29 : ServerLayout(textureLayer)
30{
31}
32
33QUrl MarbleServerLayout::downloadUrl(const QUrl &prototypeUrl, const TileId &id) const
34{
35 const QString path = QStringLiteral("%1/%2/%3/%3_%4.%5")
36 .arg(prototypeUrl.path())
37 .arg(id.zoomLevel())
38 .arg(id.y(), tileDigits, 10, QLatin1Char('0'))
39 .arg(id.x(), tileDigits, 10, QLatin1Char('0'))
40 .arg(m_textureLayer->fileFormat().toLower());
41
42 QUrl url = prototypeUrl;
43 url.setPath(path);
44
45 return url;
46}
47
48QString MarbleServerLayout::name() const
49{
50 return QStringLiteral("Marble");
51}
52
53QString ServerLayout::sourceDir() const
54{
55 return m_textureLayer ? m_textureLayer->sourceDir() : QString();
56}
57
58OsmServerLayout::OsmServerLayout(GeoSceneTileDataset *textureLayer)
59 : ServerLayout(textureLayer)
60{
61}
62
63QUrl OsmServerLayout::downloadUrl(const QUrl &prototypeUrl, const TileId &id) const
64{
65 const QString suffix = m_textureLayer->fileFormat().toLower();
66 const QString path = QStringLiteral("%1/%2/%3.%4").arg(id.zoomLevel()).arg(id.x()).arg(id.y()).arg(suffix);
67
68 QUrl url = prototypeUrl;
69 url.setPath(url.path() + path);
70
71 return url;
72}
73
74QString OsmServerLayout::name() const
75{
76 return QStringLiteral("OpenStreetMap");
77}
78
79CustomServerLayout::CustomServerLayout(GeoSceneTileDataset *texture)
80 : ServerLayout(texture)
81{
82}
83
84QUrl CustomServerLayout::downloadUrl(const QUrl &prototypeUrl, const TileId &id) const
85{
86 const GeoDataLatLonBox bbox = m_textureLayer->tileProjection()->geoCoordinates(id);
87
88 QString urlStr = prototypeUrl.toString(QUrl::DecodeReserved);
89
90 urlStr.replace(QStringLiteral("{z}"), QString::number(id.zoomLevel()));
91 urlStr.replace(QStringLiteral("{zoomLevel}"), QString::number(id.zoomLevel()));
92 urlStr.replace(QStringLiteral("{x}"), QString::number(id.x()));
93 urlStr.replace(QStringLiteral("{y}"), QString::number(id.y()));
94 urlStr.replace(QStringLiteral("{west}"), QString::number(bbox.west(GeoDataCoordinates::Degree), 'f', 12));
95 urlStr.replace(QStringLiteral("{south}"), QString::number(bbox.south(GeoDataCoordinates::Degree), 'f', 12));
96 urlStr.replace(QStringLiteral("{east}"), QString::number(bbox.east(GeoDataCoordinates::Degree), 'f', 12));
97 urlStr.replace(QStringLiteral("{north}"), QString::number(bbox.north(GeoDataCoordinates::Degree), 'f', 12));
98
99 return QUrl(urlStr);
100}
101
102QString CustomServerLayout::name() const
103{
104 return QStringLiteral("Custom");
105}
106
107WmsServerLayout::WmsServerLayout(GeoSceneTileDataset *texture)
108 : ServerLayout(texture)
109{
110}
111
112QUrl WmsServerLayout::downloadUrl(const QUrl &prototypeUrl, const Marble::TileId &tileId) const
113{
114 const GeoDataLatLonBox box = m_textureLayer->tileProjection()->geoCoordinates(tileId);
115
116 QUrlQuery url(prototypeUrl.query());
117 url.addQueryItem(QStringLiteral("service"), QStringLiteral("WMS"));
118 url.addQueryItem(QStringLiteral("request"), QStringLiteral("GetMap"));
119 url.addQueryItem(QStringLiteral("version"), QStringLiteral("1.1.1"));
120 if (!url.hasQueryItem(QStringLiteral("styles")))
121 url.addQueryItem(QStringLiteral("styles"), {});
122 if (!url.hasQueryItem(QStringLiteral("format"))) {
123 url.addQueryItem(QStringLiteral("format"), QLatin1StringView("image/") + m_textureLayer->fileFormat().toLower());
124 }
125 if (!url.hasQueryItem(QStringLiteral("srs"))) {
126 url.addQueryItem(QStringLiteral("srs"), epsgCode());
127 }
128 if (!url.hasQueryItem(QStringLiteral("layers")))
129 url.addQueryItem(QStringLiteral("layers"), m_textureLayer->name());
130 url.addQueryItem(QStringLiteral("width"), QString::number(m_textureLayer->tileSize().width()));
131 url.addQueryItem(QStringLiteral("height"), QString::number(m_textureLayer->tileSize().height()));
132 double west, south, east, north;
133 if (m_textureLayer->tileProjectionType() == GeoSceneAbstractTileProjection::Mercator) {
134 // Oddly enough epsg:3857 is measured in meters - so let's convert this accordingly
135 west = (box.west(GeoDataCoordinates::Degree) * 20037508.34) / 180;
136 south = 20037508.34 / M_PI * log(tan(((90 + box.south(GeoDataCoordinates::Degree)) * M_PI) / 360));
137 east = (box.east(GeoDataCoordinates::Degree) * 20037508.34) / 180;
138 north = 20037508.34 / M_PI * log(tan(((90 + box.north(GeoDataCoordinates::Degree)) * M_PI) / 360));
139 } else {
140 west = box.west(GeoDataCoordinates::Degree);
141 south = box.south(GeoDataCoordinates::Degree);
142 east = box.east(GeoDataCoordinates::Degree);
143 north = box.north(GeoDataCoordinates::Degree);
144 }
145
146 url.addQueryItem(
147 QStringLiteral("bbox"),
148 QStringLiteral("%1,%2,%3,%4")
149 .arg(QString::number(west, 'f', 12), QString::number(south, 'f', 12), QString::number(east, 'f', 12), QString::number(north, 'f', 12)));
150 QUrl finalUrl = prototypeUrl;
151 finalUrl.setQuery(url);
152 return finalUrl;
153}
154
155QString WmsServerLayout::name() const
156{
157 return QStringLiteral("WebMapService");
158}
159
160QString WmsServerLayout::epsgCode() const
161{
162 switch (m_textureLayer->tileProjectionType()) {
163 case GeoSceneAbstractTileProjection::Equirectangular:
164 return QStringLiteral("EPSG:4326");
165 case GeoSceneAbstractTileProjection::Mercator:
166 return QStringLiteral("EPSG:3857");
167 }
168
169 Q_ASSERT(false); // not reached
170 return {};
171}
172
173WmtsServerLayout::WmtsServerLayout(GeoSceneTileDataset *texture)
174 : ServerLayout(texture)
175{
176}
177
178QUrl WmtsServerLayout::downloadUrl(const QUrl &prototypeUrl, const Marble::TileId &id) const
179{
180 // const GeoDataLatLonBox bbox = m_textureLayer->tileProjection()->geoCoordinates(id);
181
182 QString urlStr = prototypeUrl.toString(QUrl::DecodeReserved);
183
184 urlStr.replace(urlStr.indexOf(QLatin1StringView("{TileMatrix}")), QLatin1StringView("{TileMatrix}").size(), QString::number(id.zoomLevel()));
185 urlStr.replace(urlStr.indexOf(QLatin1StringView("{TileRow}")), QLatin1StringView("{TileRow}").size(), QString::number(id.y()));
186 urlStr.replace(urlStr.indexOf(QLatin1StringView("{TileCol}")), QLatin1StringView("{TileCol}").size(), QString::number(id.x()));
187 return QUrl(urlStr);
188}
189
190QString WmtsServerLayout::name() const
191{
192 return QStringLiteral("WebMapTileService");
193}
194
195QString WmtsServerLayout::epsgCode() const
196{
197 switch (m_textureLayer->tileProjectionType()) {
198 case GeoSceneAbstractTileProjection::Equirectangular:
199 return QStringLiteral("EPSG:4326");
200 case GeoSceneAbstractTileProjection::Mercator:
201 return QStringLiteral("EPSG:3857");
202 }
203
204 Q_ASSERT(false); // not reached
205 return {};
206}
207
208QuadTreeServerLayout::QuadTreeServerLayout(GeoSceneTileDataset *textureLayer)
209 : ServerLayout(textureLayer)
210{
211}
212
213QUrl QuadTreeServerLayout::downloadUrl(const QUrl &prototypeUrl, const Marble::TileId &id) const
214{
215 QString urlStr = prototypeUrl.toString(QUrl::DecodeReserved);
216
217 urlStr.replace(QStringLiteral("{quadIndex}"), encodeQuadTree(id));
218
219 return QUrl(urlStr);
220}
221
222QString QuadTreeServerLayout::name() const
223{
224 return QStringLiteral("QuadTree");
225}
226
227QString QuadTreeServerLayout::encodeQuadTree(const Marble::TileId &id)
228{
229 QString tileNum;
230
231 for (int i = id.zoomLevel(); i >= 0; i--) {
232 const int tileX = (id.x() >> i) % 2;
233 const int tileY = (id.y() >> i) % 2;
234 const int num = (2 * tileY) + tileX;
235
236 tileNum += QString::number(num);
237 }
238
239 return tileNum;
240}
241
242TmsServerLayout::TmsServerLayout(GeoSceneTileDataset *textureLayer)
243 : ServerLayout(textureLayer)
244{
245}
246
247QUrl TmsServerLayout::downloadUrl(const QUrl &prototypeUrl, const TileId &id) const
248{
249 const QString suffix = m_textureLayer->fileFormat().toLower();
250 // y coordinate in TMS start at the bottom of the map (South) and go upwards,
251 // opposed to OSM which start at the top.
252 //
253 // https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
254 int y_frombottom = (1 << id.zoomLevel()) - id.y() - 1;
255
256 const QString path = QStringLiteral("%1/%2/%3.%4").arg(id.zoomLevel()).arg(id.x()).arg(y_frombottom).arg(suffix);
257 QUrl url = prototypeUrl;
258 url.setPath(url.path() + path);
259
260 return url;
261}
262
263QString TmsServerLayout::name() const
264{
265 return QStringLiteral("TileMapService");
266}
267
268}
QString path(const QString &relativePath)
Binds a QML item to a specific geodetic location in screen coordinates.
QString arg(Args &&... args) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
QString number(double n, char format, int precision)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QString toLower() const const
DecodeReserved
QString path(ComponentFormattingOptions options) const const
QString query(ComponentFormattingOptions options) const const
void setPath(const QString &path, ParsingMode mode)
void setQuery(const QString &query, ParsingMode mode)
QString toString(FormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:15:46 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.