Implement v6 filters
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/style/filter_expression_private.hpp>
|
||||
#include <mbgl/style/filter_comparison_private.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -123,81 +122,6 @@ FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& paren
|
||||
operator++();
|
||||
}
|
||||
|
||||
//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) {}
|
||||
|
||||
|
||||
@@ -205,8 +129,12 @@ void VectorTileTagExtractor::setTags(const pbf &pbf) {
|
||||
tags_ = pbf;
|
||||
}
|
||||
|
||||
std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) const {
|
||||
std::vector<Value> values;
|
||||
mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string &key) const {
|
||||
if (key == "$type") {
|
||||
return Value(uint64_t(type_));
|
||||
}
|
||||
|
||||
mapbox::util::optional<Value> value;
|
||||
|
||||
auto field_it = layer_.key_index.find(key);
|
||||
if (field_it != layer_.key_index.end()) {
|
||||
@@ -221,14 +149,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con
|
||||
if (!tags_pbf) {
|
||||
// This should not happen; otherwise the vector tile is invalid.
|
||||
fprintf(stderr, "[WARNING] uneven number of feature tag ids\n");
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
// 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 (layer_.values.size() > tag_val) {
|
||||
values.emplace_back(layer_.values[tag_val]);
|
||||
value = layer_.values[tag_val];
|
||||
} else {
|
||||
fprintf(stderr, "[WARNING] feature references out of range value\n");
|
||||
break;
|
||||
@@ -237,16 +165,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
|
||||
void VectorTileTagExtractor::setType(FilterExpression::GeometryType type) {
|
||||
void VectorTileTagExtractor::setType(FeatureType type) {
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
FilterExpression::GeometryType VectorTileTagExtractor::getType() const {
|
||||
return type_;
|
||||
}
|
||||
template bool mbgl::evaluate(const FilterExpression&, const VectorTileTagExtractor&);
|
||||
|
||||
void FilteredVectorTileLayer::iterator::operator++() {
|
||||
valid = false;
|
||||
@@ -256,36 +182,21 @@ void FilteredVectorTileLayer::iterator::operator++() {
|
||||
while (data.next(2)) { // feature
|
||||
feature = data.message();
|
||||
pbf feature_pbf = feature;
|
||||
bool matched = false;
|
||||
|
||||
// Treat the absence of any expression filters as a match.
|
||||
if (expression.empty()) {
|
||||
matched = true;
|
||||
}
|
||||
VectorTileTagExtractor extractor(parent.layer);
|
||||
|
||||
if (!matched) {
|
||||
VectorTileTagExtractor extractor(parent.layer);
|
||||
|
||||
// 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::LineString); break;
|
||||
case FeatureType::Polygon: extractor.setType(FilterExpression::GeometryType::Polygon); break;
|
||||
default: break;
|
||||
}
|
||||
} 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
|
||||
extractor.setType(FeatureType(feature_pbf.varint()));
|
||||
} else {
|
||||
feature_pbf.skip();
|
||||
}
|
||||
|
||||
matched = expression.compare(extractor);
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
if (evaluate(expression, extractor)) {
|
||||
valid = true;
|
||||
return; // data loop
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user