summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2018-06-28 08:18:23 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2018-06-28 10:00:40 -0700
commit1dd35eface06c253c6e039b49942bdeb32991839 (patch)
tree94a1cec6c0080aee3ee9b4c2de9006574483d9cf
parentb2f6acca6161e1547bd99e0fca1ce51ea7e632e9 (diff)
downloadqtlocation-mapboxgl-1dd35eface06c253c6e039b49942bdeb32991839.tar.gz
[core] Privatize Interpolate<T>
-rw-r--r--include/mbgl/style/expression/interpolate.hpp73
-rw-r--r--include/mbgl/style/function/convert.hpp59
-rw-r--r--src/mbgl/style/expression/interpolate.cpp95
3 files changed, 118 insertions, 109 deletions
diff --git a/include/mbgl/style/expression/interpolate.hpp b/include/mbgl/style/expression/interpolate.hpp
index 1a98189e29..dcdfa302ba 100644
--- a/include/mbgl/style/expression/interpolate.hpp
+++ b/include/mbgl/style/expression/interpolate.hpp
@@ -79,74 +79,11 @@ protected:
const std::map<double, std::unique_ptr<Expression>> stops;
};
-template <typename T>
-class Interpolate : public InterpolateBase {
-public:
- Interpolate(type::Type type_,
- Interpolator interpolator_,
- std::unique_ptr<Expression> input_,
- std::map<double, std::unique_ptr<Expression>> stops_
- ) : InterpolateBase(std::move(type_), std::move(interpolator_), std::move(input_), std::move(stops_))
- {
- static_assert(util::Interpolatable<T>::value, "Interpolate expression requires an interpolatable value type.");
- }
-
- EvaluationResult evaluate(const EvaluationContext& params) const override {
- const EvaluationResult evaluatedInput = input->evaluate(params);
- if (!evaluatedInput) {
- return evaluatedInput.error();
- }
-
- float x = *fromExpressionValue<float>(*evaluatedInput);
- if (std::isnan(x)) {
- return EvaluationError { "Input is not a number." };
- }
-
- if (stops.empty()) {
- return EvaluationError { "No stops in exponential curve." };
- }
-
- auto it = stops.upper_bound(x);
- if (it == stops.end()) {
- return stops.rbegin()->second->evaluate(params);
- } else if (it == stops.begin()) {
- return stops.begin()->second->evaluate(params);
- } else {
- float t = interpolationFactor({ std::prev(it)->first, it->first }, x);
-
- if (t == 0.0f) {
- return std::prev(it)->second->evaluate(params);
- }
- if (t == 1.0f) {
- return it->second->evaluate(params);
- }
-
- EvaluationResult lower = std::prev(it)->second->evaluate(params);
- if (!lower) {
- return lower.error();
- }
- EvaluationResult upper = it->second->evaluate(params);
- if (!upper) {
- return upper.error();
- }
-
- if (!lower->is<T>()) {
- return EvaluationError {
- "Expected value to be of type " + toString(valueTypeToExpressionType<T>()) +
- ", but found " + toString(typeOf(*lower)) + " instead."
- };
- }
-
- if (!upper->is<T>()) {
- return EvaluationError {
- "Expected value to be of type " + toString(valueTypeToExpressionType<T>()) +
- ", but found " + toString(typeOf(*upper)) + " instead."
- };
- }
- return util::interpolate(lower->get<T>(), upper->get<T>(), t);
- }
- }
-};
+ParseResult createInterpolate(type::Type type,
+ Interpolator interpolator,
+ std::unique_ptr<Expression> input,
+ std::map<double, std::unique_ptr<Expression>> stops,
+ ParsingContext& ctx);
} // namespace expression
} // namespace style
diff --git a/include/mbgl/style/function/convert.hpp b/include/mbgl/style/function/convert.hpp
index b34071d219..e5a5808e1d 100644
--- a/include/mbgl/style/function/convert.hpp
+++ b/include/mbgl/style/function/convert.hpp
@@ -91,22 +91,6 @@ struct Convert {
return std::make_unique<detail::ErrorExpression>(message);
}
- template <typename OutputType>
- static ParseResult makeInterpolate(type::Type type,
- std::unique_ptr<Expression> input,
- std::map<double, std::unique_ptr<Expression>> convertedStops,
- Interpolator interpolator)
- {
- ParseResult curve = ParseResult(std::make_unique<Interpolate<OutputType>>(
- std::move(type),
- std::move(interpolator),
- std::move(input),
- std::move(convertedStops)
- ));
- assert(curve);
- return std::move(*curve);
- }
-
template <typename Key>
static ParseResult makeMatch(type::Type type,
std::unique_ptr<Expression> input,
@@ -191,11 +175,12 @@ struct Convert {
template <typename T>
static std::unique_ptr<Expression> toExpression(const ExponentialStops<T>& stops)
{
- ParseResult e = makeInterpolate<typename ValueConverter<T>::ExpressionType>(
- valueTypeToExpressionType<T>(),
- makeZoom(),
- convertStops(stops.stops),
- ExponentialInterpolator(stops.base));
+ ParsingContext ctx;
+ ParseResult e = createInterpolate(valueTypeToExpressionType<T>(),
+ ExponentialInterpolator(stops.base),
+ makeZoom(),
+ convertStops(stops.stops),
+ ctx);
assert(e);
return std::move(*e);
}
@@ -214,10 +199,12 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const ExponentialStops<T>& stops)
{
- ParseResult e = makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeGet(type::Number, property),
- convertStops(stops.stops),
- ExponentialInterpolator(stops.base));
+ ParsingContext ctx;
+ ParseResult e = createInterpolate(valueTypeToExpressionType<T>(),
+ ExponentialInterpolator(stops.base),
+ makeGet(type::Number, property),
+ convertStops(stops.stops),
+ ctx);
assert(e);
return std::move(*e);
}
@@ -247,10 +234,12 @@ struct Convert {
template <typename T>
static typename std::enable_if_t<util::Interpolatable<T>::value,
ParseResult> makeZoomCurve(std::map<double, std::unique_ptr<Expression>> stops) {
- return makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(),
- std::move(stops),
- ExponentialInterpolator(1.0));
+ ParsingContext ctx;
+ return createInterpolate(valueTypeToExpressionType<T>(),
+ ExponentialInterpolator(1.0),
+ makeZoom(),
+ std::move(stops),
+ ctx);
}
// non-interpolatable zoom curve
@@ -264,13 +253,15 @@ struct Convert {
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) {
- std::unique_ptr<Expression> get = makeGet(type::Number, property);
- ParseResult innerInterpolate = makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- std::move(get),
- convertStops(stop.second),
- ExponentialInterpolator(stops.base));
+ 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));
}
diff --git a/src/mbgl/style/expression/interpolate.cpp b/src/mbgl/style/expression/interpolate.cpp
index 776fe1f177..e5f99f1117 100644
--- a/src/mbgl/style/expression/interpolate.cpp
+++ b/src/mbgl/style/expression/interpolate.cpp
@@ -7,6 +7,75 @@ namespace expression {
using namespace mbgl::style::conversion;
+template <typename T>
+class Interpolate : public InterpolateBase {
+public:
+ Interpolate(type::Type type_,
+ Interpolator interpolator_,
+ std::unique_ptr<Expression> input_,
+ std::map<double, std::unique_ptr<Expression>> stops_
+ ) : InterpolateBase(std::move(type_), std::move(interpolator_), std::move(input_), std::move(stops_))
+ {
+ static_assert(util::Interpolatable<T>::value, "Interpolate expression requires an interpolatable value type.");
+ }
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override {
+ const EvaluationResult evaluatedInput = input->evaluate(params);
+ if (!evaluatedInput) {
+ return evaluatedInput.error();
+ }
+
+ float x = *fromExpressionValue<float>(*evaluatedInput);
+ if (std::isnan(x)) {
+ return EvaluationError { "Input is not a number." };
+ }
+
+ if (stops.empty()) {
+ return EvaluationError { "No stops in exponential curve." };
+ }
+
+ auto it = stops.upper_bound(x);
+ if (it == stops.end()) {
+ return stops.rbegin()->second->evaluate(params);
+ } else if (it == stops.begin()) {
+ return stops.begin()->second->evaluate(params);
+ } else {
+ float t = interpolationFactor({ std::prev(it)->first, it->first }, x);
+
+ if (t == 0.0f) {
+ return std::prev(it)->second->evaluate(params);
+ }
+ if (t == 1.0f) {
+ return it->second->evaluate(params);
+ }
+
+ EvaluationResult lower = std::prev(it)->second->evaluate(params);
+ if (!lower) {
+ return lower.error();
+ }
+ EvaluationResult upper = it->second->evaluate(params);
+ if (!upper) {
+ return upper.error();
+ }
+
+ if (!lower->is<T>()) {
+ return EvaluationError {
+ "Expected value to be of type " + toString(valueTypeToExpressionType<T>()) +
+ ", but found " + toString(typeOf(*lower)) + " instead."
+ };
+ }
+
+ if (!upper->is<T>()) {
+ return EvaluationError {
+ "Expected value to be of type " + toString(valueTypeToExpressionType<T>()) +
+ ", but found " + toString(typeOf(*upper)) + " instead."
+ };
+ }
+ return util::interpolate(lower->get<T>(), upper->get<T>(), t);
+ }
+ }
+};
+
ParseResult parseInterpolate(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
@@ -151,29 +220,41 @@ ParseResult parseInterpolate(const Convertible& value, ParsingContext& ctx) {
}
assert(outputType);
-
- return outputType->match(
+
+ return createInterpolate(*outputType,
+ *interpolator,
+ std::move(*input),
+ std::move(stops),
+ ctx);
+}
+
+ParseResult createInterpolate(type::Type type,
+ Interpolator interpolator,
+ std::unique_ptr<Expression> input,
+ std::map<double, std::unique_ptr<Expression>> stops,
+ ParsingContext& ctx) {
+ return type.match(
[&](const type::NumberType&) -> ParseResult {
return ParseResult(std::make_unique<Interpolate<double>>(
- *outputType, *interpolator, std::move(*input), std::move(stops)
+ type, interpolator, std::move(input), std::move(stops)
));
},
[&](const type::ColorType&) -> ParseResult {
return ParseResult(std::make_unique<Interpolate<Color>>(
- *outputType, *interpolator, std::move(*input), std::move(stops)
+ type, interpolator, std::move(input), std::move(stops)
));
},
[&](const type::Array& arrayType) -> ParseResult {
if (arrayType.itemType != type::Number || !arrayType.N) {
- ctx.error("Type " + toString(*outputType) + " is not interpolatable.");
+ ctx.error("Type " + toString(type) + " is not interpolatable.");
return ParseResult();
}
return ParseResult(std::make_unique<Interpolate<std::vector<Value>>>(
- *outputType, *interpolator, std::move(*input), std::move(stops)
+ type, interpolator, std::move(input), std::move(stops)
));
},
[&](const auto&) {
- ctx.error("Type " + toString(*outputType) + " is not interpolatable.");
+ ctx.error("Type " + toString(type) + " is not interpolatable.");
return ParseResult();
}
);