8 #include "VectorTileModel.h"
10 #include "GeoDataDocument.h"
11 #include "GeoDataTreeModel.h"
12 #include "GeoSceneVectorTileDataset.h"
13 #include "MarbleGlobal.h"
14 #include "MarbleDebug.h"
15 #include "MathHelper.h"
16 #include "TileLoader.h"
19 #include <QThreadPool>
24 TileRunner::TileRunner(TileLoader *loader,
const GeoSceneVectorTileDataset *tileDataset,
const TileId &
id) :
26 m_tileDataset(tileDataset),
31 void TileRunner::run()
33 GeoDataDocument *
const document = m_loader->loadTileVectorData(m_tileDataset, m_id,
DownloadBrowse);
35 emit documentLoaded(m_id, document);
38 VectorTileModel::CacheDocument::CacheDocument(GeoDataDocument *doc, VectorTileModel *vectorTileModel,
const GeoDataLatLonBox &boundingBox) :
40 m_vectorTileModel(vectorTileModel),
41 m_boundingBox(boundingBox)
46 VectorTileModel::CacheDocument::~CacheDocument()
48 m_vectorTileModel->removeTile(m_document);
51 VectorTileModel::VectorTileModel(TileLoader *loader,
const GeoSceneVectorTileDataset *layer, GeoDataTreeModel *treeModel,
QThreadPool *threadPool) :
54 m_treeModel(treeModel),
55 m_threadPool(threadPool),
58 m_deleteDocumentsLater(false)
60 connect(
this, SIGNAL(tileAdded(GeoDataDocument*)), treeModel, SLOT(addDocument(GeoDataDocument*)));
61 connect(
this, SIGNAL(tileRemoved(GeoDataDocument*)), treeModel, SLOT(removeDocument(GeoDataDocument*)));
62 connect(treeModel, SIGNAL(removed(GeoDataObject*)),
this, SLOT(cleanupTile(GeoDataObject*)));
65 void VectorTileModel::setViewport(
const GeoDataLatLonBox &latLonBox)
67 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
68 int const nTiles = smallScreen ? 12 : 20;
69 qreal
const viewportArea = latLonBox.width() * latLonBox.height();
70 qreal
const level = log((nTiles * 2.0 * M_PI * M_PI) / viewportArea) / log(4);
71 m_tileZoomLevel = qFloor(level);
72 int tileLoadLevel = m_tileZoomLevel;
83 int tileLevel = tileLevels.
first();
84 for (
int i = 1, n = tileLevels.
size(); i < n; ++i) {
85 if (tileLevels[i] > tileLoadLevel) {
88 tileLevel = tileLevels[i];
90 tileLoadLevel = tileLevel;
93 if (tileLoadLevel != m_tileLoadLevel) {
94 m_deleteDocumentsLater = m_tileLoadLevel >= 0;
95 m_tileLoadLevel = tileLoadLevel;
103 const QRect rect = m_layer->tileProjection()->tileIndexes(latLonBox, tileLoadLevel);
109 if (!latLonBox.crossesDateLine()) {
110 queryTiles(tileLoadLevel, rect);
115 const int maxTileX = (1 << tileLoadLevel) * m_layer->levelZeroColumns() - 1;
120 removeTilesOutOfView(latLonBox);
123 void VectorTileModel::removeTilesOutOfView(
const GeoDataLatLonBox &boundingBox)
125 GeoDataLatLonBox
const extendedViewport = boundingBox.scaled(2.0, 2.0);
126 for (
auto iter = m_documents.begin(); iter != m_documents.end();) {
127 bool const isOutOfView = !extendedViewport.intersects(iter.value()->latLonBox());
129 iter = m_documents.erase(iter);
136 QString VectorTileModel::name()
const
138 return m_layer->name();
141 const GeoSceneVectorTileDataset *VectorTileModel::layer()
const
146 void VectorTileModel::removeTile(GeoDataDocument *document)
148 emit tileRemoved(document);
151 int VectorTileModel::tileZoomLevel()
const
153 return m_tileZoomLevel;
156 int VectorTileModel::cachedDocuments()
const
158 return m_documents.size();
161 void VectorTileModel::reload()
163 for (
auto const &tile : m_documents.keys()) {
168 void VectorTileModel::updateTile(
const TileId &idWithMapThemeHash, GeoDataDocument *document)
170 TileId
const id(0, idWithMapThemeHash.zoomLevel(), idWithMapThemeHash.x(), idWithMapThemeHash.y());
171 m_pendingDocuments.removeAll(
id);
176 if (m_tileLoadLevel !=
id.zoomLevel()) {
181 document->setName(
QString(
"%1/%2/%3").arg(
id.zoomLevel()).arg(
id.x()).arg(
id.y()));
182 m_garbageQueue << document;
183 if (m_documents.contains(
id)) {
184 m_documents.remove(
id);
186 if (m_deleteDocumentsLater) {
187 m_deleteDocumentsLater =
false;
190 const GeoDataLatLonBox boundingBox = m_layer->tileProjection()->geoCoordinates(
id);
192 emit tileAdded(document);
195 void VectorTileModel::clear()
200 void VectorTileModel::queryTiles(
int tileZoomLevel,
const QRect &rect)
203 for (
int x = rect.
left(); x <= rect.
right(); ++x) {
204 for (
int y = rect.
top(); y <= rect.
bottom(); ++y) {
205 const TileId tileId = TileId(0, tileZoomLevel, x, y);
206 if (!m_documents.contains(tileId) && !m_pendingDocuments.contains(tileId)) {
207 m_pendingDocuments << tileId;
208 TileRunner *job =
new TileRunner(m_loader, m_layer, tileId);
209 connect(job, SIGNAL(documentLoaded(TileId,GeoDataDocument*)),
this, SLOT(updateTile(TileId,GeoDataDocument*)));
210 m_threadPool->start(job);
216 void VectorTileModel::cleanupTile(GeoDataObject *
object)
218 if (GeoDataDocument *document = geodata_cast<GeoDataDocument>(
object)) {
219 if (m_garbageQueue.contains(document)) {
220 m_garbageQueue.removeAll(document);
228 #include "moc_VectorTileModel.cpp"