add filter expressions

This commit is contained in:
Konstantin Käfer
2014-06-26 15:04:18 +02:00
parent b95d023a98
commit aff667d742
14 changed files with 984 additions and 430 deletions

View File

@@ -4,125 +4,114 @@
#include <llmr/style/value.hpp>
#include <llmr/util/recursive_wrapper.hpp>
#include <vector>
#include <forward_list>
#include <string>
#include <ostream>
#include <iostream>
namespace llmr {
enum class FilterOperator {
Equal,
NotEqual,
Greater,
GreaterEqual,
Less,
LessEqual
};
class VectorTileTagExtractor;
enum class ExpressionOperator {
Or,
And
};
inline FilterOperator filterOperatorType(const std::string &op) {
if (op == "!=" || op == "not") {
return FilterOperator::NotEqual;
} else if (op == "==" || op == "eq") {
return FilterOperator::Equal;
} else if (op == ">" || op == "gt") {
return FilterOperator::Greater;
} else if (op == ">=" || op == "gte") {
return FilterOperator::GreaterEqual;
} else if (op == "<" || op == "lt") {
return FilterOperator::Less;
} else if (op == "<=" || op == "lte") {
return FilterOperator::LessEqual;
} else {
fprintf(stderr, "[WARNING] filter operator '%s' unrecognized\n", op.c_str());
return FilterOperator::Equal;
}
}
inline ExpressionOperator expressionOperatorType(const std::string &op) {
if (op == "&&" || op == "and") {
return ExpressionOperator::And;
} else if (op == "||" || op == "or") {
return ExpressionOperator::Or;
} else {
fprintf(stderr, "[WARNING] expression operator '%s' unrecognized\n", op.c_str());
return ExpressionOperator::Or;
}
}
class PropertyFilter;
class PropertyExpression;
typedef util::variant<
util::recursive_wrapper<PropertyFilter>,
util::recursive_wrapper<PropertyExpression>,
std::true_type
> PropertyFilterExpression;
class PropertyFilter {
class FilterComparison {
public:
inline PropertyFilter(const std::string &field, FilterOperator op, const Value &value) : field(field), op(op), value(value) {};
inline PropertyFilter(PropertyFilter &&filter)
: field(std::move(filter.field)),
op(filter.op),
value(std::move(filter.value)) {
}
enum class Operator : uint8_t {
Equal,
NotEqual,
Greater,
GreaterEqual,
Less,
LessEqual,
In,
NotIn
};
// Returns true if the filter passes, even if the key is missing.
inline bool isMissingFieldOkay() const {
switch (op) {
case FilterOperator::NotEqual:
return true;
default:
return false;
}
}
class Instance {
public:
Instance(Operator op, std::forward_list<Value> &&values)
: op(op), values(values) {}
inline bool compare(const Value &other) const {
switch (op) {
case FilterOperator::Equal:
return util::relaxed_equal(other, value);
case FilterOperator::NotEqual:
return !util::relaxed_equal(other, value);
case FilterOperator::Greater:
return util::relaxed_greater(other, value);
case FilterOperator::GreaterEqual:
return util::relaxed_greater_equal(other, value);
case FilterOperator::Less:
return util::relaxed_less(other, value);
case FilterOperator::LessEqual:
return util::relaxed_less_equal(other, value);
default:
return false;
}
}
bool compare(const Value &property_value) const;
bool compare(const std::forward_list<Value> &property_values) const;
private:
template <typename Comparer> inline bool includes(const Value &property_value, const Comparer &comparer) const;
template <typename Comparer> inline bool compare(const Value &property_value, const Comparer &comparer) const;
template <typename Comparer> inline bool all(const std::forward_list<Value> &property_values, const Comparer &comparer) const;
private:
Operator op = Operator::Equal;
std::forward_list<Value> values;
friend std::ostream& operator <<(std::ostream &, const Instance &);
};
public:
FilterComparison(const std::string &field) : field(field) {};
const std::string &getField() const;
inline bool compare(const VectorTileTagExtractor &extractor) const;
template <typename ...Args>
inline void add(Args&& ...args) {
instances.emplace_front(::std::forward<Args>(args)...);
}
private:
std::string field;
FilterOperator op = FilterOperator::Equal;
Value value;
std::forward_list<Instance> instances;
friend std::ostream& operator <<(std::ostream &, const FilterComparison &);
};
class PropertyExpression {
std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison);
std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance);
FilterComparison::Operator parseFilterComparisonOperator(const std::string &op);
class FilterExpression {
public:
inline PropertyExpression() {}
inline PropertyExpression(PropertyExpression &&expression)
: op(expression.op),
operands(std::move(expression.operands)) {
}
typedef util::recursive_wrapper<FilterExpression> Wrapper;
enum class Operator : uint8_t {
And,
Or,
Xor,
Nor
};
enum class GeometryType : uint8_t {
Any,
Point,
Line,
Polygon
};
public:
ExpressionOperator op = ExpressionOperator::Or;
std::vector<PropertyFilterExpression> operands;
FilterExpression() = default;
FilterExpression(Operator op) : op(op) {};
bool empty() const;
bool compare(const VectorTileTagExtractor &extractor) const;
void add(const FilterComparison &comparison);
void add(const FilterExpression &expression);
void setGeometryType(GeometryType g);
private:
Operator op = Operator::And;
GeometryType type = GeometryType::Any;
std::forward_list<FilterComparison> comparisons;
std::forward_list<FilterExpression::Wrapper> expressions;
friend std::ostream& operator <<(std::ostream &, const FilterExpression &);
};
std::ostream& operator <<(std::ostream &s, const FilterExpression &expression);
FilterExpression::GeometryType parseGeometryType(const std::string &geometry);
}
#endif

View File

@@ -42,13 +42,13 @@ private:
void addGlyph(uint64_t tileid, const std::string stackname, const std::u32string &string, const FontStack &fontStack, GlyphAtlas &glyphAtlas, GlyphPositions &face);
std::unique_ptr<Bucket> createBucket(std::shared_ptr<StyleBucket> bucket_desc);
std::unique_ptr<Bucket> createFillBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketFill &fill);
std::unique_ptr<Bucket> createLineBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketLine &line);
std::unique_ptr<Bucket> createIconBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketIcon &icon);
std::unique_ptr<Bucket> createTextBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketText &text);
std::unique_ptr<Bucket> createFillBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketFill &fill);
std::unique_ptr<Bucket> createLineBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketLine &line);
std::unique_ptr<Bucket> createIconBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketIcon &icon);
std::unique_ptr<Bucket> createTextBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketText &text);
template <class Bucket> void addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const PropertyFilterExpression &filter);
template <class Bucket, typename ...Args> void addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const PropertyFilterExpression &filter, Args&& ...args);
template <class Bucket> void addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const FilterExpression &filter);
template <class Bucket, typename ...Args> void addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const FilterExpression &filter, Args&& ...args);
private:
const VectorTile vector_data;

View File

