Marble

GeoSceneTileDataset.cpp
1/*
2 SPDX-FileCopyrightText: 2008 Torsten Rahn <rahn@kde.org>
3 SPDX-FileCopyrightText: 2008 Jens-Michael Hoffmann <jensmh@gmx.de>
4 SPDX-FileCopyrightText: 2012 Ander Pijoan <ander.pijoan@deusto.es>
5
6 SPDX-License-Identifier: LGPL-2.1-or-later
7*/
8
9#include "GeoSceneTileDataset.h"
10#include "GeoSceneTypes.h"
11#include "GeoSceneEquirectTileProjection.h"
12#include "GeoSceneMercatorTileProjection.h"
13
14#include "DownloadPolicy.h"
15#include "MarbleDebug.h"
16#include "MarbleDirs.h"
17#include "ServerLayout.h"
18#include "TileId.h"
19
20#include <QImage>
21#include <QUrl>
22
23namespace Marble
24{
25
26GeoSceneTileDataset::GeoSceneTileDataset( const QString& name )
27 : GeoSceneAbstractDataset( name ),
28 m_sourceDir(),
29 m_installMap(),
30 m_storageLayoutMode(Marble),
31 m_serverLayout( new MarbleServerLayout( this ) ),
32 m_levelZeroColumns( defaultLevelZeroColumns ),
33 m_levelZeroRows( defaultLevelZeroRows ),
34 m_minimumTileLevel(0),
35 m_maximumTileLevel( -1 ),
36 m_tileProjection(new GeoSceneEquirectTileProjection()),
37 m_blending(),
38 m_downloadUrls(),
39 m_nextUrl( m_downloadUrls.constEnd() )
40{
41 m_tileProjection->setLevelZeroColumns(m_levelZeroColumns);
42 m_tileProjection->setLevelZeroRows(m_levelZeroRows);
43}
44
45GeoSceneTileDataset::~GeoSceneTileDataset()
46{
47 qDeleteAll( m_downloadPolicies );
48 delete m_serverLayout;
49 delete m_tileProjection;
50}
51
52const char* GeoSceneTileDataset::nodeType() const
53{
54 return GeoSceneTypes::GeoSceneTileDatasetType;
55}
56
57QString GeoSceneTileDataset::sourceDir() const
58{
59 return m_sourceDir;
60}
61
62void GeoSceneTileDataset::setSourceDir( const QString& sourceDir )
63{
64 m_sourceDir = sourceDir;
65}
66
67QString GeoSceneTileDataset::installMap() const
68{
69 return m_installMap;
70}
71
72void GeoSceneTileDataset::setInstallMap( const QString& installMap )
73{
74 m_installMap = installMap;
75}
76
77GeoSceneTileDataset::StorageLayout GeoSceneTileDataset::storageLayout() const
78{
79 return m_storageLayoutMode;
80}
81
82void GeoSceneTileDataset::setStorageLayout( const StorageLayout layout )
83{
84 m_storageLayoutMode = layout;
85}
86
87void GeoSceneTileDataset::setServerLayout( const ServerLayout *layout )
88{
89 delete m_serverLayout;
90 m_serverLayout = layout;
91}
92
93const ServerLayout* GeoSceneTileDataset::serverLayout() const
94{
95 return m_serverLayout;
96}
97
98int GeoSceneTileDataset::levelZeroColumns() const
99{
100 return m_levelZeroColumns;
101}
102
103void GeoSceneTileDataset::setLevelZeroColumns( const int columns )
104{
105 m_levelZeroColumns = columns;
106 m_tileProjection->setLevelZeroColumns(m_levelZeroColumns);
107}
108
109int GeoSceneTileDataset::levelZeroRows() const
110{
111 return m_levelZeroRows;
112}
113
114void GeoSceneTileDataset::setLevelZeroRows( const int rows )
115{
116 m_levelZeroRows = rows;
117 m_tileProjection->setLevelZeroRows(m_levelZeroRows);
118}
119
120int GeoSceneTileDataset::maximumTileLevel() const
121{
122 return m_maximumTileLevel;
123}
124
125void GeoSceneTileDataset::setMaximumTileLevel( const int maximumTileLevel )
126{
127 m_maximumTileLevel = maximumTileLevel;
128}
129
130int GeoSceneTileDataset::minimumTileLevel() const
131{
132 return m_minimumTileLevel;
133}
134
135void GeoSceneTileDataset::setMinimumTileLevel(int level)
136{
137 m_minimumTileLevel = level;
138}
139
140void GeoSceneTileDataset::setTileLevels(const QString &tileLevels)
141{
142 if (tileLevels.isEmpty()) {
143 m_tileLevels.clear();
144 return;
145 }
146
147 const QStringList values = tileLevels.split(QLatin1Char(','));
148 for(const QString &value: values) {
149 bool canParse(false);
150 int const tileLevel = value.trimmed().toInt(&canParse);
151 if (canParse && tileLevel >= 0 && tileLevel < 100) {
152 m_tileLevels << tileLevel;
153 } else {
154 mDebug() << "Cannot parse tile level part " << value << " in " << tileLevels << ", ignoring it.";
155 }
156 }
157
158 if (!m_tileLevels.isEmpty()) {
159 std::sort(m_tileLevels.begin(), m_tileLevels.end());
160 m_minimumTileLevel = m_tileLevels.first();
161 m_maximumTileLevel = m_tileLevels.last();
162 }
163}
164
165QVector<int> GeoSceneTileDataset::tileLevels() const
166{
167 return m_tileLevels;
168}
169
170QVector<QUrl> GeoSceneTileDataset::downloadUrls() const
171{
172 return m_downloadUrls;
173}
174
175const QSize GeoSceneTileDataset::tileSize() const
176{
177 if ( m_tileSize.isEmpty() ) {
178 const TileId id( 0, 0, 0, 0 );
179 QString const fileName = relativeTileFileName( id );
180 QFileInfo const dirInfo( fileName );
181 QString const path = dirInfo.isAbsolute() ? fileName : MarbleDirs::path( fileName );
182
183 QImage testTile( path );
184
185 if ( testTile.isNull() ) {
186 mDebug() << "Tile size is missing in dgml and no base tile found in " << themeStr();
187 mDebug() << "Using default tile size " << c_defaultTileSize;
188 m_tileSize = QSize( c_defaultTileSize, c_defaultTileSize );
189 } else {
190 m_tileSize = testTile.size();
191 }
192
193 if ( m_tileSize.isEmpty() ) {
194 mDebug() << "Tile width or height cannot be 0. Falling back to default tile size.";
195 m_tileSize = QSize( c_defaultTileSize, c_defaultTileSize );
196 }
197 }
198
199 Q_ASSERT( !m_tileSize.isEmpty() );
200 return m_tileSize;
201}
202
203GeoDataLatLonBox GeoSceneTileDataset::latLonBox() const
204{
205 return m_latLonBox;
206}
207
208void GeoSceneTileDataset::setLatLonBox( const GeoDataLatLonBox &box )
209{
210 m_latLonBox = box;
211}
212
213void GeoSceneTileDataset::setTileSize( const QSize &tileSize )
214{
215 if ( tileSize.isEmpty() ) {
216 mDebug() << "Ignoring invalid tile size " << tileSize;
217 } else {
218 m_tileSize = tileSize;
219 }
220}
221
222void GeoSceneTileDataset::setTileProjection(GeoSceneAbstractTileProjection::Type projectionType)
223{
224 if (m_tileProjection->type() == projectionType) {
225 return;
226 }
227
228 delete m_tileProjection;
229 if (projectionType == GeoSceneAbstractTileProjection::Mercator) {
230 m_tileProjection = new GeoSceneMercatorTileProjection();
231 } else {
232 m_tileProjection = new GeoSceneEquirectTileProjection();
233 }
234
235 m_tileProjection->setLevelZeroColumns(m_levelZeroColumns);
236 m_tileProjection->setLevelZeroRows(m_levelZeroRows);
237}
238
239const GeoSceneAbstractTileProjection * GeoSceneTileDataset::tileProjection() const
240{
241 return m_tileProjection;
242}
243
244GeoSceneAbstractTileProjection::Type GeoSceneTileDataset::tileProjectionType() const
245{
246 return m_tileProjection->type();
247}
248
249// Even though this method changes the internal state, it may be const
250// because the compiler is forced to invoke this method for different TileIds.
251QUrl GeoSceneTileDataset::downloadUrl( const TileId &id ) const
252{
253 // default download url
254 if ( m_downloadUrls.empty() ) {
255 QUrl const defaultUrl = QUrl(QLatin1String("https://maps.kde.org/") + m_serverLayout->sourceDir());
256 mDebug() << "No download URL specified for tiles stored in "
257 << m_sourceDir << ", falling back to " << defaultUrl.toString();
258 return m_serverLayout->downloadUrl(defaultUrl, id);
259 } else if (m_downloadUrls.size() == 1) {
260 return m_serverLayout->downloadUrl(*m_nextUrl, id);
261 } else {
262 if (m_nextUrl == m_downloadUrls.constEnd()) {
263 m_nextUrl = m_downloadUrls.constBegin();
264 }
265 const QUrl url = m_serverLayout->downloadUrl(*m_nextUrl, id);
266 ++m_nextUrl;
267 return url;
268 }
269}
270
271void GeoSceneTileDataset::addDownloadUrl( const QUrl & url )
272{
273 m_downloadUrls.append( url );
274 // FIXME: this could be done only once
275 m_nextUrl = m_downloadUrls.constBegin();
276}
277
278QString GeoSceneTileDataset::relativeTileFileName( const TileId &id ) const
279{
280 const QString suffix = fileFormat().toLower();
281
282 QString relFileName;
283
284 switch ( m_storageLayoutMode ) {
285 case GeoSceneTileDataset::Marble:
286 relFileName = QString( "%1/%2/%3/%3_%4.%5" )
287 .arg( themeStr() )
288 .arg( id.zoomLevel() )
289 .arg(id.y(), tileDigits, 10, QLatin1Char('0'))
290 .arg(id.x(), tileDigits, 10, QLatin1Char('0'))
291 .arg( suffix );
292 break;
293 case GeoSceneTileDataset::OpenStreetMap:
294 relFileName = QString( "%1/%2/%3/%4.%5" )
295 .arg( themeStr() )
296 .arg( id.zoomLevel() )
297 .arg( id.x() )
298 .arg( id.y() )
299 .arg( suffix );
300 break;
301 case GeoSceneTileDataset::TileMapService:
302 relFileName = QString( "%1/%2/%3/%4.%5" )
303 .arg( themeStr() )
304 .arg( id.zoomLevel() )
305 .arg( id.x() )
306 .arg( ( 1<<id.zoomLevel() ) - id.y() - 1 ) //Y coord in TMS runs from bottom to top
307 .arg( suffix );
308 break;
309 }
310
311 return relFileName;
312}
313
314QString GeoSceneTileDataset::themeStr() const
315{
316 QFileInfo const dirInfo( sourceDir() );
317 return dirInfo.isAbsolute() ? sourceDir() : QLatin1String("maps/") + sourceDir();
318}
319
320QList<const DownloadPolicy *> GeoSceneTileDataset::downloadPolicies() const
321{
322 return m_downloadPolicies;
323}
324
325void GeoSceneTileDataset::addDownloadPolicy( const DownloadUsage usage, const int maximumConnections )
326{
327 DownloadPolicy * const policy = new DownloadPolicy( DownloadPolicyKey( hostNames(), usage ));
328 policy->setMaximumConnections( maximumConnections );
329 m_downloadPolicies.append( policy );
330 mDebug() << "added download policy" << hostNames() << usage << maximumConnections;
331}
332
333QStringList GeoSceneTileDataset::hostNames() const
334{
335 QStringList result;
336 result.reserve(m_downloadUrls.size());
337
338 QVector<QUrl>::const_iterator pos = m_downloadUrls.constBegin();
339 QVector<QUrl>::const_iterator const end = m_downloadUrls.constEnd();
340 for (; pos != end; ++pos )
341 result.append( (*pos).host() );
342 return result;
343}
344
345}
QString name(GameStandardAction id)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
QString path(const QString &relativePath)
QStringView level(QStringView ifopt)
Binds a QML item to a specific geodetic location in screen coordinates.
void append(QList< T > &&value)
void reserve(qsizetype size)
bool isEmpty() const const
QString arg(Args &&... args) const const
const_iterator constBegin() const const
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QString toLower() const const
QString toString(FormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 7 2024 12:03:13 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.