1 #include <mbgl/style/conversion/tileset.hpp>
2 #include <mbgl/util/geo.hpp>
3 #include <mbgl/math/clamp.hpp>
4
5 namespace mbgl {
6 namespace style {
7 namespace conversion {
8
operator ()(const Convertible & value,Error & error) const9 optional<Tileset> Converter<Tileset>::operator()(const Convertible& value, Error& error) const {
10 Tileset result;
11
12 auto tiles = objectMember(value, "tiles");
13 if (!tiles) {
14 error = { "source must have tiles" };
15 return {};
16 }
17
18 if (!isArray(*tiles)) {
19 error = { "source tiles must be an array" };
20 return {};
21 }
22
23 for (std::size_t i = 0; i < arrayLength(*tiles); i++) {
24 optional<std::string> urlTemplate = toString(arrayMember(*tiles, i));
25 if (!urlTemplate) {
26 error = { "source tiles member must be a string" };
27 return {};
28 }
29 result.tiles.push_back(std::move(*urlTemplate));
30 }
31
32 auto schemeValue = objectMember(value, "scheme");
33 if (schemeValue) {
34 optional<std::string> scheme = toString(*schemeValue);
35 if (scheme && *scheme == "tms") {
36 result.scheme = Tileset::Scheme::TMS;
37 }
38 }
39
40 auto encodingValue = objectMember(value, "encoding");
41 if (encodingValue) {
42 optional<std::string> encoding = toString(*encodingValue);
43 if (encoding && *encoding == "terrarium") {
44 result.encoding = Tileset::DEMEncoding::Terrarium;
45 } else if (encoding && *encoding != "mapbox") {
46 error = { "invalid raster-dem encoding type - valid types are 'mapbox' and 'terrarium' " };
47 }
48 }
49
50 auto minzoomValue = objectMember(value, "minzoom");
51 if (minzoomValue) {
52 optional<float> minzoom = toNumber(*minzoomValue);
53 if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) {
54 error = { "invalid minzoom" };
55 return {};
56 }
57 result.zoomRange.min = *minzoom;
58 }
59
60 auto maxzoomValue = objectMember(value, "maxzoom");
61 if (maxzoomValue) {
62 optional<float> maxzoom = toNumber(*maxzoomValue);
63 if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) {
64 error = { "invalid maxzoom" };
65 return {};
66 }
67 result.zoomRange.max = *maxzoom;
68 }
69
70 auto attributionValue = objectMember(value, "attribution");
71 if (attributionValue) {
72 optional<std::string> attribution = toString(*attributionValue);
73 if (!attribution) {
74 error = { "source attribution must be a string" };
75 return {};
76 }
77 result.attribution = std::move(*attribution);
78 }
79
80 auto boundsValue = objectMember(value, "bounds");
81 if (boundsValue) {
82 if (!isArray(*boundsValue) || arrayLength(*boundsValue) != 4) {
83 error = { "bounds must be an array with left, bottom, top, and right values" };
84 return {};
85 }
86 optional<double> left = toDouble(arrayMember(*boundsValue, 0));
87 optional<double> bottom = toDouble(arrayMember(*boundsValue, 1));
88 optional<double> right = toDouble(arrayMember(*boundsValue, 2));
89 optional<double> top = toDouble(arrayMember(*boundsValue, 3));
90
91 if (!left || !right || !bottom || !top) {
92 error = { "bounds array must contain numeric longitude and latitude values" };
93 return {};
94 }
95
96 bottom = util::clamp(*bottom, -90.0, 90.0);
97 top = util::clamp(*top, -90.0, 90.0);
98 if (top <= bottom){
99 error = { "bounds bottom latitude must be smaller than top latitude" };
100 return {};
101 }
102
103 if(*left >= *right) {
104 error = { "bounds left longitude should be less than right longitude" };
105 return {};
106 }
107 left = util::max(-180.0, *left);
108 right = util::min(180.0, *right);
109 result.bounds = LatLngBounds::hull({ *bottom, *left }, { *top, *right });
110 }
111
112 return result;
113 }
114
115 } // namespace conversion
116 } // namespace style
117 } // namespace mbgl
118