diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/mbgl/style/conversion/function.hpp | 400 | ||||
-rw-r--r-- | include/mbgl/style/conversion/property_value.hpp | 1 | ||||
-rw-r--r-- | include/mbgl/style/expression/dsl.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/style/expression/error.hpp | 39 | ||||
-rw-r--r-- | include/mbgl/style/function/categorical_stops.hpp | 40 | ||||
-rw-r--r-- | include/mbgl/style/function/composite_categorical_stops.hpp | 30 | ||||
-rw-r--r-- | include/mbgl/style/function/composite_exponential_stops.hpp | 35 | ||||
-rw-r--r-- | include/mbgl/style/function/composite_interval_stops.hpp | 32 | ||||
-rw-r--r-- | include/mbgl/style/function/convert.hpp | 322 | ||||
-rw-r--r-- | include/mbgl/style/function/exponential_stops.hpp | 56 | ||||
-rw-r--r-- | include/mbgl/style/function/identity_stops.hpp | 20 | ||||
-rw-r--r-- | include/mbgl/style/function/interval_stops.hpp | 51 |
12 files changed, 64 insertions, 966 deletions
diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp index 932925c53c..5ddede324b 100644 --- a/include/mbgl/style/conversion/function.hpp +++ b/include/mbgl/style/conversion/function.hpp @@ -3,224 +3,15 @@ #include <mbgl/style/function/camera_function.hpp> #include <mbgl/style/function/source_function.hpp> #include <mbgl/style/function/composite_function.hpp> -#include <mbgl/style/function/convert.hpp> -#include <mbgl/style/function/categorical_stops.hpp> -#include <mbgl/style/function/exponential_stops.hpp> -#include <mbgl/style/function/interval_stops.hpp> -#include <mbgl/style/function/identity_stops.hpp> -#include <mbgl/style/function/composite_exponential_stops.hpp> -#include <mbgl/style/function/composite_interval_stops.hpp> -#include <mbgl/style/function/composite_categorical_stops.hpp> #include <mbgl/style/conversion.hpp> #include <mbgl/style/conversion/constant.hpp> -#include <mbgl/util/ignore.hpp> -#include <mbgl/util/variant.hpp> +#include <mbgl/style/expression/expression.hpp> +#include <mbgl/style/expression/value.hpp> namespace mbgl { namespace style { namespace conversion { -template <class D, class R> -optional<std::map<D, R>> convertStops(const Convertible& value, Error& error) { - auto stopsValue = objectMember(value, "stops"); - if (!stopsValue) { - error = { "function value must specify stops" }; - return {}; - } - - if (!isArray(*stopsValue)) { - error = { "function stops must be an array" }; - return {}; - } - - if (arrayLength(*stopsValue) == 0) { - error = { "function must have at least one stop" }; - return {}; - } - - std::map<D, R> stops; - for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) { - const auto& stopValue = arrayMember(*stopsValue, i); - - if (!isArray(stopValue)) { - error = { "function stop must be an array" }; - return {}; - } - - if (arrayLength(stopValue) != 2) { - error = { "function stop must have two elements" }; - return {}; - } - - optional<D> d = convert<D>(arrayMember(stopValue, 0), error); - if (!d) { - return {}; - } - - optional<R> r = convert<R>(arrayMember(stopValue, 1), error); - if (!r) { - return {}; - } - - stops.emplace(*d, *r); - } - - return stops; -} - -template <class T> -struct Converter<ExponentialStops<T>> { - static constexpr const char * type = "exponential"; - - optional<ExponentialStops<T>> operator()(const Convertible& value, Error& error) const { - auto stops = convertStops<float, T>(value, error); - if (!stops) { - return {}; - } - - auto baseValue = objectMember(value, "base"); - if (!baseValue) { - return ExponentialStops<T>(*stops); - } - - optional<float> base = toNumber(*baseValue); - if (!base) { - error = { "function base must be a number"}; - return {}; - } - - return ExponentialStops<T>(*stops, *base); - } -}; - -template <class T> -struct Converter<IntervalStops<T>> { - static constexpr const char * type = "interval"; - - optional<IntervalStops<T>> operator()(const Convertible& value, Error& error) const { - auto stops = convertStops<float, T>(value, error); - if (!stops) { - return {}; - } - return IntervalStops<T>(*stops); - } -}; - -template <> -struct Converter<CategoricalValue> { - optional<CategoricalValue> operator()(const Convertible& value, Error& error) const { - auto b = toBool(value); - if (b) { - return { *b }; - } - - auto n = toNumber(value); - if (n) { - return { int64_t(*n) }; - } - - auto s = toString(value); - if (s) { - return { *s }; - } - - error = { "stop domain value must be a number, string, or boolean" }; - return {}; - } -}; - -template <class T> -struct Converter<CategoricalStops<T>> { - static constexpr const char * type = "categorical"; - - optional<CategoricalStops<T>> operator()(const Convertible& value, Error& error) const { - auto stops = convertStops<CategoricalValue, T>(value, error); - if (!stops) { - return {}; - } - return CategoricalStops<T>( - std::map<CategoricalValue, T>((*stops).begin(), (*stops).end())); - } -}; - -template <class T> -struct Converter<IdentityStops<T>> { - static constexpr const char * type = "identity"; - - optional<IdentityStops<T>> operator()(const Convertible&, Error&) const { - return IdentityStops<T>(); - } -}; - -template <class, class> -struct StopsConverter; - -template <class T, class... Ts> -struct StopsConverter<T, variant<Ts...>> { -public: - optional<variant<Ts...>> operator()(const Convertible& value, Error& error) const { - std::string type = util::Interpolatable<T>::value ? "exponential" : "interval"; - - auto typeValue = objectMember(value, "type"); - if (typeValue && toString(*typeValue)) { - type = *toString(*typeValue); - } - - bool matched = false; - optional<variant<Ts...>> result; - - // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 - auto tryConvert = [&] (auto* tp) { - using Stops = std::decay_t<decltype(*tp)>; - if (type == Converter<Stops>::type) { - matched = true; - optional<Stops> stops = convert<Stops>(value, error); - if (stops) { - result = variant<Ts...>(*stops); - } - } - }; - - util::ignore({ - (tryConvert((Ts*)nullptr), 0)... - }); - - if (!matched) { - error = { "unsupported function type" }; - return {}; - } - - return result; - } -}; - -template <class T> -struct Converter<CameraFunction<T>> { - optional<CameraFunction<T>> operator()(const Convertible& value, Error& error) const { - if (!isObject(value)) { - error = { "function must be an object" }; - return {}; - } - - using Stops = std::conditional_t< - util::Interpolatable<T>::value, - variant< - ExponentialStops<T>, - IntervalStops<T>>, - variant< - IntervalStops<T>>>; - - auto stops = StopsConverter<T, Stops>()(value, error); - if (!stops) { - return {}; - } - - return CameraFunction<T>((*stops).match([&] (const auto& s) { - return expression::Convert::toExpression(s); - }), false); - } -}; - template <class T> optional<optional<T>> convertDefaultValue(const Convertible& value, Error& error) { auto defaultValueValue = objectMember(value, "default"); @@ -237,199 +28,48 @@ optional<optional<T>> convertDefaultValue(const Convertible& value, Error& error return { *defaultValue }; } -template <class T> -struct Converter<SourceFunction<T>> { - optional<SourceFunction<T>> operator()(const Convertible& value, Error& error) const { - if (!isObject(value)) { - error = { "function must be an object" }; - return {}; - } - - auto propertyValue = objectMember(value, "property"); - if (!propertyValue) { - error = { "function must specify property" }; - return {}; - } - - auto propertyString = toString(*propertyValue); - if (!propertyString) { - error = { "function property must be a string" }; - return {}; - } - - using Stops = std::conditional_t< - util::Interpolatable<T>::value, - variant< - ExponentialStops<T>, - IntervalStops<T>, - CategoricalStops<T>, - IdentityStops<T>>, - variant< - IntervalStops<T>, - CategoricalStops<T>, - IdentityStops<T>>>; - - auto stops = StopsConverter<T, Stops>()(value, error); - if (!stops) { - return {}; - } - - auto defaultValue = convertDefaultValue<T>(value, error); - if (!defaultValue) { - return {}; - } - - return SourceFunction<T>((*stops).match([&] (const auto& s) { - return expression::Convert::toExpression(*propertyString, s); - }), *defaultValue); - } -}; - -template <class S> -struct CompositeValue : std::pair<float, S> { - using std::pair<float, S>::pair; -}; - -template <class S> -struct Converter<CompositeValue<S>> { - optional<CompositeValue<S>> operator()(const Convertible& value, Error& error) const { - if (!isObject(value)) { - error = { "stop must be an object" }; - return {}; - } - - auto zoomValue = objectMember(value, "zoom"); - if (!zoomValue) { - error = { "stop must specify zoom" }; - return {}; - } - - auto propertyValue = objectMember(value, "value"); - if (!propertyValue) { - error = { "stop must specify value" }; - return {}; - } - - optional<float> z = convert<float>(*zoomValue, error); - if (!z) { - return {}; - } - - optional<S> s = convert<S>(*propertyValue, error); - if (!s) { - return {}; - } - - return CompositeValue<S> { *z, *s }; - } -}; +optional<std::unique_ptr<expression::Expression>> convertCameraFunctionToExpression(expression::type::Type, const Convertible&, Error&); +optional<std::unique_ptr<expression::Expression>> convertSourceFunctionToExpression(expression::type::Type, const Convertible&, Error&); +optional<std::unique_ptr<expression::Expression>> convertCompositeFunctionToExpression(expression::type::Type, const Convertible&, Error&); template <class T> -struct Converter<CompositeExponentialStops<T>> { - static constexpr const char * type = "exponential"; - - optional<CompositeExponentialStops<T>> operator()(const Convertible& value, Error& error) const { - auto stops = convertStops<CompositeValue<float>, T>(value, error); - if (!stops) { +struct Converter<CameraFunction<T>> { + optional<CameraFunction<T>> operator()(const Convertible& value, Error& error) const { + auto expression = convertCameraFunctionToExpression(expression::valueTypeToExpressionType<T>(), value, error); + if (!expression) { return {}; } - - auto base = 1.0f; - auto baseValue = objectMember(value, "base"); - if (baseValue && toNumber(*baseValue)) { - base = *toNumber(*baseValue); - } - - std::map<float, std::map<float, T>> convertedStops; - for (const auto& stop : *stops) { - convertedStops[stop.first.first].emplace(stop.first.second, stop.second); - } - - return CompositeExponentialStops<T>(convertedStops, base); + return CameraFunction<T>(std::move(*expression), false); } }; template <class T> -struct Converter<CompositeIntervalStops<T>> { - static constexpr const char * type = "interval"; - - optional<CompositeIntervalStops<T>> operator()(const Convertible& value, Error& error) const { - auto stops = convertStops<CompositeValue<float>, T>(value, error); - if (!stops) { +struct Converter<SourceFunction<T>> { + optional<SourceFunction<T>> operator()(const Convertible& value, Error& error) const { + auto expression = convertSourceFunctionToExpression(expression::valueTypeToExpressionType<T>(), value, error); + if (!expression) { return {}; } - - std::map<float, std::map<float, T>> convertedStops; - for (const auto& stop : *stops) { - convertedStops[stop.first.first].emplace(stop.first.second, stop.second); - } - - return CompositeIntervalStops<T>(convertedStops); - } -}; - -template <class T> -struct Converter<CompositeCategoricalStops<T>> { - static constexpr const char * type = "categorical"; - - optional<CompositeCategoricalStops<T>> operator()(const Convertible& value, Error& error) const { - auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value, error); - if (!stops) { + auto defaultValue = convertDefaultValue<T>(value, error); + if (!defaultValue) { return {}; } - - std::map<float, std::map<CategoricalValue, T>> convertedStops; - for (const auto& stop : *stops) { - convertedStops[stop.first.first].emplace(stop.first.second, stop.second); - } - - return CompositeCategoricalStops<T>(convertedStops); + return SourceFunction<T>(std::move(*expression), *defaultValue); } }; template <class T> struct Converter<CompositeFunction<T>> { optional<CompositeFunction<T>> operator()(const Convertible& value, Error& error) const { - if (!isObject(value)) { - error = { "function must be an object" }; + auto expression = convertCompositeFunctionToExpression(expression::valueTypeToExpressionType<T>(), value, error); + if (!expression) { return {}; } - - auto propertyValue = objectMember(value, "property"); - if (!propertyValue) { - error = { "function must specify property" }; - return {}; - } - - auto propertyString = toString(*propertyValue); - if (!propertyString) { - error = { "function property must be a string" }; - return {}; - } - - using Stops = std::conditional_t< - util::Interpolatable<T>::value, - variant< - CompositeExponentialStops<T>, - CompositeIntervalStops<T>, - CompositeCategoricalStops<T>>, - variant< - CompositeIntervalStops<T>, - CompositeCategoricalStops<T>>>; - - auto stops = StopsConverter<T, Stops>()(value, error); - if (!stops) { - return {}; - } - auto defaultValue = convertDefaultValue<T>(value, error); if (!defaultValue) { return {}; } - - return CompositeFunction<T>((*stops).match([&] (const auto& s) { - return expression::Convert::toExpression(*propertyString, s); - }), *defaultValue); + return CompositeFunction<T>(std::move(*expression), *defaultValue); } }; diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp index dc1c32830f..e52c63d023 100644 --- a/include/mbgl/style/conversion/property_value.hpp +++ b/include/mbgl/style/conversion/property_value.hpp @@ -9,6 +9,7 @@ #include <mbgl/style/expression/is_expression.hpp> #include <mbgl/style/expression/find_zoom_curve.hpp> #include <mbgl/style/expression/parsing_context.hpp> +#include <mbgl/style/expression/literal.hpp> namespace mbgl { namespace style { diff --git a/include/mbgl/style/expression/dsl.hpp b/include/mbgl/style/expression/dsl.hpp index 8a5d1d84f5..22278b0975 100644 --- a/include/mbgl/style/expression/dsl.hpp +++ b/include/mbgl/style/expression/dsl.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/expression/interpolator.hpp> #include <memory> +#include <string> #include <initializer_list> namespace mbgl { @@ -15,6 +16,8 @@ namespace dsl { // This convenience API does little to no expression validation or type-checking, and is intended for // use only by test and other non-production code. +std::unique_ptr<Expression> error(std::string); + std::unique_ptr<Expression> literal(const char* value); std::unique_ptr<Expression> literal(Value value); std::unique_ptr<Expression> literal(std::initializer_list<double> value); @@ -22,6 +25,7 @@ std::unique_ptr<Expression> literal(std::initializer_list<const char *> value); std::unique_ptr<Expression> number(std::unique_ptr<Expression>); std::unique_ptr<Expression> string(std::unique_ptr<Expression>); +std::unique_ptr<Expression> boolean(std::unique_ptr<Expression>); std::unique_ptr<Expression> toColor(const char* value); std::unique_ptr<Expression> toColor(std::unique_ptr<Expression>); diff --git a/include/mbgl/style/expression/error.hpp b/include/mbgl/style/expression/error.hpp new file mode 100644 index 0000000000..bfb9247d11 --- /dev/null +++ b/include/mbgl/style/expression/error.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include <mbgl/style/expression/expression.hpp> + +#include <string> + +namespace mbgl { +namespace style { +namespace expression { + +class Error : public Expression { +public: + Error(std::string message_) + : Expression(type::Error), + message(std::move(message_)) {} + + void eachChild(const std::function<void(const Expression&)>&) const override {} + + bool operator==(const Expression& e) const override { + return dynamic_cast<const Error*>(&e); + } + + EvaluationResult evaluate(const EvaluationContext&) const override { + return EvaluationError{message}; + } + + std::vector<optional<Value>> possibleOutputs() const override { + return {}; + } + + std::string getOperator() const override { return "error"; } + +private: + std::string message; +}; + +} // namespace expression +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/categorical_stops.hpp b/include/mbgl/style/function/categorical_stops.hpp deleted file mode 100644 index c8505115ab..0000000000 --- a/include/mbgl/style/function/categorical_stops.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include <mbgl/util/feature.hpp> -#include <mbgl/util/variant.hpp> - -#include <cassert> -#include <utility> -#include <map> - -namespace mbgl { -namespace style { - -class CategoricalValue : public variant<bool, int64_t, std::string> { -public: - using variant<bool, int64_t, std::string>::variant; -}; - -template <class T> -class CategoricalStops { -public: - using Stops = std::map<CategoricalValue, T>; - - Stops stops; - - CategoricalStops() = default; - CategoricalStops(Stops stops_) - : stops(std::move(stops_)) { - assert(stops.size() > 0); - } - - optional<T> evaluate(const Value&) const; - - friend bool operator==(const CategoricalStops& lhs, - const CategoricalStops& rhs) { - return lhs.stops == rhs.stops; - } -}; - -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/composite_categorical_stops.hpp b/include/mbgl/style/function/composite_categorical_stops.hpp deleted file mode 100644 index b796621d1a..0000000000 --- a/include/mbgl/style/function/composite_categorical_stops.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include <mbgl/style/function/categorical_stops.hpp> - -namespace mbgl { -namespace style { - -template <class T> -class CompositeCategoricalStops { -public: - using Stops = std::map<float, std::map<CategoricalValue, T>>; - Stops stops; - - CompositeCategoricalStops() = default; - CompositeCategoricalStops(Stops stops_) - : stops(std::move(stops_)) { - } - - CategoricalStops<T> innerStops(const std::map<CategoricalValue, T>& stops_) const { - return CategoricalStops<T>(stops_); - } - - friend bool operator==(const CompositeCategoricalStops& lhs, - const CompositeCategoricalStops& rhs) { - return lhs.stops == rhs.stops; - } -}; - -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/composite_exponential_stops.hpp b/include/mbgl/style/function/composite_exponential_stops.hpp deleted file mode 100644 index f1ad32a04d..0000000000 --- a/include/mbgl/style/function/composite_exponential_stops.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <mbgl/style/function/exponential_stops.hpp> - -#include <map> - -namespace mbgl { -namespace style { - -template <class T> -class CompositeExponentialStops { -public: - using Stops = std::map<float, std::map<float, T>>; - - Stops stops; - float base = 1.0f; - - CompositeExponentialStops() = default; - CompositeExponentialStops(Stops stops_, float base_ = 1.0f) - : stops(std::move(stops_)), - base(base_) { - } - - ExponentialStops<T> innerStops(const std::map<float, T>& stops_) const { - return ExponentialStops<T>(stops_, base); - } - - friend bool operator==(const CompositeExponentialStops& lhs, - const CompositeExponentialStops& rhs) { - return lhs.stops == rhs.stops && lhs.base == rhs.base; - } -}; - -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/composite_interval_stops.hpp b/include/mbgl/style/function/composite_interval_stops.hpp deleted file mode 100644 index 3c495f2a7f..0000000000 --- a/include/mbgl/style/function/composite_interval_stops.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include <mbgl/style/function/interval_stops.hpp> - -#include <map> - -namespace mbgl { -namespace style { - -template <class T> -class CompositeIntervalStops { -public: - using Stops = std::map<float, std::map<float, T>>; - Stops stops; - - CompositeIntervalStops() = default; - CompositeIntervalStops(Stops stops_) - : stops(std::move(stops_)) { - } - - IntervalStops<T> innerStops(const std::map<float, T>& stops_) const { - return IntervalStops<T>(stops_); - } - - friend bool operator==(const CompositeIntervalStops& lhs, - const CompositeIntervalStops& rhs) { - return lhs.stops == rhs.stops; - } -}; - -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/convert.hpp b/include/mbgl/style/function/convert.hpp deleted file mode 100644 index a0dae992fa..0000000000 --- a/include/mbgl/style/function/convert.hpp +++ /dev/null @@ -1,322 +0,0 @@ -#pragma once - -#include <mbgl/style/expression/array_assertion.hpp> -#include <mbgl/style/expression/assertion.hpp> -#include <mbgl/style/expression/case.hpp> -#include <mbgl/style/expression/coalesce.hpp> -#include <mbgl/style/expression/compound_expression.hpp> -#include <mbgl/style/expression/coercion.hpp> -#include <mbgl/style/expression/interpolate.hpp> -#include <mbgl/style/expression/expression.hpp> -#include <mbgl/style/expression/literal.hpp> -#include <mbgl/style/expression/match.hpp> -#include <mbgl/style/expression/step.hpp> - -#include <mbgl/style/function/exponential_stops.hpp> -#include <mbgl/style/function/interval_stops.hpp> -#include <mbgl/style/function/categorical_stops.hpp> -#include <mbgl/style/function/composite_exponential_stops.hpp> -#include <mbgl/style/function/composite_interval_stops.hpp> -#include <mbgl/style/function/composite_categorical_stops.hpp> -#include <mbgl/style/function/identity_stops.hpp> - -#include <mbgl/util/enum.hpp> -#include <mbgl/style/types.hpp> - -#include <string> - - -namespace mbgl { -namespace style { -namespace expression { - -namespace detail { - -class ErrorExpression : public Expression { -public: - ErrorExpression(std::string message_) : Expression(type::Error), message(std::move(message_)) {} - void eachChild(const std::function<void(const Expression&)>&) const override {} - - bool operator==(const Expression& e) const override { - return dynamic_cast<const ErrorExpression*>(&e); - } - - EvaluationResult evaluate(const EvaluationContext&) const override { - return EvaluationError{message}; - } - - std::vector<optional<Value>> possibleOutputs() const override { - return {}; - } - - std::string getOperator() const override { return "error"; } -private: - std::string message; -}; - -} // namespace detail - - -// Create expressions representing 'classic' (i.e. stop-based) style functions - -struct Convert { - template <typename T> - static std::unique_ptr<Literal> makeLiteral(const T& value) { - return std::make_unique<Literal>(Value(toExpressionValue(value))); - } - - static std::unique_ptr<Expression> makeGet(type::Type type, const std::string& property) { - ParsingContext ctx; - std::vector<std::unique_ptr<Expression>> getArgs; - getArgs.push_back(makeLiteral(property)); - ParseResult get = createCompoundExpression("get", std::move(getArgs), ctx); - assert(get); - assert(ctx.getErrors().size() == 0); - - std::vector<std::unique_ptr<Expression>> assertionArgs; - assertionArgs.push_back(std::move(*get)); - - return std::make_unique<Assertion>(type, std::move(assertionArgs)); - } - - static std::unique_ptr<Expression> makeZoom() { - ParsingContext ctx; - ParseResult zoom = createCompoundExpression("zoom", std::vector<std::unique_ptr<Expression>>(), ctx); - assert(zoom); - assert(ctx.getErrors().size() == 0); - return std::move(*zoom); - } - - static std::unique_ptr<Expression> makeError(std::string message) { - return std::make_unique<detail::ErrorExpression>(message); - } - - template <typename Key> - static ParseResult makeMatch(type::Type type, - std::unique_ptr<Expression> input, - std::map<CategoricalValue, std::unique_ptr<Expression>> stops) { - // match expression - typename Match<Key>::Branches branches; - for(auto it = stops.begin(); it != stops.end(); it++) { - assert(it->first.template is<Key>()); - Key key = it->first.template get<Key>(); - branches.emplace( - std::move(key), - std::move(it->second) - ); - } - - return ParseResult(std::make_unique<Match<Key>>(std::move(type), - std::move(input), - std::move(branches), - makeError("No matching label"))); - } - - static ParseResult makeCase(type::Type type, - std::unique_ptr<Expression> input, - std::map<CategoricalValue, std::unique_ptr<Expression>> stops) { - // case expression - std::vector<typename Case::Branch> branches; - - auto it = stops.find(true); - std::unique_ptr<Expression> true_case = it == stops.end() ? - makeError("No matching label") : - std::move(it->second); - - it = stops.find(false); - std::unique_ptr<Expression> false_case = it == stops.end() ? - makeError("No matching label") : - std::move(it->second); - - branches.push_back(std::make_pair(std::move(input), std::move(true_case))); - return ParseResult(std::make_unique<Case>(std::move(type), std::move(branches), std::move(false_case))); - } - - template <typename T> - static ParseResult fromCategoricalStops(std::map<CategoricalValue, T> stops, const std::string& property) { - assert(stops.size() > 0); - - std::map<CategoricalValue, std::unique_ptr<Expression>> convertedStops; - for(const std::pair<CategoricalValue, T>& stop : stops) { - convertedStops.emplace( - stop.first, - makeLiteral(stop.second) - ); - } - - type::Type type = valueTypeToExpressionType<T>(); - - const CategoricalValue& firstKey = stops.begin()->first; - return firstKey.match( - [&](bool) { - return makeCase(type, makeGet(type::Boolean, property), std::move(convertedStops)); - }, - [&](const std::string&) { - return makeMatch<std::string>(type, makeGet(type::String, property), std::move(convertedStops)); - }, - [&](int64_t) { - return makeMatch<int64_t>(type, makeGet(type::Number, property), std::move(convertedStops)); - } - ); - } - - template <typename T> - static std::map<double, std::unique_ptr<Expression>> convertStops(const std::map<float, T>& stops) { - std::map<double, std::unique_ptr<Expression>> convertedStops; - for(const auto& stop : stops) { - convertedStops.emplace( - stop.first, - makeLiteral(stop.second) - ); - } - return convertedStops; - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const ExponentialStops<T>& stops) - { - ParsingContext ctx; - ParseResult e = createInterpolate(valueTypeToExpressionType<T>(), - ExponentialInterpolator(stops.base), - makeZoom(), - convertStops(stops.stops), - ctx); - assert(e); - return std::move(*e); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const IntervalStops<T>& stops) - { - ParseResult e(std::make_unique<Step>(valueTypeToExpressionType<T>(), - makeZoom(), - convertStops(stops.stops))); - assert(e); - return std::move(*e); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const std::string& property, - const ExponentialStops<T>& stops) - { - ParsingContext ctx; - ParseResult e = createInterpolate(valueTypeToExpressionType<T>(), - ExponentialInterpolator(stops.base), - makeGet(type::Number, property), - convertStops(stops.stops), - ctx); - assert(e); - return std::move(*e); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const std::string& property, - const IntervalStops<T>& stops) - { - std::unique_ptr<Expression> get = makeGet(type::Number, property); - ParseResult e(std::make_unique<Step>(valueTypeToExpressionType<T>(), - std::move(get), - convertStops(stops.stops))); - assert(e); - return std::move(*e); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const std::string& property, - const CategoricalStops<T>& stops) - { - ParseResult expr = fromCategoricalStops(stops.stops, property); - assert(expr); - return std::move(*expr); - } - - // interpolatable zoom curve - template <typename T> - static typename std::enable_if_t<util::Interpolatable<T>::value, - ParseResult> makeZoomCurve(std::map<double, std::unique_ptr<Expression>> stops) { - ParsingContext ctx; - return createInterpolate(valueTypeToExpressionType<T>(), - ExponentialInterpolator(1.0), - makeZoom(), - std::move(stops), - ctx); - } - - // non-interpolatable zoom curve - template <typename T> - static typename std::enable_if_t<!util::Interpolatable<T>::value, - ParseResult> makeZoomCurve(std::map<double, std::unique_ptr<Expression>> stops) { - return ParseResult(std::make_unique<Step>(valueTypeToExpressionType<T>(), makeZoom(), std::move(stops))); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const std::string& property, - const CompositeExponentialStops<T>& stops) - { - ParsingContext ctx; - - std::map<double, std::unique_ptr<Expression>> outerStops; - for (const std::pair<float, std::map<float, T>>& stop : stops.stops) { - ParseResult innerInterpolate = createInterpolate(valueTypeToExpressionType<T>(), - ExponentialInterpolator(stops.base), - makeGet(type::Number, property), - convertStops(stop.second), - ctx); - assert(innerInterpolate); - outerStops.emplace(stop.first, std::move(*innerInterpolate)); - } - - ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops)); - assert(zoomCurve); - return std::move(*zoomCurve); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const std::string& property, - const CompositeIntervalStops<T>& stops) - { - std::map<double, std::unique_ptr<Expression>> outerStops; - for (const std::pair<float, std::map<float, T>>& stop : stops.stops) { - std::unique_ptr<Expression> get = makeGet(type::Number, property); - ParseResult innerInterpolate(std::make_unique<Step>(valueTypeToExpressionType<T>(), - std::move(get), - convertStops(stop.second))); - assert(innerInterpolate); - outerStops.emplace(stop.first, std::move(*innerInterpolate)); - } - - ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops)); - assert(zoomCurve); - return std::move(*zoomCurve); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const std::string& property, - const CompositeCategoricalStops<T>& stops) - { - std::map<double, std::unique_ptr<Expression>> outerStops; - for (const std::pair<float, std::map<CategoricalValue, T>>& stop : stops.stops) { - ParseResult innerInterpolate = fromCategoricalStops(stop.second, property); - assert(innerInterpolate); - outerStops.emplace(stop.first, std::move(*innerInterpolate)); - } - - ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops)); - assert(zoomCurve); - return std::move(*zoomCurve); - } - - template <typename T> - static std::unique_ptr<Expression> toExpression(const std::string& property, - const IdentityStops<T>&) - { - return fromIdentityFunction(property, expression::valueTypeToExpressionType<T>()); - } - -private: - static std::unique_ptr<Expression> fromIdentityFunction(const std::string& property, type::Type type); -}; - -} // namespace expression -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/exponential_stops.hpp b/include/mbgl/style/function/exponential_stops.hpp deleted file mode 100644 index b3866c4059..0000000000 --- a/include/mbgl/style/function/exponential_stops.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include <mbgl/util/feature.hpp> -#include <mbgl/util/interpolate.hpp> - -#include <map> - -namespace mbgl { -namespace style { - -template <class T> -class ExponentialStops { -public: - using Stops = std::map<float, T>; - - Stops stops; - float base = 1.0f; - - ExponentialStops() = default; - ExponentialStops(Stops stops_, float base_ = 1.0f) - : stops(std::move(stops_)), - base(base_) { - } - - optional<T> evaluate(float z) const { - if (stops.empty()) { - return {}; - } - - auto it = stops.upper_bound(z); - if (it == stops.end()) { - return stops.rbegin()->second; - } else if (it == stops.begin()) { - return stops.begin()->second; - } else { - return util::interpolate(std::prev(it)->second, it->second, - util::interpolationFactor(base, { std::prev(it)->first, it->first }, z)); - } - } - - optional<T> evaluate(const Value& value) const { - optional<float> z = numericValue<float>(value); - if (!z) { - return {}; - } - return evaluate(*z); - } - - friend bool operator==(const ExponentialStops& lhs, - const ExponentialStops& rhs) { - return lhs.stops == rhs.stops && lhs.base == rhs.base; - } -}; - -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/identity_stops.hpp b/include/mbgl/style/function/identity_stops.hpp deleted file mode 100644 index 741ebbbe0c..0000000000 --- a/include/mbgl/style/function/identity_stops.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include <mbgl/util/feature.hpp> - -namespace mbgl { -namespace style { - -template <class T> -class IdentityStops { -public: - optional<T> evaluate(const Value&) const; - - friend bool operator==(const IdentityStops&, - const IdentityStops&) { - return true; - } -}; - -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/interval_stops.hpp b/include/mbgl/style/function/interval_stops.hpp deleted file mode 100644 index 45e2dc6f2e..0000000000 --- a/include/mbgl/style/function/interval_stops.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include <mbgl/util/feature.hpp> - -#include <map> - -namespace mbgl { -namespace style { - -template <class T> -class IntervalStops { -public: - using Stops = std::map<float, T>; - Stops stops; - - IntervalStops() = default; - IntervalStops(Stops stops_) - : stops(std::move(stops_)) { - } - - optional<T> evaluate(float z) const { - if (stops.empty()) { - return {}; - } - - auto it = stops.upper_bound(z); - if (it == stops.end()) { - return stops.rbegin()->second; - } else if (it == stops.begin()) { - return stops.begin()->second; - } else { - return std::prev(it)->second; - } - } - - optional<T> evaluate(const Value& value) const { - optional<float> z = numericValue<float>(value); - if (!z) { - return {}; - } - return evaluate(*z); - } - - friend bool operator==(const IntervalStops& lhs, - const IntervalStops& rhs) { - return lhs.stops == rhs.stops; - } -}; - -} // namespace style -} // namespace mbgl |