Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core] Prepare Filter and FilterEvaluator for extraction (#5366)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfirebaugh authored Jun 15, 2016
1 parent 199ea2a commit a0b2982
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 98 deletions.
34 changes: 6 additions & 28 deletions benchmark/parse/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
});
}
}

Expand Down
42 changes: 26 additions & 16 deletions include/mbgl/style/filter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,15 @@

#include <mbgl/util/variant.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/geometry.hpp>

#include <string>
#include <vector>

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 {};

Expand Down Expand Up @@ -101,5 +87,29 @@ class NotHasFilter {
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
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -107,10 +122,10 @@ class FilterEvaluator {
}

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>
Expand Down Expand Up @@ -155,9 +170,12 @@ class FilterEvaluator {
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
7 changes: 7 additions & 0 deletions include/mbgl/util/geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>;

Expand Down
4 changes: 1 addition & 3 deletions src/mbgl/renderer/symbol_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 1 addition & 4 deletions src/mbgl/style/bucket_parameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
7 changes: 0 additions & 7 deletions src/mbgl/tile/geometry_tile_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
37 changes: 6 additions & 31 deletions test/style/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -14,43 +13,19 @@ 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);
return parseFilter(doc);
}

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) {
Expand Down

0 comments on commit a0b2982

Please sign in to comment.