summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/style.json119
-rw-r--r--include/mbgl/style/function_properties.hpp28
-rw-r--r--src/style/function_properties.cpp87
-rw-r--r--src/style/style_parser.cpp105
-rw-r--r--test/fixtures/styles/road-width.style.json1
-rw-r--r--test/functions.cpp44
6 files changed, 71 insertions, 313 deletions
diff --git a/bin/style.json b/bin/style.json
index dc6eb78dda..aea2a1a3ac 100755
--- a/bin/style.json
+++ b/bin/style.json
@@ -64,124 +64,94 @@
"@street_night": "#0186ac",
"@contour_night": "#ffff80",
"@river_canal_width": {
- "fn": "stops",
"stops": [[10, 0.5], [11, 1], [13, 2], [15, 3]]
},
"@stream_width": {
- "fn": "stops",
"stops": [[12, 0.25], [13, 0.5], [15, 1.5], [17, 2]]
},
"@motorway_width": {
- "fn": "stops",
"stops": [[4, 0], [5, 0.5], [7, 0.8], [9, 1], [10, 1.2], [11, 2], [12, 3], [13, 4], [14, 6], [15, 9], [16, 12], [17, 14]]
},
"@motorway_casing_width": {
- "fn": "stops",
"stops": [[6.5, 0.6], [7, 0.8], [9, 2.8], [10, 3], [11, 4], [12, 5], [13, 6.5], [14, 9], [15, 12], [16, 15], [17, 17]]
},
"@motorway_link_width": {
- "fn": "stops",
"stops": [[11, 1.2], [13, 2], [15, 3], [17, 4]]
},
"@motorway_link_casing_width": {
- "fn": "stops",
"stops": [[11, 2.8], [13, 3.5], [15, 5], [17, 6]]
},
"@main_width": {
- "fn": "stops",
"stops": [[4, 1], [11, 1], [12, 1.5], [13, 2], [14, 3], [15, 6], [16, 10], [17, 12]]
},
"@main_casing_width": {
- "fn": "stops",
"stops": [[8, 2.9], [11, 2.9], [12, 3.5], [13, 4], [14, 5.5], [15, 9], [16, 12], [17, 14]]
},
"@street_width": {
- "fn": "stops",
"stops": [[13.5, 0], [14, 1.5], [15, 3], [16, 8]]
},
"@street_casing_width": {
- "fn": "stops",
"stops": [[12, 0.4], [13, 1], [14, 2.5], [15, 4], [16, 10]]
},
"@street_casing_opacity": {
- "fn": "stops",
"stops": [[13, 0], [13.5, 1]]
},
"@service_casing_width": {
- "fn": "stops",
"stops": [[13, 0.5], [14, 3], [15, 3.5], [16, 4], [17, 5], [18, 6]]
},
"@runway_width": {
- "fn": "stops",
"stops": [[9, 1], [10, 2], [11, 3], [12, 5], [13, 7], [14, 11], [15, 15], [16, 19], [17, 23]]
},
"@taxiway_width": {
- "fn": "stops",
"stops": [[9, 0.2], [11, 0.2], [12, 1], [13, 1.5], [14, 2], [15, 3], [16, 4], [17, 5]]
},
"@aerialway_width": {
- "fn": "stops",
"stops": [[12.5, 0.8], [13, 1.4], [14, 1.6], [15, 2], [16, 2.4], [17, 3]]
},
"@aerialway_casing_width": {
- "fn": "stops",
"stops": [[12.5, 2], [13, 2.5], [14, 3], [15, 3.5], [16, 4], [21, 5]]
},
"@path_width": {
- "fn": "stops",
"stops": [[13, 1.2], [14, 1.5], [15, 1.8]]
},
"@admin_l2_width": {
- "fn": "stops",
"stops": [[1, 0.5], [2, 0.7], [3, 0.7], [4, 0.8], [5, 1], [7, 2], [9, 3]]
},
"@admin_l3_width": {
- "fn": "stops",
"stops": [[5, 0.6], [7, 1], [11, 2]]
},
"@road_label_1_size": {
- "fn": "stops",
"stops": [[12, 11], [13, 12], [14, 13], [15, 14], [16, 16], [17, 18]]
},
"@road_label_2_size": {
- "fn": "stops",
"stops": [[12, 11], [13, 12], [15, 14], [17, 16]]
},
"@road_label_3_size": {
- "fn": "stops",
"stops": [[14, 10], [15, 12], [17, 14]]
},
"@fence_width": {
- "fn": "stops",
"stops": [[16, 0.6], [18, 1]]
},
"@hedge_width": {
- "fn": "stops",
"stops": [[15, 0.6], [16, 1.2], [18, 1.6]]
},
"@barrier_line_land_width": {
- "fn": "stops",
"stops": [[13, 0.4], [14, 0.75], [15, 1.5], [16, 3], [17, 6], [18, 12], [19, 24], [20, 48]]
},
"@country_label_size": {
- "fn": "stops",
"stops": [[0, 14], [11, 24]]
},
"@poi_label_1-2_size": {
- "fn": "stops",
"stops": [[14, 10], [15, 11], [16, 12]]
},
"@poi_label_3_size": {
- "fn": "stops",
"stops": [[15, 10], [16, 11]]
},
"@hillshade_rasterize": {
"enabled": {
- "fn": "stops",
"stops": [[10, false], [11, true]]
},
"size": {
- "fn": "stops",
"stops": [[10, 1024], [11, 512], [12, 256]]
},
"blur": 1
@@ -229,14 +199,12 @@
"style": {
"fill-color": "@grass",
"fill-opacity": {
- "fn": "stops",
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
},
"style.night": {
"fill-color": "@grass_night",
"fill-opacity": {
- "fn": "stops",
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
}
@@ -249,14 +217,12 @@
"style": {
"fill-color": "@scrub",
"fill-opacity": {
- "fn": "stops",
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
},
"style.night": {
"fill-color": "@scrub_night",
"fill-opacity": {
- "fn": "stops",
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
}
@@ -269,14 +235,12 @@
"style": {
"fill-color": "@wood",
"fill-opacity": {
- "fn": "stops",
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
},
"style.night": {
"fill-color": "@wood_night",
"fill-opacity": {
- "fn": "stops",
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
}
@@ -514,7 +478,6 @@
"fill-color": "#d5d1c6",
"fill-translate": [1, 1],
"fill-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [16, 1]]
},
"fill-outline-color": "#d5d1c6"
@@ -523,7 +486,6 @@
"fill-color": "#026688",
"fill-translate": [1, 1],
"fill-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [16, 1]]
},
"fill-outline-color": "#026688"
@@ -543,7 +505,6 @@
"style": {
"fill-color": "#ebe7db",
"fill-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [16, 0.7]]
},
"fill-outline-color": "#d5d1c6"
@@ -551,7 +512,6 @@
"style.night": {
"fill-color": "#027797",
"fill-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [16, 0.7]]
},
"fill-outline-color": "#026688"
@@ -567,7 +527,6 @@
"fill-color": "#fffff3",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[14, 0.3], [15, 0.3], [16, 0.2], [17, 0.2], [18, 0.1]]
}
},
@@ -575,7 +534,6 @@
"fill-color": "#fdfdad",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[13, 0.4], [14, 0.3], [16, 0.2], [17, 0.1], [18, 0.05]]
}
}
@@ -590,7 +548,6 @@
"fill-color": "#ffd",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[14, 0.3], [15, 0.3], [16, 0.2], [17, 0.2], [18, 0.1]]
}
},
@@ -598,7 +555,6 @@
"fill-color": "#ffe1b7",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[14, 0.3], [16, 0.2], [17, 0.15], [18, 0.05]]
}
}
@@ -613,7 +569,6 @@
"fill-color": "#206",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[14, 0.08], [15, 0.075], [16, 0.05], [17, 0.05], [18, 0.025]]
}
},
@@ -621,7 +576,6 @@
"fill-color": "#206",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[15, 0.3], [16, 0.2], [17, 0.1], [18, 0.05]]
}
}
@@ -636,7 +590,6 @@
"fill-color": "#103",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[14, 0.08], [15, 0.075], [16, 0.05], [17, 0.05], [18, 0.025]]
}
},
@@ -644,7 +597,6 @@
"fill-color": "#103",
"fill-antialias": false,
"fill-opacity": {
- "fn": "stops",
"stops": [[15, 0.3], [16, 0.2], [17, 0.1], [18, 0.05]]
}
}
@@ -661,7 +613,6 @@
"line-color": "#008",
"line-width": 0.9,
"line-opacity": {
- "fn": "stops",
"stops": [[11, 0.05], [12, 0.11]]
}
},
@@ -669,7 +620,6 @@
"line-color": "@contour_night",
"line-width": 0.9,
"line-opacity": {
- "fn": "stops",
"stops": [[11, 0.1], [12, 0.2]]
}
}
@@ -685,7 +635,6 @@
"line-color": "#008",
"line-width": 0.5,
"line-opacity": {
- "fn": "stops",
"stops": [[11, 0.05], [12, 0.11]]
}
},
@@ -693,7 +642,6 @@
"line-color": "@contour_night",
"line-width": 0.5,
"line-opacity": {
- "fn": "stops",
"stops": [[11, 0.1], [12, 0.4]]
}
}
@@ -876,7 +824,6 @@
"line-dasharray": [6, 6],
"line-width": "@main_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8, 0], [9, 1]]
}
},
@@ -885,7 +832,6 @@
"line-dasharray": [6, 6],
"line-width": "@main_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8, 0], [9, 1]]
}
}
@@ -945,7 +891,6 @@
"line-color": "#e6cec7",
"line-width": "@main_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
},
@@ -953,7 +898,6 @@
"line-color": "#78b0c1",
"line-width": "@main_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
}
@@ -968,7 +912,6 @@
"line-dasharray": [6, 6],
"line-width": "@motorway_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8.5, 0], [9, 1]]
}
},
@@ -977,7 +920,6 @@
"line-dasharray": [6, 6],
"line-width": "@motorway_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8.5, 0], [9, 1]]
}
}
@@ -988,7 +930,6 @@
"line-color": "#e6cec7",
"line-width": "@motorway_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
},
@@ -996,7 +937,6 @@
"line-color": "#78b0c1",
"line-width": "@motorway_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
}
@@ -1010,7 +950,6 @@
"line-color": "#ffd",
"line-opacity": 0.4,
"line-width": {
- "fn": "stops",
"stops": [[14, 3], [15, 4]]
}
},
@@ -1045,7 +984,6 @@
"line-dasharray": [10, 4],
"line-opacity": 0.8,
"line-width": {
- "fn": "stops",
"stops": [[13, 0.8], [14, 0.9], [15, 1.2]]
}
},
@@ -1054,7 +992,6 @@
"line-dasharray": [10, 4],
"line-opacity": 0.8,
"line-width": {
- "fn": "stops",
"stops": [[13, 0.8], [14, 0.9], [15, 1.2]]
}
}
@@ -1189,7 +1126,6 @@
"line-color": "@case",
"line-width": "@main_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8, 0], [9, 1]]
}
},
@@ -1197,7 +1133,6 @@
"line-color": "@case_night",
"line-width": "@main_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8, 0], [9, 1]]
}
}
@@ -1261,7 +1196,6 @@
"line-color": "@main",
"line-width": "@main_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
},
@@ -1269,7 +1203,6 @@
"line-color": "@main_night",
"line-width": "@main_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
}
@@ -1287,7 +1220,6 @@
"line-color": "@case",
"line-width": "@motorway_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8.5, 0], [9, 1]]
}
},
@@ -1295,7 +1227,6 @@
"line-color": "@case_night",
"line-width": "@motorway_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8.5, 0], [9, 1]]
}
}
@@ -1306,7 +1237,6 @@
"line-color": "@motorway",
"line-width": "@motorway_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
},
@@ -1314,7 +1244,6 @@
"line-color": "@motorway_night",
"line-width": "@motorway_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
}
@@ -1371,7 +1300,6 @@
"line-color": "@case",
"line-width": "@main_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8, 0], [9, 1]]
}
},
@@ -1379,7 +1307,6 @@
"line-color": "@case_night",
"line-width": "@main_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8, 0], [9, 1]]
}
}
@@ -1439,7 +1366,6 @@
"line-color": "@main",
"line-width": "@main_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
},
@@ -1447,7 +1373,6 @@
"line-color": "@main_night",
"line-width": "@main_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
}
@@ -1461,7 +1386,6 @@
"line-color": "@case",
"line-width": "@motorway_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8.5, 0], [9, 1]]
}
},
@@ -1469,7 +1393,6 @@
"line-color": "@case_night",
"line-width": "@motorway_casing_width",
"line-opacity": {
- "fn": "stops",
"stops": [[8.5, 0], [9, 1]]
}
}
@@ -1480,7 +1403,6 @@
"line-color": "@motorway",
"line-width": "@motorway_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
},
@@ -1488,7 +1410,6 @@
"line-color": "@motorway_night",
"line-width": "@motorway_width",
"line-opacity": {
- "fn": "stops",
"stops": [[5.5, 0], [6, 1]]
}
}
@@ -1534,7 +1455,6 @@
"line-color": "#88a",
"line-dasharray": [60, 20],
"line-opacity": {
- "fn": "stops",
"stops": [[3, 0], [5, 1]]
},
"line-width": "@admin_l3_width"
@@ -1543,7 +1463,6 @@
"line-color": "@admin_night",
"line-dasharray": [60, 20],
"line-opacity": {
- "fn": "stops",
"stops": [[3, 0], [5, 1]]
},
"line-width": "@admin_l3_width"
@@ -1590,14 +1509,12 @@
"style": {
"line-color": "#c0d6d6",
"line-width": {
- "fn": "stops",
"stops": [[5, 1], [7, 2], [11, 3]]
}
},
"style.night": {
"line-color": "#0a1347",
"line-width": {
- "fn": "stops",
"stops": [[5, 1], [7, 2], [11, 3]]
}
}
@@ -1661,7 +1578,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water"
@@ -1669,7 +1585,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water_night"
@@ -1690,7 +1605,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water"
@@ -1698,7 +1612,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water_night"
@@ -1719,7 +1632,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water"
@@ -1727,7 +1639,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water_night"
@@ -1748,7 +1659,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water"
@@ -1756,7 +1666,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water_night"
@@ -1779,7 +1688,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water"
@@ -1787,7 +1695,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water_night"
@@ -1810,7 +1717,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water"
@@ -1818,7 +1724,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water_night"
@@ -1841,7 +1746,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water"
@@ -1849,7 +1753,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water_night"
@@ -1872,7 +1775,6 @@
"style": {
"text-color": "@marine_text",
"text-size": {
- "fn": "stops",
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water"
@@ -1880,7 +1782,6 @@
"style.night": {
"text-color": "@water_dark_night",
"text-size": {
- "fn": "stops",
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water_night"
@@ -1903,7 +1804,6 @@
"text-halo-width": 0.4,
"text-halo-color": "rgba(244,239,225,0.8)",
"text-size": {
- "fn": "stops",
"stops": [[2.99, 0], [3, 10], [8.99, 16], [9, 0]]
}
},
@@ -1912,7 +1812,6 @@
"text-halo-width": 0.4,
"text-halo-color": "@land_night",
"text-size": {
- "fn": "stops",
"stops": [[2.99, 0], [3, 10], [8.99, 16], [9, 0]]
}
}
@@ -1934,7 +1833,6 @@
"text-halo-width": 0.4,
"text-halo-color": "@text_stroke",
"text-size": {
- "fn": "stops",
"stops": [[2.99, 0], [3, 10], [6, 14], [13.99, 20], [14, 0]]
}
},
@@ -1943,7 +1841,6 @@
"text-halo-width": 0.4,
"text-halo-color": "@text2_stroke_night",
"text-size": {
- "fn": "stops",
"stops": [[2.99, 0], [3, 10], [6, 14], [13.99, 20], [14, 0]]
}
}
@@ -1965,7 +1862,6 @@
"text-halo-width": 0.3,
"text-halo-color": "@text_stroke",
"text-size": {
- "fn": "stops",
"stops": [[8, 10], [11, 13], [13, 17], [15, 22]]
}
},
@@ -1974,7 +1870,6 @@
"text-halo-width": 0.3,
"text-halo-color": "@text2_stroke_night",
"text-size": {
- "fn": "stops",
"stops": [[8, 10], [11, 13], [13, 17], [15, 22]]
}
}
@@ -1996,7 +1891,6 @@
"text-halo-width": 0.3,
"text-halo-color": "@text_stroke",
"text-size": {
- "fn": "stops",
"stops": [[8, 8], [11, 10], [13, 14], [15, 16], [16, 20]]
}
},
@@ -2005,7 +1899,6 @@
"text-halo-width": 0.3,
"text-halo-color": "@text2_stroke_night",
"text-size": {
- "fn": "stops",
"stops": [[8, 8], [11, 10], [13, 14], [15, 16], [16, 20]]
}
}
@@ -2026,7 +1919,6 @@
"text-color": "#7d6c55",
"text-halo-color": "@text_stroke",
"text-size": {
- "fn": "stops",
"stops": [[12, 11], [13, 12], [15, 14], [17, 18]]
}
},
@@ -2035,7 +1927,6 @@
"text-halo-color": "@text2_stroke_night",
"text-halo-width": 0.3,
"text-size": {
- "fn": "stops",
"stops": [[12, 11], [13, 12], [15, 14], [17, 18]]
}
}
@@ -2235,13 +2126,11 @@
},
"style": {
"icon-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [15.75, 1]]
}
},
"style.night": {
"icon-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [15.75, 1]]
}
}
@@ -2266,7 +2155,6 @@
"text-halo-color": "@land",
"text-halo-width": 0.3,
"text-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [15.75, 1]]
}
},
@@ -2276,7 +2164,6 @@
"text-halo-color": "@text2_stroke_night",
"text-halo-width": 0.3,
"text-opacity": {
- "fn": "stops",
"stops": [[15.5, 0], [15.75, 1]]
}
}
@@ -2292,13 +2179,11 @@
},
"style": {
"icon-opacity": {
- "fn": "stops",
"stops": [[17.5, 0], [17.75, 1]]
}
},
"style.night": {
"icon-opacity": {
- "fn": "stops",
"stops": [[17.5, 0], [17.75, 1]]
}
}
@@ -2321,7 +2206,6 @@
"text-color": "#444",
"text-size": 10,
"text-opacity": {
- "fn": "stops",
"stops": [[17.5, 0], [17.75, 1]]
},
"text-halo-color": "@land",
@@ -2331,7 +2215,6 @@
"text-color": "#fff",
"text-size": 10,
"text-opacity": {
- "fn": "stops",
"stops": [[17.5, 0], [17.75, 1]]
},
"text-halo-color": "@text2_stroke_night",
@@ -2349,13 +2232,11 @@
},
"style": {
"icon-opacity": {
- "fn": "stops",
"stops": [[12, 0], [12.25, 1]]
}
},
"style.night": {
"icon-opacity": {
- "fn": "stops",
"stops": [[12, 0], [12.25, 1]]
}
}
diff --git a/include/mbgl/style/function_properties.hpp b/include/mbgl/style/function_properties.hpp
index 74ac80f83c..8cd7ce6e28 100644
--- a/include/mbgl/style/function_properties.hpp
+++ b/include/mbgl/style/function_properties.hpp
@@ -17,43 +17,19 @@ private:
};
template <typename T>
-struct LinearFunction {
- inline LinearFunction(const T &value, float z_base, float slope, const T &min, const T &max)
- : value(value), min(min), max(max), z_base(z_base), slope(slope) {}
- T evaluate(float z) const;
-
-private:
- const T value, min, max;
- const float z_base, slope;
-};
-
-template <typename T>
-struct ExponentialFunction {
- inline ExponentialFunction(const T &value, float z_base, float exp_base, float slope, const T &min,
- const T &max)
- : value(value), min(min), max(max), z_base(z_base), exp_base(exp_base), slope(slope) {}
- T evaluate(float z) const;
-
-private:
- const T value, min, max;
- const float z_base, exp_base, slope;
-};
-
-template <typename T>
struct StopsFunction {
- inline StopsFunction(const std::vector<std::pair<float, T>> &values) : values(values) {}
+ inline StopsFunction(const std::vector<std::pair<float, T>> &values, float base) : values(values), base(base) {}
T evaluate(float z) const;
private:
const std::vector<std::pair<float, T>> values;
+ const float base;
};
template <typename T>
using Function = util::variant<
std::false_type,
ConstantFunction<T>,
- LinearFunction<T>,
- ExponentialFunction<T>,
StopsFunction<T>
>;
diff --git a/src/style/function_properties.cpp b/src/style/function_properties.cpp
index 2b378fb6b9..879de84f85 100644
--- a/src/style/function_properties.cpp
+++ b/src/style/function_properties.cpp
@@ -6,82 +6,36 @@
namespace mbgl {
-template <>
-bool LinearFunction<bool>::evaluate(float z) const {
- return z < z_base ? slope >= 0 : z > z_base ? slope >= 0 : value;
-}
-
-template <>
-float LinearFunction<float>::evaluate(float z) const {
- return std::fmin(std::fmax(min, value + (z - z_base) * slope), max);
-}
-
-template <>
-Color LinearFunction<Color>::evaluate(float z) const {
- return {{
- std::fmin(std::fmax(min[0], value[0] + (z - z_base) * slope), max[0]),
- std::fmin(std::fmax(min[1], value[1] + (z - z_base) * slope), max[1]),
- std::fmin(std::fmax(min[2], value[2] + (z - z_base) * slope), max[2]),
- std::fmin(std::fmax(min[3], value[3] + (z - z_base) * slope), max[3])
- }};
-}
-
-
-template <>
-bool ExponentialFunction<bool>::evaluate(float z) const {
- return z < z_base ? slope >= 0 : z > z_base ? slope >= 0 : value;
-}
-
-template <>
-float ExponentialFunction<float>::evaluate(float z) const {
- return std::fmin(std::fmax(min, value + std::pow(exp_base, (z - z_base)) * slope), max);
-}
-
-template <>
-Color ExponentialFunction<Color>::evaluate(float z) const {
- return {{
- std::fmin(std::fmax(min[0], value[0] + float(std::pow(exp_base, (z - z_base))) * slope), max[0]),
- std::fmin(std::fmax(min[1], value[1] + float(std::pow(exp_base, (z - z_base))) * slope), max[1]),
- std::fmin(std::fmax(min[2], value[2] + float(std::pow(exp_base, (z - z_base))) * slope), max[2]),
- std::fmin(std::fmax(min[3], value[3] + float(std::pow(exp_base, (z - z_base))) * slope), max[3])
- }};
-}
-
template <typename T>
-inline T exponentialInterpolate(T smaller, T larger, const float factor);
+inline T interpolate(T smaller, T larger, const float factor);
template <>
-inline float exponentialInterpolate(const float smaller, const float larger, const float factor) {
- // Linear interpolation if base is 0
- if (smaller == 0.0f) {
- return factor * larger;
- }
- // Exponential interpolation between the values
- return smaller * std::pow(larger / smaller, factor);
+inline float interpolate(const float smaller, const float larger, const float factor) {
+ return (smaller * (1 - factor)) + (larger * factor);
}
template <>
-inline bool exponentialInterpolate(const bool smaller, const bool larger, const float factor) {
- return exponentialInterpolate(float(smaller), float(larger), factor);
+inline bool interpolate(const bool smaller, const bool larger, const float factor) {
+ return interpolate(float(smaller), float(larger), factor);
}
template <>
-inline Color exponentialInterpolate(const Color smaller, const Color larger, const float factor) {
+inline Color interpolate(const Color smaller, const Color larger, const float factor) {
return {{
- exponentialInterpolate(smaller[0], larger[0], factor),
- exponentialInterpolate(smaller[1], larger[1], factor),
- exponentialInterpolate(smaller[2], larger[2], factor),
- exponentialInterpolate(smaller[3], larger[3], factor)
+ interpolate(smaller[0], larger[0], factor),
+ interpolate(smaller[1], larger[1], factor),
+ interpolate(smaller[2], larger[2], factor),
+ interpolate(smaller[3], larger[3], factor)
}};
}
template <typename T>
-T exponentialDefault();
+inline T defaultStopsValue();
-template <> bool exponentialDefault() { return true; }
-template <> float exponentialDefault() { return 1.0f; }
-template <> Color exponentialDefault() { return {{ 0, 0, 0, 1 }}; }
+template <> inline bool defaultStopsValue() { return true; }
+template <> inline float defaultStopsValue() { return 1.0f; }
+template <> inline Color defaultStopsValue() { return {{ 0, 0, 0, 1 }}; }
template <typename T>
@@ -112,15 +66,22 @@ T StopsFunction<T>::evaluate(float z) const {
if (larger_z == smaller_z || larger_val == smaller_val) {
return smaller_val;
}
- float factor = (z - smaller_z) / (larger_z - smaller_z);
- return exponentialInterpolate<T>(smaller_val, larger_val, factor);
+ const float zoomDiff = larger_z - smaller_z;
+ const float zoomProgress = z - smaller_z;
+ if (base == 1.0f) {
+ const float t = zoomProgress / zoomDiff;
+ return interpolate<T>(smaller_val, larger_val, t);
+ } else {
+ const float t = (std::pow(base, zoomProgress) - 1) / (std::pow(base, zoomDiff) - 1);
+ return interpolate<T>(smaller_val, larger_val, t);
+ }
} else if (larger) {
return larger_val;
} else if (smaller) {
return smaller_val;
} else {
// No stop defined.
- return exponentialDefault<T>();
+ return defaultStopsValue<T>();
}
}
diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp
index c4faf81f5a..e5aa3acc15 100644
--- a/src/style/style_parser.cpp
+++ b/src/style/style_parser.cpp
@@ -231,95 +231,56 @@ Color StyleParser::parseFunctionArgument(JSVal value) {
return parseColor(rvalue);
}
+template <typename T> inline float defaultBaseValue() { return 1.75; }
+template <> inline float defaultBaseValue<Color>() { return 1.0; }
+
template <typename T>
std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
- if (!value.HasMember("fn")) {
- Log::Warning(Event::ParseStyle, "function must specify a function name");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
-
- JSVal value_fn = value["fn"];
- if (!value_fn.IsString()) {
+ if (!value.HasMember("stops")) {
Log::Warning(Event::ParseStyle, "function must specify a function type");
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
}
- const std::string type { value_fn.GetString(), value_fn.GetStringLength() };
+ float base = defaultBaseValue<T>();
- if (type == "linear") {
- if (!value.HasMember("z")) {
- Log::Warning(Event::ParseStyle, "linear function must specify a base zoom level");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
- if (!value.HasMember("val")) {
- Log::Warning(Event::ParseStyle, "linear function must specify a base value");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
+ if (value.HasMember("base")) {
+ JSVal value_base = value["base"];
+ if (value_base.IsNumber()) {
+ base = value_base.GetDouble();
+ } else {
+ Log::Warning(Event::ParseStyle, "base must be numeric");
}
- const float z_base = parseFunctionArgument<float>(value["z"]);
- const T val = parseFunctionArgument<T>(value["val"]);
- const float slope = value.HasMember("slope") ? parseFunctionArgument<float>(value["slope"]) : 1;
- const T min = value.HasMember("min") ? parseFunctionArgument<T>(value["min"]) : T();
- const T max = value.HasMember("max") ? parseFunctionArgument<T>(value["max"]) : T();
- return std::tuple<bool, Function<T>> { true, LinearFunction<T>(val, z_base, slope, min, max) };
}
- else if (type == "exponential") {
- if (!value.HasMember("z")) {
- Log::Warning(Event::ParseStyle, "exponential function must specify a base zoom level");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
- if (!value.HasMember("val")) {
- Log::Warning(Event::ParseStyle, "exponential function must specify a base value");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
- const float z_base = parseFunctionArgument<float>(value["z"]);
- const float exp_base = value.HasMember("base") ? parseFunctionArgument<float>(value["base"]) : 1.75;
- const T val = parseFunctionArgument<T>(value["val"]);
- const float slope = value.HasMember("slope") ? parseFunctionArgument<float>(value["slope"]) : 1;
- const T min = value.HasMember("min") ? parseFunctionArgument<T>(value["min"]) : T();
- const T max = value.HasMember("max") ? parseFunctionArgument<T>(value["max"]) : T();
- return std::tuple<bool, Function<T>> { true, ExponentialFunction<T>(val, z_base, exp_base, slope, min, max) };
- }
- else if (type == "stops") {
- if (!value.HasMember("stops")) {
- Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
- JSVal value_stops = value["stops"];
- if (!value_stops.IsArray()) {
- Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
-
- std::vector<std::pair<float, T>> stops;
- for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
- JSVal stop = value_stops[i];
- if (stop.IsArray()) {
- if (stop.Size() != 2) {
- Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
+ JSVal value_stops = value["stops"];
+ if (!value_stops.IsArray()) {
+ Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
+ return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
+ }
- JSVal z = stop[rapidjson::SizeType(0)];
- if (!z.IsNumber()) {
- Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
+ std::vector<std::pair<float, T>> stops;
+ for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
+ JSVal stop = value_stops[i];
+ if (stop.IsArray()) {
+ if (stop.Size() != 2) {
+ Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
+ return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
+ }
- stops.emplace_back(z.GetDouble(), parseFunctionArgument<T>(stop[rapidjson::SizeType(1)]));
- } else {
- Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
+ JSVal z = stop[rapidjson::SizeType(0)];
+ if (!z.IsNumber()) {
+ Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
}
- }
- return std::tuple<bool, Function<T>> { true, StopsFunction<T>(stops) };
- }
- else {
- Log::Warning(Event::ParseStyle, "function type '%s' is unknown", type.c_str());
+ stops.emplace_back(z.GetDouble(), parseFunctionArgument<T>(stop[rapidjson::SizeType(1)]));
+ } else {
+ Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
+ return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
+ }
}
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
+ return std::tuple<bool, Function<T>> { true, StopsFunction<T>(stops, base) };
}
diff --git a/test/fixtures/styles/road-width.style.json b/test/fixtures/styles/road-width.style.json
index 5738546b33..76d7b5258c 100644
--- a/test/fixtures/styles/road-width.style.json
+++ b/test/fixtures/styles/road-width.style.json
@@ -23,7 +23,6 @@
"type": "line",
"style": {
"line-width": {
- "fn": "stops",
"stops": [[13, 0], [13.999, 0], [14, 4], [14.1, 10], [14.2, 20]]
}
}
diff --git a/test/functions.cpp b/test/functions.cpp
index a2ad93c4e1..56b2a31706 100644
--- a/test/functions.cpp
+++ b/test/functions.cpp
@@ -19,11 +19,11 @@ TEST(Function, Constant) {
TEST(Function, Stops) {
// Explicit constant slope in fringe regions.
- mbgl::StopsFunction<float> slope_1({ { 0, 1.5 }, { 6, 1.5 }, { 8, 3 }, { 22, 3 } });
+ mbgl::StopsFunction<float> slope_1({ { 0, 1.5 }, { 6, 1.5 }, { 8, 3 }, { 22, 3 } }, 1.75);
EXPECT_EQ(1.5, slope_1.evaluate(0));
EXPECT_EQ(1.5, slope_1.evaluate(4));
EXPECT_EQ(1.5, slope_1.evaluate(6));
- ASSERT_FLOAT_EQ(2.12132, slope_1.evaluate(7));
+ ASSERT_FLOAT_EQ(2.0454545454545454, slope_1.evaluate(7));
EXPECT_EQ(3.0, slope_1.evaluate(8));
EXPECT_EQ(3.0, slope_1.evaluate(9));
EXPECT_EQ(3.0, slope_1.evaluate(15));
@@ -31,48 +31,28 @@ TEST(Function, Stops) {
// Test constant values in fringe regions.
- mbgl::StopsFunction<float> slope_2({ { 6, 1.5 }, { 8, 3 } });
+ mbgl::StopsFunction<float> slope_2({ { 6, 1.5 }, { 8, 3 } }, 1.75);
EXPECT_EQ(1.5, slope_2.evaluate(0));
EXPECT_EQ(1.5, slope_2.evaluate(4));
EXPECT_EQ(1.5, slope_2.evaluate(6));
- ASSERT_FLOAT_EQ(2.12132, slope_2.evaluate(7));
+ ASSERT_FLOAT_EQ(2.0454545454545454, slope_2.evaluate(7));
EXPECT_EQ(3.0, slope_2.evaluate(8));
EXPECT_EQ(3.0, slope_2.evaluate(9));
EXPECT_EQ(3.0, slope_2.evaluate(15));
EXPECT_EQ(3.0, slope_2.evaluate(22));
// Test no values.
- mbgl::StopsFunction<float> slope_3({});
+ mbgl::StopsFunction<float> slope_3({}, 1.75);
EXPECT_EQ(1, slope_3.evaluate(2));
EXPECT_EQ(1, slope_3.evaluate(6));
EXPECT_EQ(1, slope_3.evaluate(12));
-}
-
-
-TEST(Function, Linear) {
- mbgl::LinearFunction<float> slope_1(/* val */ 7.5, /* z_base */ 4, /* slope */ 2, /* min */ 7.5, /* max */ 20);
- ASSERT_FLOAT_EQ(7.5, slope_1.evaluate(3));
- ASSERT_FLOAT_EQ(7.5, slope_1.evaluate(4));
- ASSERT_FLOAT_EQ(8.5, slope_1.evaluate(4.5));
- ASSERT_FLOAT_EQ(9.5, slope_1.evaluate(5));
- ASSERT_FLOAT_EQ(11.5, slope_1.evaluate(6));
- ASSERT_FLOAT_EQ(19.5, slope_1.evaluate(10));
- ASSERT_FLOAT_EQ(20, slope_1.evaluate(11));
- ASSERT_FLOAT_EQ(20, slope_1.evaluate(20));
-}
-TEST(Function, Exponential) {
- mbgl::ExponentialFunction<float> slope_1(/* val */ 7.5, /* z_base */ 4, /* exp_base */ 1.75, /* slope */ 2, /* min */ 7.5, /* max */ 20);
- ASSERT_FLOAT_EQ(8.6428576, slope_1.evaluate(3)); // 7.5 + 1.75^(3 - 4) * 2
- ASSERT_FLOAT_EQ(9.5, slope_1.evaluate(4)); // 7.5 + 1.75^(4 - 4) * 2
- ASSERT_FLOAT_EQ(10.145751, slope_1.evaluate(4.5)); // 7.5 + 1.75^(4.5 - 4) * 2
- ASSERT_FLOAT_EQ(11, slope_1.evaluate(5)); // 7.5 + 1.75^(5 - 4) * 2
- ASSERT_FLOAT_EQ(13.625, slope_1.evaluate(6)); // 7.5 + 1.75^(6 - 4) * 2
- ASSERT_FLOAT_EQ(18.21875, slope_1.evaluate(7)); // 7.5 + 1.75^(7 - 4) * 2
- ASSERT_FLOAT_EQ(20, slope_1.evaluate(8)); // 7.5 + 1.75^(8 - 4) * 2 ==> clamped to 20
- ASSERT_FLOAT_EQ(20, slope_1.evaluate(20)); // 7.5 + 1.75^(20 - 4) * 2 ==> clamped to 20
+ // Explicit constant slope in fringe regions.
+ mbgl::StopsFunction<float> slope_4({ { 0, 2 }, { 8, 10 } }, 1);
+ EXPECT_EQ(2, slope_4.evaluate(0));
+ EXPECT_EQ(3, slope_4.evaluate(1));
+ EXPECT_EQ(4, slope_4.evaluate(2));
+ EXPECT_EQ(4.75, slope_4.evaluate(2.75));
+ EXPECT_EQ(10, slope_4.evaluate(8));
}
-
-
-