diff options
-rw-r--r-- | benchmark/parse/filter.cpp | 34 | ||||
-rw-r--r-- | include/mbgl/style/filter.hpp | 42 | ||||
-rw-r--r-- | include/mbgl/style/filter_evaluator.hpp (renamed from src/mbgl/style/filter_evaluator.hpp) | 36 | ||||
-rw-r--r-- | include/mbgl/util/geometry.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/renderer/symbol_bucket.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/bucket_parameters.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_data.hpp | 7 | ||||
-rw-r--r-- | test/style/filter.cpp | 37 |
8 files changed, 74 insertions, 98 deletions
diff --git a/benchmark/parse/filter.cpp b/benchmark/parse/filter.cpp index 7450fc7804..8beff3b308 100644 --- a/benchmark/parse/filter.cpp +++ b/benchmark/parse/filter.cpp @@ -13,32 +13,6 @@ using namespace mbgl; typedef std::multimap<std::string, Value> Properties; -class StubFeature : public GeometryTileFeature { -public: - inline StubFeature(const Properties& properties_, FeatureType type_) - : properties(properties_), type(type_) { - } - - optional<Value> getValue(const std::string& key) const override { - auto it = properties.find(key); - if (it == properties.end()) - return optional<Value>(); - return it->second; - } - - FeatureType getType() const override { - return type; - } - - GeometryCollection getGeometries() const override { - return GeometryCollection(); - } - -private: - const Properties properties; - FeatureType type; -}; - style::Filter parse(const char* expression) { rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc; doc.Parse<0>(expression); @@ -54,10 +28,14 @@ static void Parse_Filter(benchmark::State& state) { static void Parse_EvaluateFilter(benchmark::State& state) { const style::Filter filter = parse(R"FILTER(["==", "foo", "bar"])FILTER"); const Properties properties = { { "foo", std::string("bar") } }; - const StubFeature feature(properties, FeatureType::Unknown); while (state.KeepRunning()) { - style::Filter::visit(filter, style::FilterEvaluator{ feature }); + filter(FeatureType::Unknown, [&] (const std::string& key) -> optional<Value> { + auto it = properties.find(key); + if (it == properties.end()) + return {}; + return it->second; + }); } } diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp index 9cf84f5e1d..6a5afb7b47 100644 --- a/include/mbgl/style/filter.hpp +++ b/include/mbgl/style/filter.hpp @@ -2,6 +2,7 @@ #include <mbgl/util/variant.hpp> #include <mbgl/util/feature.hpp> +#include <mbgl/util/geometry.hpp> #include <string> #include <vector> @@ -9,22 +10,7 @@ namespace mbgl { namespace style { -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, - class HasFilter, - class NotHasFilter - > Filter; +class Filter; class NullFilter {}; @@ -101,5 +87,29 @@ public: std::string key; }; +using FilterBase = 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, + class HasFilter, + class NotHasFilter>; + +class Filter : public FilterBase { +public: + using FilterBase::FilterBase; + + template <class PropertyAccessor> + bool operator()(FeatureType type, PropertyAccessor accessor) const; +}; + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp index 9d5919ced1..a458a2807b 100644 --- a/src/mbgl/style/filter_evaluator.hpp +++ b/include/mbgl/style/filter_evaluator.hpp @@ -1,17 +1,32 @@ #pragma once #include <mbgl/style/filter.hpp> -#include <mbgl/tile/geometry_tile_data.hpp> +#include <mbgl/util/geometry.hpp> #include <type_traits> namespace mbgl { namespace style { +/* + A visitor that evaluates a `Filter` for a given feature type and properties. For maximum + flexibility, it is templated on the PropertyAccessor type, which must be a callable type with + function signature `optional<Value> (const std::string&)`, returning the value for the given + key, if it exists. + + Use via `Filter::operator()`. For example: + + if (filter(feature.getType(), [&] (const std::string& key) { return feature.getValue(key); })) { + // matches the filter + } else { + // does not match + } +*/ +template <class PropertyAccessor> class FilterEvaluator { public: - FilterEvaluator(const GeometryTileFeature& feature_) - : feature(feature_) {} + const FeatureType featureType; + const PropertyAccessor propertyAccessor; bool operator()(const NullFilter&) const { return true; @@ -107,10 +122,10 @@ public: } private: - optional<Value> getValue(const std::string& key) const { - return key == "$type" - ? optional<Value>(uint64_t(feature.getType())) - : feature.getValue(key); + optional<Value> getValue(const std::string& key_) const { + return key_ == "$type" + ? optional<Value>(uint64_t(featureType)) + : propertyAccessor(key_); } template <class Op> @@ -155,9 +170,12 @@ private: bool equal(const Value& lhs, const Value& rhs) const { return compare(lhs, rhs, [] (const auto& lhs_, const auto& rhs_) { return lhs_ == rhs_; }); } - - const GeometryTileFeature& feature; }; +template <class PropertyAccessor> +inline bool Filter::operator()(FeatureType type, PropertyAccessor accessor) const { + return FilterBase::visit(*this, FilterEvaluator<PropertyAccessor> { type, accessor }); +} + } // namespace style } // namespace mbgl diff --git a/include/mbgl/util/geometry.hpp b/include/mbgl/util/geometry.hpp index 6b9c332bf2..7fc2668c2c 100644 --- a/include/mbgl/util/geometry.hpp +++ b/include/mbgl/util/geometry.hpp @@ -5,6 +5,13 @@ namespace mbgl { +enum class FeatureType : uint8_t { + Unknown = 0, + Point = 1, + LineString = 2, + Polygon = 3 +}; + template <class T> using Point = mapbox::geometry::point<T>; diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index e34aedb47e..496745dda1 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -119,9 +119,7 @@ void SymbolBucket::parseFeatures(const GeometryTileLayer& layer, const Filter& f const GLsizei featureCount = static_cast<GLsizei>(layer.featureCount()); for (GLsizei i = 0; i < featureCount; i++) { auto feature = layer.getFeature(i); - - FilterEvaluator evaluator(*feature); - if (!Filter::visit(filter, evaluator)) + if (!filter(feature->getType(), [&] (const auto& key) { return feature->getValue(key); })) continue; SymbolFeature ft; diff --git a/src/mbgl/style/bucket_parameters.cpp b/src/mbgl/style/bucket_parameters.cpp index 1a928dcecc..5bb08af873 100644 --- a/src/mbgl/style/bucket_parameters.cpp +++ b/src/mbgl/style/bucket_parameters.cpp @@ -10,11 +10,8 @@ void BucketParameters::eachFilteredFeature(const Filter& filter, auto name = layer.getName(); for (std::size_t i = 0; !cancelled() && i < layer.featureCount(); i++) { auto feature = layer.getFeature(i); - - FilterEvaluator evaluator(*feature); - if (!Filter::visit(filter, evaluator)) + if (!filter(feature->getType(), [&] (const auto& key) { return feature->getValue(key); })) continue; - function(*feature, i, name); } } diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp index 753ba6b8a2..1dc22e0c55 100644 --- a/src/mbgl/tile/geometry_tile_data.hpp +++ b/src/mbgl/tile/geometry_tile_data.hpp @@ -17,13 +17,6 @@ namespace mbgl { -enum class FeatureType : uint8_t { - Unknown = 0, - Point = 1, - LineString = 2, - Polygon = 3 -}; - class CanonicalTileID; // Normalized vector tile coordinates. diff --git a/test/style/filter.cpp b/test/style/filter.cpp index d28ee4a357..4a1010445e 100644 --- a/test/style/filter.cpp +++ b/test/style/filter.cpp @@ -3,7 +3,6 @@ #include <mbgl/style/filter.hpp> #include <mbgl/style/filter_evaluator.hpp> #include <mbgl/style/parser.hpp> -#include <mbgl/tile/geometry_tile_data.hpp> #include <rapidjson/document.h> @@ -14,33 +13,6 @@ using namespace mbgl::style; typedef std::multimap<std::string, mbgl::Value> Properties; -class StubFeature : public GeometryTileFeature { -public: - inline StubFeature(Properties properties_, FeatureType type_) - : properties(std::move(properties_)) - , type(type_) - {} - - optional<Value> getValue(const std::string &key) const override { - auto it = properties.find(key); - if (it == properties.end()) - return optional<Value>(); - return it->second; - } - - FeatureType getType() const override { - return type; - } - - GeometryCollection getGeometries() const override { - return GeometryCollection(); - } - -private: - const Properties properties; - FeatureType type; -}; - Filter parse(const char * expression) { rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc; doc.Parse<0>(expression); @@ -48,9 +20,12 @@ Filter parse(const char * expression) { } bool evaluate(const Filter& filter, const Properties& properties, FeatureType type = FeatureType::Unknown) { - StubFeature feature(properties, type); - FilterEvaluator evaluator(feature); - return Filter::visit(filter, evaluator); + return filter(type, [&] (const std::string& key) -> optional<Value> { + auto it = properties.find(key); + if (it == properties.end()) + return {}; + return it->second; + }); } TEST(Filter, EqualsString) { |