summaryrefslogtreecommitdiff
path: root/src/map/vector_tile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/vector_tile.cpp')
-rw-r--r--src/map/vector_tile.cpp199
1 files changed, 123 insertions, 76 deletions
diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp
index 24f03e1a97..54a971cd87 100644
--- a/src/map/vector_tile.cpp
+++ b/src/map/vector_tile.cpp
@@ -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
+ 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::Line); break;
+ case FeatureType::Polygon: extractor.setType(FilterExpression::GeometryType::Polygon); break;
+ default: break;
}
+ } else {
+ feature_pbf.skip();
}
- } 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;
- }
-
- // TODO: Parse feature type
-// if (type != parent.bucket_desc.feature_type) {
-// matched = false;
-// break; // feature_pbf loop early
-// }
- } else {
- feature_pbf.skip();
}
+
+ matched = expression.compare(extractor);
}
if (matched) {