#pragma once #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { template class SourceFunction { public: using Stops = std::conditional_t< util::Interpolatable::value, variant< ExponentialStops, IntervalStops, CategoricalStops, IdentityStops>, variant< IntervalStops, CategoricalStops, IdentityStops>>; SourceFunction(std::unique_ptr expression_) : isExpression(true), expression(std::move(expression_)) { assert(expression::isZoomConstant(*expression)); assert(!expression::isFeatureConstant(*expression)); } SourceFunction(const std::string& property, const Stops& stops, optional defaultValue_ = {}) : isExpression(false), defaultValue(std::move(defaultValue_)), expression(stops.match([&] (const IdentityStops&) { return expression::Convert::fromIdentityFunction(expression::valueTypeToExpressionType(), property); }, [&] (const auto& s) { return expression::Convert::toExpression(property, s); })) {} template T evaluate(const Feature& feature, T finalDefaultValue) const { const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext(&feature)); if (result) { const optional typed = expression::fromExpressionValue(*result); return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue; } return defaultValue ? *defaultValue : finalDefaultValue; } std::vector> possibleOutputs() const { return expression::fromExpressionValues(expression->possibleOutputs()); } friend bool operator==(const SourceFunction& lhs, const SourceFunction& rhs) { return *lhs.expression == *rhs.expression; } bool useIntegerZoom = false; bool isExpression; const expression::Expression& getExpression() const { return *expression; } private: optional defaultValue; std::shared_ptr expression; }; } // namespace style } // namespace mbgl