@@ -40,6 +40,22 @@ public:
std::ostream& operator<<(std::ostream&, const VectorTileFeature& feature);
class VectorTileTagExtractor {
public:
VectorTileTagExtractor(const VectorTileLayer &layer);
void setTags(const pbf &pbf);
std::forward_list<Value> getValues(const std::string &key) const;
void setType(FilterExpression::GeometryType type);
FilterExpression::GeometryType getType() const;
private:
const VectorTileLayer &layer_;
pbf tags_;
FilterExpression::GeometryType type_ = FilterExpression::GeometryType::Any;
};
/*
* Allows iterating over the features of a VectorTileLayer using a
* BucketDescription as filter. Only features matching the descriptions will
@@ -54,11 +70,6 @@ public:
bool operator!=(const iterator& other) const;
const pbf& operator*() const;
private:
bool matchesFilterExpression(const PropertyFilterExpression &filterExpression, const pbf &tags_pbf);
bool matchesExpression(const PropertyExpression &expression, const pbf &tags_pbf);
bool matchesFilter(const PropertyFilter &filter, const pbf &tags_pbf);
private:
const FilteredVectorTileLayer& parent;
bool valid = false;
@@ -67,14 +78,14 @@ public:
};
public:
FilteredVectorTileLayer(const VectorTileLayer& layer, const PropertyFilterExpression &filterExpression);
FilteredVectorTileLayer(const VectorTileLayer& layer, const FilterExpression &filterExpression);
iterator begin() const;
iterator end() const;
private:
const VectorTileLayer& layer;
const PropertyFilterExpression& filterExpression;
const FilterExpression& filterExpression;
};
std::ostream& operator<<(std::ostream&, const GlyphPlacement& placement);

View File

@@ -22,7 +22,7 @@ public:
std::string source_name;
std::string source_layer;
PropertyFilterExpression filter = std::true_type();
FilterExpression filter;
// Specifies how the geometry for this bucket should be created
StyleBucketRender render;

View File

@@ -7,6 +7,7 @@
#include <llmr/util/variant.hpp>
#include <memory>
#include <forward_list>
namespace llmr {
@@ -73,7 +74,7 @@ public:
std::string name;
std::shared_ptr<Source> source;
std::string source_layer;
PropertyFilterExpression filter = std::true_type();
FilterExpression filter;
StyleBucketRender render = std::false_type();
};

View File

@@ -39,7 +39,6 @@ private:
void parseRasterize(JSVal value, std::shared_ptr<StyleLayer> &layer);
void parseReference(JSVal value, std::shared_ptr<StyleLayer> &layer);
void parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer);
void parseFilter(JSVal value, std::shared_ptr<StyleLayer> &layer);
void parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer);
// Parses optional properties into a render bucket.
@@ -54,9 +53,11 @@ private:
template <typename T>
bool parseStyleProperty(const char *property_name, const std::vector<ClassPropertyKey> &keys, ClassProperties &klass, JSVal value);
// PropertyFilterExpression parseFilterOrExpression(JSVal value);
// Value parseValue(JSVal value);
//
FilterExpression parseFilter(JSVal, FilterExpression::Operator op);
FilterExpression parseFilter(JSVal);
Value parseValue(JSVal value);
std::forward_list<Value> parseValues(JSVal values);
private:
std::unordered_map<std::string, const rapidjson::Value *> constants;

View File

@@ -62,6 +62,8 @@ template <> struct string_to_number<uint64_t> {
template <typename Operator>
struct relaxed_operator_visitor {
typedef bool result_type;
bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); }
template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
@@ -114,23 +116,23 @@ struct relaxed_less_equal_operator {
} // end namespace detail
inline bool relaxed_equal(Value const &lhs, Value const &rhs) {
return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor<detail::relaxed_equal_operator>());
return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_equal_operator>(), lhs, rhs);
}
inline bool relaxed_greater(Value const &lhs, Value const &rhs) {
return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor<detail::relaxed_greater_operator>());
return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_operator>(), lhs, rhs);
}
inline bool relaxed_greater_equal(Value const &lhs, Value const &rhs) {
return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor<detail::relaxed_greater_equal_operator>());
return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_equal_operator>(), lhs, rhs);
}
inline bool relaxed_less(Value const &lhs, Value const &rhs) {
return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor<detail::relaxed_less_operator>());
return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_operator>(), lhs, rhs);
}
inline bool relaxed_less_equal(Value const &lhs, Value const &rhs) {
return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor<detail::relaxed_less_equal_operator>());
return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_equal_operator>(), lhs, rhs);
}
}

View File

@@ -1,19 +1,15 @@
#ifndef LLMR_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#define LLMR_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#ifndef MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#define MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#include <utility>
namespace llmr {
namespace util {
namespace llmr { namespace util {
template <typename T>
class recursive_wrapper
{
public:
typedef T type;
using type = T;
private:
T* p_;
@@ -34,19 +30,19 @@ private:
public:
recursive_wrapper& operator=(const recursive_wrapper& rhs)
inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
{
assign( rhs.get() );
return *this;
}
recursive_wrapper& operator=(const T& rhs)
inline recursive_wrapper& operator=(T const& rhs)
{
assign( rhs );
return *this;
}
void swap(recursive_wrapper& operand) noexcept
inline void swap(recursive_wrapper& operand) noexcept
{
T* temp = operand.p_;
operand.p_ = p_;
@@ -71,10 +67,10 @@ public:
T& get() { return *get_pointer(); }
const T& get() const { return *get_pointer(); }
T* get_pointer() { return p_; }
const T* get_pointer() const { return p_; }
operator T const&() const { return this->get(); }
operator T&() { return this->get(); }
};
template <typename T>
@@ -103,8 +99,9 @@ recursive_wrapper<T>::recursive_wrapper(T const& operand)
template <typename T>
recursive_wrapper<T>::recursive_wrapper(recursive_wrapper&& operand)
: p_(new T( std::move(operand.get()) ))
: p_(operand.p_)
{
operand.p_ = nullptr;
}
template <typename T>
@@ -125,8 +122,6 @@ inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
lhs.swap(rhs);
}
}
}}
}
#endif // LLMR_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#endif // MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP

View File

@@ -1,5 +1,5 @@
#ifndef UTIL_VARIANT_HPP
#define UTIL_VARIANT_HPP
#ifndef MAPBOX_UTIL_VARIANT_HPP
#define MAPBOX_UTIL_VARIANT_HPP
#include <utility>
#include <typeinfo>
@@ -9,50 +9,119 @@
#include <new> // operator new
#include <cstddef> // size_t
#include <iosfwd>
#include <string>
#ifdef NDEBUG
#define VARIANT_INLINE inline __attribute__((always_inline))
#include "recursive_wrapper.hpp"
#ifdef _MSC_VER
// http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx
#ifdef NDEBUG
#define VARIANT_INLINE __forceinline
#else
#define VARIANT_INLINE __declspec(noinline)
#endif
#else
#define VARIANT_INLINE __attribute__((noinline))
#ifdef NDEBUG
#define VARIANT_INLINE inline __attribute__((always_inline))
#else
#define VARIANT_INLINE __attribute__((noinline))
#endif
#endif
namespace llmr {
#define VARIANT_MAJOR_VERSION 0
#define VARIANT_MINOR_VERSION 1
#define VARIANT_PATCH_VERSION 0
namespace util {
// translates to 100
#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION)
namespace detail {
namespace llmr { namespace util { namespace detail {
static constexpr std::size_t invalid_value = std::size_t(-1);
template <typename T, typename...Types>
struct type_traits;
struct direct_type;
template <typename T, typename First, typename...Types>
struct type_traits<T, First, Types...>
struct direct_type<T, First, Types...>
{
static constexpr std::size_t id = std::is_same<T, First>::value ? sizeof...(Types) : type_traits<T, Types...>::id;
static constexpr std::size_t index = std::is_same<T, First>::value
? sizeof...(Types) : direct_type<T, Types...>::index;
};
template <typename T>
struct type_traits<T>
struct direct_type<T>
{
static constexpr std::size_t id = invalid_value;
static constexpr std::size_t index = invalid_value;
};
template <typename T, typename...Types>
struct convertible_type;
template <typename T, typename First, typename...Types>
struct convertible_type<T, First, Types...>
{
static constexpr std::size_t index = std::is_convertible<T, First>::value
? sizeof...(Types) : convertible_type<T, Types...>::index;
};
template <typename T>
struct convertible_type<T>
{
static constexpr std::size_t index = invalid_value;
};
template <typename T, typename...Types>
struct value_traits
{
static constexpr std::size_t direct_index = direct_type<T, Types...>::index;
static constexpr std::size_t index =
(direct_index == invalid_value) ? convertible_type<T, Types...>::index : direct_index;
};
template <typename T, typename...Types>
struct is_valid_type;
template <typename T, typename First, typename... Types>
struct is_valid_type<T,First,Types...>
struct is_valid_type<T, First, Types...>
{
static constexpr bool value = std::is_same<T,First>::value
|| is_valid_type<T,Types...>::value;
static constexpr bool value = std::is_convertible<T, First>::value
|| is_valid_type<T, Types...>::value;
};
template <typename T>
struct is_valid_type<T> : std::false_type {};
}
template <std::size_t N, typename ... Types>
struct select_type
{
static_assert(N < sizeof...(Types), "index out of bounds");
};
template <std::size_t N, typename T, typename ... Types>
struct select_type<N, T, Types...>
{
using type = typename select_type<N - 1, Types...>::type;
};
template <typename T, typename ... Types>
struct select_type<0, T, Types...>
{
using type = T;
};
} // namespace detail
// static visitor
template <typename R = void>
struct static_visitor
{
using result_type = R;
protected:
static_visitor() {}
~static_visitor() {}
};
template <std::size_t arg1, std::size_t ... others>
struct static_max;
@@ -125,37 +194,77 @@ template<> struct variant_helper<>
namespace detail {
template <typename T>
struct unwrapper
{
T const& operator() (T const& obj) const
{
return obj;
}
T& operator() (T & obj) const
{
return obj;
}
};
template <typename T>
struct unwrapper<recursive_wrapper<T>>
{
auto operator() (recursive_wrapper<T> const& obj) const
-> typename recursive_wrapper<T>::type const&
{
return obj.get();
}
};
template <typename F, typename V, typename...Types>
struct dispatcher;
template <typename F, typename V, typename T, typename...Types>
struct dispatcher<F,V,T,Types...>
struct dispatcher<F, V, T, Types...>
{
typedef typename std::result_of<F(V const&)>::type result_type;
VARIANT_INLINE static result_type apply(V const& v, F f)
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const& v, F f)
{
if (v.get_type_id() == sizeof...(Types))
if (v.get_type_index() == sizeof...(Types))
{
return f(v. template get<T>());
return f(unwrapper<T>()(v. template get<T>()));
}
else
{
return dispatcher<F,V,Types...>::apply(v, f);
return dispatcher<F, V, Types...>::apply_const(v, f);
}
}
VARIANT_INLINE static result_type apply(V & v, F f)
{
if (v.get_type_index() == sizeof...(Types))
{
return f(unwrapper<T>()(v. template get<T>()));
}
else
{
return dispatcher<F, V, Types...>::apply(v, f);
}
}
};
template<typename F,typename V>
struct dispatcher<F,V>
template<typename F, typename V>
struct dispatcher<F, V>
{
typedef typename std::result_of<F(V const&)>::type result_type;
VARIANT_INLINE static result_type apply(V const&, F)
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const&, F)
{
throw std::runtime_error("unary dispatch: FAIL");
throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name());
}
VARIANT_INLINE static result_type apply(V &, F)
{
throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name());
}
};
@@ -163,28 +272,46 @@ template <typename F, typename V, typename T, typename...Types>
struct binary_dispatcher_rhs;
template <typename F, typename V, typename T0, typename T1, typename...Types>
struct binary_dispatcher_rhs<F,V,T0,T1,Types...>
struct binary_dispatcher_rhs<F, V, T0, T1, Types...>
{
typedef typename std::result_of<F(V const&, V const&)>::type result_type;
VARIANT_INLINE static result_type apply(V const& lhs, V const& rhs, F f)
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f)
{
if (rhs.get_type_id() == sizeof...(Types)) // call binary functor
if (rhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(lhs. template get<T0>(), rhs. template get<T1>());
return f(unwrapper<T0>()(lhs. template get<T0>()),
unwrapper<T1>()(rhs. template get<T1>()));
}
else
{
return binary_dispatcher_rhs<F,V,T0,Types...>::apply(lhs, rhs, f);
return binary_dispatcher_rhs<F, V, T0, Types...>::apply_const(lhs, rhs, f);
}
}
VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f)
{
if (rhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(unwrapper<T0>()(lhs. template get<T0>()),
unwrapper<T1>()(rhs. template get<T1>()));
}
else
{
return binary_dispatcher_rhs<F, V, T0, Types...>::apply(lhs, rhs, f);
}
}
};
template<typename F,typename V, typename T>
struct binary_dispatcher_rhs<F,V,T>
template<typename F, typename V, typename T>
struct binary_dispatcher_rhs<F, V, T>
{
typedef typename std::result_of<F(V const&, V const&)>::type result_type;
VARIANT_INLINE static result_type apply(V const&, V const&, F)
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const&, V const&, F)
{
throw std::runtime_error("binary dispatch: FAIL");
}
VARIANT_INLINE static result_type apply(V &, V &, F)
{
throw std::runtime_error("binary dispatch: FAIL");
}
@@ -195,28 +322,45 @@ template <typename F, typename V, typename T, typename...Types>
struct binary_dispatcher_lhs;
template <typename F, typename V, typename T0, typename T1, typename...Types>
struct binary_dispatcher_lhs<F,V,T0,T1,Types...>
struct binary_dispatcher_lhs<F, V, T0, T1, Types...>
{
typedef typename std::result_of<F(V const&, V const&)>::type binary_result_type;
VARIANT_INLINE static binary_result_type apply(V const& lhs, V const& rhs, F f)
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f)
{
if (lhs.get_type_id() == sizeof...(Types)) // call binary functor
if (lhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(lhs. template get<T1>(), rhs. template get<T0>());
}
else
{
return binary_dispatcher_lhs<F,V,T0,Types...>::apply(lhs, rhs, f);
return binary_dispatcher_lhs<F, V, T0, Types...>::apply_const(lhs, rhs, f);
}
}
VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f)
{
if (lhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(lhs. template get<T1>(), rhs. template get<T0>());
}
else
{
return binary_dispatcher_lhs<F, V, T0, Types...>::apply(lhs, rhs, f);
}
}
};
template<typename F,typename V, typename T>
struct binary_dispatcher_lhs<F,V,T>
template<typename F, typename V, typename T>
struct binary_dispatcher_lhs<F, V, T>
{
typedef typename std::result_of<F(V const&, V const&)>::type result_type;
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const&, V const&, F)
{
throw std::runtime_error("binary dispatch: FAIL");
}
VARIANT_INLINE static result_type apply(V const&, V const&, F)
VARIANT_INLINE static result_type apply(V &, V &, F)
{
throw std::runtime_error("binary dispatch: FAIL");
}
@@ -226,37 +370,60 @@ template <typename F, typename V, typename...Types>
struct binary_dispatcher;
template <typename F, typename V, typename T, typename...Types>
struct binary_dispatcher<F,V,T,Types...>
struct binary_dispatcher<F, V, T, Types...>
{
typedef typename std::result_of<F(V const&, V const&)>::type binary_result_type;
VARIANT_INLINE static binary_result_type apply(V const& v0, V const& v1, F f)
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f)
{
if (v0.get_type_id() == sizeof...(Types))
if (v0.get_type_index() == sizeof...(Types))
{
if (v0.get_type_id() == v1.get_type_id())
if (v0.get_type_index() == v1.get_type_index())
{
return f(v0. template get<T>(), v1. template get<T>()); // call binary functor
}
else
{
return binary_dispatcher_rhs<F,V,T,Types...>::apply(v0, v1, f);
return binary_dispatcher_rhs<F, V, T, Types...>::apply_const(v0, v1, f);
}
}
else if (v1.get_type_id() == sizeof...(Types))
else if (v1.get_type_index() == sizeof...(Types))
{
return binary_dispatcher_lhs<F,V,T,Types...>::apply(v0, v1, f);
return binary_dispatcher_lhs<F, V, T, Types...>::apply_const(v0, v1, f);
}
return binary_dispatcher<F,V,Types...>::apply(v0, v1, f);
return binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f);
}
VARIANT_INLINE static result_type apply(V & v0, V & v1, F f)
{
if (v0.get_type_index() == sizeof...(Types))
{
if (v0.get_type_index() == v1.get_type_index())
{
return f(v0. template get<T>(), v1. template get<T>()); // call binary functor
}
else
{
return binary_dispatcher_rhs<F, V, T, Types...>::apply(v0, v1, f);
}
}
else if (v1.get_type_index() == sizeof...(Types))
{
return binary_dispatcher_lhs<F, V, T, Types...>::apply(v0, v1, f);
}
return binary_dispatcher<F, V, Types...>::apply(v0, v1, f);
}
};
template<typename F,typename V>
struct binary_dispatcher<F,V>
template<typename F, typename V>
struct binary_dispatcher<F, V>
{
typedef typename std::result_of<F(V const&, V const&)>::type binary_result_type;
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const&, V const&, F)
{
throw std::runtime_error("binary dispatch: FAIL");
}
VARIANT_INLINE static binary_result_type apply(V const&, V const&, F)
VARIANT_INLINE static result_type apply(V &, V &, F)
{
throw std::runtime_error("binary dispatch: FAIL");
}
@@ -275,19 +442,19 @@ struct equal_comp
struct less_comp
{
template <typename T>
bool operator()(const T& lhs, const T& rhs) const
bool operator()(T const& lhs, T const& rhs) const
{
return lhs < rhs;
}
};
template <typename Variant, typename Comp>
class comparer
class comparer : public static_visitor<bool>
{
public:
explicit comparer(Variant const& lhs) noexcept
: lhs_(lhs) {}
comparer& operator=(const comparer&) = delete;
comparer& operator=(comparer const&) = delete;
// visitor
template<typename T>
bool operator()(T const& rhs_content) const
@@ -301,16 +468,16 @@ private:
// operator<< helper
template <typename Out>
class printer
class printer : public static_visitor<>
{
public:
explicit printer(Out & out)
: out_(out) {}
printer& operator=(printer const &) = delete;
printer& operator=(printer const&) = delete;
// visitor
template <typename T>
void operator()( T const & operand) const
void operator()(T const& operand) const
{
out_ << operand;
}
@@ -318,7 +485,7 @@ private:
Out & out_;
};
} // detail
} // namespace detail
template<typename... Types>
class variant
@@ -329,81 +496,106 @@ private:
static const std::size_t data_align = static_max<alignof(Types)...>::value;
using data_type = typename std::aligned_storage<data_size, data_align>::type;
using helper_type = variant_helper<Types...>;
std::size_t type_id;
std::size_t type_index;
data_type data;
public:
VARIANT_INLINE variant()
: type_id(detail::invalid_value) {}
template <typename T>
VARIANT_INLINE explicit variant(T const& val) noexcept
: type_id(detail::type_traits<T, Types...>::id)
: type_index(sizeof...(Types) - 1)
{
static_assert(detail::is_valid_type<T,Types...>::value, "Not a valid type for this variant");
new (&data) T(val);
new (&data) typename detail::select_type<0, Types...>::type();
}
template <typename T>
VARIANT_INLINE variant(T && val) noexcept
: type_id(detail::type_traits<T,Types...>::id)
template <typename T, class = typename std::enable_if<
detail::is_valid_type<T, Types...>::value>::type>
VARIANT_INLINE explicit variant(T const& val) noexcept
: type_index(detail::value_traits<T, Types...>::index)
{
static_assert(detail::is_valid_type<T,Types...>::value, "Not a valid type for this variant");
new (&data) T(std::forward<T>(val)); // nothrow
constexpr std::size_t index = sizeof...(Types) - detail::value_traits<T, Types...>::index - 1;
using target_type = typename detail::select_type<index, Types...>::type;
new (&data) target_type(val);
}
template <typename T, class = typename std::enable_if<
detail::is_valid_type<T, Types...>::value>::type>
VARIANT_INLINE variant(T && val) noexcept
: type_index(detail::value_traits<T, Types...>::index)
{
constexpr std::size_t index = sizeof...(Types) - detail::value_traits<T, Types...>::index - 1;
using target_type = typename detail::select_type<index, Types...>::type;
new (&data) target_type(std::forward<T>(val)); // nothrow
}
VARIANT_INLINE variant(variant<Types...> const& old)
: type_id(old.type_id)
: type_index(old.type_index)
{
helper_type::copy(old.type_id, &old.data, &data);
helper_type::copy(old.type_index, &old.data, &data);
}
VARIANT_INLINE variant(variant<Types...>&& old) noexcept
: type_id(old.type_id)
: type_index(old.type_index)
{
helper_type::move(old.type_id, &old.data, &data);
helper_type::move(old.type_index, &old.data, &data);
}
friend void swap(variant<Types...> & first, variant<Types...> & second)
{
using std::swap; //enable ADL
swap(first.type_id, second.type_id);
swap(first.type_index, second.type_index);
swap(first.data, second.data);
}
VARIANT_INLINE variant<Types...>& operator= (variant<Types...> other)
VARIANT_INLINE variant<Types...>& operator=(variant<Types...> other)
{
swap(*this, other);
return *this;
}
// conversions
// move-assign
template <typename T>
VARIANT_INLINE variant<Types...>& operator=(T && rhs) noexcept
{
variant<Types...> temp(std::move(rhs));
swap(*this, temp);
return *this;
}
// copy-assign
template <typename T>
VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
{
variant<Types...> temp(rhs);
swap(*this, temp);
return *this;
}
template<typename T>
VARIANT_INLINE bool is() const
{
return (type_id == detail::type_traits<T, Types...>::id);
return (type_index == detail::direct_type<T, Types...>::index);
}
VARIANT_INLINE bool valid() const
{
return (type_id != detail::invalid_value);
return (type_index != detail::invalid_value);
}
template<typename T, typename... Args>
VARIANT_INLINE void set(Args&&... args)
{
helper_type::destroy(type_id, &data);
helper_type::destroy(type_index, &data);
new (&data) T(std::forward<Args>(args)...);
type_id = detail::type_traits<T,Types...>::id;
type_index = detail::direct_type<T, Types...>::index;
}
template<typename T>
VARIANT_INLINE T& get()
{
if (type_id == detail::type_traits<T,Types...>::id)
if (type_index == detail::direct_type<T, Types...>::index)
{
return *reinterpret_cast<T*>(&data);
}
@@ -416,7 +608,7 @@ public:
template<typename T>
VARIANT_INLINE T const& get() const
{
if (type_id == detail::type_traits<T,Types...>::id)
if (type_index == detail::direct_type<T, Types...>::index)
{
return *reinterpret_cast<T const*>(&data);
}
@@ -426,37 +618,57 @@ public:
}
}
VARIANT_INLINE std::size_t get_type_id() const
VARIANT_INLINE std::size_t get_type_index() const
{
return type_id;
return type_index;
}
// visitor
// unary
template <typename F, typename V>
typename std::result_of<F(V const&)>::type
VARIANT_INLINE static visit(V const& v, F f)
auto VARIANT_INLINE
static visit(V const& v, F f)
-> decltype(detail::dispatcher<F, V, Types...>::apply_const(v, f))
{
return detail::dispatcher<F, V, Types...>::apply_const(v, f);
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE
static visit(V & v, F f)
-> decltype(detail::dispatcher<F, V, Types...>::apply(v, f))
{
return detail::dispatcher<F, V, Types...>::apply(v, f);
}
// binary
// const
template <typename F, typename V>
typename std::result_of<F(V const&, V const& )>::type
VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F f)
auto VARIANT_INLINE
static binary_visit(V const& v0, V const& v1, F f)
-> decltype(detail::binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f))
{
return detail::binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f);
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE
static binary_visit(V& v0, V& v1, F f)
-> decltype(detail::binary_dispatcher<F, V, Types...>::apply(v0, v1, f))
{
return detail::binary_dispatcher<F, V, Types...>::apply(v0, v1, f);
}
~variant() noexcept
{
helper_type::destroy(type_id, &data);
helper_type::destroy(type_index, &data);
}
// comparison operators
// equality
VARIANT_INLINE bool operator==(variant const& rhs) const
{
if (this->get_type_id() != rhs.get_type_id())
if (this->get_type_index() != rhs.get_type_index())
return false;
detail::comparer<variant, detail::equal_comp> visitor(*this);
return visit(rhs, visitor);
@@ -464,9 +676,9 @@ public:
// less than
VARIANT_INLINE bool operator<(variant const& rhs) const
{
if (this->get_type_id() != rhs.get_type_id())
if (this->get_type_index() != rhs.get_type_index())
{
return this->get_type_id() < rhs.get_type_id();
return this->get_type_index() < rhs.get_type_index();
// ^^ borrowed from boost::variant
}
detail::comparer<variant, detail::less_comp> visitor(*this);
@@ -475,17 +687,30 @@ public:
};
// unary visitor interface
// const
template <typename V, typename F>
typename std::result_of<F(V const&)>::type
VARIANT_INLINE static apply_visitor(V const& v, F f)
auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f))
{
return V::visit(v,f);
return V::visit(v, f);
}
// non-const
template <typename V, typename F>
auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f))
{
return V::visit(v, f);
}
// binary visitor interface
// const
template <typename V, typename F>
typename std::result_of<F(V const&, V const&)>::type
VARIANT_INLINE static apply_visitor(V const& v0, V const& v1, F f)
auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f))
{
return V::binary_visit(v0, v1, f);
}
// non-const
template <typename V, typename F>
auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f))
{
return V::binary_visit(v0, v1, f);
}
@@ -493,14 +718,14 @@ VARIANT_INLINE static apply_visitor(V const& v0, V const& v1, F f)
// operator<<
template <typename charT, typename traits, typename Variant>
VARIANT_INLINE std::basic_ostream<charT,traits>&
operator<< (std::basic_ostream<charT,traits>& out, Variant const& rhs)
VARIANT_INLINE std::basic_ostream<charT, traits>&
operator<< (std::basic_ostream<charT, traits>& out, Variant const& rhs)
{
detail::printer<std::basic_ostream<charT,traits> > visitor(out);
apply_visitor(rhs, visitor);
detail::printer<std::basic_ostream<charT, traits>> visitor(out);
apply_visitor(visitor, rhs);
return out;
}
}
}
#endif // UTIL_VARIANT_HPP
}}
#endif // MAPBOX_UTIL_VARIANT_HPP

View File

@@ -0,0 +1,282 @@
#include <llmr/map/filter_expression.hpp>
#include <llmr/map/vector_tile.hpp>
namespace llmr {
template <typename Comparer>
inline bool FilterComparison::Instance::includes(const Value &property_value, const Comparer &comparer) const {
for (const Value &filter_value : values) {
if (comparer(property_value, filter_value)) {
return true;
}
}
return false;
}
template <typename Comparer>
inline bool FilterComparison::Instance::compare(const Value &property_value, const Comparer &comparer) const {
for (const Value &filter_value : values) {
if (!comparer(property_value, filter_value)) {
return false;
}
}
return true;
}
template <typename Comparer>
inline bool FilterComparison::Instance::all(const std::forward_list<Value> &property_values, const Comparer &comparer) const {
for (const Value &property_value : property_values) {
if (!compare(property_value, comparer)) {
return false;
}
}
return true;
}
bool FilterComparison::Instance::compare(const Value &property_value) const {
switch (op) {
case Operator::Equal:
case Operator::In:
return includes(property_value, util::relaxed_equal);
case Operator::NotEqual:
case Operator::NotIn:
return !includes(property_value, util::relaxed_equal);
case Operator::Greater:
return compare(property_value, util::relaxed_greater);
case Operator::GreaterEqual:
return compare(property_value, util::relaxed_greater_equal);
case Operator::Less:
return compare(property_value, util::relaxed_less);
case Operator::LessEqual:
return compare(property_value, util::relaxed_less_equal);
default:
return false;
}
}
bool FilterComparison::Instance::compare(const std::forward_list<Value> &property_values) const {
switch (op) {
case Operator::Equal:
for (const Value &property_value : property_values) {
if (!includes(property_value, util::relaxed_equal)) {
return false;
}
}
return true;
case Operator::NotEqual:
for (const Value &property_value : property_values) {
if (includes(property_value, util::relaxed_equal)) {
return false;
}
}
return true;
case Operator::In:
for (const Value &property_value : property_values) {
if (includes(property_value, util::relaxed_equal)) {
return true;
}
}
return false;
case Operator::NotIn:
for (const Value &property_value : property_values) {
if (!includes(property_value, util::relaxed_equal)) {
return true;
}
}
return false;
case Operator::Greater:
return all(property_values, util::relaxed_greater);
case Operator::GreaterEqual:
return all(property_values, util::relaxed_greater_equal);
case Operator::Less:
return all(property_values, util::relaxed_less);
case Operator::LessEqual:
return all(property_values, util::relaxed_less_equal);
}
}
const std::string &FilterComparison::getField() const {
return field;
}
inline bool FilterComparison::compare(const VectorTileTagExtractor &extractor) const {
const std::forward_list<Value> values = extractor.getValues(field);
// All instances are ANDed together.
for (const Instance &instance : instances) {
if (!instance.compare(values)) {
return false;
}
}
return true;
}
std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison) {
s << "comparison" << std::endl;
for (const FilterComparison::Instance &instance : comparison.instances) {
s << " - " << comparison.field << " " << instance << std::endl;
}
return s;
}
std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance) {
switch (instance.op) {
case FilterComparison::Operator::Equal: s << "=="; break;
case FilterComparison::Operator::NotEqual: s << "!="; break;
case FilterComparison::Operator::Greater: s << ">"; break;
case FilterComparison::Operator::GreaterEqual: s << ">="; break;
case FilterComparison::Operator::Less: s << "<"; break;
case FilterComparison::Operator::LessEqual: s << "<="; break;
case FilterComparison::Operator::In: s << "in"; break;
case FilterComparison::Operator::NotIn: s << "!in"; break;
}
s << " [ ";
for (const Value &value : instance.values) {
s << toString(value) << " ";
}
s << "]";
return s;
}
FilterComparison::Operator parseFilterComparisonOperator(const std::string &op) {
if (op == "==") return FilterComparison::Operator::Equal;
if (op == "!=") return FilterComparison::Operator::NotEqual;
if (op == ">") return FilterComparison::Operator::Greater;
if (op == ">=") return FilterComparison::Operator::GreaterEqual;
if (op == "<") return FilterComparison::Operator::Less;
if (op == "<=") return FilterComparison::Operator::LessEqual;
if (op == "in") return FilterComparison::Operator::In;
if (op == "!in") return FilterComparison::Operator::NotIn;
return FilterComparison::Operator::Equal;
}
std::ostream& operator <<(std::ostream &s, FilterExpression::Operator op) {
switch (op) {
case FilterExpression::Operator::And: s << "AND"; break;
case FilterExpression::Operator::Or: s << "OR"; break;
case FilterExpression::Operator::Xor: s << "XOR"; break;
case FilterExpression::Operator::Nor: s << "NOR"; break;
}
return s;
}
std::ostream& operator <<(std::ostream &s, FilterExpression::GeometryType type) {
switch (type) {
case FilterExpression::GeometryType::Point: s << "point"; break;
case FilterExpression::GeometryType::Line: s << "line"; break;
case FilterExpression::GeometryType::Polygon: s << "polygon"; break;
case FilterExpression::GeometryType::Any: s << "any"; break;
}
return s;
}
bool FilterExpression::compare(const VectorTileTagExtractor &extractor) const {
if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) {
return false;
}
switch (op) {
case Operator::And:
for (const FilterComparison &comparison : comparisons) {
if (!comparison.compare(extractor)) {
return false;
}
}
for (const FilterExpression &expression: expressions) {
if (!expression.compare(extractor)) {
return false;
}
}
return true;
case Operator::Or:
for (const FilterComparison &comparison : comparisons) {
if (comparison.compare(extractor)) {
return true;
}
}
for (const FilterExpression &expression: expressions) {
if (expression.compare(extractor)) {
return true;
}
}
return false;
case Operator::Xor: {
int count = 0;
for (const FilterComparison &comparison : comparisons) {
count += comparison.compare(extractor);
if (count > 1) {
return false;
}
}
for (const FilterExpression &expression: expressions) {
count += expression.compare(extractor);
if (count > 1) {
return false;
}
}
return count == 1;
}
case Operator::Nor:
for (const FilterComparison &comparison : comparisons) {
if (comparison.compare(extractor)) {
return false;
}
}
for (const FilterExpression &expression: expressions) {
if (expression.compare(extractor)) {
return false;
}
}
return true;
default:
return true;
}
}
bool FilterExpression::empty() const {
return type == GeometryType::Any && comparisons.empty() && expressions.empty();
}
void FilterExpression::add(const FilterComparison &comparison) {
comparisons.emplace_front(comparison);
}
void FilterExpression::add(const FilterExpression &expression) {
expressions.emplace_front(expression);
}
void FilterExpression::setGeometryType(GeometryType g) {
type = g;
}
FilterExpression::GeometryType parseGeometryType(const std::string &geometry) {
if (geometry == "point") return FilterExpression::GeometryType::Point;
if (geometry == "line") return FilterExpression::GeometryType::Line;
if (geometry == "polygon") return FilterExpression::GeometryType::Polygon;
return FilterExpression::GeometryType::Any;
}
std::ostream& operator <<(std::ostream &s, const FilterExpression &expression) {
s << "expression " << expression.op << std::endl;
s << " - $type = " << expression.type << std::endl;
for (const FilterComparison &comparison : expression.comparisons) {
s << comparison;
}
s << "end expression" << std::endl;
return s;
}
}

View File

@@ -169,8 +169,6 @@ void Map::setup() {
view.make_active();
painter.setup();
setStyleJSON(styleJSON);
}
void Map::setStyleJSON(std::string newStyleJSON) {

View File

@@ -132,7 +132,7 @@ std::unique_ptr<Bucket> TileParser::createBucket(std::shared_ptr<StyleBucket> bu
}
template <class Bucket>
void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const PropertyFilterExpression &filter) {
void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const FilterExpression &filter) {
FilteredVectorTileLayer filtered_layer(layer, filter);
for (pbf feature : filtered_layer) {
if (obsolete())
@@ -150,7 +150,7 @@ void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer,
}
template <class Bucket, typename... Args>
void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const PropertyFilterExpression &filter, Args&& ...args) {
void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const FilterExpression &filter, Args&& ...args) {
FilteredVectorTileLayer filtered_layer(layer, filter);
for (const pbf &feature_pbf : filtered_layer) {
if (obsolete()) {
@@ -161,25 +161,25 @@ void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer,
}
std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketFill &fill) {
std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketFill &fill) {
std::unique_ptr<FillBucket> bucket = std::make_unique<FillBucket>(tile.fillVertexBuffer, tile.triangleElementsBuffer, tile.lineElementsBuffer, fill);
addBucketFeatures(bucket, layer, filter);
return obsolete() ? nullptr : std::move(bucket);
}
std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketLine &line) {
std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketLine &line) {
std::unique_ptr<LineBucket> bucket = std::make_unique<LineBucket>(tile.lineVertexBuffer, tile.triangleElementsBuffer, tile.pointElementsBuffer, line);
addBucketFeatures(bucket, layer, filter);
return obsolete() ? nullptr : std::move(bucket);
}
std::unique_ptr<Bucket> TileParser::createIconBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketIcon &icon) {
std::unique_ptr<Bucket> TileParser::createIconBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketIcon &icon) {
std::unique_ptr<IconBucket> bucket = std::make_unique<IconBucket>(tile.iconVertexBuffer, icon);
addBucketFeatures(bucket, layer, filter, *spriteAtlas);
return obsolete() ? nullptr : std::move(bucket);
}
std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& layer, const PropertyFilterExpression &filter, const StyleBucketText &text) {
std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketText &text) {
const StyleBucketText &properties = text;
@@ -235,9 +235,3 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& laye
return std::move(bucket);
}
//typedef std::pair<uint16_t, uint16_t> GlyphRange;
//

View File

@@ -102,7 +102,7 @@ VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) {
}
}
FilteredVectorTileLayer::FilteredVectorTileLayer(const VectorTileLayer& layer, const PropertyFilterExpression &filterExpression)
FilteredVectorTileLayer::FilteredVectorTileLayer(const VectorTileLayer& layer, const FilterExpression &filterExpression)
: layer(layer),
filterExpression(filterExpression) {
}
@@ -122,120 +122,167 @@ FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& paren
operator++();
}
bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const PropertyFilterExpression &filterExpression, const pbf &tags_pbf) {
if (filterExpression.is<util::recursive_wrapper<PropertyFilter>>()) {
return matchesFilter(filterExpression.get<util::recursive_wrapper<PropertyFilter>>().get(), tags_pbf);
} else if (filterExpression.is<util::recursive_wrapper<PropertyExpression>>()) {
return matchesExpression(filterExpression.get<util::recursive_wrapper<PropertyExpression>>().get(), tags_pbf);
} else if (filterExpression.is<std::true_type>()) {
return true;
} else {
return false;
}
//bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const FilterExpression &filterExpression, const pbf &tags_pbf) {
// if (filterExpression.empty()) {
// return true;
// }
//
//
//
//
// if (filterExpression.is<util::recursive_wrapper<PropertyFilter>>()) {
// return matchesFilter(filterExpression.get<util::recursive_wrapper<PropertyFilter>>().get(), tags_pbf);
// } else if (filterExpression.is<util::recursive_wrapper<PropertyExpression>>()) {
// return matchesExpression(filterExpression.get<util::recursive_wrapper<PropertyExpression>>().get(), tags_pbf);
// } else if (filterExpression.is<std::true_type>()) {
// return true;
// } else {
// return false;
// }
// return true;
//}
//
//bool FilteredVectorTileLayer::iterator::matchesFilter(const PropertyFilter &filter, const pbf &const_tags_pbf) {
// auto field_it = parent.layer.key_index.find(filter.field);
// if (field_it != parent.layer.key_index.end()) {
// const uint32_t filter_key = field_it->second;
//
// // Now loop through all the key/value pair tags.
// // tags are packed varints. They should have an even length.
// pbf tags_pbf = const_tags_pbf;
// while (tags_pbf) {
// uint32_t tag_key = tags_pbf.varint();
// if (!tags_pbf) {
// // This should not happen; otherwise the vector tile
// // is invalid.
// throw std::runtime_error("uneven number of feature tag ids");
// }
// uint32_t tag_val = tags_pbf.varint();
//
// if (tag_key == filter_key) {
// if (parent.layer.values.size() > tag_val) {
// const Value &value = parent.layer.values[tag_val];
// return filter.compare(value);
// } else {
// throw std::runtime_error("feature references out of range value");
// }
// }
// }
// }
//
// // The feature doesn't contain the field that we're looking to compare.
// // Depending on the filter, this may still be okay.
// return filter.isMissingFieldOkay();
//}
//
//bool FilteredVectorTileLayer::iterator::matchesExpression(const PropertyExpression &expression, const pbf &tags_pbf) {
// if (expression.op == ExpressionOperator::Or) {
// for (const PropertyFilterExpression &filterExpression : expression.operands) {
// if (matchesFilterExpression(filterExpression, tags_pbf)) {
// return true;
// }
// }
// return false;
// } else if (expression.op == ExpressionOperator::And) {
// for (const PropertyFilterExpression &filterExpression : expression.operands) {
// if (!matchesFilterExpression(filterExpression, tags_pbf)) {
// return false;
// }
// }
// return true;
// } else {
// return false;
// }
//}
//
VectorTileTagExtractor::VectorTileTagExtractor(const VectorTileLayer &layer) : layer_(layer) {}
void VectorTileTagExtractor::setTags(const pbf &pbf) {
tags_ = pbf;
}
std::forward_list<Value> VectorTileTagExtractor::getValues(const std::string &key) const {
std::forward_list<Value> values;
bool FilteredVectorTileLayer::iterator::matchesFilter(const PropertyFilter &filter, const pbf &const_tags_pbf) {
auto field_it = parent.layer.key_index.find(filter.field);
if (field_it != parent.layer.key_index.end()) {
auto field_it = layer_.key_index.find(key);
if (field_it != layer_.key_index.end()) {
auto it = values.before_begin();
const uint32_t filter_key = field_it->second;
// Now loop through all the key/value pair tags.
// tags are packed varints. They should have an even length.
pbf tags_pbf = const_tags_pbf;
pbf tags_pbf = tags_;
uint32_t tag_key, tag_val;
while (tags_pbf) {
uint32_t tag_key = tags_pbf.varint();
tag_key = tags_pbf.varint();
if (!tags_pbf) {
// This should not happen; otherwise the vector tile
// is invalid.
throw std::runtime_error("uneven number of feature tag ids");
// This should not happen; otherwise the vector tile is invalid.
fprintf(stderr, "[WARNING] uneven number of feature tag ids\n");
return values;
}
uint32_t tag_val = tags_pbf.varint();
// Note: We need to run this command in all cases, even if the keys don't match.
tag_val = tags_pbf.varint();
if (tag_key == filter_key) {
if (parent.layer.values.size() > tag_val) {
const Value &value = parent.layer.values[tag_val];
return filter.compare(value);
if (layer_.values.size() > tag_val) {
it = values.emplace_after(it, layer_.values[tag_val]);
} else {
throw std::runtime_error("feature references out of range value");
fprintf(stderr, "[WARNING] feature references out of range value\n");
break;
}
}
}
}
// The feature doesn't contain the field that we're looking to compare.
// Depending on the filter, this may still be okay.
return filter.isMissingFieldOkay();
return values;
}
bool FilteredVectorTileLayer::iterator::matchesExpression(const PropertyExpression &expression, const pbf &tags_pbf) {
if (expression.op == ExpressionOperator::Or) {
for (const PropertyFilterExpression &filterExpression : expression.operands) {
if (matchesFilterExpression(filterExpression, tags_pbf)) {
return true;
}
}
return false;
} else if (expression.op == ExpressionOperator::And) {
for (const PropertyFilterExpression &filterExpression : expression.operands) {
if (!matchesFilterExpression(filterExpression, tags_pbf)) {
return false;
}
}
return true;
} else {
return false;
}
void VectorTileTagExtractor::setType(FilterExpression::GeometryType type) {
type_ = type;
}
FilterExpression::GeometryType VectorTileTagExtractor::getType() const {
return type_;
}
void FilteredVectorTileLayer::iterator::operator++() {
valid = false;
const PropertyFilterExpression &expression = parent.filterExpression;
const FilterExpression &expression = parent.filterExpression;
while (data.next(2)) { // feature
feature = data.message();
pbf feature_pbf = feature;
BucketType type = BucketType::None;
bool matched = false;
// Treat the absence of any expression filters as a match.
if (!expression.valid() || expression.is<std::true_type>()) {
if (expression.empty()) {
matched = true;
}
while (feature_pbf.next()) {
if (feature_pbf.tag == 2) { // tags
if (matched) {
// There is no filter, so we want to parse the entire layer anyway.
feature_pbf.skip();
} else {
// We only want to parse some features.
const pbf tags_pbf = feature_pbf.message();
matched = matchesFilterExpression(expression, tags_pbf);
if (!matched) {
break; // feature_pbf loop early
}
}
} else if (feature_pbf.tag == 3) { // geometry type
switch (feature_pbf.varint()) {
case 1 /* Point */: type = BucketType::Icon; break;
case 2 /* LineString */: type = BucketType::Line; break;
case 3 /* Polygon */: type = BucketType::Fill; break;
default: type = BucketType::None; break;
}
if (!matched) {
VectorTileTagExtractor extractor(parent.layer);
// TODO: Parse feature type
// if (type != parent.bucket_desc.feature_type) {
// matched = false;
// break; // feature_pbf loop early
// }
} else {
feature_pbf.skip();
// Retrieve the basic information
while (feature_pbf.next()) {
if (feature_pbf.tag == 2) { // tags
extractor.setTags(feature_pbf.message());
} else if (feature_pbf.tag == 3) { // geometry type
switch (FeatureType(feature_pbf.varint())) {
case FeatureType::Point: extractor.setType(FilterExpression::GeometryType::Point); break;
case FeatureType::LineString: extractor.setType(FilterExpression::GeometryType::Line); break;
case FeatureType::Polygon: extractor.setType(FilterExpression::GeometryType::Polygon); break;
default: break;
}
} else {
feature_pbf.skip();
}
}
matched = expression.compare(extractor);
}
if (matched) {

View File

@@ -622,7 +622,7 @@ void StyleParser::parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer) {
if (value.HasMember("filter")) {
JSVal value_filter = replaceConstant(value["filter"]);
parseFilter(value_filter, layer);
layer->bucket->filter = parseFilter(value_filter);
}
if (value.HasMember("render")) {
@@ -631,8 +631,92 @@ void StyleParser::parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer) {
}
}
void StyleParser::parseFilter(JSVal value, std::shared_ptr<StyleLayer> &layer) {
// TODO
FilterExpression StyleParser::parseFilter(JSVal value) {
return parseFilter(value, value.IsArray() ? FilterExpression::Operator::Or : FilterExpression::Operator::And);
}
FilterExpression StyleParser::parseFilter(JSVal value, FilterExpression::Operator op) {
FilterExpression expression(op);
if (value.IsObject()) {
rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
for (; itr != value.MemberEnd(); ++itr) {
const std::string name { itr->name.GetString(), itr->name.GetStringLength() };
if (name == "&") {
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::And));
} else if (name == "|") {
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Or));
} else if (name == "^") {
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Xor));
} else if (name == "!") {
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Nor));
} else if (name == "$type") {
JSVal type = replaceConstant(itr->value);
if (type.IsString()) {
expression.setGeometryType(parseGeometryType({ type.GetString(), type.GetStringLength() }));
}
} else {
FilterComparison comparison(name);
JSVal filterValue = replaceConstant(itr->value);
if (filterValue.IsObject()) {
rapidjson::Value::ConstMemberIterator itr = filterValue.MemberBegin();
for (; itr != filterValue.MemberEnd(); ++itr) {
comparison.add(
parseFilterComparisonOperator({ itr->name.GetString(), itr->name.GetStringLength() }),
parseValues(replaceConstant(itr->value))
);
}
} else if (filterValue.IsArray()) {
comparison.add(FilterComparison::Operator::In, parseValues(filterValue));
} else {
comparison.add(FilterComparison::Operator::Equal, std::forward_list<Value>({ parseValue(filterValue) }));
}
expression.add(comparison);
}
}
} else if (value.IsArray()) {
for (rapidjson::SizeType i = 0; i < value.Size(); i++) {
expression.add(parseFilter(replaceConstant(value[i])));
}
} else {
fprintf(stderr, "[WARNING] expression must be either an array or an object\n");
}
return expression;
}
Value StyleParser::parseValue(JSVal value) {
switch (value.GetType()) {
case rapidjson::kNullType:
case rapidjson::kFalseType:
return false;
case rapidjson::kTrueType:
return true;
case rapidjson::kStringType:
return std::string { value.GetString(), value.GetStringLength() };
case rapidjson::kNumberType:
if (value.IsUint64()) return value.GetUint64();
if (value.IsInt64()) return value.GetInt64();
return value.GetDouble();
default:
return false;
}
}
std::forward_list<Value> StyleParser::parseValues(JSVal value) {
std::forward_list<Value> values;
if (value.IsArray()) {
auto it = values.before_begin();
for (rapidjson::SizeType i = 0; i < value.Size(); i++) {
it = values.emplace_after(it, parseValue(replaceConstant(value[i])));
}
} else {
values.emplace_front(parseValue(value));
}
return values;
}
void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) {
@@ -724,79 +808,4 @@ void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) {
}
}
//PropertyFilterExpression StyleParser::parseFilterOrExpression(JSVal value) {
// if (value.IsArray()) {
// // This is an expression.
// util::recursive_wrapper<PropertyExpression> expression;
// for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
// JSVal filter_item = value[i];
//
// if (filter_item.IsString()) {
// expression.get().op = expressionOperatorType({ filter_item.GetString(), filter_item.GetStringLength() });
// } else {
// expression.get().operands.emplace_back(parseFilterOrExpression(filter_item));
// }
// }
// return std::move(expression);
// } else if (value.IsObject() && value.HasMember("field") && value.HasMember("value")) {
// // This is a filter.
// JSVal field = value["field"];
// JSVal val = value["value"];
//
// if (!field.IsString()) {
// throw Style::exception("field name must be a string");
// }
//
// const std::string field_name { field.GetString(), field.GetStringLength() };
// const FilterOperator op = [&]{
// if (value.HasMember("operator")) {
// JSVal op_val = value["operator"];
// return filterOperatorType({ op_val.GetString(), op_val.GetStringLength() });
// } else {
// return FilterOperator::Equal;
// }
// }();
//
// if (val.IsArray()) {
// // The filter has several values, so it's an OR sub-expression.
// util::recursive_wrapper<PropertyExpression> expression;
// for (rapidjson::SizeType i = 0; i < val.Size(); ++i) {
// expression.get().operands.emplace_back(util::recursive_wrapper<PropertyFilter>(PropertyFilter { field_name, op, parseValue(val[i]) }));
// }
//
// return std::move(expression);
// } else {
// // The filter only has a single value, so it is a real filter.
// return std::move(util::recursive_wrapper<PropertyFilter>(PropertyFilter { field_name, op, parseValue(val) }));
// }
// }
//
// return std::true_type();
//Value StyleParser::parseValue(JSVal value) {
// switch (value.GetType()) {
// case rapidjson::kNullType:
// case rapidjson::kFalseType:
// return false;
//
// case rapidjson::kTrueType:
// return true;
//
// case rapidjson::kStringType:
// return std::string { value.GetString(), value.GetStringLength() };
//
// case rapidjson::kNumberType:
// if (value.IsUint64()) return value.GetUint64();
// if (value.IsInt64()) return value.GetInt64();
// return value.GetDouble();
//
// case rapidjson::kObjectType:
// case rapidjson::kArrayType:
// throw Style::exception("value cannot be an object or array");
// return false;
// }
// throw Style::exception("unhandled value type in style");
// return false;
//}
}