summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnand Thakker <github@anandthakker.net>2017-11-01 22:36:24 -0400
committerAnand Thakker <github@anandthakker.net>2017-11-02 08:44:06 -0400
commitac86e41f95b7578eb3135b17f15358e27b97e7b2 (patch)
tree74514d1de158b6d33df9821635422e26e3463dd6
parentfb1ecbfa1381c73d48dd766580c00a8c96e653e0 (diff)
downloadqtlocation-mapboxgl-ac86e41f95b7578eb3135b17f15358e27b97e7b2.tar.gz
Split "curve" into "step" and "interpolate" expressions
-rw-r--r--cmake/core-files.cmake9
-rw-r--r--include/mbgl/style/conversion/data_driven_property_value.hpp6
-rw-r--r--include/mbgl/style/expression/find_zoom_curve.hpp50
-rw-r--r--include/mbgl/style/expression/get_covering_stops.hpp18
-rw-r--r--include/mbgl/style/expression/interpolate.hpp (renamed from include/mbgl/style/expression/curve.hpp)81
-rw-r--r--include/mbgl/style/expression/step.hpp43
-rw-r--r--include/mbgl/style/function/camera_function.hpp23
-rw-r--r--include/mbgl/style/function/composite_function.hpp23
-rw-r--r--include/mbgl/style/function/convert.hpp102
-rw-r--r--include/mbgl/style/function/source_function.hpp6
m---------mapbox-gl-js0
-rw-r--r--platform/node/test/expression.test.js3
-rw-r--r--platform/node/test/ignores.json2
-rw-r--r--src/mbgl/style/expression/get_covering_stops.cpp26
-rw-r--r--src/mbgl/style/expression/interpolate.cpp (renamed from src/mbgl/style/expression/curve.cpp)100
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp6
-rw-r--r--src/mbgl/style/expression/step.cpp147
-rw-r--r--test/fixtures/style_parser/expressions.info.json4
-rw-r--r--test/fixtures/style_parser/expressions.style.json4
-rw-r--r--test/style/conversion/function.test.cpp12
20 files changed, 440 insertions, 225 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 8d30de0a17..9a9236d363 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -404,14 +404,17 @@ set(MBGL_CORE_FILES
include/mbgl/style/expression/coalesce.hpp
include/mbgl/style/expression/coercion.hpp
include/mbgl/style/expression/compound_expression.hpp
- include/mbgl/style/expression/curve.hpp
include/mbgl/style/expression/expression.hpp
+ include/mbgl/style/expression/find_zoom_curve.hpp
+ include/mbgl/style/expression/get_covering_stops.hpp
+ include/mbgl/style/expression/interpolate.hpp
include/mbgl/style/expression/is_constant.hpp
include/mbgl/style/expression/is_expression.hpp
include/mbgl/style/expression/let.hpp
include/mbgl/style/expression/literal.hpp
include/mbgl/style/expression/match.hpp
include/mbgl/style/expression/parsing_context.hpp
+ include/mbgl/style/expression/step.hpp
include/mbgl/style/expression/type.hpp
include/mbgl/style/expression/value.hpp
src/mbgl/style/expression/array_assertion.cpp
@@ -423,13 +426,15 @@ set(MBGL_CORE_FILES
src/mbgl/style/expression/coalesce.cpp
src/mbgl/style/expression/coercion.cpp
src/mbgl/style/expression/compound_expression.cpp
- src/mbgl/style/expression/curve.cpp
+ src/mbgl/style/expression/get_covering_stops.cpp
+ src/mbgl/style/expression/interpolate.cpp
src/mbgl/style/expression/is_constant.cpp
src/mbgl/style/expression/is_expression.cpp
src/mbgl/style/expression/let.cpp
src/mbgl/style/expression/literal.cpp
src/mbgl/style/expression/match.cpp
src/mbgl/style/expression/parsing_context.cpp
+ src/mbgl/style/expression/step.cpp
src/mbgl/style/expression/util.cpp
src/mbgl/style/expression/util.hpp
src/mbgl/style/expression/value.cpp
diff --git a/include/mbgl/style/conversion/data_driven_property_value.hpp b/include/mbgl/style/conversion/data_driven_property_value.hpp
index 2fc98494ac..7a0ac56ff4 100644
--- a/include/mbgl/style/conversion/data_driven_property_value.hpp
+++ b/include/mbgl/style/conversion/data_driven_property_value.hpp
@@ -6,8 +6,8 @@
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/expression.hpp>
#include <mbgl/style/expression/is_expression.hpp>
-#include <mbgl/style/expression/curve.hpp>
#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <unordered_set>
@@ -34,8 +34,8 @@ struct Converter<DataDrivenPropertyValue<T>> {
bool zoomConstant = isZoomConstant(expression->get());
- if (!zoomConstant && !CameraFunction<T>::Curve::findZoomCurve(expression->get())) {
- error = { R"("zoom" expression may only be used as input to a top-level "curve" expression.)" };
+ if (!zoomConstant && !findZoomCurve<typename CameraFunction<T>::ExpressionType>(expression->get())) {
+ error = { R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)" };
return {};
}
diff --git a/include/mbgl/style/expression/find_zoom_curve.hpp b/include/mbgl/style/expression/find_zoom_curve.hpp
new file mode 100644
index 0000000000..81a4951bf5
--- /dev/null
+++ b/include/mbgl/style/expression/find_zoom_curve.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/let.hpp>
+#include <mbgl/style/expression/coalesce.hpp>
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/optional.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+template <typename T>
+optional<variant<Interpolate<T>*, Step*>> findZoomCurve(expression::Expression* e) {
+ if (auto curve = dynamic_cast<Interpolate<T>*>(e)) {
+ auto z = dynamic_cast<CompoundExpressionBase*>(curve->getInput().get());
+ if (z && z->getName() == "zoom") {
+ return {curve};
+ } else {
+ return optional<variant<Interpolate<T>*, Step*>>();
+ }
+ } else if (auto step = dynamic_cast<Step*>(e)) {
+ auto z = dynamic_cast<CompoundExpressionBase*>(step->getInput().get());
+ if (z && z->getName() == "zoom") {
+ return {step};
+ } else {
+ return optional<variant<Interpolate<T>*, Step*>>();
+ }
+ } else if (auto let = dynamic_cast<Let*>(e)) {
+ return findZoomCurve<T>(let->getResult());
+ } else if (auto coalesce = dynamic_cast<Coalesce*>(e)) {
+ std::size_t length = coalesce->getLength();
+ for (std::size_t i = 0; i < length; i++) {
+ optional<variant<Interpolate<T>*, Step*>> childInterpolate = findZoomCurve<T>(coalesce->getChild(i));
+ if (!childInterpolate) {
+ continue;
+ } else {
+ return childInterpolate;
+ }
+ }
+ }
+
+ return optional<variant<Interpolate<T>*, Step*>>();
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/get_covering_stops.hpp b/include/mbgl/style/expression/get_covering_stops.hpp
new file mode 100644
index 0000000000..157aefe7bc
--- /dev/null
+++ b/include/mbgl/style/expression/get_covering_stops.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/util/range.hpp>
+#include <memory>
+#include <map>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+// Return the smallest range of stops that covers the interval [lower, upper]
+Range<float> getCoveringStops(const std::map<double, std::unique_ptr<Expression>>& stops,
+ const double lower, const double upper);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/curve.hpp b/include/mbgl/style/expression/interpolate.hpp
index c1d0eb6ac9..8d11bbcb05 100644
--- a/include/mbgl/style/expression/curve.hpp
+++ b/include/mbgl/style/expression/interpolate.hpp
@@ -2,9 +2,7 @@
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
-#include <mbgl/style/expression/compound_expression.hpp>
-#include <mbgl/style/expression/let.hpp>
-#include <mbgl/style/expression/coalesce.hpp>
+#include <mbgl/style/expression/get_covering_stops.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/interpolate.hpp>
@@ -19,13 +17,6 @@ namespace mbgl {
namespace style {
namespace expression {
-class StepInterpolator {
-public:
- double interpolationFactor(const Range<double>&, const double) const {
- return 0;
- }
-
-};
class ExponentialInterpolator {
public:
@@ -55,20 +46,15 @@ public:
};
-ParseResult parseCurve(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+ParseResult parseInterpolate(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
template <typename T>
-class Curve : public Expression {
+class Interpolate : public Expression {
public:
- using Interpolator = std::conditional_t<
- util::Interpolatable<T>::value,
- variant<StepInterpolator,
- ExponentialInterpolator,
- CubicBezierInterpolator>,
- variant<StepInterpolator>>;
+ using Interpolator = variant<ExponentialInterpolator, CubicBezierInterpolator>;
- Curve(const type::Type& type_,
+ Interpolate(const type::Type& type_,
Interpolator interpolator_,
std::unique_ptr<Expression> input_,
std::map<double, std::unique_ptr<Expression>> stops_
@@ -76,7 +62,9 @@ public:
interpolator(std::move(interpolator_)),
input(std::move(input_)),
stops(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);
@@ -123,46 +111,11 @@ public:
}
}
- static optional<Curve*> findZoomCurve(expression::Expression* e) {
- if (auto curve = dynamic_cast<Curve*>(e)) {
- auto z = dynamic_cast<CompoundExpressionBase*>(curve->input.get());
- if (z && z->getName() == "zoom") {
- return {curve};
- } else {
- return optional<Curve*>();
- }
- } else if (auto let = dynamic_cast<Let*>(e)) {
- return findZoomCurve(let->getResult());
- } else if (auto coalesce = dynamic_cast<Coalesce*>(e)) {
- std::size_t length = coalesce->getLength();
- for (std::size_t i = 0; i < length; i++) {
- optional<Curve*> childCurve = findZoomCurve(coalesce->getChild(i));
- if (!childCurve) {
- continue;
- } else {
- return childCurve;
- }
- }
- }
-
- return optional<Curve*>();
- }
+ const std::unique_ptr<Expression>& getInput() const { return input; }
// Return the smallest range of stops that covers the interval [lower, upper]
Range<float> getCoveringStops(const double lower, const double upper) const {
- assert(!stops.empty());
- auto minIt = stops.lower_bound(lower);
- auto maxIt = stops.lower_bound(upper);
-
- // lower_bound yields first element >= lowerZoom, but we want the *last*
- // element <= lowerZoom, so if we found a stop > lowerZoom, back up by one.
- if (minIt != stops.begin() && minIt != stops.end() && minIt->first > lower) {
- minIt--;
- }
- return Range<float> {
- static_cast<float>(minIt == stops.end() ? stops.rbegin()->first : minIt->first),
- static_cast<float>(maxIt == stops.end() ? stops.rbegin()->first : maxIt->first)
- };
+ return ::mbgl::style::expression::getCoveringStops(stops, lower, upper);
}
double interpolationFactor(const Range<double>& inputLevels, const double inputValue) const {
@@ -172,18 +125,7 @@ public:
}
private:
- template <typename OutputType = T>
- static EvaluationResult interpolate(const Range<Value>&, const double,
- typename std::enable_if<!util::Interpolatable<OutputType>::value>::type* = nullptr) {
- // Assume that Curve::evaluate() will always short circuit due to
- // interpolationFactor always returning 0.
- assert(false);
- return Null;
- }
-
- template <typename OutputType = T>
- static EvaluationResult interpolate(const Range<Value>& outputs, const double t,
- typename std::enable_if<util::Interpolatable<OutputType>::value>::type* = nullptr) {
+ static EvaluationResult interpolate(const Range<Value>& outputs, const double t) {
optional<T> lower = fromExpressionValue<T>(outputs.min);
if (!lower) {
// TODO - refactor fromExpressionValue to return EvaluationResult<T> so as to
@@ -204,7 +146,6 @@ private:
return toExpressionValue(result);
}
-
const Interpolator interpolator;
const std::unique_ptr<Expression> input;
const std::map<double, std::unique_ptr<Expression>> stops;
diff --git a/include/mbgl/style/expression/step.hpp b/include/mbgl/style/expression/step.hpp
new file mode 100644
index 0000000000..81e1aef4e9
--- /dev/null
+++ b/include/mbgl/style/expression/step.hpp
@@ -0,0 +1,43 @@
+
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <mbgl/util/range.hpp>
+
+#include <memory>
+#include <map>
+
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Step : public Expression {
+public:
+ Step(const type::Type& type_,
+ std::unique_ptr<Expression> input_,
+ std::map<double, std::unique_ptr<Expression>> stops_
+ ) : Expression(type_),
+ input(std::move(input_)),
+ stops(std::move(stops_))
+ {}
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression*)>& visit) const override;
+
+ const std::unique_ptr<Expression>& getInput() const { return input; }
+ Range<float> getCoveringStops(const double lower, const double upper) const;
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+private:
+ const std::unique_ptr<Expression> input;
+ const std::map<double, std::unique_ptr<Expression>> stops;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/camera_function.hpp b/include/mbgl/style/function/camera_function.hpp
index c44002e8c1..721d3083e1 100644
--- a/include/mbgl/style/function/camera_function.hpp
+++ b/include/mbgl/style/function/camera_function.hpp
@@ -1,7 +1,9 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/curve.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/function/convert.hpp>
@@ -17,7 +19,7 @@ namespace style {
template <class T>
class CameraFunction {
public:
- using Curve = expression::Curve<typename expression::ValueConverter<T>::ExpressionType>;
+ using ExpressionType = typename expression::ValueConverter<T>::ExpressionType;
using Stops = std::conditional_t<
util::Interpolatable<T>::value,
@@ -29,7 +31,7 @@ public:
CameraFunction(std::unique_ptr<expression::Expression> expression_)
: expression(std::move(expression_)),
- zoomCurve(*Curve::findZoomCurve(expression.get()))
+ zoomCurve(*expression::findZoomCurve<ExpressionType>(expression.get()))
{
assert(!isZoomConstant(expression.get()));
assert(isFeatureConstant(expression.get()));
@@ -40,7 +42,7 @@ public:
expression(stops.match([&] (const auto& s) {
return expression::Convert::toExpression(s);
})),
- zoomCurve(*Curve::findZoomCurve(expression.get()))
+ zoomCurve(*expression::findZoomCurve<ExpressionType>(expression.get()))
{}
T evaluate(float zoom) const {
@@ -53,11 +55,18 @@ public:
}
float interpolationFactor(const Range<float>& inputLevels, const float inputValue) const {
- return zoomCurve->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
+ return zoomCurve.match(
+ [&](expression::Interpolate<ExpressionType>* z) {
+ return z->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
+ },
+ [&](expression::Step*) { return 0.0f; }
+ );
}
Range<float> getCoveringStops(const float lower, const float upper) const {
- return zoomCurve->getCoveringStops(lower, upper);
+ return zoomCurve.match(
+ [&](auto z) { return z->getCoveringStops(lower, upper); }
+ );
}
friend bool operator==(const CameraFunction& lhs,
@@ -72,7 +81,7 @@ public:
private:
std::shared_ptr<expression::Expression> expression;
- const Curve* zoomCurve;
+ const variant<expression::Interpolate<ExpressionType>*, expression::Step*> zoomCurve;
};
} // namespace style
diff --git a/include/mbgl/style/function/composite_function.hpp b/include/mbgl/style/function/composite_function.hpp
index ead31294bb..5c91f1d6c9 100644
--- a/include/mbgl/style/function/composite_function.hpp
+++ b/include/mbgl/style/function/composite_function.hpp
@@ -1,7 +1,9 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/curve.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/function/convert.hpp>
@@ -48,11 +50,11 @@ public:
CompositeIntervalStops<T>,
CompositeCategoricalStops<T>>>;
- using Curve = expression::Curve<typename expression::ValueConverter<T>::ExpressionType>;
+ using ExpressionType = typename expression::ValueConverter<T>::ExpressionType;
CompositeFunction(std::unique_ptr<expression::Expression> expression_)
: expression(std::move(expression_)),
- zoomCurve(*Curve::findZoomCurve(expression.get()))
+ zoomCurve(*expression::findZoomCurve<ExpressionType>(expression.get()))
{
assert(!isZoomConstant(expression.get()));
assert(!isFeatureConstant(expression.get()));
@@ -65,7 +67,7 @@ public:
expression(stops.match([&] (const auto& s) {
return expression::Convert::toExpression(property, s);
})),
- zoomCurve(*Curve::findZoomCurve(expression.get()))
+ zoomCurve(*expression::findZoomCurve<ExpressionType>(expression.get()))
{}
// Return the range obtained by evaluating the function at each of the zoom levels in zoomRange
@@ -88,11 +90,18 @@ public:
}
float interpolationFactor(const Range<float>& inputLevels, const float inputValue) const {
- return zoomCurve->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
+ return zoomCurve.match(
+ [&](expression::Interpolate<ExpressionType>* z) {
+ return z->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
+ },
+ [&](expression::Step*) { return 0.0f; }
+ );
}
Range<float> getCoveringStops(const float lower, const float upper) const {
- return zoomCurve->getCoveringStops(lower, upper);
+ return zoomCurve.match(
+ [&](auto z) { return z->getCoveringStops(lower, upper); }
+ );
}
friend bool operator==(const CompositeFunction& lhs,
@@ -108,7 +117,7 @@ public:
private:
std::shared_ptr<expression::Expression> expression;
- const Curve* zoomCurve;
+ const variant<expression::Interpolate<ExpressionType>*, expression::Step*> zoomCurve;
};
} // namespace style
diff --git a/include/mbgl/style/function/convert.hpp b/include/mbgl/style/function/convert.hpp
index e07b4038ea..82537f5bfa 100644
--- a/include/mbgl/style/function/convert.hpp
+++ b/include/mbgl/style/function/convert.hpp
@@ -6,10 +6,11 @@
#include <mbgl/style/expression/coalesce.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/coercion.hpp>
-#include <mbgl/style/expression/curve.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>
@@ -82,12 +83,12 @@ struct Convert {
}
template <typename OutputType>
- static ParseResult makeCurve(type::Type type,
+ static ParseResult makeInterpolate(type::Type type,
std::unique_ptr<Expression> input,
std::map<double, std::unique_ptr<Expression>> convertedStops,
- typename Curve<OutputType>::Interpolator interpolator)
+ typename Interpolate<OutputType>::Interpolator interpolator)
{
- ParseResult curve = ParseResult(std::make_unique<Curve<OutputType>>(
+ ParseResult curve = ParseResult(std::make_unique<Interpolate<OutputType>>(
std::move(type),
std::move(interpolator),
std::move(input),
@@ -181,7 +182,7 @@ struct Convert {
template <typename T>
static std::unique_ptr<Expression> toExpression(const ExponentialStops<T>& stops)
{
- ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(
+ ParseResult e = makeInterpolate<typename ValueConverter<T>::ExpressionType>(
valueTypeToExpressionType<T>(),
makeZoom(),
convertStops(stops.stops),
@@ -193,10 +194,9 @@ struct Convert {
template <typename T>
static std::unique_ptr<Expression> toExpression(const IntervalStops<T>& stops)
{
- ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(),
- convertStops(stops.stops),
- StepInterpolator());
+ ParseResult e(std::make_unique<Step>(valueTypeToExpressionType<T>(),
+ makeZoom(),
+ convertStops(stops.stops)));
assert(e);
return std::move(*e);
}
@@ -205,7 +205,7 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const ExponentialStops<T>& stops)
{
- ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
+ ParseResult e = makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
makeGet(type::Number, property),
convertStops(stops.stops),
ExponentialInterpolator(stops.base));
@@ -218,10 +218,9 @@ struct Convert {
const IntervalStops<T>& stops)
{
std::unique_ptr<Expression> get = makeGet(type::Number, property);
- ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- std::move(get),
- convertStops(stops.stops),
- StepInterpolator());
+ ParseResult e(std::make_unique<Step>(valueTypeToExpressionType<T>(),
+ std::move(get),
+ convertStops(stops.stops)));
assert(e);
return std::move(*e);
}
@@ -235,17 +234,23 @@ struct Convert {
return std::move(*expr);
}
+ // interpolatable zoom curve
template <typename T>
- static typename Curve<std::enable_if_t<util::Interpolatable<T>::value, T>>::Interpolator zoomInterpolator() {
- return ExponentialInterpolator(1.0);
+ 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));
}
+ // non-interpolatable zoom curve
template <typename T>
- static typename Curve<std::enable_if_t<!util::Interpolatable<T>::value, T>>::Interpolator zoomInterpolator() {
- return StepInterpolator();
+ 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)
@@ -253,19 +258,17 @@ struct Convert {
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 innerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
+ ParseResult innerInterpolate = makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
std::move(get),
convertStops(stop.second),
ExponentialInterpolator(stops.base));
- assert(innerCurve);
- outerStops.emplace(stop.first, std::move(*innerCurve));
+ assert(innerInterpolate);
+ outerStops.emplace(stop.first, std::move(*innerInterpolate));
}
- ParseResult outerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(),
- std::move(outerStops),
- zoomInterpolator<T>());
- assert(outerCurve);
- return std::move(*outerCurve);
+
+ ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops));
+ assert(zoomCurve);
+ return std::move(*zoomCurve);
}
template <typename T>
@@ -275,19 +278,16 @@ struct Convert {
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 innerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- std::move(get),
- convertStops(stop.second),
- StepInterpolator());
- assert(innerCurve);
- outerStops.emplace(stop.first, std::move(*innerCurve));
+ ParseResult innerInterpolate(std::make_unique<Step>(valueTypeToExpressionType<T>(),
+ std::move(get),
+ convertStops(stop.second)));
+ assert(innerInterpolate);
+ outerStops.emplace(stop.first, std::move(*innerInterpolate));
}
- ParseResult outerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(),
- std::move(outerStops),
- zoomInterpolator<T>());
- assert(outerCurve);
- return std::move(*outerCurve);
+
+ ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops));
+ assert(zoomCurve);
+ return std::move(*zoomCurve);
}
template <typename T>
@@ -296,24 +296,20 @@ struct Convert {
{
std::map<double, std::unique_ptr<Expression>> outerStops;
for (const std::pair<float, std::map<CategoricalValue, T>>& stop : stops.stops) {
- ParseResult innerCurve = fromCategoricalStops(stop.second, property);
- assert(innerCurve);
- outerStops.emplace(stop.first, std::move(*innerCurve));
+ ParseResult innerInterpolate = fromCategoricalStops(stop.second, property);
+ assert(innerInterpolate);
+ outerStops.emplace(stop.first, std::move(*innerInterpolate));
}
- ParseResult outerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(),
- std::move(outerStops),
- zoomInterpolator<T>());
- assert(outerCurve);
- return std::move(*outerCurve);
+
+ 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>&)
+ static std::unique_ptr<Expression> fromIdentityFunction(type::Type type, const std::string& property)
{
- std::unique_ptr<Expression> input = valueTypeToExpressionType<T>().match(
+ std::unique_ptr<Expression> input = type.match(
[&] (const type::StringType&) {
return makeGet(type::String, property);
},
diff --git a/include/mbgl/style/function/source_function.hpp b/include/mbgl/style/function/source_function.hpp
index 6b3dfb449e..40e0de737e 100644
--- a/include/mbgl/style/function/source_function.hpp
+++ b/include/mbgl/style/function/source_function.hpp
@@ -40,8 +40,10 @@ public:
: property(std::move(property_)),
stops(std::move(stops_)),
defaultValue(std::move(defaultValue_)),
- expression(stops.match([&] (const auto& s) {
- return expression::Convert::toExpression(property, s);
+ expression(stops.match([&] (const IdentityStops<T>&) {
+ return expression::Convert::fromIdentityFunction(expression::valueTypeToExpressionType<T>(), property);
+ }, [&] (const auto& s) {
+ return expression::Convert::toExpression(property, s);
}))
{}
diff --git a/mapbox-gl-js b/mapbox-gl-js
-Subproject e505df99a4559c6c5109247026f6b02ab203767
+Subproject 575e42d332fa26b9f7574047e3c67a44bf5ca87
diff --git a/platform/node/test/expression.test.js b/platform/node/test/expression.test.js
index 6ffea28d40..aac039ce18 100644
--- a/platform/node/test/expression.test.js
+++ b/platform/node/test/expression.test.js
@@ -2,6 +2,7 @@
var suite = require('../../../mapbox-gl-js/test/integration').expression;
var mbgl = require('../index');
+var ignores = require('./ignores.json');
var tests;
@@ -29,7 +30,7 @@ function getExpectedType(spec) {
return typeof spec.type === 'string' ? {kind: spec.type} : null;
}
-suite.run('native', {tests: tests}, (fixture) => {
+suite.run('native', {ignores: ignores, tests: tests}, (fixture) => {
const compiled = {};
const result = {
compiled
diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json
index ef0568b369..e1a68be449 100644
--- a/platform/node/test/ignores.json
+++ b/platform/node/test/ignores.json
@@ -1,4 +1,6 @@
{
+ "expression-tests/curve/step": "https://github.com/mapbox/mapbox-gl-js/issues/5580",
+ "expression-tests/curve/interpolate": "https://github.com/mapbox/mapbox-gl-js/issues/5580",
"query-tests/circle-stroke-width/inside": "https://github.com/mapbox/mapbox-gl-native/issues/10307",
"query-tests/geometry/multilinestring": "needs investigation",
"query-tests/geometry/multipolygon": "needs investigation",
diff --git a/src/mbgl/style/expression/get_covering_stops.cpp b/src/mbgl/style/expression/get_covering_stops.cpp
new file mode 100644
index 0000000000..c9f87d93ac
--- /dev/null
+++ b/src/mbgl/style/expression/get_covering_stops.cpp
@@ -0,0 +1,26 @@
+#include <mbgl/style/expression/get_covering_stops.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+Range<float> getCoveringStops(const std::map<double, std::unique_ptr<Expression>>& stops,
+ const double lower, const double upper) {
+ assert(!stops.empty());
+ auto minIt = stops.lower_bound(lower);
+ auto maxIt = stops.lower_bound(upper);
+
+ // lower_bound yields first element >= lowerZoom, but we want the *last*
+ // element <= lowerZoom, so if we found a stop > lowerZoom, back up by one.
+ if (minIt != stops.begin() && minIt != stops.end() && minIt->first > lower) {
+ minIt--;
+ }
+ return Range<float> {
+ static_cast<float>(minIt == stops.end() ? stops.rbegin()->first : minIt->first),
+ static_cast<float>(maxIt == stops.end() ? stops.rbegin()->first : maxIt->first)
+ };
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/curve.cpp b/src/mbgl/style/expression/interpolate.cpp
index d786a147aa..c94e3ff64e 100644
--- a/src/mbgl/style/expression/curve.cpp
+++ b/src/mbgl/style/expression/interpolate.cpp
@@ -1,42 +1,36 @@
-#include <mbgl/style/expression/curve.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
namespace mbgl {
namespace style {
namespace expression {
-using Interpolator = variant<StepInterpolator,
- ExponentialInterpolator,
+using Interpolator = variant<ExponentialInterpolator,
CubicBezierInterpolator>;
using namespace mbgl::style::conversion;
-ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
+ParseResult parseInterpolate(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
auto length = arrayLength(value);
- // first parse interpolation, because further validation of the input depends upon
- // whether or not this is a step curve
if (length < 2) {
ctx.error("Expected an interpolation type expression.");
return ParseResult();
}
+
const Convertible& interp = arrayMember(value, 1);
if (!isArray(interp) || arrayLength(interp) == 0) {
ctx.error("Expected an interpolation type expression.");
return ParseResult();
}
- Interpolator interpolator;
- bool isStep = false;
+ optional<Interpolator> interpolator;
const optional<std::string> interpName = toString(arrayMember(interp, 0));
- if (interpName && *interpName == "step") {
- interpolator = StepInterpolator();
- isStep = true;
- } else if (interpName && *interpName == "linear") {
- interpolator = ExponentialInterpolator(1.0);
+ if (interpName && *interpName == "linear") {
+ interpolator = {ExponentialInterpolator(1.0)};
} else if (interpName && *interpName == "exponential") {
optional<double> base;
if (arrayLength(interp) == 2) {
@@ -46,7 +40,7 @@ ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
ctx.error("Exponential interpolation requires a numeric base.", 1, 1);
return ParseResult();
}
- interpolator = ExponentialInterpolator(*base);
+ interpolator = {ExponentialInterpolator(*base)};
} else if (interpName && *interpName == "cubic-bezier") {
optional<double> x1;
optional<double> y1;
@@ -69,31 +63,31 @@ ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
return ParseResult();
}
- interpolator = CubicBezierInterpolator(*x1, *y1, *x2, *y2);
- } else {
+ interpolator = {CubicBezierInterpolator(*x1, *y1, *x2, *y2)};
+ }
+
+ if (!interpolator) {
ctx.error("Unknown interpolation type " + (interpName ? *interpName : ""), 1, 0);
return ParseResult();
}
- std::size_t minArgs = isStep ? 5 : 4;
+ std::size_t minArgs = 4;
if (length - 1 < minArgs) {
- ctx.error("Expected at least " + std::to_string(minArgs) + " arguments, but found only " + std::to_string(length - 1) + ".");
+ ctx.error("Expected at least 4 arguments, but found only " + std::to_string(length - 1) + ".");
return ParseResult();
}
- bool parity = minArgs % 2;
- // [curve, interp, input, 2 * (n pairs)...]
- if ((length - 1) % 2 != parity) {
- ctx.error("Expected an " + std::string(parity ? "odd" : "even") + " number of arguments.");
+ // [interpolation, interp_type, input, 2 * (n pairs)...]
+ if ((length - 1) % 2 != 0) {
+ ctx.error("Expected an even number of arguments.");
return ParseResult();
}
-
ParseResult input = ctx.parse(arrayMember(value, 2), 2, {type::Number});
if (!input) {
return input;
}
-
+
std::map<double, std::unique_ptr<Expression>> stops;
optional<type::Type> outputType;
if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
@@ -102,21 +96,7 @@ ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
double previous = - std::numeric_limits<double>::infinity();
- // If this is a step curve, the definition begins with an output value rather
- // than an input level, so consume that output value before proceeding into the
- // "stops" loop below.
- if (isStep) {
- auto output = ctx.parse(arrayMember(value, 3), 3, outputType);
- if (!output) {
- return ParseResult();
- }
- if (!outputType) {
- outputType = (*output)->getType();
- }
- stops.emplace(-std::numeric_limits<double>::infinity(), std::move(*output));
- }
-
- for (std::size_t i = isStep ? 4 : 3; i + 1 < length; i += 2) {
+ for (std::size_t i = 3; i + 1 < length; i += 2) {
const optional<mbgl::Value> labelValue = toValue(arrayMember(value, i));
optional<double> label;
optional<std::string> labelError;
@@ -148,14 +128,14 @@ ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
}
if (!label) {
ctx.error(labelError ? *labelError :
- R"(Input/output pairs for "curve" expressions must be defined using literal numeric values (not computed expressions) for the input values.)",
+ R"(Input/output pairs for "interpolate" expressions must be defined using literal numeric values (not computed expressions) for the input values.)",
i);
return ParseResult();
}
if (*label < previous) {
ctx.error(
- R"(Input/output pairs for "curve" expressions must be arranged with input values in strictly ascending order.)",
+ R"(Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.)",
i
);
return ParseResult();
@@ -176,7 +156,6 @@ ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
assert(outputType);
if (
- !interpolator.template is<StepInterpolator>() &&
*outputType != type::Number &&
*outputType != type::Color &&
!(
@@ -186,58 +165,43 @@ ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
)
)
{
- ctx.error("Type " + toString(*outputType) +
- " is not interpolatable, and thus cannot be used as a " +
- *interpName + " curve's output type.");
+ ctx.error("Type " + toString(*outputType) + " is not interpolatable.");
return ParseResult();
}
return outputType->match(
[&](const type::NumberType&) -> ParseResult {
- return interpolator.match([&](const auto& interpolator_) {
- return ParseResult(std::make_unique<Curve<double>>(
+ return interpolator->match([&](const auto& interpolator_) {
+ return ParseResult(std::make_unique<Interpolate<double>>(
*outputType, interpolator_, std::move(*input), std::move(stops)
));
});
},
[&](const type::ColorType&) -> ParseResult {
- return interpolator.match([&](const auto& interpolator_) {
- return ParseResult(std::make_unique<Curve<Color>>(
+ return interpolator->match([&](const auto& interpolator_) {
+ return ParseResult(std::make_unique<Interpolate<Color>>(
*outputType, interpolator_, std::move(*input), std::move(stops)
));
});
},
[&](const type::Array& arrayType) -> ParseResult {
- return interpolator.match(
- [&](const StepInterpolator& stepInterpolator) {
- return ParseResult(std::make_unique<Curve<std::vector<Value>>>(
- *outputType, stepInterpolator, std::move(*input), std::move(stops)
- ));
- },
+ return interpolator->match(
[&](const auto& continuousInterpolator) {
if (arrayType.itemType != type::Number || !arrayType.N) {
assert(false); // interpolability already checked above.
return ParseResult();
}
- return ParseResult(std::make_unique<Curve<std::vector<Value>>>(
+ return ParseResult(std::make_unique<Interpolate<std::vector<Value>>>(
*outputType, continuousInterpolator, std::move(*input), std::move(stops)
));
}
);
},
[&](const auto&) {
- // Null, Boolean, String, Object, Value output types only support step interpolation
- return interpolator.match(
- [&](const StepInterpolator& stepInterpolator) {
- return ParseResult(std::make_unique<Curve<double>>(
- *outputType, stepInterpolator, std::move(*input), std::move(stops)
- ));
- },
- [&](const auto&) {
- assert(false); // interpolability already checked above.
- return ParseResult();
- }
- );
+ // unreachable: Null, Boolean, String, Object, Value output types
+ // are not interpolatable, and interpolability was already checked above
+ assert(false);
+ return ParseResult();
}
);
}
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 18a88b8199..46d5942c70 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -13,10 +13,11 @@
#include <mbgl/style/expression/coalesce.hpp>
#include <mbgl/style/expression/coercion.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
-#include <mbgl/style/expression/curve.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/let.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/match.hpp>
+#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/conversion/get_json_type.hpp>
@@ -77,12 +78,13 @@ const ExpressionRegistry& getExpressionRegistry() {
{"boolean", Assertion::parse},
{"case", Case::parse},
{"coalesce", Coalesce::parse},
- {"curve", parseCurve},
+ {"interpolate", parseInterpolate},
{"let", Let::parse},
{"literal", Literal::parse},
{"match", parseMatch},
{"number", Assertion::parse},
{"object", Assertion::parse},
+ {"step", Step::parse},
{"string", Assertion::parse},
{"to-color", Coercion::parse},
{"to-number", Coercion::parse},
diff --git a/src/mbgl/style/expression/step.cpp b/src/mbgl/style/expression/step.cpp
new file mode 100644
index 0000000000..f180f5c587
--- /dev/null
+++ b/src/mbgl/style/expression/step.cpp
@@ -0,0 +1,147 @@
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/get_covering_stops.hpp>
+
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult Step::evaluate(const EvaluationContext& params) const {
+ const EvaluationResult evaluatedInput = input->evaluate(params);
+ if (!evaluatedInput) { return evaluatedInput.error(); }
+ float x = *fromExpressionValue<float>(*evaluatedInput);
+
+ if (stops.empty()) {
+ return EvaluationError { "No stops in step 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 {
+ return std::prev(it)->second->evaluate(params);
+ }
+}
+
+void Step::eachChild(const std::function<void(const Expression*)>& visit) const {
+ visit(input.get());
+ for (auto it = stops.begin(); it != stops.end(); it++) {
+ visit(it->second.get());
+ }
+}
+
+Range<float> Step::getCoveringStops(const double lower, const double upper) const {
+ return ::mbgl::style::expression::getCoveringStops(stops, lower, upper);
+}
+
+
+ParseResult Step::parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+
+ auto length = arrayLength(value);
+
+ if (length - 1 < 4) {
+ ctx.error("Expected at least 4 arguments, but found only " + std::to_string(length - 1) + ".");
+ return ParseResult();
+ }
+
+ // [step, input, first_output_value, 2 * (n pairs)...]
+ if ((length - 1) % 2 != 0) {
+ ctx.error("Expected an even number of arguments.");
+ return ParseResult();
+ }
+
+ ParseResult input = ctx.parse(arrayMember(value, 1), 1, {type::Number});
+ if (!input) {
+ return input;
+ }
+
+ std::map<double, std::unique_ptr<Expression>> stops;
+ optional<type::Type> outputType;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
+ }
+
+ double previous = - std::numeric_limits<double>::infinity();
+
+ // consume the first output value, which doesn't have a corresponding input value,
+ // before proceeding into the "stops" loop below.
+ auto first_output = ctx.parse(arrayMember(value, 2), 2, outputType);
+ if (!first_output) {
+ return ParseResult();
+ }
+ if (!outputType) {
+ outputType = (*first_output)->getType();
+ }
+ stops.emplace(-std::numeric_limits<double>::infinity(), std::move(*first_output));
+
+
+ for (std::size_t i = 3; i + 1 < length; i += 2) {
+ const optional<mbgl::Value> labelValue = toValue(arrayMember(value, i));
+ optional<double> label;
+ optional<std::string> labelError;
+ if (labelValue) {
+ labelValue->match(
+ [&](uint64_t n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](int64_t n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](double n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](const auto&) {}
+ );
+ }
+ if (!label) {
+ ctx.error(labelError ? *labelError :
+ R"(Input/output pairs for "step" expressions must be defined using literal numeric values (not computed expressions) for the input values.)",
+ i);
+ return ParseResult();
+ }
+
+ if (*label < previous) {
+ ctx.error(
+ R"(Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.)",
+ i
+ );
+ return ParseResult();
+ }
+ previous = *label;
+
+ auto output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
+ if (!output) {
+ return ParseResult();
+ }
+ if (!outputType) {
+ outputType = (*output)->getType();
+ }
+
+ stops.emplace(*label, std::move(*output));
+ }
+
+ assert(outputType);
+
+ return ParseResult(std::make_unique<Step>(*outputType, std::move(*input), std::move(stops)));
+}
+
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/test/fixtures/style_parser/expressions.info.json b/test/fixtures/style_parser/expressions.info.json
index 49e0280d3f..9e1765ecd0 100644
--- a/test/fixtures/style_parser/expressions.info.json
+++ b/test/fixtures/style_parser/expressions.info.json
@@ -3,10 +3,10 @@
"log": [
[1, "WARNING", "ParseStyle", "Expected color but found number instead."],
[1, "WARNING", "ParseStyle", "[2]: Expected number but found string instead."],
- [1, "WARNING", "ParseStyle", "\"zoom\" expression may only be used as input to a top-level \"curve\" expression."],
+ [1, "WARNING", "ParseStyle", "\"zoom\" expression may only be used as input to a top-level \"step\" or \"interpolate\" expression."],
[1, "WARNING", "ParseStyle", "value must be a string"],
[1, "WARNING", "ParseStyle", "property expressions not supported"],
- [1, "WARNING", "ParseStyle", "Type array<number> is not interpolatable, and thus cannot be used as a linear curve's output type."]
+ [1, "WARNING", "ParseStyle", "Type array<number> is not interpolatable."]
]
}
}
diff --git a/test/fixtures/style_parser/expressions.style.json b/test/fixtures/style_parser/expressions.style.json
index 389cd923ea..b9b4aeac7f 100644
--- a/test/fixtures/style_parser/expressions.style.json
+++ b/test/fixtures/style_parser/expressions.style.json
@@ -40,7 +40,7 @@
"source": "source",
"source-layer": "layer",
"paint": {
- "fill-opacity": ["+", 0.5, ["curve", ["linear"], ["zoom"], 0, 0, 1, 1]]
+ "fill-opacity": ["+", 0.5, ["interpolate", ["linear"], ["zoom"], 0, 0, 1, 1]]
}
},
{
@@ -67,7 +67,7 @@
"source": "source",
"source-layer": "layer",
"paint": {
- "line-dasharray": ["curve", ["linear"], ["zoom"], 0, ["literal", [1, 2]], 1, ["literal", [3, 4]]]
+ "line-dasharray": ["interpolate", ["linear"], ["zoom"], 0, ["literal", [1, 2]], 1, ["literal", [3, 4]]]
}
}
]
diff --git a/test/style/conversion/function.test.cpp b/test/style/conversion/function.test.cpp
index 7a8b66f3e9..a48be2c075 100644
--- a/test/style/conversion/function.test.cpp
+++ b/test/style/conversion/function.test.cpp
@@ -62,19 +62,19 @@ TEST(StyleConversion, CompositeFunctionExpression) {
return convert<DataDrivenPropertyValue<float>>(doc, error);
};
- auto fn1 = parseFunction(R"(["curve", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10])");
+ auto fn1 = parseFunction(R"(["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10])");
ASSERT_TRUE(fn1);
- auto fn2 = parseFunction(R"(["coalesce", ["curve", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10], 0])");
+ auto fn2 = parseFunction(R"(["coalesce", ["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10], 0])");
ASSERT_TRUE(fn2);
- auto fn3 = parseFunction(R"(["let", "a", 0, ["curve", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10] ])");
+ auto fn3 = parseFunction(R"(["let", "a", 0, ["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10] ])");
ASSERT_TRUE(fn3);
- auto fn4 = parseFunction(R"(["coalesce", ["let", "a", 0, ["curve", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10], 0 ])");
+ auto fn4 = parseFunction(R"(["coalesce", ["let", "a", 0, ["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10], 0 ])");
ASSERT_TRUE(fn4);
- auto fn5 = parseFunction(R"(["coalesce", ["curve", ["linear"], ["number", ["get", "x"]], 0, ["zoom"], 10, 10], 0])");
+ auto fn5 = parseFunction(R"(["coalesce", ["interpolate", ["linear"], ["number", ["get", "x"]], 0, ["zoom"], 10, 10], 0])");
ASSERT_FALSE(fn5);
- ASSERT_EQ(R"("zoom" expression may only be used as input to a top-level "curve" expression.)", error.message);
+ ASSERT_EQ(R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)", error.message);
}