diff options
Diffstat (limited to 'src/mbgl/style/conversion/geojson_options.cpp')
-rw-r--r-- | src/mbgl/style/conversion/geojson_options.cpp | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/src/mbgl/style/conversion/geojson_options.cpp b/src/mbgl/style/conversion/geojson_options.cpp index 11bd7cc507..08553e34bb 100644 --- a/src/mbgl/style/conversion/geojson_options.cpp +++ b/src/mbgl/style/conversion/geojson_options.cpp @@ -1,11 +1,15 @@ #include <mbgl/style/conversion/geojson_options.hpp> #include <mbgl/style/conversion_impl.hpp> +#include <mbgl/style/expression/dsl.hpp> + +#include <sstream> namespace mbgl { namespace style { namespace conversion { -optional<GeoJSONOptions> Converter<GeoJSONOptions>::operator()(const Convertible& value, Error& error) const { +optional<GeoJSONOptions> Converter<GeoJSONOptions>::operator()(const Convertible& value, + Error& error) const { GeoJSONOptions options; const auto minzoomValue = objectMember(value, "minzoom"); @@ -83,12 +87,71 @@ optional<GeoJSONOptions> Converter<GeoJSONOptions>::operator()(const Convertible if (toBool(*lineMetricsValue)) { options.lineMetrics = *toBool(*lineMetricsValue); } else { - error = { "GeoJSON source lineMetrics value must be a boolean" }; + error.message = "GeoJSON source lineMetrics value must be a boolean"; + return nullopt; + } + } + + const auto clusterProperties = objectMember(value, "clusterProperties"); + if (clusterProperties) { + if (!isObject(*clusterProperties)) { + error.message = "GeoJSON source clusterProperties value must be an object"; + return nullopt; + } + GeoJSONOptions::ClusterProperties result; + assert(error.message.empty()); + eachMember( + *clusterProperties, + [&](const std::string& k, + const mbgl::style::conversion::Convertible& v) -> optional<conversion::Error> { + // Each property shall be formed as ["key" : [operator, [mapExpression]]] + // or ["key" : [[operator, ['accumulated'], ['get', key]], [mapExpression]]] + if (!isArray(v) || arrayLength(v) != 2) { + error.message = + "GeoJSON source clusterProperties member must be an array with length of 2"; + return nullopt; + } + auto map = expression::dsl::createExpression(arrayMember(v, 1)); + if (!map) { + error.message = + "Failed to convert GeoJSON source clusterProperties map expression"; + return nullopt; + } + std::unique_ptr<expression::Expression> reduce; + if (isArray(arrayMember(v, 0))) { + reduce = expression::dsl::createExpression(arrayMember(v, 0)); + } else { + auto reduceOp = toString(arrayMember(v, 0)); + if (!reduceOp) { + error.message = + "GeoJSON source clusterProperties member must contain a valid operator"; + return nullopt; + } + std::stringstream ss; + // Reformulate reduce expression to [operator, ['accumulated'], ['get', key]] + // The reason to create expression via parsing string instead of invoking function + // createCompoundExpression is due to expression type disunity can’t be resolved + // with current logic of createCompoundExpression + ss << std::string(R"([")") << *reduceOp + << std::string(R"(", ["accumulated"], ["get", ")") << k + << std::string(R"("]])"); + reduce = expression::dsl::createExpression(ss.str().c_str()); + } + if (!reduce) { + error.message = + "Failed to convert GeoJSON source clusterProperties reduce expression"; + return nullopt; + } + result.emplace(k, std::make_pair(std::move(map), std::move(reduce))); + return nullopt; + }); + if (!error.message.empty()) { return nullopt; } + options.clusterProperties = std::move(result); } - return { options }; + return { std::move(options) }; } } // namespace conversion |