Implement v6 filters

This commit is contained in:
John Firebaugh
2014-10-28 11:17:03 -04:00
parent f25cf70689
commit c151f12997
15 changed files with 592 additions and 1101 deletions

View File

@@ -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 {