summaryrefslogtreecommitdiff
path: root/src/mbgl/style/conversion/function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style/conversion/function.cpp')
-rw-r--r--src/mbgl/style/conversion/function.cpp297
1 files changed, 132 insertions, 165 deletions
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 64adf522a1..39e061d75a 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -66,29 +66,6 @@ static bool interpolatable(type::Type type) {
);
}
-static FunctionType functionType(type::Type type, const Convertible& value) {
- auto typeValue = objectMember(value, "type");
- if (!typeValue) {
- return interpolatable(type) ? FunctionType::Exponential : FunctionType::Interval;
- }
-
- optional<std::string> string = toString(*typeValue);
- if (!string) {
- return FunctionType::Invalid;
- }
-
- if (*string == "interval")
- return FunctionType::Interval;
- if (*string == "exponential" && interpolatable(type))
- return FunctionType::Exponential;
- if (*string == "categorical")
- return FunctionType::Categorical;
- if (*string == "identity")
- return FunctionType::Identity;
-
- return FunctionType::Invalid;
-}
-
static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error) {
return type.match(
[&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
@@ -426,106 +403,16 @@ static optional<std::unique_ptr<Expression>> convertCategoricalFunction(type::Ty
return {};
}
-optional<std::unique_ptr<Expression>> convertCameraFunctionToExpression(type::Type type,
- const Convertible& value,
- Error& error) {
- if (!isObject(value)) {
- error = { "function must be an object" };
- return {};
- }
-
- switch (functionType(type, value)) {
- case FunctionType::Interval:
- return convertIntervalFunction(type, value, error, zoom());
- case FunctionType::Exponential:
- return convertExponentialFunction(type, value, error, zoom());
- default:
- error = { "unsupported function type" };
- return {};
- }
-}
-
-optional<std::unique_ptr<Expression>> convertSourceFunctionToExpression(type::Type type,
- const Convertible& value,
- Error& error) {
- if (!isObject(value)) {
- error = { "function must be an object" };
- return {};
- }
-
- auto propertyValue = objectMember(value, "property");
- if (!propertyValue) {
- error = { "function must specify property" };
- return {};
- }
-
- auto property = toString(*propertyValue);
- if (!property) {
- error = { "function property must be a string" };
- return {};
- }
-
- switch (functionType(type, value)) {
- case FunctionType::Interval:
- return convertIntervalFunction(type, value, error, number(get(literal(*property))));
- case FunctionType::Exponential:
- return convertExponentialFunction(type, value, error, number(get(literal(*property))));
- case FunctionType::Categorical:
- return convertCategoricalFunction(type, value, error, *property);
- case FunctionType::Identity:
- return type.match(
- [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
- return string(get(literal(*property)));
- },
- [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
- return number(get(literal(*property)));
- },
- [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
- return boolean(get(literal(*property)));
- },
- [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
- return toColor(get(literal(*property)));
- },
- [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
- return std::unique_ptr<Expression>(
- std::make_unique<ArrayAssertion>(array, get(literal(*property))));
- },
- [&] (const auto&) -> optional<std::unique_ptr<Expression>> {
- assert(false); // No properties use this type.
- return {};
- }
- );
- default:
- error = { "unsupported function type" };
- return {};
- }
-}
-
-template <class T>
+template <class T, class Fn>
optional<std::unique_ptr<Expression>> composite(type::Type type,
const Convertible& value,
Error& error,
- std::unique_ptr<Expression> (*makeInnerExpression) (type::Type type,
- double base,
- const std::string& property,
- std::map<T, std::unique_ptr<Expression>>)) {
- auto propertyValue = objectMember(value, "property");
- if (!propertyValue) {
- error = { "function must specify property" };
- return {};
- }
-
+ const Fn& makeInnerExpression) {
auto base = convertBase(value, error);
if (!base) {
return {};
}
- auto propertyString = toString(*propertyValue);
- if (!propertyString) {
- error = { "function property must be a string" };
- return {};
- }
-
auto stopsValue = objectMember(value, "stops");
// Checked by caller.
@@ -587,7 +474,7 @@ optional<std::unique_ptr<Expression>> composite(type::Type type,
std::map<double, std::unique_ptr<Expression>> stops;
for (auto& e : map) {
- stops.emplace(e.first, makeInnerExpression(type, *base, *propertyString, std::move(e.second)));
+ stops.emplace(e.first, makeInnerExpression(type, *base, std::move(e.second)));
}
if (interpolatable(type)) {
@@ -597,14 +484,83 @@ optional<std::unique_ptr<Expression>> composite(type::Type type,
}
}
-optional<std::unique_ptr<Expression>> convertCompositeFunctionToExpression(type::Type type,
- const Convertible& value,
- Error& err) {
+optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type type,
+ const Convertible& value,
+ Error& err) {
if (!isObject(value)) {
err = { "function must be an object" };
return {};
}
+ FunctionType functionType = FunctionType::Invalid;
+
+ auto typeValue = objectMember(value, "type");
+ if (!typeValue) {
+ functionType = interpolatable(type) ? FunctionType::Exponential : FunctionType::Interval;
+ } else {
+ optional<std::string> string = toString(*typeValue);
+ if (string) {
+ if (*string == "interval")
+ functionType = FunctionType::Interval;
+ if (*string == "exponential" && interpolatable(type))
+ functionType = FunctionType::Exponential;
+ if (*string == "categorical")
+ functionType = FunctionType::Categorical;
+ if (*string == "identity")
+ functionType = FunctionType::Identity;
+ }
+ }
+
+ if (!objectMember(value, "property")) {
+ // Camera function.
+ switch (functionType) {
+ case FunctionType::Interval:
+ return convertIntervalFunction(type, value, err, zoom());
+ case FunctionType::Exponential:
+ return convertExponentialFunction(type, value, err, zoom());
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ auto propertyValue = objectMember(value, "property");
+ if (!propertyValue) {
+ err = { "function must specify property" };
+ return {};
+ }
+
+ auto property = toString(*propertyValue);
+ if (!property) {
+ err = { "function property must be a string" };
+ return {};
+ }
+
+ if (functionType == FunctionType::Identity) {
+ return type.match(
+ [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
+ return string(get(literal(*property)));
+ },
+ [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
+ return number(get(literal(*property)));
+ },
+ [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
+ return boolean(get(literal(*property)));
+ },
+ [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
+ return toColor(get(literal(*property)));
+ },
+ [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
+ return std::unique_ptr<Expression>(
+ std::make_unique<ArrayAssertion>(array, get(literal(*property))));
+ },
+ [&] (const auto&) -> optional<std::unique_ptr<Expression>> {
+ assert(false); // No properties use this type.
+ return {};
+ }
+ );
+ }
+
auto stopsValue = objectMember(value, "stops");
if (!stopsValue) {
err = { "function value must specify stops" };
@@ -636,62 +592,73 @@ optional<std::unique_ptr<Expression>> convertCompositeFunctionToExpression(type:
const auto& stop = arrayMember(first, 0);
if (!isObject(stop)) {
- err = { "stop must be an object" };
- return {};
- }
-
- auto sourceValue = objectMember(stop, "value");
- if (!sourceValue) {
- err = { "stop must specify value" };
- return {};
- }
-
- if (toBool(*sourceValue)) {
- switch (functionType(type, value)) {
- case FunctionType::Categorical:
- return composite<bool>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<bool, std::unique_ptr<Expression>> stops) {
- return categorical<bool>(type_, property, std::move(stops));
- });
- default:
- err = { "unsupported function type" };
- return {};
- }
- }
-
- if (toNumber(*sourceValue)) {
- switch (functionType(type, value)) {
+ // Source function.
+ switch (functionType) {
case FunctionType::Interval:
- return composite<double>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<double, std::unique_ptr<Expression>> stops) {
- return step(type_, number(get(literal(property))), std::move(stops));
- });
+ return convertIntervalFunction(type, value, err, number(get(literal(*property))));
case FunctionType::Exponential:
- return composite<double>(type, value, err, [] (type::Type type_, double base, const std::string& property, std::map<double, std::unique_ptr<Expression>> stops) {
- return interpolate(type_, exponential(base), number(get(literal(property))), std::move(stops));
- });
+ return convertExponentialFunction(type, value, err, number(get(literal(*property))));
case FunctionType::Categorical:
- return composite<int64_t>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<int64_t, std::unique_ptr<Expression>> stops) {
- return categorical<int64_t>(type_, property, std::move(stops));
- });
+ return convertCategoricalFunction(type, value, err, *property);
default:
err = { "unsupported function type" };
return {};
}
- }
-
- if (toString(*sourceValue)) {
- switch (functionType(type, value)) {
- case FunctionType::Categorical:
- return composite<std::string>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<std::string, std::unique_ptr<Expression>> stops) {
- return categorical<std::string>(type_, property, std::move(stops));
- });
- default:
- err = { "unsupported function type" };
+ } else {
+ // Composite function.
+ auto sourceValue = objectMember(stop, "value");
+ if (!sourceValue) {
+ err = { "stop must specify value" };
return {};
}
- }
- err = { "stop domain value must be a number, string, or boolean" };
- return {};
+ if (toBool(*sourceValue)) {
+ switch (functionType) {
+ case FunctionType::Categorical:
+ return composite<bool>(type, value, err, [&] (type::Type type_, double, std::map<bool, std::unique_ptr<Expression>> stops) {
+ return categorical<bool>(type_, *property, std::move(stops));
+ });
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ if (toNumber(*sourceValue)) {
+ switch (functionType) {
+ case FunctionType::Interval:
+ return composite<double>(type, value, err, [&] (type::Type type_, double, std::map<double, std::unique_ptr<Expression>> stops) {
+ return step(type_, number(get(literal(*property))), std::move(stops));
+ });
+ case FunctionType::Exponential:
+ return composite<double>(type, value, err, [&] (type::Type type_, double base, std::map<double, std::unique_ptr<Expression>> stops) {
+ return interpolate(type_, exponential(base), number(get(literal(*property))), std::move(stops));
+ });
+ case FunctionType::Categorical:
+ return composite<int64_t>(type, value, err, [&] (type::Type type_, double, std::map<int64_t, std::unique_ptr<Expression>> stops) {
+ return categorical<int64_t>(type_, *property, std::move(stops));
+ });
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ if (toString(*sourceValue)) {
+ switch (functionType) {
+ case FunctionType::Categorical:
+ return composite<std::string>(type, value, err, [&] (type::Type type_, double, std::map<std::string, std::unique_ptr<Expression>> stops) {
+ return categorical<std::string>(type_, *property, std::move(stops));
+ });
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ err = { "stop domain value must be a number, string, or boolean" };
+ return {};
+ }
}
} // namespace conversion