diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-06-15 14:55:45 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-15 14:55:45 -0700 |
commit | a0b298211908036da269e7dcc2c78025476e2bf2 (patch) | |
tree | 3ef9df845e52290f8d6df918728c8eae92abd340 /include | |
parent | 199ea2a82a74cf2f7b63078e2dd4b8274c061851 (diff) | |
download | qtlocation-mapboxgl-a0b298211908036da269e7dcc2c78025476e2bf2.tar.gz |
[core] Prepare Filter and FilterEvaluator for extraction (#5366)
Diffstat (limited to 'include')
-rw-r--r-- | include/mbgl/style/filter.hpp | 42 | ||||
-rw-r--r-- | include/mbgl/style/filter_evaluator.hpp | 181 | ||||
-rw-r--r-- | include/mbgl/util/geometry.hpp | 7 |
3 files changed, 214 insertions, 16 deletions
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/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp new file mode 100644 index 0000000000..a458a2807b --- /dev/null +++ b/include/mbgl/style/filter_evaluator.hpp @@ -0,0 +1,181 @@ +#pragma once + +#include <mbgl/style/filter.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: + const FeatureType featureType; + const PropertyAccessor propertyAccessor; + + bool operator()(const NullFilter&) const { + return true; + } + + bool operator()(const EqualsFilter& filter) const { + optional<Value> actual = getValue(filter.key); + return actual && equal(*actual, filter.value); + } + + bool operator()(const NotEqualsFilter& filter) const { + optional<Value> actual = getValue(filter.key); + return !actual || !equal(*actual, filter.value); + } + + bool operator()(const LessThanFilter& filter) const { + optional<Value> actual = 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 = 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 = 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 = 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 = 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 = 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; + } + + bool operator()(const HasFilter& filter) const { + return bool(getValue(filter.key)); + } + + bool operator()(const NotHasFilter& filter) const { + return !getValue(filter.key); + } + +private: + optional<Value> getValue(const std::string& key_) const { + return key_ == "$type" + ? optional<Value>(uint64_t(featureType)) + : propertyAccessor(key_); + } + + 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 std::vector<Value>&, + const std::vector<Value>&) const { + return false; + } + + bool operator()(const std::unordered_map<std::string, Value>&, + const std::unordered_map<std::string, Value>&) const { + 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_; }); + } +}; + +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>; |