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

KDE's Doxygen guidelines are available online.