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)