Marble

ServerLayout.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2010, 2011 Bernhard Beschow <[email protected]>
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 
18 namespace Marble
19 {
20 
21 ServerLayout::ServerLayout( GeoSceneTileDataset *textureLayer )
22  : m_textureLayer( textureLayer )
23 {
24 }
25 
26 ServerLayout::~ServerLayout()
27 {
28 }
29 
30 MarbleServerLayout::MarbleServerLayout( GeoSceneTileDataset *textureLayer )
31  : ServerLayout( textureLayer )
32 {
33 }
34 
35 QUrl 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 
50 QString MarbleServerLayout::name() const
51 {
52  return "Marble";
53 }
54 
55 QString ServerLayout::sourceDir() const
56 {
57  return m_textureLayer ? m_textureLayer->sourceDir() : QString();
58 }
59 
60 
61 OsmServerLayout::OsmServerLayout( GeoSceneTileDataset *textureLayer )
62  : ServerLayout( textureLayer )
63 {
64 }
65 
66 QUrl 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 
80 QString OsmServerLayout::name() const
81 {
82  return "OpenStreetMap";
83 }
84 
85 
86 CustomServerLayout::CustomServerLayout( GeoSceneTileDataset *texture )
87  : ServerLayout( texture )
88 {
89 }
90 
91 QUrl 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 
109 QString CustomServerLayout::name() const
110 {
111  return "Custom";
112 }
113 
114 
115 WmsServerLayout::WmsServerLayout( GeoSceneTileDataset *texture )
116  : ServerLayout( texture )
117 {
118 }
119 
120 QUrl 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 
164 QString WmsServerLayout::name() const
165 {
166  return "WebMapService";
167 }
168 
169 QString 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 
182 WmtsServerLayout::WmtsServerLayout( GeoSceneTileDataset *texture )
183  : ServerLayout( texture )
184 {
185 }
186 
187 QUrl 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 
199 QString WmtsServerLayout::name() const
200 {
201  return "WebMapTileService";
202 }
203 
204 QString 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 
218 QuadTreeServerLayout::QuadTreeServerLayout( GeoSceneTileDataset *textureLayer )
219  : ServerLayout( textureLayer )
220 {
221 }
222 
223 QUrl 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 
232 QString QuadTreeServerLayout::name() const
233 {
234  return "QuadTree";
235 }
236 
237 QString 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 
252 TmsServerLayout::TmsServerLayout(GeoSceneTileDataset *textureLayer )
253  : ServerLayout( textureLayer )
254 {
255 }
256 
257 QUrl 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 
276 QString TmsServerLayout::name() const
277 {
278  return "TileMapService";
279 }
280 
281 }
QString number(int n, int base)
QString query(QUrl::ComponentFormattingOptions options) const const
QString toString(QUrl::FormattingOptions options) const const
void addQueryItem(const QString &key, const QString &value)
DecodeReserved
Binds a QML item to a specific geodetic location in screen coordinates.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString & replace(int position, int n, QChar after)
void setQuery(const QString &query, QUrl::ParsingMode mode)
QString toLower() const const
QString path(QUrl::ComponentFormattingOptions options) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString path(const QString &relativePath)
void setPath(const QString &path, QUrl::ParsingMode mode)
bool hasQueryItem(const QString &key) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Oct 2 2023 03:52:10 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.