8#include "VectorTileModel.h"
10#include "GeoDataDocument.h"
11#include "GeoDataTreeModel.h"
12#include "GeoSceneVectorTileDataset.h"
13#include "MarbleDebug.h"
14#include "MarbleGlobal.h"
15#include "MathHelper.h"
16#include "TileLoader.h"
24TileRunner::TileRunner(TileLoader *loader,
const GeoSceneVectorTileDataset *tileDataset,
const TileId &
id)
26 , m_tileDataset(tileDataset)
33 GeoDataDocument *
const document = m_loader->loadTileVectorData(m_tileDataset, m_id, DownloadBrowse);
35 Q_EMIT documentLoaded(m_id, document);
38VectorTileModel::CacheDocument::CacheDocument(GeoDataDocument *doc, VectorTileModel *vectorTileModel,
const GeoDataLatLonBox &boundingBox)
40 , m_vectorTileModel(vectorTileModel)
41 , m_boundingBox(boundingBox)
46VectorTileModel::CacheDocument::~CacheDocument()
48 m_vectorTileModel->removeTile(m_document);
51VectorTileModel::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, &VectorTileModel::tileAdded, treeModel, &GeoDataTreeModel::addDocument);
61 connect(
this, SIGNAL(tileRemoved(GeoDataDocument *)), treeModel, SLOT(removeDocument(GeoDataDocument *)));
62 connect(treeModel, SIGNAL(removed(GeoDataObject *)),
this, SLOT(cleanupTile(GeoDataObject *)));
65void 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);
123void 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);
136QString VectorTileModel::name()
const
138 return m_layer->name();
141const GeoSceneVectorTileDataset *VectorTileModel::layer()
const
146void VectorTileModel::removeTile(GeoDataDocument *document)
148 Q_EMIT tileRemoved(document);
151int VectorTileModel::tileZoomLevel()
const
153 return m_tileZoomLevel;
156int VectorTileModel::cachedDocuments()
const
158 return m_documents.size();
161void VectorTileModel::reload()
163 const auto tiles = m_documents.keys();
164 for (
auto const &tile : tiles) {
165 m_loader->downloadTile(m_layer, tile, DownloadBrowse);
169void VectorTileModel::updateTile(
const TileId &idWithMapThemeHash, GeoDataDocument *document)
171 TileId
const id(0, idWithMapThemeHash.zoomLevel(), idWithMapThemeHash.x(), idWithMapThemeHash.y());
172 m_pendingDocuments.removeAll(
id);
177 if (m_tileLoadLevel !=
id.zoomLevel()) {
182 document->setName(QStringLiteral(
"%1/%2/%3").arg(
id.zoomLevel()).arg(
id.x()).arg(
id.y()));
183 m_garbageQueue << document;
184 if (m_documents.contains(
id)) {
185 m_documents.remove(
id);
187 if (m_deleteDocumentsLater) {
188 m_deleteDocumentsLater =
false;
191 const GeoDataLatLonBox boundingBox = m_layer->tileProjection()->geoCoordinates(
id);
193 Q_EMIT tileAdded(document);
196void VectorTileModel::clear()
201void VectorTileModel::queryTiles(
int tileZoomLevel,
const QRect &rect)
204 for (
int x = rect.
left(); x <= rect.
right(); ++x) {
205 for (
int y = rect.
top(); y <= rect.
bottom(); ++y) {
206 const TileId tileId = TileId(0, tileZoomLevel, x, y);
207 if (!m_documents.contains(tileId) && !m_pendingDocuments.contains(tileId)) {
208 m_pendingDocuments << tileId;
209 auto job =
new TileRunner(m_loader, m_layer, tileId);
210 connect(job, SIGNAL(documentLoaded(TileId, GeoDataDocument *)),
this, SLOT(updateTile(TileId, GeoDataDocument *)));
211 m_threadPool->start(job);
217void VectorTileModel::cleanupTile(GeoDataObject *
object)
219 if (
auto document = geodata_cast<GeoDataDocument>(
object)) {
220 if (m_garbageQueue.contains(document)) {
221 m_garbageQueue.removeAll(document);
229#include "moc_VectorTileModel.cpp"
QStringView level(QStringView ifopt)
Binds a QML item to a specific geodetic location in screen coordinates.
bool isEmpty() const const
qsizetype size() const const
QPoint bottomRight() const const
QPoint topLeft() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)