summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-06-15 14:55:45 -0700
committerGitHub <noreply@github.com>2016-06-15 14:55:45 -0700
commita0b298211908036da269e7dcc2c78025476e2bf2 (patch)
tree3ef9df845e52290f8d6df918728c8eae92abd340 /include
parent199ea2a82a74cf2f7b63078e2dd4b8274c061851 (diff)
downloadqtlocation-mapboxgl-a0b298211908036da269e7dcc2c78025476e2bf2.tar.gz
[core] Prepare Filter and FilterEvaluator for extraction (#5366)
Diffstat (limited to 'include')
-rw-r--r--include/mbgl/style/filter.hpp42
-rw-r--r--include/mbgl/style/filter_evaluator.hpp181
-rw-r--r--include/mbgl/util/geometry.hpp7
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>;