diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-04-28 16:33:09 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-04-28 16:33:09 -0700 |
commit | da78422c5c37b2150eefeb399658903e45bf05d9 (patch) | |
tree | 1a7219a082c02de4f9f4d1274abb289090989826 /src | |
parent | 10528091db0baaad4b528555498d43236e32ccce (diff) | |
download | qtlocation-mapboxgl-da78422c5c37b2150eefeb399658903e45bf05d9.tar.gz |
[core] Prepare Filter for public API (#4900)
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/renderer/symbol_bucket.cpp | 23 | ||||
-rw-r--r-- | src/mbgl/renderer/symbol_bucket.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/style/filter.hpp | 91 | ||||
-rw-r--r-- | src/mbgl/style/filter_evaluator.hpp | 138 | ||||
-rw-r--r-- | src/mbgl/style/filter_expression.cpp | 128 | ||||
-rw-r--r-- | src/mbgl/style/filter_expression.hpp | 124 | ||||
-rw-r--r-- | src/mbgl/style/filter_expression_private.hpp | 119 | ||||
-rw-r--r-- | src/mbgl/style/style_bucket_parameters.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/style/style_bucket_parameters.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/style_layer.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/style_parser.cpp | 146 | ||||
-rw-r--r-- | src/mbgl/style/style_parser.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/style/value.cpp | 33 | ||||
-rw-r--r-- | src/mbgl/style/value.hpp | 20 | ||||
-rw-r--r-- | src/mbgl/style/value_comparison.hpp | 109 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/value.hpp | 9 |
18 files changed, 415 insertions, 554 deletions
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index cdb30bf222..c6d49101fc 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -1,4 +1,5 @@ #include <mbgl/renderer/symbol_bucket.hpp> +#include <mbgl/style/filter_evaluator.hpp> #include <mbgl/layer/symbol_layer.hpp> #include <mbgl/tile/geometry_tile.hpp> #include <mbgl/sprite/sprite_image.hpp> @@ -26,6 +27,7 @@ #include <mbgl/util/std.hpp> #include <mbgl/util/get_geometries.hpp> #include <mbgl/util/constants.hpp> +#include <mbgl/util/string.hpp> namespace mbgl { @@ -99,8 +101,7 @@ bool SymbolBucket::needsClipping() const { return mode == MapMode::Still; } -void SymbolBucket::parseFeatures(const GeometryTileLayer& layer, - const FilterExpression& filter) { +void SymbolBucket::parseFeatures(const GeometryTileLayer& layer, const Filter& filter) { const bool has_text = !layout.textField.value.empty() && !layout.textFont.value.empty(); const bool has_icon = !layout.iconImage.value.empty(); @@ -113,15 +114,27 @@ void SymbolBucket::parseFeatures(const GeometryTileLayer& layer, for (GLsizei i = 0; i < featureCount; i++) { auto feature = layer.getFeature(i); - GeometryTileFeatureExtractor extractor(*feature); - if (!evaluate(filter, extractor)) + FilterEvaluator<GeometryTileFeatureExtractor> evaluator(*feature); + if (!Filter::visit(filter, evaluator)) continue; SymbolFeature ft; auto getValue = [&feature](const std::string& key) -> std::string { auto value = feature->getValue(key); - return value ? toString(*value) : std::string(); + if (!value) + return std::string(); + if (value->is<std::string>()) + return value->get<std::string>(); + if (value->is<bool>()) + return value->get<bool>() ? "true" : "false"; + if (value->is<int64_t>()) + return util::toString(value->get<int64_t>()); + if (value->is<uint64_t>()) + return util::toString(value->get<uint64_t>()); + if (value->is<double>()) + return util::toString(value->get<double>()); + return "null"; }; if (has_text) { diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index 243ae99de9..1b37a1e005 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -13,7 +13,7 @@ #include <mbgl/text/collision_feature.hpp> #include <mbgl/text/shaping.hpp> #include <mbgl/text/quads.hpp> -#include <mbgl/style/filter_expression.hpp> +#include <mbgl/style/filter.hpp> #include <mbgl/layer/symbol_layer.hpp> #include <memory> @@ -88,8 +88,7 @@ public: void drawIcons(IconShader&, gl::GLObjectStore&); void drawCollisionBoxes(CollisionBoxShader&, gl::GLObjectStore&); - void parseFeatures(const GeometryTileLayer&, - const FilterExpression&); + void parseFeatures(const GeometryTileLayer&, const Filter&); bool needsDependencies(GlyphStore&, SpriteStore&); void placeFeatures(CollisionTile&) override; diff --git a/src/mbgl/style/filter.hpp b/src/mbgl/style/filter.hpp new file mode 100644 index 0000000000..85878543f8 --- /dev/null +++ b/src/mbgl/style/filter.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include <mbgl/util/variant.hpp> +#include <mbgl/util/value.hpp> + +#include <string> +#include <vector> + +namespace mbgl { + +typedef variant< + class NullFilter, + class EqualsFilter, + class NotEqualsFilter, + class LessThanFilter, + class LessThanEqualsFilter, + class GreaterThanFilter, + class GreaterThanEqualsFilter, + class InFilter, + class NotInFilter, + class AnyFilter, + class AllFilter, + class NoneFilter + > Filter; + +class NullFilter {}; + +class EqualsFilter { +public: + std::string key; + Value value; +}; + +class NotEqualsFilter { +public: + std::string key; + Value value; +}; + +class LessThanFilter { +public: + std::string key; + Value value; +}; + +class LessThanEqualsFilter { +public: + std::string key; + Value value; +}; + +class GreaterThanFilter { +public: + std::string key; + Value value; +}; + +class GreaterThanEqualsFilter { +public: + std::string key; + Value value; +}; + +class InFilter { +public: + std::string key; + std::vector<Value> values; +}; + +class NotInFilter { +public: + std::string key; + std::vector<Value> values; +}; + +class AnyFilter { +public: + std::vector<Filter> filters; +}; + +class AllFilter { +public: + std::vector<Filter> filters; +}; + +class NoneFilter { +public: + std::vector<Filter> filters; +}; + +} // namespace mbgl diff --git a/src/mbgl/style/filter_evaluator.hpp b/src/mbgl/style/filter_evaluator.hpp new file mode 100644 index 0000000000..27402ac211 --- /dev/null +++ b/src/mbgl/style/filter_evaluator.hpp @@ -0,0 +1,138 @@ +#pragma once + +#include <mbgl/style/filter.hpp> +#include <mbgl/util/optional.hpp> + +#include <type_traits> + +namespace mbgl { + +template <class Extractor> +class FilterEvaluator { +public: + FilterEvaluator(const Extractor& extractor_) + : extractor(extractor_) {} + + bool operator()(const NullFilter&) const { + return true; + } + + bool operator()(const EqualsFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + return actual && equal(*actual, filter.value); + } + + bool operator()(const NotEqualsFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + return !actual || !equal(*actual, filter.value); + } + + bool operator()(const LessThanFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ < rhs_; }); + } + + bool operator()(const LessThanEqualsFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ <= rhs_; }); + } + + bool operator()(const GreaterThanFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ > rhs_; }); + } + + bool operator()(const GreaterThanEqualsFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ >= rhs_; }); + } + + bool operator()(const InFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + if (!actual) + return false; + for (const auto& v: filter.values) { + if (equal(*actual, v)) { + return true; + } + } + return false; + } + + bool operator()(const NotInFilter& filter) const { + optional<Value> actual = extractor.getValue(filter.key); + if (!actual) + return true; + for (const auto& v: filter.values) { + if (equal(*actual, v)) { + return false; + } + } + return true; + } + + bool operator()(const AnyFilter& filter) const { + for (const auto& f: filter.filters) { + if (Filter::visit(f, *this)) { + return true; + } + } + return false; + } + + bool operator()(const AllFilter& filter) const { + for (const auto& f: filter.filters) { + if (!Filter::visit(f, *this)) { + return false; + } + } + return true; + } + + bool operator()(const NoneFilter& filter) const { + for (const auto& f: filter.filters) { + if (Filter::visit(f, *this)) { + return false; + } + } + return true; + } + +private: + template <class Op> + struct Comparator { + const Op& op; + + template <class T> + bool operator()(const T& lhs, const T& rhs) const { + return op(lhs, rhs); + } + + template <class T0, class T1> + auto operator()(const T0& lhs, const T1& rhs) const + -> typename std::enable_if_t<std::is_arithmetic<T0>::value && !std::is_same<T0, bool>::value && + std::is_arithmetic<T1>::value && !std::is_same<T1, bool>::value, bool> { + return op(double(lhs), double(rhs)); + } + + template <class T0, class T1> + auto operator()(const T0&, const T1&) const + -> typename std::enable_if_t<!std::is_arithmetic<T0>::value || std::is_same<T0, bool>::value || + !std::is_arithmetic<T1>::value || std::is_same<T1, bool>::value, bool> { + return false; + } + }; + + template <class Op> + bool compare(const Value& lhs, const Value& rhs, const Op& op) const { + return Value::binary_visit(lhs, rhs, Comparator<Op> { op }); + } + + bool equal(const Value& lhs, const Value& rhs) const { + return compare(lhs, rhs, [] (const auto& lhs_, const auto& rhs_) { return lhs_ == rhs_; }); + } + + const Extractor& extractor; +}; + +} // namespace mbgl diff --git a/src/mbgl/style/filter_expression.cpp b/src/mbgl/style/filter_expression.cpp deleted file mode 100644 index 660c978f0d..0000000000 --- a/src/mbgl/style/filter_expression.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include <mbgl/style/filter_expression.hpp> -#include <mbgl/tile/geometry_tile.hpp> -#include <mbgl/platform/log.hpp> - -namespace mbgl { - -Value parseFeatureType(const Value& value) { - if (value == std::string("Point")) { - return Value(uint64_t(FeatureType::Point)); - } else if (value == std::string("LineString")) { - return Value(uint64_t(FeatureType::LineString)); - } else if (value == std::string("Polygon")) { - return Value(uint64_t(FeatureType::Polygon)); - } else { - Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon"); - return Value(uint64_t(FeatureType::Unknown)); - } -} - -template <class Expression> -FilterExpression parseBinaryFilter(const JSValue& value) { - FilterExpression empty; - - if (value.Size() < 3) { - Log::Warning(Event::ParseStyle, "filter expression must have 3 elements"); - return empty; - } - - if (!value[1u].IsString()) { - Log::Warning(Event::ParseStyle, "filter expression key must be a string"); - return empty; - } - - Expression expression; - expression.key = { value[1u].GetString(), value[1u].GetStringLength() }; - expression.value = parseValue(value[2u]); - - if (expression.key == "$type") { - expression.value = parseFeatureType(expression.value); - } - - return expression; -} - -template <class Expression> -FilterExpression parseSetFilter(const JSValue& value) { - FilterExpression empty; - - if (value.Size() < 2) { - Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements"); - return empty; - } - - if (!value[1u].IsString()) { - Log::Warning(Event::ParseStyle, "filter expression key must be a string"); - return empty; - } - - Expression expression; - expression.key = { value[1u].GetString(), value[1u].GetStringLength() }; - for (rapidjson::SizeType i = 2; i < value.Size(); ++i) { - Value parsedValue = parseValue(value[i]); - if (expression.key == "$type") { - parsedValue = parseFeatureType(parsedValue); - } - expression.values.push_back(parsedValue); - } - return expression; -} - -template <class Expression> -FilterExpression parseCompoundFilter(const JSValue& value) { - Expression expression; - for (rapidjson::SizeType i = 1; i < value.Size(); ++i) { - expression.expressions.push_back(parseFilterExpression(value[i])); - } - return expression; -} - -FilterExpression parseFilterExpression(const JSValue& value) { - FilterExpression empty; - - if (!value.IsArray()) { - Log::Warning(Event::ParseStyle, "filter expression must be an array"); - return empty; - } - - if (value.Size() < 1) { - Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element"); - return empty; - } - - if (!value[0u].IsString()) { - Log::Warning(Event::ParseStyle, "filter operator must be a string"); - return empty; - } - - std::string op = { value[0u].GetString(), value[0u].GetStringLength() }; - - if (op == "==") { - return parseBinaryFilter<EqualsExpression>(value); - } else if (op == "!=") { - return parseBinaryFilter<NotEqualsExpression>(value); - } else if (op == ">") { - return parseBinaryFilter<GreaterThanExpression>(value); - } else if (op == ">=") { - return parseBinaryFilter<GreaterThanEqualsExpression>(value); - } else if (op == "<") { - return parseBinaryFilter<LessThanExpression>(value); - } else if (op == "<=") { - return parseBinaryFilter<LessThanEqualsExpression>(value); - } else if (op == "in") { - return parseSetFilter<InExpression>(value); - } else if (op == "!in") { - return parseSetFilter<NotInExpression>(value); - } else if (op == "all") { - return parseCompoundFilter<AllExpression>(value); - } else if (op == "any") { - return parseCompoundFilter<AnyExpression>(value); - } else if (op == "none") { - return parseCompoundFilter<NoneExpression>(value); - } else { - Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\""); - return empty; - } -} - -} // namespace mbgl diff --git a/src/mbgl/style/filter_expression.hpp b/src/mbgl/style/filter_expression.hpp deleted file mode 100644 index 1fa26a69f4..0000000000 --- a/src/mbgl/style/filter_expression.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef MBGL_STYLE_FILTER_EXPRESSION -#define MBGL_STYLE_FILTER_EXPRESSION - -#include <mbgl/style/value.hpp> -#include <mbgl/util/rapidjson.hpp> - -#include <string> -#include <vector> - -namespace mbgl { - -typedef variant< - struct NullExpression, - struct EqualsExpression, - struct NotEqualsExpression, - struct LessThanExpression, - struct LessThanEqualsExpression, - struct GreaterThanExpression, - struct GreaterThanEqualsExpression, - struct InExpression, - struct NotInExpression, - struct AnyExpression, - struct AllExpression, - struct NoneExpression - > FilterExpression; - -FilterExpression parseFilterExpression(const JSValue&); - -template <class Extractor> -bool evaluate(const FilterExpression&, const Extractor&); - -struct NullExpression { - template <class Extractor> - bool evaluate(const Extractor&) const { return true; } -}; - -struct EqualsExpression { - std::string key; - Value value; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct NotEqualsExpression { - std::string key; - Value value; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct LessThanExpression { - std::string key; - Value value; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct LessThanEqualsExpression { - std::string key; - Value value; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct GreaterThanExpression { - std::string key; - Value value; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct GreaterThanEqualsExpression { - std::string key; - Value value; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct InExpression { - std::string key; - std::vector<Value> values; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct NotInExpression { - std::string key; - std::vector<Value> values; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct AnyExpression { - std::vector<FilterExpression> expressions; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct AllExpression { - std::vector<FilterExpression> expressions; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -struct NoneExpression { - std::vector<FilterExpression> expressions; - - template <class Extractor> - bool evaluate(const Extractor&) const; -}; - -} // namespace mbgl - -#endif diff --git a/src/mbgl/style/filter_expression_private.hpp b/src/mbgl/style/filter_expression_private.hpp deleted file mode 100644 index bbc72526d2..0000000000 --- a/src/mbgl/style/filter_expression_private.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#include <mbgl/util/optional.hpp> - -#include <mbgl/style/value_comparison.hpp> - -namespace mbgl { - -template <class Extractor> -struct Evaluator : public mapbox::util::static_visitor<bool> -{ - const Extractor& extractor; - - Evaluator(const Extractor& extractor_) - : extractor(extractor_) {} - - template <class E> - bool operator()(const E& e) const { return e.evaluate(extractor); } -}; - -template <class Extractor> -bool evaluate(const FilterExpression& expression, const Extractor& extractor) { - return mapbox::util::apply_visitor(Evaluator<Extractor>(extractor), expression); -}; - -template <class Extractor> -bool EqualsExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - return actual && util::relaxed_equal(*actual, value); -} - -template <class Extractor> -bool NotEqualsExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - return !actual || util::relaxed_not_equal(*actual, value); -} - -template <class Extractor> -bool LessThanExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - return actual && util::relaxed_less(*actual, value); -} - -template <class Extractor> -bool LessThanEqualsExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - return actual && util::relaxed_less_equal(*actual, value); -} - -template <class Extractor> -bool GreaterThanExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - return actual && util::relaxed_greater(*actual, value); -} - -template <class Extractor> -bool GreaterThanEqualsExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - return actual && util::relaxed_greater_equal(*actual, value); -} - -template <class Extractor> -bool InExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - if (!actual) - return false; - for (const auto& v: values) { - if (util::relaxed_equal(*actual, v)) { - return true; - } - } - return false; -} - -template <class Extractor> -bool NotInExpression::evaluate(const Extractor& extractor) const { - optional<Value> actual = extractor.getValue(key); - if (!actual) - return true; - for (const auto& v: values) { - if (util::relaxed_equal(*actual, v)) { - return false; - } - } - return true; -} - -template <class Extractor> -bool AnyExpression::evaluate(const Extractor& extractor) const { - Evaluator<Extractor> evaluator(extractor); - for (const auto& e: expressions) { - if (mapbox::util::apply_visitor(evaluator, e)) { - return true; - } - } - return false; -} - -template <class Extractor> -bool AllExpression::evaluate(const Extractor& extractor) const { - Evaluator<Extractor> evaluator(extractor); - for (const auto& e: expressions) { - if (!mapbox::util::apply_visitor(evaluator, e)) { - return false; - } - } - return true; -} - -template <class Extractor> -bool NoneExpression::evaluate(const Extractor& extractor) const { - Evaluator<Extractor> evaluator(extractor); - for (const auto& e: expressions) { - if (mapbox::util::apply_visitor(evaluator, e)) { - return false; - } - } - return true; -} - -} // namespace mbgl diff --git a/src/mbgl/style/style_bucket_parameters.cpp b/src/mbgl/style/style_bucket_parameters.cpp index 7bde1fd80e..8591dd430c 100644 --- a/src/mbgl/style/style_bucket_parameters.cpp +++ b/src/mbgl/style/style_bucket_parameters.cpp @@ -1,15 +1,16 @@ #include <mbgl/style/style_bucket_parameters.hpp> +#include <mbgl/style/filter_evaluator.hpp> #include <mbgl/tile/geometry_tile.hpp> namespace mbgl { -void StyleBucketParameters::eachFilteredFeature(const FilterExpression& filter, +void StyleBucketParameters::eachFilteredFeature(const Filter& filter, std::function<void (const GeometryTileFeature&)> function) { for (std::size_t i = 0; !cancelled() && i < layer.featureCount(); i++) { auto feature = layer.getFeature(i); - GeometryTileFeatureExtractor extractor(*feature); - if (!evaluate(filter, extractor)) + FilterEvaluator<GeometryTileFeatureExtractor> evaluator(*feature); + if (!Filter::visit(filter, evaluator)) continue; function(*feature); diff --git a/src/mbgl/style/style_bucket_parameters.hpp b/src/mbgl/style/style_bucket_parameters.hpp index 134850066d..c77980f37c 100644 --- a/src/mbgl/style/style_bucket_parameters.hpp +++ b/src/mbgl/style/style_bucket_parameters.hpp @@ -2,7 +2,7 @@ #define STYLE_BUCKET_PARAMETERS #include <mbgl/map/mode.hpp> -#include <mbgl/style/filter_expression.hpp> +#include <mbgl/style/filter.hpp> #include <mbgl/tile/tile_data.hpp> #include <functional> @@ -42,7 +42,7 @@ public: return state == TileData::State::obsolete; } - void eachFilteredFeature(const FilterExpression&, std::function<void (const GeometryTileFeature&)>); + void eachFilteredFeature(const Filter&, std::function<void (const GeometryTileFeature&)>); const TileID& tileID; const GeometryTileLayer& layer; diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp index fa09ee2e82..9313138587 100644 --- a/src/mbgl/style/style_layer.hpp +++ b/src/mbgl/style/style_layer.hpp @@ -2,7 +2,7 @@ #define MBGL_STYLE_STYLE_LAYER #include <mbgl/style/types.hpp> -#include <mbgl/style/filter_expression.hpp> +#include <mbgl/style/filter.hpp> #include <mbgl/renderer/render_pass.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/rapidjson.hpp> @@ -65,7 +65,7 @@ public: std::string ref; std::string source; std::string sourceLayer; - FilterExpression filter; + Filter filter; float minZoom = -std::numeric_limits<float>::infinity(); float maxZoom = std::numeric_limits<float>::infinity(); VisibilityType visibility = VisibilityType::Visible; diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index d99339b84a..27edf15f97 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -11,6 +11,7 @@ #include <mapbox/geojsonvt.hpp> #include <mapbox/geojsonvt/convert.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/util/mapbox.hpp> #include <rapidjson/document.h> @@ -451,7 +452,7 @@ void StyleParser::parseLayer(const std::string& id, const JSValue& value, std::u } if (value.HasMember("filter")) { - layer->filter = parseFilterExpression(value["filter"]); + layer->filter = parseFilter(value["filter"]); } if (value.HasMember("minzoom")) { @@ -497,6 +498,149 @@ void StyleParser::parseVisibility(StyleLayer& layer, const JSValue& value) { layer.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() }); } +Value parseFeatureType(const Value& value) { + if (value == std::string("Point")) { + return Value(uint64_t(FeatureType::Point)); + } else if (value == std::string("LineString")) { + return Value(uint64_t(FeatureType::LineString)); + } else if (value == std::string("Polygon")) { + return Value(uint64_t(FeatureType::Polygon)); + } else { + Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon"); + return Value(uint64_t(FeatureType::Unknown)); + } +} + +Value parseValue(const JSValue& value) { + switch (value.GetType()) { + case rapidjson::kNullType: + case rapidjson::kFalseType: + return false; + + case rapidjson::kTrueType: + return true; + + case rapidjson::kStringType: + return std::string { value.GetString(), value.GetStringLength() }; + + case rapidjson::kNumberType: + if (value.IsUint64()) return value.GetUint64(); + if (value.IsInt64()) return value.GetInt64(); + return value.GetDouble(); + + default: + return false; + } +} + +template <class Expression> +Filter parseBinaryFilter(const JSValue& value) { + Filter empty; + + if (value.Size() < 3) { + Log::Warning(Event::ParseStyle, "filter expression must have 3 elements"); + return empty; + } + + if (!value[1u].IsString()) { + Log::Warning(Event::ParseStyle, "filter expression key must be a string"); + return empty; + } + + Expression expression; + expression.key = { value[1u].GetString(), value[1u].GetStringLength() }; + expression.value = parseValue(value[2u]); + + if (expression.key == "$type") { + expression.value = parseFeatureType(expression.value); + } + + return expression; +} + +template <class Expression> +Filter parseSetFilter(const JSValue& value) { + Filter empty; + + if (value.Size() < 2) { + Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements"); + return empty; + } + + if (!value[1u].IsString()) { + Log::Warning(Event::ParseStyle, "filter expression key must be a string"); + return empty; + } + + Expression expression; + expression.key = { value[1u].GetString(), value[1u].GetStringLength() }; + for (rapidjson::SizeType i = 2; i < value.Size(); ++i) { + Value parsedValue = parseValue(value[i]); + if (expression.key == "$type") { + parsedValue = parseFeatureType(parsedValue); + } + expression.values.push_back(parsedValue); + } + return expression; +} + +template <class Expression> +Filter parseCompoundFilter(const JSValue& value) { + Expression expression; + for (rapidjson::SizeType i = 1; i < value.Size(); ++i) { + expression.filters.push_back(parseFilter(value[i])); + } + return expression; +} + +Filter parseFilter(const JSValue& value) { + Filter empty; + + if (!value.IsArray()) { + Log::Warning(Event::ParseStyle, "filter expression must be an array"); + return empty; + } + + if (value.Size() < 1) { + Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element"); + return empty; + } + + if (!value[0u].IsString()) { + Log::Warning(Event::ParseStyle, "filter operator must be a string"); + return empty; + } + + std::string op = { value[0u].GetString(), value[0u].GetStringLength() }; + + if (op == "==") { + return parseBinaryFilter<EqualsFilter>(value); + } else if (op == "!=") { + return parseBinaryFilter<NotEqualsFilter>(value); + } else if (op == ">") { + return parseBinaryFilter<GreaterThanFilter>(value); + } else if (op == ">=") { + return parseBinaryFilter<GreaterThanEqualsFilter>(value); + } else if (op == "<") { + return parseBinaryFilter<LessThanFilter>(value); + } else if (op == "<=") { + return parseBinaryFilter<LessThanEqualsFilter>(value); + } else if (op == "in") { + return parseSetFilter<InFilter>(value); + } else if (op == "!in") { + return parseSetFilter<NotInFilter>(value); + } else if (op == "all") { + return parseCompoundFilter<AllFilter>(value); + } else if (op == "any") { + return parseCompoundFilter<AnyFilter>(value); + } else if (op == "none") { + return parseCompoundFilter<NoneFilter>(value); + } else { + Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\""); + return empty; + } +} + std::vector<FontStack> StyleParser::fontStacks() const { std::set<FontStack> result; diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp index 4cc4e2f2cb..2c1feac15a 100644 --- a/src/mbgl/style/style_parser.hpp +++ b/src/mbgl/style/style_parser.hpp @@ -4,6 +4,7 @@ #include <mbgl/style/types.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/source/source.hpp> +#include <mbgl/style/filter.hpp> #include <mbgl/util/rapidjson.hpp> #include <vector> @@ -17,6 +18,8 @@ namespace mbgl { class StyleLayer; class Source; +Filter parseFilter(const JSValue&); + class StyleParser { public: ~StyleParser(); diff --git a/src/mbgl/style/value.cpp b/src/mbgl/style/value.cpp deleted file mode 100644 index a0fa99edf3..0000000000 --- a/src/mbgl/style/value.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include <mbgl/style/value.hpp> -#include <mbgl/util/string.hpp> - -std::string mbgl::toString(const mbgl::Value& value) { - if (value.is<std::string>()) return value.get<std::string>(); - else if (value.is<bool>()) return value.get<bool>() ? "true" : "false"; - else if (value.is<int64_t>()) return util::toString(value.get<int64_t>()); - else if (value.is<uint64_t>()) return util::toString(value.get<uint64_t>()); - else if (value.is<double>()) return util::toString(value.get<double>()); - else return "null"; -} - -mbgl::Value mbgl::parseValue(const JSValue& value) { - switch (value.GetType()) { - case rapidjson::kNullType: - case rapidjson::kFalseType: - return false; - - case rapidjson::kTrueType: - return true; - - case rapidjson::kStringType: - return std::string { value.GetString(), value.GetStringLength() }; - - case rapidjson::kNumberType: - if (value.IsUint64()) return value.GetUint64(); - if (value.IsInt64()) return value.GetInt64(); - return value.GetDouble(); - - default: - return false; - } -} diff --git a/src/mbgl/style/value.hpp b/src/mbgl/style/value.hpp deleted file mode 100644 index 869ddd6668..0000000000 --- a/src/mbgl/style/value.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MBGL_STYLE_VALUE -#define MBGL_STYLE_VALUE - -#include <mbgl/util/variant.hpp> -#include <mbgl/util/rapidjson.hpp> - -#include <cstdlib> -#include <cerrno> - -namespace mbgl { - -typedef variant<bool, int64_t, uint64_t, double, std::string> Value; - -std::string toString(const Value &value); - -Value parseValue(const JSValue&); - -} // namespace mbgl - -#endif diff --git a/src/mbgl/style/value_comparison.hpp b/src/mbgl/style/value_comparison.hpp deleted file mode 100644 index 9f6ae3a0de..0000000000 --- a/src/mbgl/style/value_comparison.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef MBGL_STYLE_VALUE_COMPARISON -#define MBGL_STYLE_VALUE_COMPARISON - -#include <mbgl/style/value.hpp> -#include <cstdlib> -#include <cerrno> - -namespace mbgl { - -namespace util { - -namespace detail { - -template <typename Operator> -struct relaxed_operator_visitor { - typedef bool result_type; - - template <typename T0, typename T1> - inline bool operator()(T0, T1) const { return false; } - - template <typename T> - inline bool operator()(T lhs, T rhs) const { return Operator()(lhs, rhs); } - - inline bool operator()(int64_t lhs, uint64_t rhs) const { - return Operator()(double(lhs), double(rhs)); - } - - inline bool operator()(int64_t lhs, double rhs) const { - return Operator()(double(lhs), rhs); - } - - inline bool operator()(uint64_t lhs, int64_t rhs) const { - return Operator()(double(lhs), double(rhs)); - } - - inline bool operator()(uint64_t lhs, double rhs) const { - return Operator()(double(lhs), rhs); - } - - inline bool operator()(double lhs, uint64_t rhs) const { - return Operator()(lhs, double(rhs)); - } - - inline bool operator()(double lhs, int64_t rhs) const { - return Operator()(lhs, double(rhs)); - } -}; - -struct relaxed_equal_operator { - template <typename T0, typename T1> - inline bool operator()(T0 lhs, T1 rhs) const { return lhs == rhs; } -}; - -struct relaxed_not_equal_operator { - template <typename T0, typename T1> - inline bool operator()(T0 lhs, T1 rhs) const { return lhs != rhs; } -}; - -struct relaxed_greater_operator { - template <typename T0, typename T1> - inline bool operator()(T0 lhs, T1 rhs) const { return lhs > rhs; } -}; - -struct relaxed_greater_equal_operator { - template <typename T0, typename T1> - inline bool operator()(T0 lhs, T1 rhs) const { return lhs >= rhs; } -}; - -struct relaxed_less_operator { - template <typename T0, typename T1> - inline bool operator()(T0 lhs, T1 rhs) const { return lhs < rhs; } -}; - -struct relaxed_less_equal_operator { - template <typename T0, typename T1> - inline bool operator()(T0 lhs, T1 rhs) const { return lhs <= rhs; } -}; - -} // end namespace detail - -inline bool relaxed_equal(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_equal_operator>(), lhs, rhs); -} - -inline bool relaxed_not_equal(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_not_equal_operator>(), lhs, rhs); -} - -inline bool relaxed_greater(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_operator>(), lhs, rhs); -} - -inline bool relaxed_greater_equal(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_equal_operator>(), lhs, rhs); -} - -inline bool relaxed_less(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_operator>(), lhs, rhs); -} - -inline bool relaxed_less_equal(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_equal_operator>(), lhs, rhs); -} - -} // namespace util - -} // namespace mbgl - -#endif diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index fa41481d4d..e3c7437a9c 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -1,6 +1,4 @@ #include <mbgl/tile/geometry_tile.hpp> -#include <mbgl/style/filter_expression.hpp> -#include <mbgl/style/filter_expression_private.hpp> namespace mbgl { @@ -12,6 +10,4 @@ optional<Value> GeometryTileFeatureExtractor::getValue(const std::string& key) c return feature.getValue(key); } -template bool evaluate(const FilterExpression&, const GeometryTileFeatureExtractor&); - } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index d6e073e203..71077d03ac 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_MAP_GEOMETRY_TILE #define MBGL_MAP_GEOMETRY_TILE -#include <mbgl/style/value.hpp> +#include <mbgl/util/value.hpp> #include <mbgl/util/chrono.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/util/vec.hpp> diff --git a/src/mbgl/util/value.hpp b/src/mbgl/util/value.hpp new file mode 100644 index 0000000000..78507c7f25 --- /dev/null +++ b/src/mbgl/util/value.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include <mbgl/util/variant.hpp> + +namespace mbgl { + +typedef variant<bool, int64_t, uint64_t, double, std::string> Value; + +} // namespace mbgl |