diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/style/expression/compound_expression.cpp | 17 | ||||
-rw-r--r-- | src/mbgl/style/expression/match.cpp | 33 | ||||
-rw-r--r-- | src/mbgl/style/expression/value.cpp | 222 | ||||
-rw-r--r-- | src/mbgl/style/function/expression.cpp | 4 |
4 files changed, 237 insertions, 39 deletions
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp index 6767842b9a..9134b769f9 100644 --- a/src/mbgl/style/expression/compound_expression.cpp +++ b/src/mbgl/style/expression/compound_expression.cpp @@ -71,13 +71,16 @@ static Definition defineGet() { definition.push_back( std::make_unique<Signature<Result<Value> (const EvaluationParameters&, const std::string&)>>( [](const EvaluationParameters& params, const std::string& key) -> Result<Value> { - const auto propertyValue = params.feature.getValue(key); + optional<mbgl::Value> propertyValue; + if (params.feature) { + propertyValue = params.feature->getValue(key); + } if (!propertyValue) { return EvaluationError { "Property '" + key + "' not found in feature.properties" }; } - return convertValue(*propertyValue); + return Value(toExpressionValue(*propertyValue)); }, false ) @@ -117,7 +120,6 @@ std::unordered_map<std::string, CompoundExpression::Definition> CompoundExpressi define("number", assertion<float>), define("string", assertion<std::string>), define("boolean", assertion<bool>), - define("array", assertion<std::vector<Value>>), // TODO: [array, type, value], [array, type, length, value] define("to_string", [](const Value& v) -> Result<std::string> { return stringify(v); }), define("to_number", [](const Value& v) -> Result<float> { @@ -160,6 +162,15 @@ std::unordered_map<std::string, CompoundExpression::Definition> CompoundExpressi }; }), + define("zoom", [](const EvaluationParameters& params) -> Result<float> { + if (!params.zoom) { + return EvaluationError { + "The 'zoom' expression is unavailable in the current evaluation context." + }; + } + return *(params.zoom); + }), + std::pair<std::string, Definition>("get", defineGet()), define("+", [](const Varargs<float>& args) -> Result<float> { diff --git a/src/mbgl/style/expression/match.cpp b/src/mbgl/style/expression/match.cpp new file mode 100644 index 0000000000..9286e96d50 --- /dev/null +++ b/src/mbgl/style/expression/match.cpp @@ -0,0 +1,33 @@ +#include <mbgl/style/expression/match.hpp> + +namespace mbgl { +namespace style { +namespace expression { + +template<> Result<std::string> TypedMatch<std::string>::evaluateInput(const EvaluationParameters& params) const { + const auto& inputValue = input->evaluate<std::string>(params); + if (!inputValue) { + return inputValue.error(); + } + return *inputValue; +} + +template<> Result<int64_t> TypedMatch<int64_t>::evaluateInput(const EvaluationParameters& params) const { + const auto& inputValue = input->evaluate<float>(params); + if (!inputValue) { + return inputValue.error(); + } + int64_t rounded = ceilf(*inputValue); + if (*inputValue == rounded) { + return rounded; + } else { + return EvaluationError { + "Input to \"match\" must be an integer value; found " + + std::to_string(*inputValue) + " instead ." + }; + } +} + +} // namespace expression +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp index 4e670ec5dd..324fc06f17 100644 --- a/src/mbgl/style/expression/value.cpp +++ b/src/mbgl/style/expression/value.cpp @@ -4,38 +4,6 @@ namespace mbgl { namespace style { namespace expression { -struct ConvertValue { -// null_value_t, bool, uint64_t, int64_t, double, std::string, -// mapbox::util::recursive_wrapper<std::vector<value>>, -// mapbox::util::recursive_wrapper<std::unordered_map<std::string, value>> - Value operator()(const std::vector<mbgl::Value>& v) { - std::vector<Value> result; - for(const auto& item : v) { - result.emplace_back(convertValue(item)); - } - return result; - } - - Value operator()(const std::unordered_map<std::string, mbgl::Value>& v) { - std::unordered_map<std::string, Value> result; - for(const auto& entry : v) { - result.emplace(entry.first, convertValue(entry.second)); - } - return result; - } - - Value operator()(const std::string& s) { return s; } - Value operator()(const bool& b) { return b; } - Value operator()(const mbgl::NullValue) { return Null; } - - template <typename T> - Value operator()(const T& v) { return *numericValue<float>(v); } -}; - -Value convertValue(const mbgl::Value& value) { - return mbgl::Value::visit(value, ConvertValue()); -} - type::Type typeOf(const Value& value) { return value.match( [&](bool) -> type::Type { return type::Boolean; }, @@ -92,6 +60,165 @@ std::string stringify(const Value& value) { ); } + +template <class T, class Enable = void> +struct Converter { + static Value toExpressionValue(const T& value) { + return Value(value); + } + static optional<T> fromExpressionValue(const Value& value) { + return value.template is<T>() ? value.template get<T>() : optional<T>(); + } +}; + +template<> +struct Converter<mbgl::Value> { + static Value toExpressionValue(const mbgl::Value& value) { + return mbgl::Value::visit(value, Converter<mbgl::Value>()); + } + + + // Double duty as a variant visitor for mbgl::Value: + Value operator()(const std::vector<mbgl::Value>& v) { + std::vector<Value> result; + for(const auto& item : v) { + result.emplace_back(toExpressionValue(item)); + } + return result; + } + + Value operator()(const std::unordered_map<std::string, mbgl::Value>& v) { + std::unordered_map<std::string, Value> result; + for(const auto& entry : v) { + result.emplace(entry.first, toExpressionValue(entry.second)); + } + return result; + } + + Value operator()(const std::string& s) { return s; } + Value operator()(const bool& b) { return b; } + Value operator()(const mbgl::NullValue) { return Null; } + + template <typename T> + Value operator()(const T& v) { return *numericValue<float>(v); } +}; + +template <typename T, std::size_t N> +struct Converter<std::array<T, N>> { + static Value toExpressionValue(const std::array<T, N>& value) { + std::vector<Value> result; + std::copy_n(value.begin(), N, result.begin()); + return result; + } + + static optional<std::array<T, N>> fromExpressionValue(const Value& v) { + return v.match( + [&] (const std::vector<Value>& v) -> optional<std::array<T, N>> { + if (v.size() != N) return optional<std::array<T, N>>(); + std::array<T, N> result; + auto it = result.begin(); + for(const auto& item : v) { + if (!item.template is<T>()) { + return optional<std::array<T, N>>(); + } + *it = item.template get<T>(); + it = std::next(it); + } + return result; + }, + [&] (const auto&) { return optional<std::array<T, N>>(); } + ); + } + + static type::Type expressionType() { + return type::Array(valueTypeToExpressionType<T>(), N); + } +}; + +template <typename T> +struct Converter<std::vector<T>> { + static Value toExpressionValue(const std::vector<T>& value) { + std::vector<Value> v; + std::copy(value.begin(), value.end(), v.begin()); + return v; + } + + static optional<std::vector<T>> fromExpressionValue(const Value& v) { + return v.match( + [&] (const std::vector<Value>& v) -> optional<std::vector<T>> { + std::vector<T> result; + for(const auto& item : v) { + if (!item.template is<T>()) { + return optional<std::vector<T>>(); + } + result.push_back(item.template get<T>()); + } + return result; + }, + [&] (const auto&) { return optional<std::vector<T>>(); } + ); + } + + static type::Type expressionType() { + return type::Array(valueTypeToExpressionType<T>()); + } +}; + +template <> +struct Converter<Position> { + static Value toExpressionValue(const mbgl::style::Position& value) { + return Converter<std::array<float, 3>>::toExpressionValue(value.getSpherical()); + } + + static optional<Position> fromExpressionValue(const Value& v) { + auto pos = Converter<std::array<float, 3>>::fromExpressionValue(v); + return pos ? optional<Position>(Position(*pos)) : optional<Position>(); + } + + static type::Type expressionType() { + return type::Array(type::Number, 3); + } +}; + +template <typename T> +struct Converter<T, std::enable_if_t< std::is_enum<T>::value >> { + static Value toExpressionValue(const T& value) { + return std::string(Enum<T>::toString(value)); + } + + static optional<T> fromExpressionValue(const Value& v) { + return v.match( + [&] (const std::string& v) { return Enum<T>::toEnum(v); }, + [&] (const auto&) { return optional<T>(); } + ); + } + + static type::Type expressionType() { + return type::String; + } +}; + +Value toExpressionValue(const Value& v) { + return v; +} + +template <typename T, typename Enable> +Value toExpressionValue(const T& value) { + return Converter<T>::toExpressionValue(value); +} + +template <typename T> +std::enable_if_t< !std::is_convertible<T, Value>::value, +optional<T>> fromExpressionValue(const Value& v) +{ + return Converter<T>::fromExpressionValue(v); +} + +template <typename T> +type::Type valueTypeToExpressionType() { + return Converter<T>::expressionType(); +} + template <> type::Type valueTypeToExpressionType<Value>() { return type::Value; } template <> type::Type valueTypeToExpressionType<NullValue>() { return type::Null; } template <> type::Type valueTypeToExpressionType<bool>() { return type::Boolean; } @@ -99,10 +226,37 @@ template <> type::Type valueTypeToExpressionType<float>() { return type::Number; template <> type::Type valueTypeToExpressionType<std::string>() { return type::String; } template <> type::Type valueTypeToExpressionType<mbgl::Color>() { return type::Color; } template <> type::Type valueTypeToExpressionType<std::unordered_map<std::string, Value>>() { return type::Object; } -template <> type::Type valueTypeToExpressionType<std::array<float, 2>>() { return type::Array(type::Number, 2); } -template <> type::Type valueTypeToExpressionType<std::array<float, 4>>() { return type::Array(type::Number, 4); } template <> type::Type valueTypeToExpressionType<std::vector<Value>>() { return type::Array(type::Value); } + +template Value toExpressionValue(const mbgl::Value&); + +// instantiate templates fromExpressionValue<T>, toExpressionValue<T>, and valueTypeToExpressionType<T> +template <typename T> +struct instantiate { + void noop(const T& t) { + fromExpressionValue<T>(toExpressionValue(t)); + valueTypeToExpressionType<T>(); + } +}; + +template struct instantiate<std::array<float, 2>>; +template struct instantiate<std::array<float, 4>>; +template struct instantiate<std::vector<float>>; +template struct instantiate<std::vector<std::string>>; +template struct instantiate<AlignmentType>; +template struct instantiate<CirclePitchScaleType>; +template struct instantiate<IconTextFitType>; +template struct instantiate<LineCapType>; +template struct instantiate<LineJoinType>; +template struct instantiate<SymbolPlacementType>; +template struct instantiate<TextAnchorType>; +template struct instantiate<TextJustifyType>; +template struct instantiate<TextTransformType>; +template struct instantiate<TranslateAnchorType>; +template struct instantiate<LightAnchorType>; +template struct instantiate<Position>; + } // namespace expression } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/function/expression.cpp b/src/mbgl/style/function/expression.cpp index 76d4b3cd1f..4fef6e45d9 100644 --- a/src/mbgl/style/function/expression.cpp +++ b/src/mbgl/style/function/expression.cpp @@ -28,8 +28,8 @@ public: EvaluationResult TypedExpression::evaluate(float z, const Feature& feature) const { - std::unique_ptr<const GeometryTileFeature> f = std::make_unique<const GeoJSONFeature>(feature); - return this->evaluate(EvaluationParameters {z, *f}); + GeoJSONFeature f(feature); + return this->evaluate(EvaluationParameters {z, &f}); } } // namespace expression |