Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b3bd102

Browse files
nyalldawsongithub-actions[bot]
authored andcommittedApr 22, 2023
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
1 parent b2bb25a commit b3bd102

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed
 

‎src/core/vectortile/qgsmapboxglstyleconverter.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,17 @@ void QgsMapBoxGlStyleConverter::parseLayers( const QVariantList &layers, QgsMapB
136136
const QString layerName = jsonLayer.value( QStringLiteral( "source-layer" ) ).toString();
137137

138138
const int minZoom = jsonLayer.value( QStringLiteral( "minzoom" ), QStringLiteral( "-1" ) ).toInt();
139-
const int maxZoom = jsonLayer.value( QStringLiteral( "maxzoom" ), QStringLiteral( "-1" ) ).toInt();
139+
140+
// WARNING -- the QGIS renderers for vector tiles treat maxzoom different to the MapBox Style Specifications.
141+
// from the MapBox Specifications:
142+
//
143+
// "The maximum zoom level for the layer. At zoom levels equal to or greater than the maxzoom, the layer will be hidden."
144+
//
145+
// However the QGIS styles will be hidden if the zoom level is GREATER THAN (not equal to) maxzoom.
146+
// Accordingly we need to subtract 1 from the maxzoom value in the JSON:
147+
int maxZoom = jsonLayer.value( QStringLiteral( "maxzoom" ), QStringLiteral( "-1" ) ).toInt();
148+
if ( maxZoom != -1 )
149+
maxZoom--;
140150

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

‎tests/src/python/test_qgsmapboxglconverter.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,72 @@ def testLabelWithField(self):
941941
self.assertFalse(labeling_style.labelSettings().isExpression)
942942
self.assertEqual(labeling_style.labelSettings().fieldName, 'substance')
943943

944+
def test_parse_zoom_levels(self):
945+
context = QgsMapBoxGlStyleConversionContext()
946+
style = {
947+
"sources": {
948+
"Basemaps": {
949+
"type": "vector",
950+
"url": "https://xxxxxx"
951+
}
952+
},
953+
"layers": [
954+
{
955+
"id": "water",
956+
"source": "streets",
957+
"source-layer": "water",
958+
"minzoom": 3,
959+
"maxzoom": 11,
960+
"type": "fill",
961+
"paint": {
962+
"fill-color": "#00ffff"
963+
}
964+
},
965+
{
966+
"layout": {
967+
"text-field": "{name_en}",
968+
"text-font": [
969+
"Open Sans Semibold",
970+
"Arial Unicode MS Bold"
971+
],
972+
"text-max-width": 8,
973+
"text-anchor": "top",
974+
"text-size": 11,
975+
"icon-size": 1
976+
},
977+
"type": "symbol",
978+
"id": "poi_label",
979+
"minzoom": 3,
980+
"maxzoom": 11,
981+
"paint": {
982+
"text-color": "#666",
983+
"text-halo-width": 1.5,
984+
"text-halo-color": "rgba(255,255,255,0.95)",
985+
"text-halo-blur": 1
986+
},
987+
"source-layer": "poi_label"
988+
}
989+
]
990+
}
991+
992+
converter = QgsMapBoxGlStyleConverter()
993+
converter.convert(style, context)
994+
995+
renderer = converter.renderer()
996+
style = renderer.style(0)
997+
self.assertEqual(style.minZoomLevel(), 3)
998+
# This differs from the handling of the max zoom as defined
999+
# in the MapBox Style, since in MapBox styles the style is rendered
1000+
# only if the zoom level is less than the maximum zoom but in QGIS
1001+
# styles the style is rendered if the zoom level is less than OR EQUAL TO
1002+
# the maximum zoom
1003+
self.assertEqual(style.maxZoomLevel(), 10)
1004+
1005+
labeling = converter.labeling()
1006+
style = labeling.style(0)
1007+
self.assertEqual(style.minZoomLevel(), 3)
1008+
self.assertEqual(style.maxZoomLevel(), 10)
1009+
9441010
def test_parse_raster_source(self):
9451011
context = QgsMapBoxGlStyleConversionContext()
9461012
style = {

0 commit comments

Comments
 (0)
Please sign in to comment.