diff options
author | Lucas Wojciechowski <lucas@lucaswoj.com> | 2018-03-08 15:48:08 -0800 |
---|---|---|
committer | Tobrun <tobrun@mapbox.com> | 2018-03-09 11:12:14 +0100 |
commit | 8a3deab73373c8f3182e4337a3619ebcc58ecc2c (patch) | |
tree | 46774560da0eac1e710dccbf41af2f2e7e8794c4 /include/mbgl/style | |
parent | 6179110b6bfe8ee0880a055a31c12a88f9bd9b20 (diff) | |
download | qtlocation-mapboxgl-8a3deab73373c8f3182e4337a3619ebcc58ecc2c.tar.gz |
[core] Add expression filter support (#11251)
* WIP
* WIP
* WIP
* Remove Filter::operator()(const Feature&)
* WIP
* WIP
* WIP
* WIP
* Hook up expression filter evaluator
* Replace `shared_ptr` with &reference
* Fill in implementation of `void operator()(const ExpressionFilter&)`
* Fix failing tests
* Switch back to a shared_ptr per chat with @anandthakker
* Fix benchmark compilation
* Shot in the dark to fix CI
* Shot in the dark to fix CI (part 2)
* Shot in the dark to fix CI (part 3)
* In src/mbgl/style/conversion/filter.cpp, add a port of isExpressionFilter and use it to decide in Converter<Filter>::operator() whether to parse the incoming JSON as an ExpressionFilter or one of the legacy filter types
* Remove bool Filter::operator()(const GeometryTileFeature&) const
* Ensure the map zoom is passed into filtering operations wherever applicable
* Add expression filter tests
* Addressed PR feedback
* Implement `NSPredicate *operator()(mbgl::style::ExpressionFilter filter)`
* Fix formatting& nit
Diffstat (limited to 'include/mbgl/style')
-rw-r--r-- | include/mbgl/style/filter.hpp | 22 | ||||
-rw-r--r-- | include/mbgl/style/filter_evaluator.hpp | 259 |
2 files changed, 40 insertions, 241 deletions
diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp index a204a2b17a..ccf8dce188 100644 --- a/include/mbgl/style/filter.hpp +++ b/include/mbgl/style/filter.hpp @@ -3,6 +3,7 @@ #include <mbgl/util/variant.hpp> #include <mbgl/util/feature.hpp> #include <mbgl/util/geometry.hpp> +#include <mbgl/style/expression/expression.hpp> #include <string> #include <vector> @@ -232,6 +233,15 @@ public: return true; } }; + +class ExpressionFilter { +public: + std::shared_ptr<const expression::Expression> expression; + + friend bool operator==(const ExpressionFilter& lhs, const ExpressionFilter& rhs) { + return *(lhs.expression) == *(rhs.expression); + } +}; using FilterBase = variant< @@ -258,19 +268,13 @@ using FilterBase = variant< class IdentifierInFilter, class IdentifierNotInFilter, class HasIdentifierFilter, - class NotHasIdentifierFilter>; + class NotHasIdentifierFilter, + class ExpressionFilter>; class Filter : public FilterBase { public: using FilterBase::FilterBase; - - bool operator()(const Feature&) const; - - template <class GeometryTileFeature> - bool operator()(const GeometryTileFeature&) const; - - template <class PropertyAccessor> - bool operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const; + bool operator()(const expression::EvaluationContext& context) const; }; } // namespace style diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp index 66223d7282..a4a4098b3f 100644 --- a/include/mbgl/style/filter_evaluator.hpp +++ b/include/mbgl/style/filter_evaluator.hpp @@ -19,242 +19,37 @@ namespace style { // does not match } */ -template <class PropertyAccessor> class FilterEvaluator { public: - const FeatureType featureType; - const optional<FeatureIdentifier> featureIdentifier; - const PropertyAccessor propertyAccessor; + const expression::EvaluationContext context; + + bool operator()(const NullFilter&) const; + bool operator()(const EqualsFilter& filter) const; + bool operator()(const NotEqualsFilter& filter) const; + bool operator()(const LessThanFilter& filter) const; + bool operator()(const LessThanEqualsFilter& filter) const; + bool operator()(const GreaterThanFilter& filter) const; + bool operator()(const GreaterThanEqualsFilter& filter) const; + bool operator()(const InFilter& filter) const; + bool operator()(const NotInFilter& filter) const; + bool operator()(const AnyFilter& filter) const; + bool operator()(const AllFilter& filter) const; + bool operator()(const NoneFilter& filter) const; + bool operator()(const HasFilter& filter) const; + bool operator()(const NotHasFilter& filter) const; + bool operator()(const TypeEqualsFilter& filter) const; + bool operator()(const TypeNotEqualsFilter& filter) const; + bool operator()(const TypeInFilter& filter) const; + bool operator()(const TypeNotInFilter& filter) const; + bool operator()(const IdentifierEqualsFilter& filter) const; + bool operator()(const IdentifierNotEqualsFilter& filter) const; + bool operator()(const IdentifierInFilter& filter) const; + bool operator()(const IdentifierNotInFilter& filter) const; + bool operator()(const HasIdentifierFilter&) const; + bool operator()(const NotHasIdentifierFilter&) const; + bool operator()(const ExpressionFilter&) const; - bool operator()(const NullFilter&) const { - return true; - } - - bool operator()(const EqualsFilter& filter) const { - optional<Value> actual = propertyAccessor(filter.key); - return actual && equal(*actual, filter.value); - } - - bool operator()(const NotEqualsFilter& filter) const { - optional<Value> actual = propertyAccessor(filter.key); - return !actual || !equal(*actual, filter.value); - } - - bool operator()(const LessThanFilter& filter) const { - optional<Value> actual = propertyAccessor(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 = propertyAccessor(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 = propertyAccessor(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 = propertyAccessor(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 = propertyAccessor(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 = propertyAccessor(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; - } - - bool operator()(const HasFilter& filter) const { - return bool(propertyAccessor(filter.key)); - } - - bool operator()(const NotHasFilter& filter) const { - return !propertyAccessor(filter.key); - } - - - bool operator()(const TypeEqualsFilter& filter) const { - return featureType == filter.value; - } - - bool operator()(const TypeNotEqualsFilter& filter) const { - return featureType != filter.value; - } - - bool operator()(const TypeInFilter& filter) const { - for (const auto& v: filter.values) { - if (featureType == v) { - return true; - } - } - return false; - } - - bool operator()(const TypeNotInFilter& filter) const { - for (const auto& v: filter.values) { - if (featureType == v) { - return false; - } - } - return true; - } - - - bool operator()(const IdentifierEqualsFilter& filter) const { - return featureIdentifier == filter.value; - } - - bool operator()(const IdentifierNotEqualsFilter& filter) const { - return featureIdentifier != filter.value; - } - - bool operator()(const IdentifierInFilter& filter) const { - for (const auto& v: filter.values) { - if (featureIdentifier == v) { - return true; - } - } - return false; - } - - bool operator()(const IdentifierNotInFilter& filter) const { - for (const auto& v: filter.values) { - if (featureIdentifier == v) { - return false; - } - } - return true; - } - - bool operator()(const HasIdentifierFilter&) const { - return bool(featureIdentifier); - } - - bool operator()(const NotHasIdentifierFilter&) const { - return !featureIdentifier; - } - -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; - } - - bool operator()(const NullValue&, - const NullValue&) const { - // Should be unreachable; null is not currently allowed by the style specification. - assert(false); - return false; - } - - bool operator()(const std::vector<Value>&, - const std::vector<Value>&) const { - // Should be unreachable; nested values are not currently allowed by the style specification. - assert(false); - return false; - } - - bool operator()(const PropertyMap&, - const PropertyMap&) const { - // Should be unreachable; nested values are not currently allowed by the style specification. - assert(false); - 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_; }); - } }; -inline bool Filter::operator()(const Feature& feature) const { - return operator()(apply_visitor(ToFeatureType(), feature.geometry), feature.id, [&] (const std::string& key) -> optional<Value> { - auto it = feature.properties.find(key); - if (it == feature.properties.end()) - return {}; - return it->second; - }); -} - -template <class GeometryTileFeature> -bool Filter::operator()(const GeometryTileFeature& feature) const { - return operator()(feature.getType(), feature.getID(), [&] (const auto& key) { return feature.getValue(key); }); -} - -template <class PropertyAccessor> -bool Filter::operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const { - return FilterBase::visit(*this, FilterEvaluator<PropertyAccessor> { type, id, accessor }); -} - } // namespace style } // namespace mbgl |