Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QML Map: Limit tile fetch to specific zoom levels.



  • I'm working on an application containing an offline map using the OpenStreetMap plugin.
    My offline tile maps only provide tiles between zoom level 1 - 6 due to disk space restrictions. When I zoom in more than zoom level 6 following warnings appear:

    QGeoTileRequestManager: Failed to fetch tile (67,41,7) 5 times, giving up. Last error message was: 'Error opening C:/Path/To/offline_tiles/7/67/41.png: The system cannot find the path specified.'
    

    It is important that the user can zoom in all the way, I do not want to prevent that.
    Is there a way to limit the map tile fetcher to only fetch tiles up to a certain zoom level?

    In the Qt source code I found the following parameter MaximumZoomLevel :
    https://code.qt.io/cgit/qt/qtlocation.git/tree/src/plugins/geoservices/osm/qgeotileproviderosm.cpp#n414

         * MinimumZoomLevel and MaximumZoomLevel are also optional, and allow to prevent invalid tile
         * requests to the providers, if they do not support the specific ZL. Default is 0 and 19,
         * respectively.
    

    This parameter would be the solution, however, I do not know how I to set it... The documentation for the OSM plugin does not list such a parameter (https://doc.qt.io/qt-5/location-plugin-osm.html). Is there another way to set this parameter?

    My QML:

    Window {
        id: win
        objectName: "window"
        visible: true
        width: 512
        height: 512
    
        Map {
            id: map
            anchors.fill: parent
            zoomLevel: 1
            plugin: Plugin {
                name: 'osm';
                PluginParameter {
                    name: 'osm.mapping.custom.host'
                    value: 'file:///C:/Path/To/offline_tiles/'
                }
                PluginParameter {
                    name: "osm.mapping.providersrepository.disabled"
                    value: true
                }
                PluginParameter {
                    name: "osm.mapping.cache.disk.size"
                    value: "0"
                }
            }
    
            Component.onCompleted: {
                for( var i_type in supportedMapTypes) {
                    console.log(supportedMapTypes[i_type].name)
                    if ( supportedMapTypes[i_type].name.localeCompare( "Custom URL Map" ) === 0) {
                        activeMapType = supportedMapTypes[i_type]
                    }
                }
            }
        }
    }
    


  • I looked through the Qt source a bit more closely and saw that the "offline" constructor for the TileProvider sets the minimumZoomLevel and maximumZoomLevel by default:

    https://code.qt.io/cgit/qt/qtlocation.git/tree/src/plugins/geoservices/osm/qgeotileproviderosm.h#n67

        // Offline constructor. Doesn't need URLRedirector and networkmanager
        TileProvider(const QString &urlTemplate,
                 const QString &format,
                 const QString &copyRightMap,
                 const QString &copyRightData,
                 bool highDpi = false,
                 int minimumZoomLevel = 0,
                 int maximumZoomLevel = 19);
    

    There does not seem to be a way to set those values. QGeoTiledMappingManagerEngineOsm instantiates the TileProvider without setting minimumZoomLevel or maximumZoomLevel, so they are stuck forever at 0 or 19 respectively...
    https://code.qt.io/cgit/qt/qtlocation.git/tree/src/plugins/geoservices/osm/qgeotileproviderosm.h#n67

    m_providers.push_back(
                new QGeoTileProviderOsm( nmCached,
                    QGeoMapType(QGeoMapType::CustomMap, tr("Custom URL Map"), tr("Custom url map view set via urlprefix parameter"), false, false, 8, pluginName, cameraCaps),
                    { new TileProvider(tmsServer + QStringLiteral("%z/%x/%y.png"),
                        QStringLiteral("png"),
                        mapCopyright,
                        dataCopyright) }, cameraCaps
                    ));
    

    Would be handy if these could be set for offline maps...



  • use maximumZoomLevel in Map component



  • @akadirdd
    Thanks for the suggestion.
    The 'maximumZoomLevel' property limits how much I can zoom on the map. But I do not want to limit that. I display icons that can be close to each other. The user has to zoom in close to differentiate the icons. However, at high zoom levels I do not have offline tiles which results in aforementioned tile fetching errors.

    I wish we could tell the tile fetcher what zoom levels we provide, so that it doesn't try to fetch tiles that are not there.

    For now I ended up ignoring the error with a custom message handler:

    // Default message handler to be called to bypass all other warnings.
    static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0);
    // A custom message handler to intercept warnings
    void
    customMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
    {
    	if (type == QtWarningMsg &&
    	    // suppress following warnings
    	    (msg.contains("QGeoTileRequestManager: Failed to fetch tile"))) {
    		return;
    	}
    
    	(*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg);
    }
    

    And then

    qInstallMessageHandler(customMessageHandler);
    

Log in to reply