From b81243daa9ec5a16594fa280236e2ee903540f64 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 3 Nov 2015 15:04:25 -0800 Subject: [PATCH] [core] Merge PiecewiseConstantFunction into Function --- src/mbgl/layer/background_layer.cpp | 2 +- src/mbgl/layer/fill_layer.cpp | 2 +- src/mbgl/layer/line_layer.cpp | 4 +- src/mbgl/style/class_properties.hpp | 3 +- src/mbgl/style/function.cpp | 80 +++++++++++++---- src/mbgl/style/function.hpp | 31 ++++++- .../style/piecewisefunction_properties.cpp | 54 ----------- .../style/piecewisefunction_properties.hpp | 35 -------- src/mbgl/style/property_evaluator.hpp | 5 -- src/mbgl/style/property_parsing.cpp | 90 +++++++------------ src/mbgl/style/property_value.hpp | 5 +- .../style/style_calculation_parameters.hpp | 2 +- test/miscellaneous/functions.cpp | 66 +++++++------- 13 files changed, 167 insertions(+), 212 deletions(-) delete mode 100644 src/mbgl/style/piecewisefunction_properties.cpp delete mode 100644 src/mbgl/style/piecewisefunction_properties.hpp diff --git a/src/mbgl/layer/background_layer.cpp b/src/mbgl/layer/background_layer.cpp index bbfd56a1b..d52905708 100644 --- a/src/mbgl/layer/background_layer.cpp +++ b/src/mbgl/layer/background_layer.cpp @@ -7,7 +7,7 @@ void BackgroundLayer::parsePaints(const JSVal& layer) { paints.parseEach(layer, [&] (ClassProperties& paint, const JSVal& value) { parseProperty>("background-opacity", PropertyKey::BackgroundOpacity, paint, value); parseProperty>("background-color", PropertyKey::BackgroundColor, paint, value); - parseProperty>>("background-pattern", PropertyKey::BackgroundImage, paint, value, "background-pattern-transition"); + parseProperty>>("background-pattern", PropertyKey::BackgroundImage, paint, value, "background-pattern-transition"); }); } diff --git a/src/mbgl/layer/fill_layer.cpp b/src/mbgl/layer/fill_layer.cpp index 5ff26337b..7d53fa97c 100644 --- a/src/mbgl/layer/fill_layer.cpp +++ b/src/mbgl/layer/fill_layer.cpp @@ -17,7 +17,7 @@ void FillLayer::parsePaints(const JSVal& layer) { parseProperty>>("fill-translate", PropertyKey::FillTranslate, paint, value); parseProperty("fill-translate-transition", PropertyKey::FillTranslate, paint, value); parseProperty>("fill-translate-anchor", PropertyKey::FillTranslateAnchor, paint, value); - parseProperty>>("fill-pattern", PropertyKey::FillImage, paint, value, "fill-pattern-transition"); + parseProperty>>("fill-pattern", PropertyKey::FillImage, paint, value, "fill-pattern-transition"); }); } diff --git a/src/mbgl/layer/line_layer.cpp b/src/mbgl/layer/line_layer.cpp index a27cf65ee..a0b216bda 100644 --- a/src/mbgl/layer/line_layer.cpp +++ b/src/mbgl/layer/line_layer.cpp @@ -28,8 +28,8 @@ void LineLayer::parsePaints(const JSVal& layer) { parseProperty("line-gap-width-transition", PropertyKey::LineGapWidth, paint, value); parseProperty>("line-blur", PropertyKey::LineBlur, paint, value); parseProperty("line-blur-transition", PropertyKey::LineBlur, paint, value); - parseProperty>>>("line-dasharray", PropertyKey::LineDashArray, paint, value, "line-dasharray-transition"); - parseProperty>>("line-pattern", PropertyKey::LineImage, paint, value, "line-pattern-transition"); + parseProperty>>>("line-dasharray", PropertyKey::LineDashArray, paint, value, "line-dasharray-transition"); + parseProperty>>("line-pattern", PropertyKey::LineImage, paint, value, "line-pattern-transition"); }); } diff --git a/src/mbgl/style/class_properties.hpp b/src/mbgl/style/class_properties.hpp index 84b91d769..153fc11ee 100644 --- a/src/mbgl/style/class_properties.hpp +++ b/src/mbgl/style/class_properties.hpp @@ -34,8 +34,7 @@ public: void calculate(PropertyKey key, T& target, const float z) const { auto it = properties.find(key); if (it != properties.end()) { - const PropertyEvaluator evaluator(z); - target = mapbox::util::apply_visitor(evaluator, it->second); + target = mapbox::util::apply_visitor(PropertyEvaluator(StyleCalculationParameters(z)), it->second); } } diff --git a/src/mbgl/style/function.cpp b/src/mbgl/style/function.cpp index 19ccd7f60..5c8f294da 100644 --- a/src/mbgl/style/function.cpp +++ b/src/mbgl/style/function.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -27,7 +27,8 @@ template <> inline TextTransformType defaultStopsValue() { return {}; }; template <> inline RotationAlignmentType defaultStopsValue() { return {}; }; template -T Function::evaluate(float z) const { +T Function::evaluate(const StyleCalculationParameters& parameters) const { + float z = parameters.z; bool smaller = false; float smaller_z = 0.0f; T smaller_val = T(); @@ -73,21 +74,66 @@ T Function::evaluate(float z) const { } } -template bool Function::evaluate(float z) const; -template float Function::evaluate(float z) const; -template Color Function::evaluate(float z) const; -template std::vector Function>::evaluate(float z) const; -template std::array Function>::evaluate(float z) const; +template class Function; +template class Function; +template class Function; +template class Function>; +template class Function>; -template std::string Function::evaluate(float z) const; -template TranslateAnchorType Function::evaluate(float z) const; -template RotateAnchorType Function::evaluate(float z) const; -template CapType Function::evaluate(float z) const; -template JoinType Function::evaluate(float z) const; -template PlacementType Function::evaluate(float z) const; -template TextAnchorType Function::evaluate(float z) const; -template TextJustifyType Function::evaluate(float z) const; -template TextTransformType Function::evaluate(float z) const; -template RotationAlignmentType Function::evaluate(float z) const; +template class Function; +template class Function; +template class Function; +template class Function; +template class Function; +template class Function; +template class Function; +template class Function; +template class Function; +template class Function; + +template +size_t getBiggestStopLessThan(std::vector> stops, float z) { + for (uint32_t i = 0; i < stops.size(); i++) { + if (stops[i].first > z) { + return i == 0 ? i : i - 1; + } + } + return stops.size() - 1; +} + +template +Faded Function>::evaluate(const StyleCalculationParameters& parameters) const { + Faded result; + + float z = parameters.z; + float fraction = std::fmod(z, 1.0f); + std::chrono::duration d = duration ? *duration : parameters.defaultFadeDuration; + float t = std::min((Clock::now() - parameters.zoomHistory.lastIntegerZoomTime) / d, 1.0f); + float fromScale = 1.0f; + float toScale = 1.0f; + size_t from, to; + + if (z > parameters.zoomHistory.lastIntegerZoom) { + result.t = fraction + (1.0f - fraction) * t; + from = getBiggestStopLessThan(stops, z - 1.0f); + to = getBiggestStopLessThan(stops, z); + fromScale *= 2.0f; + + } else { + result.t = 1 - (1 - t) * fraction; + to = getBiggestStopLessThan(stops, z); + from = getBiggestStopLessThan(stops, z + 1.0f); + fromScale /= 2.0f; + } + + result.from = stops[from].second; + result.to = stops[to].second; + result.fromScale = fromScale; + result.toScale = toScale; + return result; +} + +template class Function>; +template class Function>>; } diff --git a/src/mbgl/style/function.hpp b/src/mbgl/style/function.hpp index 6ef4fcf5d..e28b0efdd 100644 --- a/src/mbgl/style/function.hpp +++ b/src/mbgl/style/function.hpp @@ -1,11 +1,18 @@ #ifndef MBGL_STYLE_FUNCTION #define MBGL_STYLE_FUNCTION +#include +#include + +#include + #include #include namespace mbgl { +class StyleCalculationParameters; + template class Function { public: @@ -19,13 +26,35 @@ public: explicit Function(const Stops& stops_, float base_) : base(base_), stops(stops_) {} - T evaluate(float z) const; + T evaluate(const StyleCalculationParameters&) const; private: const float base = 1; const std::vector> stops; }; +// Partial specialization for cross-faded properties (*-pattern, line-dasharray). +template +class Function> { +public: + using Stop = std::pair; + using Stops = std::vector; + + // TODO: make explicit + /* explicit */ Function(const T& constant) + : stops({{ 0, constant }}) {} + + explicit Function(const Stops& stops_, + mapbox::util::optional duration_) + : stops(stops_), duration(duration_) {} + + Faded evaluate(const StyleCalculationParameters&) const; + +private: + const std::vector> stops; + const mapbox::util::optional duration = {}; +}; + } #endif diff --git a/src/mbgl/style/piecewisefunction_properties.cpp b/src/mbgl/style/piecewisefunction_properties.cpp deleted file mode 100644 index d74169829..000000000 --- a/src/mbgl/style/piecewisefunction_properties.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include - -#include - -namespace mbgl { - -template -size_t getBiggestStopLessThan(std::vector> stops, float z) { - for (uint32_t i = 0; i < stops.size(); i++) { - if (stops[i].first > z) { - return i == 0 ? i : i - 1; - } - } - return stops.size() - 1; -} - -template -T PiecewiseConstantFunction::evaluate(const StyleCalculationParameters& parameters) const { - T result; - - float z = parameters.z; - float fraction = std::fmod(z, 1.0f); - std::chrono::duration d = duration ? *duration : parameters.defaultFadeDuration; - float t = std::min((Clock::now() - parameters.zoomHistory.lastIntegerZoomTime) / d, 1.0f); - float fromScale = 1.0f; - float toScale = 1.0f; - size_t from, to; - - if (z > parameters.zoomHistory.lastIntegerZoom) { - result.t = fraction + (1.0f - fraction) * t; - from = getBiggestStopLessThan(values, z - 1.0f); - to = getBiggestStopLessThan(values, z); - fromScale *= 2.0f; - - } else { - result.t = 1 - (1 - t) * fraction; - to = getBiggestStopLessThan(values, z); - from = getBiggestStopLessThan(values, z + 1.0f); - fromScale /= 2.0f; - } - - - result.from = values[from].second.to; - result.to = values[to].second.to; - result.fromScale = fromScale; - result.toScale = toScale; - return result; -} - -template Faded PiecewiseConstantFunction>::evaluate(const StyleCalculationParameters&) const; -template Faded> PiecewiseConstantFunction>>::evaluate(const StyleCalculationParameters&) const; - -} diff --git a/src/mbgl/style/piecewisefunction_properties.hpp b/src/mbgl/style/piecewisefunction_properties.hpp deleted file mode 100644 index 491442958..000000000 --- a/src/mbgl/style/piecewisefunction_properties.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef MBGL_STYLE_FADEDFUNCTION_PROPERTIES -#define MBGL_STYLE_FADEDFUNCTION_PROPERTIES - -#include -#include - -#include - -#include - -namespace mbgl { - -template -struct PiecewiseConstantFunction { - PiecewiseConstantFunction(const std::vector>& values_, - mapbox::util::optional duration_) - : values(values_), - duration(duration_) { - } - - PiecewiseConstantFunction(const T& value) - : values({{ 0, value }}), - duration() { - } - - T evaluate(const StyleCalculationParameters&) const; - -private: - const std::vector> values; - const mapbox::util::optional duration; -}; - -} - -#endif diff --git a/src/mbgl/style/property_evaluator.hpp b/src/mbgl/style/property_evaluator.hpp index dd4960c8e..81d2c9334 100644 --- a/src/mbgl/style/property_evaluator.hpp +++ b/src/mbgl/style/property_evaluator.hpp @@ -3,7 +3,6 @@ #include #include -#include #include namespace mbgl { @@ -24,10 +23,6 @@ public: } T operator()(const Function& value) const { - return value.evaluate(parameters.z); - } - - T operator()(const PiecewiseConstantFunction& value) const { return value.evaluate(parameters); } diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp index 6df3d4c0f..73345fcc6 100644 --- a/src/mbgl/style/property_parsing.cpp +++ b/src/mbgl/style/property_parsing.cpp @@ -7,29 +7,6 @@ namespace mbgl { namespace detail { -optional> parseFloatArray(const JSVal& value) { - if (!value.IsArray()) { - Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers"); - return {}; - } - - std::vector result; - - for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { - const JSVal& part = value[i]; - - if (!part.IsNumber()) { - Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers"); - return {}; - } - - result.push_back(part.GetDouble()); - } - - return result; -} - - template <> optional parseProperty(const char* name, const JSVal& value) { if (!value.IsBool()) { @@ -205,6 +182,29 @@ optional> parseProperty(const char* name, const JSVal& valu } } +template <> +optional> parseProperty(const char* name, const JSVal& value) { + if (!value.IsArray()) { + Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name); + return {}; + } + + std::vector result; + + for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { + const JSVal& part = value[i]; + + if (!part.IsNumber()) { + Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name); + return {}; + } + + result.push_back(part.GetDouble()); + } + + return result; +} + template <> optional parseProperty(const char *, const JSVal& value) { PropertyTransition transition; @@ -360,7 +360,7 @@ template<> optional> parseProperty(const char* name, const JSVal } template -optional> parsePiecewiseConstantFunction(const JSVal& value, const JSVal& transition) { +optional>> parseFadedFunction(const JSVal& value, const JSVal& transition) { mapbox::util::optional duration; if (transition.HasMember("duration")) { duration = std::chrono::milliseconds(transition["duration"].GetUint()); @@ -377,57 +377,33 @@ optional> parsePiecewiseConstantFunction(const JSVa return {}; } - return PiecewiseConstantFunction(*stops, duration); + return Function>(*stops, duration); } template <> -optional>> parseProperty(const char*, const JSVal& value) { - auto floatarray = parseFloatArray(value); - if (!floatarray) { - return {}; - } - - Faded> parsed; - parsed.to = *floatarray; - return parsed; -} - -template <> -optional> parseProperty(const char* name, const JSVal& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string, or a string function", name); - return {}; - } - - Faded parsed; - parsed.to = { value.GetString(), value.GetStringLength() }; - return parsed; -} - -template <> -optional>>> parseProperty(const char* name, const JSVal& value, const JSVal& transition) { +optional>>> parseProperty(const char* name, const JSVal& value, const JSVal& transition) { if (value.IsObject()) { - return parsePiecewiseConstantFunction>>(value, transition); + return parseFadedFunction>(value, transition); } - auto constant = parseProperty>>(name, value); + auto constant = parseProperty>(name, value); if (!constant) { return {}; } - return PiecewiseConstantFunction>>(*constant); + return Function>>(*constant); } template <> -optional>> parseProperty(const char* name, const JSVal& value, const JSVal& transition) { +optional>> parseProperty(const char* name, const JSVal& value, const JSVal& transition) { if (value.IsObject()) { - return parsePiecewiseConstantFunction>(value, transition); + return parseFadedFunction(value, transition); } - auto constant = parseProperty>(name, value); + auto constant = parseProperty(name, value); if (!constant) { return {}; } - return PiecewiseConstantFunction>(*constant); + return Function>(*constant); } } diff --git a/src/mbgl/style/property_value.hpp b/src/mbgl/style/property_value.hpp index 60ddb7fc7..8d6b95753 100644 --- a/src/mbgl/style/property_value.hpp +++ b/src/mbgl/style/property_value.hpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -28,8 +27,8 @@ typedef mapbox::util::variant< Function, Function, Function, - PiecewiseConstantFunction>>, - PiecewiseConstantFunction> + Function>>, + Function> > PropertyValue; } diff --git a/src/mbgl/style/style_calculation_parameters.hpp b/src/mbgl/style/style_calculation_parameters.hpp index 3b54fd4bd..0c42d8fbf 100644 --- a/src/mbgl/style/style_calculation_parameters.hpp +++ b/src/mbgl/style/style_calculation_parameters.hpp @@ -8,7 +8,7 @@ namespace mbgl { class StyleCalculationParameters { public: - StyleCalculationParameters(float z_) + explicit StyleCalculationParameters(float z_) : z(z_) {} StyleCalculationParameters(float z_, diff --git a/test/miscellaneous/functions.cpp b/test/miscellaneous/functions.cpp index 5772cfe45..d19d2ea88 100644 --- a/test/miscellaneous/functions.cpp +++ b/test/miscellaneous/functions.cpp @@ -7,53 +7,53 @@ using namespace mbgl; TEST(Function, Constant) { - EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(0)); - EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(0)); - EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(0)); - EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(4)); - EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(4)); - EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(4)); - EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(22)); - EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(22)); - EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(22)); + EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(StyleCalculationParameters(0))); + EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(StyleCalculationParameters(0))); + EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(StyleCalculationParameters(0))); + EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(StyleCalculationParameters(4))); + EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(StyleCalculationParameters(4))); + EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(StyleCalculationParameters(4))); + EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(StyleCalculationParameters(22))); + EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(StyleCalculationParameters(22))); + EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(StyleCalculationParameters(22))); } TEST(Function, Stops) { // Explicit constant slope in fringe regions. mbgl::Function slope_1({ { 0, 1.5 }, { 6, 1.5 }, { 8, 3 }, { 22, 3 } }, 1.75); - EXPECT_EQ(1.5, slope_1.evaluate(0)); - EXPECT_EQ(1.5, slope_1.evaluate(4)); - EXPECT_EQ(1.5, slope_1.evaluate(6)); - ASSERT_FLOAT_EQ(2.0454545454545454, slope_1.evaluate(7)); - EXPECT_EQ(3.0, slope_1.evaluate(8)); - EXPECT_EQ(3.0, slope_1.evaluate(9)); - EXPECT_EQ(3.0, slope_1.evaluate(15)); - EXPECT_EQ(3.0, slope_1.evaluate(22)); + EXPECT_EQ(1.5, slope_1.evaluate(StyleCalculationParameters(0))); + EXPECT_EQ(1.5, slope_1.evaluate(StyleCalculationParameters(4))); + EXPECT_EQ(1.5, slope_1.evaluate(StyleCalculationParameters(6))); + ASSERT_FLOAT_EQ(2.0454545454545454, slope_1.evaluate(StyleCalculationParameters(7))); + EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(8))); + EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(9))); + EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(15))); + EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(22))); // Test constant values in fringe regions. mbgl::Function slope_2({ { 6, 1.5 }, { 8, 3 } }, 1.75); - EXPECT_EQ(1.5, slope_2.evaluate(0)); - EXPECT_EQ(1.5, slope_2.evaluate(4)); - EXPECT_EQ(1.5, slope_2.evaluate(6)); - ASSERT_FLOAT_EQ(2.0454545454545454, slope_2.evaluate(7)); - EXPECT_EQ(3.0, slope_2.evaluate(8)); - EXPECT_EQ(3.0, slope_2.evaluate(9)); - EXPECT_EQ(3.0, slope_2.evaluate(15)); - EXPECT_EQ(3.0, slope_2.evaluate(22)); + EXPECT_EQ(1.5, slope_2.evaluate(StyleCalculationParameters(0))); + EXPECT_EQ(1.5, slope_2.evaluate(StyleCalculationParameters(4))); + EXPECT_EQ(1.5, slope_2.evaluate(StyleCalculationParameters(6))); + ASSERT_FLOAT_EQ(2.0454545454545454, slope_2.evaluate(StyleCalculationParameters(7))); + EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(8))); + EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(9))); + EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(15))); + EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(22))); // Test no values. mbgl::Function slope_3({}, 1.75); - EXPECT_EQ(1, slope_3.evaluate(2)); - EXPECT_EQ(1, slope_3.evaluate(6)); - EXPECT_EQ(1, slope_3.evaluate(12)); + EXPECT_EQ(1, slope_3.evaluate(StyleCalculationParameters(2))); + EXPECT_EQ(1, slope_3.evaluate(StyleCalculationParameters(6))); + EXPECT_EQ(1, slope_3.evaluate(StyleCalculationParameters(12))); // Explicit constant slope in fringe regions. mbgl::Function slope_4({ { 0, 2 }, { 8, 10 } }, 1); - EXPECT_EQ(2, slope_4.evaluate(0)); - EXPECT_EQ(3, slope_4.evaluate(1)); - EXPECT_EQ(4, slope_4.evaluate(2)); - EXPECT_EQ(4.75, slope_4.evaluate(2.75)); - EXPECT_EQ(10, slope_4.evaluate(8)); + EXPECT_EQ(2, slope_4.evaluate(StyleCalculationParameters(0))); + EXPECT_EQ(3, slope_4.evaluate(StyleCalculationParameters(1))); + EXPECT_EQ(4, slope_4.evaluate(StyleCalculationParameters(2))); + EXPECT_EQ(4.75, slope_4.evaluate(StyleCalculationParameters(2.75))); + EXPECT_EQ(10, slope_4.evaluate(StyleCalculationParameters(8))); }