[core] Prepare Filter and FilterEvaluator for extraction (#5366)
This commit is contained in:
@@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user