Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix conversion of max zoom level from mapbox styles
The QGIS renderers for vector tiles treat maxzoom
different to the MapBox Style Specifications.

From the MapBox Specifications:

"The maximum zoom level for the layer. At zoom levels
equal to or greater than the maxzoom, the layer will be hidden."

However the QGIS styles will be hidden if the zoom
level is GREATER THAN (not equal to) maxzoom.

Accordingly we need to subtract 1 from the maxzoom value when
converting mapbox styles
  • Loading branch information
nyalldawson authored and github-actions[bot] committed Apr 22, 2023
1 parent 222c65c commit 236cdaf
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/core/vectortile/qgsmapboxglstyleconverter.cpp
Expand Up @@ -136,7 +136,17 @@ void QgsMapBoxGlStyleConverter::parseLayers( const QVariantList &layers, QgsMapB
const QString layerName = jsonLayer.value( QStringLiteral( "source-layer" ) ).toString();

const int minZoom = jsonLayer.value( QStringLiteral( "minzoom" ), QStringLiteral( "-1" ) ).toInt();
const int maxZoom = jsonLayer.value( QStringLiteral( "maxzoom" ), QStringLiteral( "-1" ) ).toInt();

// WARNING -- the QGIS renderers for vector tiles treat maxzoom different to the MapBox Style Specifications.
// from the MapBox Specifications:
//
// "The maximum zoom level for the layer. At zoom levels equal to or greater than the maxzoom, the layer will be hidden."
//
// However the QGIS styles will be hidden if the zoom level is GREATER THAN (not equal to) maxzoom.
// Accordingly we need to subtract 1 from the maxzoom value in the JSON:
int maxZoom = jsonLayer.value( QStringLiteral( "maxzoom" ), QStringLiteral( "-1" ) ).toInt();
if ( maxZoom != -1 )
maxZoom--;

const bool enabled = jsonLayer.value( QStringLiteral( "visibility" ) ).toString() != QLatin1String( "none" );

Expand Down
66 changes: 66 additions & 0 deletions tests/src/python/test_qgsmapboxglconverter.py
Expand Up @@ -940,6 +940,72 @@ def testLabelWithField(self):
self.assertFalse(labeling_style.labelSettings().isExpression)
self.assertEqual(labeling_style.labelSettings().fieldName, 'substance')

def test_parse_zoom_levels(self):
context = QgsMapBoxGlStyleConversionContext()
style = {
"sources": {
"Basemaps": {
"type": "vector",
"url": "https://xxxxxx"
}
},
"layers": [
{
"id": "water",
"source": "streets",
"source-layer": "water",
"minzoom": 3,
"maxzoom": 11,
"type": "fill",
"paint": {
"fill-color": "#00ffff"
}
},
{
"layout": {
"text-field": "{name_en}",
"text-font": [
"Open Sans Semibold",
"Arial Unicode MS Bold"
],
"text-max-width": 8,
"text-anchor": "top",
"text-size": 11,
"icon-size": 1
},
"type": "symbol",
"id": "poi_label",
"minzoom": 3,
"maxzoom": 11,
"paint": {
"text-color": "#666",
"text-halo-width": 1.5,
"text-halo-color": "rgba(255,255,255,0.95)",
"text-halo-blur": 1
},
"source-layer": "poi_label"
}
]
}

converter = QgsMapBoxGlStyleConverter()
converter.convert(style, context)

renderer = converter.renderer()
style = renderer.style(0)
self.assertEqual(style.minZoomLevel(), 3)
# This differs from the handling of the max zoom as defined
# in the MapBox Style, since in MapBox styles the style is rendered
# only if the zoom level is less than the maximum zoom but in QGIS
# styles the style is rendered if the zoom level is less than OR EQUAL TO
# the maximum zoom
self.assertEqual(style.maxZoomLevel(), 10)

labeling = converter.labeling()
style = labeling.style(0)
self.assertEqual(style.minZoomLevel(), 3)
self.assertEqual(style.maxZoomLevel(), 10)

def test_parse_raster_source(self):
context = QgsMapBoxGlStyleConversionContext()
style = {
Expand Down

0 comments on commit 236cdaf

Please sign in to comment.