From 3bc5e0325395ba54db58b9f20159b253bd81f94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Sat, 31 May 2014 16:10:20 +0200 Subject: [PATCH 01/11] simple expression support --- include/llmr/map/vector_tile.hpp | 12 +- include/llmr/style/bucket_description.hpp | 67 ++++++++++- src/map/vector_tile.cpp | 131 +++++++++++++--------- src/style/bucket_description.cpp | 5 +- src/style/style_parser.cpp | 36 +++--- 5 files changed, 177 insertions(+), 74 deletions(-) diff --git a/include/llmr/map/vector_tile.hpp b/include/llmr/map/vector_tile.hpp index 1e809556e..8c70016bc 100644 --- a/include/llmr/map/vector_tile.hpp +++ b/include/llmr/map/vector_tile.hpp @@ -7,12 +7,15 @@ #include #include #include +#include #include #include namespace llmr { class BucketDescription; +class BucketExpression; +class BucketFilter; class VectorTileLayer; struct pbf; @@ -53,7 +56,11 @@ public: const pbf& operator*() const; private: - const FilteredVectorTileLayer& filter; + bool matchesExpression(const BucketExpression &expression, const pbf &tags_pbf); + bool matchesFilter(const BucketFilter &filter, const pbf &tags_pbf); + + private: + const FilteredVectorTileLayer& parent; bool valid = false; pbf feature; pbf data; @@ -68,8 +75,6 @@ public: private: const VectorTileLayer& layer; const BucketDescription& bucket_desc; - int32_t key = -1; - std::set values; }; std::ostream& operator<<(std::ostream&, const GlyphPlacement& placement); @@ -82,6 +87,7 @@ public: std::string name; uint32_t extent = 4096; std::vector keys; + std::unordered_map key_index; std::vector values; std::map> shaping; }; diff --git a/include/llmr/style/bucket_description.hpp b/include/llmr/style/bucket_description.hpp index 3b6fc4313..e7b8a63e7 100644 --- a/include/llmr/style/bucket_description.hpp +++ b/include/llmr/style/bucket_description.hpp @@ -38,6 +38,16 @@ enum class TextPathType { Curve = 1 }; +enum class FilterOperator { + Equal, + NotEqual +}; + +enum class ExpressionOperator { + Or, + And +}; + inline BucketType bucketType(const std::string& type) { if (type == "fill") return BucketType::Fill; @@ -81,6 +91,23 @@ inline float verticalAlignmentType(const std::string& alignment) { else return 0.5; }; +inline FilterOperator filterOperatorType(const std::string &op) { + if (op == "!=" || op == "not") { + return FilterOperator::NotEqual; + } else { + return FilterOperator::Equal; + } +} + +inline ExpressionOperator expressionOperatorType(const std::string &op) { + if (op == "&&" || op == "and") { + return ExpressionOperator::And; + } else { + return ExpressionOperator::Or; + } +} + + class BucketGeometryDescription { public: CapType cap = CapType::None; @@ -105,6 +132,42 @@ public: bool alwaysVisible = false; }; + +class BucketFilter { +public: + inline BucketFilter(const std::string &field, const Value &value) : field(field), value(value) {}; + + // 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; + } + } + + inline bool compare(const Value &other) const { + switch (op) { + case FilterOperator::NotEqual: + return !util::relaxed_equal(value)(other); + default: + return util::relaxed_equal(value)(other); + } + } + +public: + std::string field; + Value value; + FilterOperator op = FilterOperator::Equal; +}; + +class BucketExpression { +public: + ExpressionOperator op = ExpressionOperator::Or; + std::vector operands; +}; + class BucketDescription { public: BucketType feature_type = BucketType::None; @@ -113,8 +176,8 @@ public: // Specify what data to pull into this bucket std::string source_name; std::string source_layer; - std::string source_field; - std::vector source_value; + + BucketExpression filter; // Specifies how the geometry for this bucket should be created BucketGeometryDescription geometry; diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp index f0f5a85cd..bc6386e85 100644 --- a/src/map/vector_tile.cpp +++ b/src/map/vector_tile.cpp @@ -91,6 +91,7 @@ VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) { name = layer.string(); } else if (layer.tag == 3) { // keys keys.emplace_back(layer.string()); + key_index.emplace(keys.back(), keys.size() - 1); } else if (layer.tag == 4) { // values values.emplace_back(std::move(parseValue(layer.message()))); } else if (layer.tag == 5) { // extent @@ -104,81 +105,108 @@ VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) { FilteredVectorTileLayer::FilteredVectorTileLayer(const VectorTileLayer& layer, const BucketDescription& bucket_desc) : layer(layer), bucket_desc(bucket_desc) { - // If we filter further by field/value, parse the key/value indices first - // because protobuf doesn't mandate a particular key order. - if (bucket_desc.source_field.size()) { - // Get the ID of the desired layer key. - auto key_it = std::find(layer.keys.begin(), layer.keys.end(), bucket_desc.source_field); - if (key_it != layer.keys.end()) { - key = (int32_t)(key_it - layer.keys.begin()); - } - // Get the ID of the desired layer value(s), comparing as strings in - // order to avoid numeric type mismatches between the layer and the - // style definition. - for (const Value& source_value : bucket_desc.source_value) { - auto value_it = std::find_if(layer.values.begin(), layer.values.end(), util::relaxed_equal(source_value)); - if (value_it != layer.values.end()) { - values.insert((uint32_t)(value_it - layer.values.begin())); - } - } - } } FilteredVectorTileLayer::iterator FilteredVectorTileLayer::begin() const { - if (bucket_desc.source_field.size() && (key < 0 || values.empty())) { - // There are no valid values that we could possibly find. Abort early. - return end(); - } else { - return iterator(*this, layer.data); - } + return iterator(*this, layer.data); } FilteredVectorTileLayer::iterator FilteredVectorTileLayer::end() const { return iterator(*this, pbf(layer.data.end, 0)); } -FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& filter, const pbf& data) - : filter(filter), +FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& parent, const pbf& data) + : parent(parent), feature(pbf()), data(data) { operator++(); } +bool FilteredVectorTileLayer::iterator::matchesFilter(const BucketFilter &filter, const pbf &const_tags_pbf) { + bool missing = true; + + 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 BucketExpression &expression, const pbf &tags_pbf) { + if (expression.op == ExpressionOperator::Or) { + for (const BucketFilter &filter : expression.operands) { + if (matchesFilter(filter, tags_pbf)) { + return true; + } + } + return false; + } else if (expression.op == ExpressionOperator::And) { + for (const BucketFilter &filter : expression.operands) { + if (!matchesFilter(filter, tags_pbf)) { + return false; + } + } + return true; + } else { + return false; + } +} + + + void FilteredVectorTileLayer::iterator::operator++() { valid = false; + BucketExpression expression = parent.bucket_desc.filter; + while (data.next(2)) { // feature feature = data.message(); pbf feature_pbf = feature; BucketType type = BucketType::None; - bool skip = false; - while (!skip && feature_pbf.next()) { + bool matched = false; + + // Treat the absence of any expression filters as a match. + if (expression.operands.size() == 0) { + matched = true; + } + + while (feature_pbf.next()) { if (feature_pbf.tag == 2) { // tags - if (filter.key < 0) { - // We want to parse the entire layer anyway + 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. - skip = true; - - // tags are packed varints. They should have an even length. - pbf tags_pbf = feature_pbf.message(); - while (tags_pbf) { - int32_t tag_key = tags_pbf.varint(); - if (tags_pbf) { - uint32_t tag_val = tags_pbf.varint(); - // Now check if the tag_key/tag_val pair is included - // in the set of key/values that we are looking for. - if (filter.key == tag_key && filter.values.find(tag_val) != filter.values.end()) { - skip = false; - break; // feature_pbf loop - } - } else { - // This should not happen; otherwise the vector tile - // is invalid. - throw std::runtime_error("uneven number of feature tag ids"); - } + const pbf tags_pbf = feature_pbf.message(); + matched = matchesExpression(expression, tags_pbf); + if (!matched) { + break; // feature_pbf loop early } } } else if (feature_pbf.tag == 3) { // geometry type @@ -189,7 +217,8 @@ void FilteredVectorTileLayer::iterator::operator++() { default: type = BucketType::None; break; } - if (type != filter.bucket_desc.feature_type) { + if (type != parent.bucket_desc.feature_type) { + matched = false; break; // feature_pbf loop early } } else { @@ -197,7 +226,7 @@ void FilteredVectorTileLayer::iterator::operator++() { } } - if (!skip && type == filter.bucket_desc.feature_type) { + if (matched) { valid = true; return; // data loop } else { diff --git a/src/style/bucket_description.cpp b/src/style/bucket_description.cpp index 864603e31..b154c3a17 100644 --- a/src/style/bucket_description.cpp +++ b/src/style/bucket_description.cpp @@ -2,15 +2,12 @@ #include + std::ostream& llmr::operator<<(std::ostream& os, const BucketDescription& bucket) { os << "Bucket:" << std::endl; os << " - type: " << (uint32_t)bucket.type << std::endl; os << " - source_name: " << bucket.source_name << std::endl; os << " - source_layer: " << bucket.source_layer << std::endl; - os << " - source_field: " << bucket.source_field << std::endl; - for (const Value& value : bucket.source_value) { - os << " - source_value: " << value << std::endl; - } os << " - cap: " << (uint32_t)bucket.geometry.cap << std::endl; os << " - join: " << (uint32_t)bucket.geometry.join << std::endl; os << " - font: " << bucket.geometry.font << std::endl; diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 2b6c0e3f2..21840397c 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -52,20 +52,6 @@ BucketDescription StyleParser::parseBucket(JSVal value) { } else { throw Style::exception("layer name must be a string"); } - } else if (name == "field") { - if (value.IsString()) { - bucket.source_field = { value.GetString(), value.GetStringLength() }; - } else { - throw Style::exception("field name must be a string"); - } - } else if (name == "value") { - if (value.IsArray()) { - for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { - bucket.source_value.push_back(parseValue(value[i])); - } - } else { - bucket.source_value.push_back(parseValue(value)); - } } else if (name == "cap") { if (value.IsString()) { bucket.geometry.cap = capType({ value.GetString(), value.GetStringLength() }); @@ -167,6 +153,28 @@ BucketDescription StyleParser::parseBucket(JSVal value) { } + + if (value.HasMember("field") && value.HasMember("value")) { + 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() }; + + bucket.filter = {}; + + if (val.IsArray()) { + for (rapidjson::SizeType i = 0; i < val.Size(); ++i) { + bucket.filter.operands.emplace_back(field_name, parseValue(val[i])); + } + } else { + bucket.filter.operands.emplace_back(field_name, parseValue(val)); + } + } + if (bucket.feature_type == BucketType::None) { bucket.feature_type = bucket.type; } From 606ad5622013b8dd36a1dcf6b0f05c4c321de3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Sat, 31 May 2014 23:21:15 +0200 Subject: [PATCH 02/11] implement nested expression parsing --- bin/style.js | 7 ++- include/llmr/map/vector_tile.hpp | 8 +-- include/llmr/style/bucket_description.hpp | 68 ++------------------ include/llmr/style/style_parser.hpp | 2 + src/map/vector_tile.cpp | 29 ++++++--- src/style/style_parser.cpp | 75 +++++++++++++++++------ 6 files changed, 89 insertions(+), 100 deletions(-) diff --git a/bin/style.js b/bin/style.js index d851c1f16..09fd7c0e6 100644 --- a/bin/style.js +++ b/bin/style.js @@ -263,8 +263,11 @@ module.exports = { "contour_label": { "source": "outdoors", "layer": "contour", - "field": "index", - "value": [5, 10], + "filter": [ + "and", + { "field": "index", "value": [ 5, 10 ] }, + { "field": "ele", "operator": "not", "value": 0 } + ], "path": "curve", "text_field": "{{ele}} m", "font": "Open Sans Regular, Arial Unicode MS Regular", diff --git a/include/llmr/map/vector_tile.hpp b/include/llmr/map/vector_tile.hpp index 8c70016bc..904cc9a2e 100644 --- a/include/llmr/map/vector_tile.hpp +++ b/include/llmr/map/vector_tile.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,8 +15,6 @@ namespace llmr { class BucketDescription; -class BucketExpression; -class BucketFilter; class VectorTileLayer; struct pbf; @@ -56,8 +55,9 @@ public: const pbf& operator*() const; private: - bool matchesExpression(const BucketExpression &expression, const pbf &tags_pbf); - bool matchesFilter(const BucketFilter &filter, const pbf &tags_pbf); + 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; diff --git a/include/llmr/style/bucket_description.hpp b/include/llmr/style/bucket_description.hpp index e7b8a63e7..4ce25d238 100644 --- a/include/llmr/style/bucket_description.hpp +++ b/include/llmr/style/bucket_description.hpp @@ -5,8 +5,9 @@ #include #include -#include "value.hpp" -#include "../util/vec.hpp" +#include +#include +#include namespace llmr { @@ -38,16 +39,6 @@ enum class TextPathType { Curve = 1 }; -enum class FilterOperator { - Equal, - NotEqual -}; - -enum class ExpressionOperator { - Or, - And -}; - inline BucketType bucketType(const std::string& type) { if (type == "fill") return BucketType::Fill; @@ -91,22 +82,6 @@ inline float verticalAlignmentType(const std::string& alignment) { else return 0.5; }; -inline FilterOperator filterOperatorType(const std::string &op) { - if (op == "!=" || op == "not") { - return FilterOperator::NotEqual; - } else { - return FilterOperator::Equal; - } -} - -inline ExpressionOperator expressionOperatorType(const std::string &op) { - if (op == "&&" || op == "and") { - return ExpressionOperator::And; - } else { - return ExpressionOperator::Or; - } -} - class BucketGeometryDescription { public: @@ -133,41 +108,6 @@ public: }; -class BucketFilter { -public: - inline BucketFilter(const std::string &field, const Value &value) : field(field), value(value) {}; - - // 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; - } - } - - inline bool compare(const Value &other) const { - switch (op) { - case FilterOperator::NotEqual: - return !util::relaxed_equal(value)(other); - default: - return util::relaxed_equal(value)(other); - } - } - -public: - std::string field; - Value value; - FilterOperator op = FilterOperator::Equal; -}; - -class BucketExpression { -public: - ExpressionOperator op = ExpressionOperator::Or; - std::vector operands; -}; - class BucketDescription { public: BucketType feature_type = BucketType::None; @@ -177,7 +117,7 @@ public: std::string source_name; std::string source_layer; - BucketExpression filter; + PropertyFilterExpression filter; // Specifies how the geometry for this bucket should be created BucketGeometryDescription geometry; diff --git a/include/llmr/style/style_parser.hpp b/include/llmr/style/style_parser.hpp index c00c49677..10f367475 100644 --- a/include/llmr/style/style_parser.hpp +++ b/include/llmr/style/style_parser.hpp @@ -39,6 +39,8 @@ private: RasterClass parseRasterClass(JSVal value); CompositeClass parseCompositeClass(JSVal value); + PropertyFilterExpression parseFilterOrExpression(JSVal value); + bool parseBoolean(JSVal value); std::string parseString(JSVal value); JSVal replaceConstant(JSVal value); diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp index bc6386e85..0e96cccd1 100644 --- a/src/map/vector_tile.cpp +++ b/src/map/vector_tile.cpp @@ -122,9 +122,18 @@ FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& paren operator++(); } -bool FilteredVectorTileLayer::iterator::matchesFilter(const BucketFilter &filter, const pbf &const_tags_pbf) { - bool missing = true; +bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const PropertyFilterExpression &filterExpression, const pbf &tags_pbf) { + if (filterExpression.is()) { + return matchesFilter(filterExpression.get(), tags_pbf); + } else if (filterExpression.is>()) { + return matchesExpression(filterExpression.get>().get(), tags_pbf); + } else { + return false; + } +} + +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; @@ -157,17 +166,17 @@ bool FilteredVectorTileLayer::iterator::matchesFilter(const BucketFilter &filter return filter.isMissingFieldOkay(); } -bool FilteredVectorTileLayer::iterator::matchesExpression(const BucketExpression &expression, const pbf &tags_pbf) { +bool FilteredVectorTileLayer::iterator::matchesExpression(const PropertyExpression &expression, const pbf &tags_pbf) { if (expression.op == ExpressionOperator::Or) { - for (const BucketFilter &filter : expression.operands) { - if (matchesFilter(filter, tags_pbf)) { + for (const PropertyFilterExpression &filterExpression : expression.operands) { + if (matchesFilterExpression(filterExpression, tags_pbf)) { return true; } } return false; } else if (expression.op == ExpressionOperator::And) { - for (const BucketFilter &filter : expression.operands) { - if (!matchesFilter(filter, tags_pbf)) { + for (const PropertyFilterExpression &filterExpression : expression.operands) { + if (!matchesFilterExpression(filterExpression, tags_pbf)) { return false; } } @@ -182,7 +191,7 @@ bool FilteredVectorTileLayer::iterator::matchesExpression(const BucketExpression void FilteredVectorTileLayer::iterator::operator++() { valid = false; - BucketExpression expression = parent.bucket_desc.filter; + const PropertyFilterExpression &expression = parent.bucket_desc.filter; while (data.next(2)) { // feature feature = data.message(); @@ -192,7 +201,7 @@ void FilteredVectorTileLayer::iterator::operator++() { bool matched = false; // Treat the absence of any expression filters as a match. - if (expression.operands.size() == 0) { + if (expression.is>() && expression.get>().get().operands.size() == 0) { matched = true; } @@ -204,7 +213,7 @@ void FilteredVectorTileLayer::iterator::operator++() { } else { // We only want to parse some features. const pbf tags_pbf = feature_pbf.message(); - matched = matchesExpression(expression, tags_pbf); + matched = matchesFilterExpression(expression, tags_pbf); if (!matched) { break; // feature_pbf loop early } diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 21840397c..18b2ab3af 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -20,6 +20,56 @@ void StyleParser::parseBuckets(JSVal value, std::map(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. + PropertyExpression expression; + for (rapidjson::SizeType i = 0; i < val.Size(); ++i) { + expression.operands.emplace_back(PropertyFilter { field_name, op, parseValue(val[i]) }); + } + + return util::recursive_wrapper(std::move(expression)); + } else { + // The filter only has a single value, so it is a real filter. + return PropertyFilter { field_name, op, parseValue(val) }; + } + } + + return util::recursive_wrapper(); +} + BucketDescription StyleParser::parseBucket(JSVal value) { BucketDescription bucket; @@ -153,26 +203,11 @@ BucketDescription StyleParser::parseBucket(JSVal value) { } - - if (value.HasMember("field") && value.HasMember("value")) { - 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() }; - - bucket.filter = {}; - - if (val.IsArray()) { - for (rapidjson::SizeType i = 0; i < val.Size(); ++i) { - bucket.filter.operands.emplace_back(field_name, parseValue(val[i])); - } - } else { - bucket.filter.operands.emplace_back(field_name, parseValue(val)); - } + if (value.HasMember("filter")) { + bucket.filter = std::move(parseFilterOrExpression(value["filter"])); + } else { + // Allow a filter triple to be specified at the bucket root as well. + bucket.filter = std::move(parseFilterOrExpression(value)); } if (bucket.feature_type == BucketType::None) { From 1d3d0bd85ccd54a1bb8a5f05121189e47d600789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Sat, 31 May 2014 23:21:46 +0200 Subject: [PATCH 03/11] add missing files --- include/llmr/map/filter_expression.hpp | 102 ++++++++++++++++++ include/llmr/util/recursive_wrapper.hpp | 132 ++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 include/llmr/map/filter_expression.hpp create mode 100644 include/llmr/util/recursive_wrapper.hpp diff --git a/include/llmr/map/filter_expression.hpp b/include/llmr/map/filter_expression.hpp new file mode 100644 index 000000000..d536a5a34 --- /dev/null +++ b/include/llmr/map/filter_expression.hpp @@ -0,0 +1,102 @@ +#ifndef LLMR_MAP_FILTER_EXPRESSION +#define LLMR_MAP_FILTER_EXPRESSION + +#include +#include + +#include +#include + +namespace llmr { + +enum class FilterOperator { + Equal, + NotEqual +}; + +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 { + 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 PropertyExpression; + +class PropertyFilter { +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)) { + } + + // 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; + } + } + + inline bool compare(const Value &other) const { + switch (op) { + case FilterOperator::NotEqual: + return !util::relaxed_equal(value)(other); + default: + return util::relaxed_equal(value)(other); + } + } + +public: + std::string field; + FilterOperator op = FilterOperator::Equal; + Value value; +}; + +typedef util::variant> PropertyFilterExpression; + + +class PropertyExpression { +public: + inline PropertyExpression() {} + inline PropertyExpression(PropertyExpression &&expression) + : op(expression.op), + operands(std::move(expression.operands)) { + } + +public: + ExpressionOperator op = ExpressionOperator::Or; + std::vector operands; +}; + + +} + +#endif diff --git a/include/llmr/util/recursive_wrapper.hpp b/include/llmr/util/recursive_wrapper.hpp new file mode 100644 index 000000000..557b576c0 --- /dev/null +++ b/include/llmr/util/recursive_wrapper.hpp @@ -0,0 +1,132 @@ +#ifndef LLMR_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP +#define LLMR_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP + +#include + +namespace llmr { + +namespace util { + +template +class recursive_wrapper +{ +public: + + typedef T type; + +private: + + T* p_; + +public: + + ~recursive_wrapper(); + recursive_wrapper(); + + recursive_wrapper(recursive_wrapper const& operand); + recursive_wrapper(T const& operand); + recursive_wrapper(recursive_wrapper&& operand); + recursive_wrapper(T&& operand); + +private: + + void assign(const T& rhs); + +public: + + recursive_wrapper& operator=(const recursive_wrapper& rhs) + { + assign( rhs.get() ); + return *this; + } + + recursive_wrapper& operator=(const T& rhs) + { + assign( rhs ); + return *this; + } + + void swap(recursive_wrapper& operand) noexcept + { + T* temp = operand.p_; + operand.p_ = p_; + p_ = temp; + } + + + recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept + { + swap(rhs); + return *this; + } + + recursive_wrapper& operator=(T&& rhs) + { + get() = std::move(rhs); + return *this; + } + + +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_; } + +}; + +template +recursive_wrapper::~recursive_wrapper() +{ + delete p_; +} + +template +recursive_wrapper::recursive_wrapper() + : p_(new T) +{ +} + +template +recursive_wrapper::recursive_wrapper(recursive_wrapper const& operand) + : p_(new T( operand.get() )) +{ +} + +template +recursive_wrapper::recursive_wrapper(T const& operand) + : p_(new T(operand)) +{ +} + +template +recursive_wrapper::recursive_wrapper(recursive_wrapper&& operand) + : p_(new T( std::move(operand.get()) )) +{ +} + +template +recursive_wrapper::recursive_wrapper(T&& operand) + : p_(new T( std::move(operand) )) +{ +} + +template +void recursive_wrapper::assign(const T& rhs) +{ + this->get() = rhs; +} + +template +inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept +{ + lhs.swap(rhs); +} + +} + +} + +#endif // LLMR_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP From 99b6a700ef8e3bedd6cc0aae189026eabb3e9c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Sun, 1 Jun 2014 00:01:22 +0200 Subject: [PATCH 04/11] move both variant options to recursive_wrapper --- include/llmr/map/filter_expression.hpp | 11 +++++++---- src/map/vector_tile.cpp | 4 ++-- src/style/style_parser.cpp | 18 +++++++++--------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/llmr/map/filter_expression.hpp b/include/llmr/map/filter_expression.hpp index d536a5a34..0748a63fc 100644 --- a/include/llmr/map/filter_expression.hpp +++ b/include/llmr/map/filter_expression.hpp @@ -43,9 +43,15 @@ inline ExpressionOperator expressionOperatorType(const std::string &op) { } - +class PropertyFilter; class PropertyExpression; +typedef util::variant< + util::recursive_wrapper, + util::recursive_wrapper +> PropertyFilterExpression; + + class PropertyFilter { public: inline PropertyFilter(const std::string &field, FilterOperator op, const Value &value) : field(field), op(op), value(value) {}; @@ -80,9 +86,6 @@ public: Value value; }; -typedef util::variant> PropertyFilterExpression; - - class PropertyExpression { public: inline PropertyExpression() {} diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp index 0e96cccd1..b30b997e7 100644 --- a/src/map/vector_tile.cpp +++ b/src/map/vector_tile.cpp @@ -123,8 +123,8 @@ FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& paren } bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const PropertyFilterExpression &filterExpression, const pbf &tags_pbf) { - if (filterExpression.is()) { - return matchesFilter(filterExpression.get(), tags_pbf); + if (filterExpression.is>()) { + return matchesFilter(filterExpression.get>().get(), tags_pbf); } else if (filterExpression.is>()) { return matchesExpression(filterExpression.get>().get(), tags_pbf); } else { diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 18b2ab3af..c774d0fca 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -23,17 +23,17 @@ void StyleParser::parseBuckets(JSVal value, std::map expression; for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { JSVal filter_item = value[i]; if (filter_item.IsString()) { - expression.op = expressionOperatorType({ filter_item.GetString(), filter_item.GetStringLength() }); + expression.get().op = expressionOperatorType({ filter_item.GetString(), filter_item.GetStringLength() }); } else { - expression.operands.emplace_back(parseFilterOrExpression(filter_item)); + expression.get().operands.emplace_back(parseFilterOrExpression(filter_item)); } } - return util::recursive_wrapper(std::move(expression)); + return std::move(expression); } else if (value.IsObject() && value.HasMember("field") && value.HasMember("value")) { // This is a filter. JSVal field = value["field"]; @@ -55,19 +55,19 @@ PropertyFilterExpression StyleParser::parseFilterOrExpression(JSVal value) { if (val.IsArray()) { // The filter has several values, so it's an OR sub-expression. - PropertyExpression expression; + util::recursive_wrapper expression; for (rapidjson::SizeType i = 0; i < val.Size(); ++i) { - expression.operands.emplace_back(PropertyFilter { field_name, op, parseValue(val[i]) }); + expression.get().operands.emplace_back(util::recursive_wrapper(PropertyFilter { field_name, op, parseValue(val[i]) })); } - return util::recursive_wrapper(std::move(expression)); + return std::move(expression); } else { // The filter only has a single value, so it is a real filter. - return PropertyFilter { field_name, op, parseValue(val) }; + return std::move(util::recursive_wrapper(PropertyFilter { field_name, op, parseValue(val) })); } } - return util::recursive_wrapper(); + return std::move(util::recursive_wrapper()); } BucketDescription StyleParser::parseBucket(JSVal value) { From dd4c8a67ba7610679f0049ebccce989eafc36ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Sun, 1 Jun 2014 00:06:33 +0200 Subject: [PATCH 05/11] add explicit true type == "no filter" --- include/llmr/map/filter_expression.hpp | 3 ++- include/llmr/style/bucket_description.hpp | 2 +- src/map/vector_tile.cpp | 4 +++- src/style/style_parser.cpp | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/llmr/map/filter_expression.hpp b/include/llmr/map/filter_expression.hpp index 0748a63fc..29abb9a25 100644 --- a/include/llmr/map/filter_expression.hpp +++ b/include/llmr/map/filter_expression.hpp @@ -48,7 +48,8 @@ class PropertyExpression; typedef util::variant< util::recursive_wrapper, - util::recursive_wrapper + util::recursive_wrapper, + std::true_type > PropertyFilterExpression; diff --git a/include/llmr/style/bucket_description.hpp b/include/llmr/style/bucket_description.hpp index 4ce25d238..f77ff5170 100644 --- a/include/llmr/style/bucket_description.hpp +++ b/include/llmr/style/bucket_description.hpp @@ -117,7 +117,7 @@ public: std::string source_name; std::string source_layer; - PropertyFilterExpression filter; + PropertyFilterExpression filter = std::true_type(); // Specifies how the geometry for this bucket should be created BucketGeometryDescription geometry; diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp index b30b997e7..97adec277 100644 --- a/src/map/vector_tile.cpp +++ b/src/map/vector_tile.cpp @@ -127,6 +127,8 @@ bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const PropertyFi return matchesFilter(filterExpression.get>().get(), tags_pbf); } else if (filterExpression.is>()) { return matchesExpression(filterExpression.get>().get(), tags_pbf); + } else if (filterExpression.is()) { + return true; } else { return false; } @@ -201,7 +203,7 @@ void FilteredVectorTileLayer::iterator::operator++() { bool matched = false; // Treat the absence of any expression filters as a match. - if (expression.is>() && expression.get>().get().operands.size() == 0) { + if (expression.is()) { matched = true; } diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index c774d0fca..b686c0ec5 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -67,7 +67,7 @@ PropertyFilterExpression StyleParser::parseFilterOrExpression(JSVal value) { } } - return std::move(util::recursive_wrapper()); + return std::true_type(); } BucketDescription StyleParser::parseBucket(JSVal value) { From 2973d0b2b9eb88f66ef4f265fe391f43276f438a Mon Sep 17 00:00:00 2001 From: Eden Halperin Date: Sun, 1 Jun 2014 11:13:15 -0700 Subject: [PATCH 06/11] fix admin boundary buckets --- bin/style.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/bin/style.js b/bin/style.js index 09fd7c0e6..6e17b3338 100644 --- a/bin/style.js +++ b/bin/style.js @@ -14,8 +14,11 @@ module.exports = { "admin_l2": { "source": "outdoors", "layer": "admin", - "field": "admin_level", - "value": 2, + "filter": [ + "and", + {"field": "admin_level", "value": 2}, + {"field": "maritime", "operator": "not", "value": 1} + ], "join": "round", "cap": "round", "type": "line" @@ -23,11 +26,10 @@ module.exports = { "admin_l3": { "source": "outdoors", "layer": "admin", - "field": "admin_level", - "value": [ - 3, - 4, - 5 + "filter": [ + "and", + {"field": "admin_level", "value": [3,4,5]}, + {"field": "maritime", "operator": "not", "value": 1} ], "join": "round", "type": "line" From 3c26f53e63e7e3a9ff9973ebc3d99b39488b0251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 2 Jun 2014 13:50:25 +0200 Subject: [PATCH 07/11] generalize variant comparison and add more operators --- include/llmr/map/filter_expression.hpp | 28 ++- include/llmr/style/value.hpp | 75 ++++++-- test/variant.cpp | 245 +++++++++++++------------ 3 files changed, 209 insertions(+), 139 deletions(-) diff --git a/include/llmr/map/filter_expression.hpp b/include/llmr/map/filter_expression.hpp index 29abb9a25..bf6d41480 100644 --- a/include/llmr/map/filter_expression.hpp +++ b/include/llmr/map/filter_expression.hpp @@ -11,7 +11,11 @@ namespace llmr { enum class FilterOperator { Equal, - NotEqual + NotEqual, + Greater, + GreaterEqual, + Less, + LessEqual }; enum class ExpressionOperator { @@ -25,6 +29,14 @@ inline FilterOperator filterOperatorType(const std::string &op) { 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; @@ -74,10 +86,20 @@ public: inline bool compare(const Value &other) const { switch (op) { + case FilterOperator::Equal: + return util::relaxed_equal(value, other); case FilterOperator::NotEqual: - return !util::relaxed_equal(value)(other); + return !util::relaxed_equal(value, other); + case FilterOperator::Greater: + return util::relaxed_greater(value, other); + case FilterOperator::GreaterEqual: + return util::relaxed_greater_equal(value, other); + case FilterOperator::Less: + return util::relaxed_less(value, other); + case FilterOperator::LessEqual: + return util::relaxed_less_equal(value, other); default: - return util::relaxed_equal(value)(other); + return false; } } diff --git a/include/llmr/style/value.hpp b/include/llmr/style/value.hpp index f29590363..e1247af1d 100644 --- a/include/llmr/style/value.hpp +++ b/include/llmr/style/value.hpp @@ -14,6 +14,8 @@ Value parseValue(pbf data); namespace util { +namespace detail { + inline int string_to_bool(std::string str) { std::transform(str.begin(), str.end(), str.begin(), ::tolower); if (str == "false" || str == "null" || !str.length()) return 0; @@ -52,44 +54,85 @@ template <> struct string_to_number { } }; -struct relaxed_equal_visitor { - bool operator()(bool lhs, bool rhs) const { return lhs == rhs; } +template +struct relaxed_operator_visitor { + bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); } template ::value>::type> - bool operator()(bool lhs, T rhs) const { return lhs == bool(rhs); } + bool operator()(bool lhs, T rhs) const { return Operator()(lhs, bool(rhs)); } template ::value>::type> - bool operator()(T lhs, bool rhs) const { return bool(lhs) == rhs; } + bool operator()(T lhs, bool rhs) const { return Operator()(bool(lhs), rhs); } - bool operator()(int64_t lhs, uint64_t rhs) const { return lhs < 0 ? false : uint64_t(lhs) == rhs; } - bool operator()(uint64_t lhs, int64_t rhs) const { return rhs < 0 ? false : lhs == uint64_t(rhs); } + bool operator()(int64_t lhs, uint64_t rhs) const { return lhs < 0 ? false : Operator()(uint64_t(lhs), rhs); } + bool operator()(uint64_t lhs, int64_t rhs) const { return rhs < 0 ? false : Operator()(lhs, uint64_t(rhs)); } template ::value>::type> - bool operator()(T lhs, const std::string &rhs) const try { return lhs == string_to_number()(rhs); } + bool operator()(const std::string &lhs, T rhs) const try { return Operator()(string_to_number()(lhs), rhs); } catch(...) { return false; } template ::value>::type> - bool operator()(const std::string &lhs, T rhs) const try { return string_to_number()(lhs) == rhs; } + bool operator()(T lhs, const std::string &rhs) const try { return Operator()(lhs, string_to_number()(rhs)); } catch(...) { return false; } + template + bool operator()(T0 lhs, T1 rhs) const { return Operator()(lhs, rhs); } +}; + +struct relaxed_equal_operator { template bool operator()(T0 lhs, T1 rhs) const { return lhs == rhs; } }; -struct relaxed_equal { - relaxed_equal(Value const &lhs) : lhs(lhs) {} - - bool operator()(Value const &rhs) const { - return apply_visitor(lhs, rhs, relaxed_equal_visitor()); - } - Value const &lhs; +struct relaxed_greater_operator { + template + bool operator()(T0 lhs, T1 rhs) const { return lhs > rhs; } }; + +struct relaxed_greater_equal_operator { + template + bool operator()(T0 lhs, T1 rhs) const { return lhs >= rhs; } +}; + +struct relaxed_less_operator { + template + bool operator()(T0 lhs, T1 rhs) const { return lhs < rhs; } +}; + +struct relaxed_less_equal_operator { + template + bool operator()(T0 lhs, T1 rhs) const { return lhs <= rhs; } +}; + + +} // end namespace detail + +inline bool relaxed_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor()); +} + +inline bool relaxed_greater(Value const &lhs, Value const &rhs) { + return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor()); +} + +inline bool relaxed_greater_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor()); +} + +inline bool relaxed_less(Value const &lhs, Value const &rhs) { + return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor()); +} + +inline bool relaxed_less_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(lhs, rhs, detail::relaxed_operator_visitor()); +} + } template T toNumber(const Value &value) { - if (value.is()) return util::string_to_number()(value.get()); + if (value.is()) return util::detail::string_to_number()(value.get()); else if (value.is()) return value.get(); else if (value.is()) return value.get(); else if (value.is()) return value.get(); diff --git a/test/variant.cpp b/test/variant.cpp index 9a855d15c..2cd545fe1 100644 --- a/test/variant.cpp +++ b/test/variant.cpp @@ -20,141 +20,146 @@ TEST(Variant, toString) { TEST(Variant, RelaxedEquality) { // Compare to bool - EXPECT_TRUE(util::relaxed_equal(bool(true))(int64_t(386))); - EXPECT_TRUE(util::relaxed_equal(bool(true))(int64_t(-7042))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(int64_t(0))); - EXPECT_TRUE(util::relaxed_equal(bool(true))(uint64_t(386))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(uint64_t(0))); - EXPECT_TRUE(util::relaxed_equal(bool(true))(double(386))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(double(0))); - EXPECT_TRUE(util::relaxed_equal(bool(true))(std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string(""))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("false"))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("False"))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("null"))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("nuLL"))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("NULL"))); - EXPECT_TRUE(util::relaxed_equal(bool(true))(bool(true))); - EXPECT_TRUE(util::relaxed_equal(bool(false))(bool(false))); + EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(386))); + EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(-7042))); + EXPECT_TRUE(util::relaxed_equal(bool(false), int64_t(0))); + EXPECT_TRUE(util::relaxed_equal(bool(true), uint64_t(386))); + EXPECT_TRUE(util::relaxed_equal(bool(false), uint64_t(0))); + EXPECT_TRUE(util::relaxed_equal(bool(true), double(386))); + EXPECT_TRUE(util::relaxed_equal(bool(false), double(0))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("386"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(""))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("false"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("False"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("null"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("nuLL"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("NULL"))); + EXPECT_TRUE(util::relaxed_equal(bool(true), bool(true))); + EXPECT_TRUE(util::relaxed_equal(bool(false), bool(false))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(int64_t(0))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(uint64_t(0))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(double(0))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string(""))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("FALSE"))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("null"))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("Null"))); - EXPECT_FALSE(util::relaxed_equal(bool(false))(int64_t(-754))); - EXPECT_FALSE(util::relaxed_equal(bool(false))(uint64_t(3))); - EXPECT_FALSE(util::relaxed_equal(bool(false))(double(3.145))); - EXPECT_FALSE(util::relaxed_equal(bool(false))(std::string("test"))); - EXPECT_FALSE(util::relaxed_equal(bool(true))(bool(false))); - EXPECT_FALSE(util::relaxed_equal(bool(false))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(0))); + EXPECT_FALSE(util::relaxed_equal(bool(true), uint64_t(0))); + EXPECT_FALSE(util::relaxed_equal(bool(true), double(0))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(""))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("FALSE"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("null"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("Null"))); + EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(-754))); + EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(3))); + EXPECT_FALSE(util::relaxed_equal(bool(false), double(3.145))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("test"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), bool(false))); + EXPECT_FALSE(util::relaxed_equal(bool(false), bool(true))); // Compare to int64_t - EXPECT_TRUE(util::relaxed_equal(int64_t(386))(int64_t(386))); - EXPECT_TRUE(util::relaxed_equal(int64_t(-7042))(int64_t(-7042))); - EXPECT_TRUE(util::relaxed_equal(int64_t(386))(uint64_t(386))); - EXPECT_TRUE(util::relaxed_equal(int64_t(386))(double(386))); - EXPECT_TRUE(util::relaxed_equal(int64_t(386))(std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(int64_t(1))(bool(true))); - EXPECT_TRUE(util::relaxed_equal(int64_t(0))(bool(false))); - EXPECT_TRUE(util::relaxed_equal(int64_t(1))(std::string("true"))); - EXPECT_TRUE(util::relaxed_equal(int64_t(0))(std::string("false"))); + EXPECT_TRUE(util::relaxed_equal(int64_t(386), int64_t(386))); + EXPECT_TRUE(util::relaxed_equal(int64_t(-7042), int64_t(-7042))); + EXPECT_TRUE(util::relaxed_equal(int64_t(386), uint64_t(386))); + EXPECT_TRUE(util::relaxed_equal(int64_t(386), double(386))); + EXPECT_TRUE(util::relaxed_equal(int64_t(386), std::string("386"))); + EXPECT_TRUE(util::relaxed_equal(int64_t(1), bool(true))); + EXPECT_TRUE(util::relaxed_equal(int64_t(0), bool(false))); + EXPECT_TRUE(util::relaxed_equal(int64_t(1), std::string("true"))); + EXPECT_TRUE(util::relaxed_equal(int64_t(0), std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(int64_t(386))(int64_t(387))); - EXPECT_FALSE(util::relaxed_equal(int64_t(-7042))(int64_t(-7043))); - EXPECT_FALSE(util::relaxed_equal(int64_t(386))(uint64_t(387))); - EXPECT_FALSE(util::relaxed_equal(int64_t(386))(double(387))); - EXPECT_FALSE(util::relaxed_equal(int64_t(386))(std::string("387"))); - EXPECT_FALSE(util::relaxed_equal(int64_t(1))(bool(false))); - EXPECT_FALSE(util::relaxed_equal(int64_t(0))(bool(true))); - EXPECT_FALSE(util::relaxed_equal(int64_t(1))(std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(int64_t(0))(std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(int64_t(386), int64_t(387))); + EXPECT_FALSE(util::relaxed_equal(int64_t(-7042), int64_t(-7043))); + EXPECT_FALSE(util::relaxed_equal(int64_t(386), uint64_t(387))); + EXPECT_FALSE(util::relaxed_equal(int64_t(386), double(387))); + EXPECT_FALSE(util::relaxed_equal(int64_t(386), std::string("387"))); + EXPECT_FALSE(util::relaxed_equal(int64_t(1), bool(false))); + EXPECT_FALSE(util::relaxed_equal(int64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_equal(int64_t(1), std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(int64_t(0), std::string("true"))); // Compare to uint64_t - EXPECT_TRUE(util::relaxed_equal(uint64_t(386))(int64_t(386))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(386))(uint64_t(386))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(0))(uint64_t(0))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(386))(double(386))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(386))(std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(1))(bool(true))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(0))(bool(false))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(1))(std::string("true"))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(0))(std::string("false"))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(386), int64_t(386))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(386), uint64_t(386))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(0), uint64_t(0))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(386), double(386))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(386), std::string("386"))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(1), bool(true))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(0), bool(false))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(1), std::string("true"))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(0), std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(386))(int64_t(387))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(386))(uint64_t(387))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(0))(uint64_t(1))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(386))(double(387))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(386))(std::string("387"))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(1))(bool(false))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(0))(bool(true))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(1))(std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(uint64_t(0))(std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(386), int64_t(387))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(386), uint64_t(387))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(0), uint64_t(1))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(386), double(387))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(386), std::string("387"))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(1), bool(false))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(1), std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(0), std::string("true"))); // Compare to double - EXPECT_TRUE(util::relaxed_equal(double(3.159385))(double(3.159385))); - EXPECT_TRUE(util::relaxed_equal(double(386))(int64_t(386))); - EXPECT_TRUE(util::relaxed_equal(double(386))(uint64_t(386))); - EXPECT_TRUE(util::relaxed_equal(double(0))(uint64_t(0))); - EXPECT_TRUE(util::relaxed_equal(double(386))(double(386))); - EXPECT_TRUE(util::relaxed_equal(double(386))(std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(double(1))(bool(true))); - EXPECT_TRUE(util::relaxed_equal(double(0))(bool(false))); - EXPECT_TRUE(util::relaxed_equal(double(1))(std::string("true"))); - EXPECT_TRUE(util::relaxed_equal(double(1))(std::string("TRue"))); - EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("false"))); - EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("FALSe"))); - EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("null"))); - EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("Null"))); + EXPECT_TRUE(util::relaxed_equal(double(3.159385), double(3.159385))); + EXPECT_TRUE(util::relaxed_equal(double(386), int64_t(386))); + EXPECT_TRUE(util::relaxed_equal(double(386), uint64_t(386))); + EXPECT_TRUE(util::relaxed_equal(double(0), uint64_t(0))); + EXPECT_TRUE(util::relaxed_equal(double(386), double(386))); + EXPECT_TRUE(util::relaxed_equal(double(386), std::string("386"))); + EXPECT_TRUE(util::relaxed_equal(double(1), bool(true))); + EXPECT_TRUE(util::relaxed_equal(double(0), bool(false))); + EXPECT_TRUE(util::relaxed_equal(double(1), std::string("true"))); + EXPECT_TRUE(util::relaxed_equal(double(1), std::string("TRue"))); + EXPECT_TRUE(util::relaxed_equal(double(0), std::string("false"))); + EXPECT_TRUE(util::relaxed_equal(double(0), std::string("FALSe"))); + EXPECT_TRUE(util::relaxed_equal(double(0), std::string("null"))); + EXPECT_TRUE(util::relaxed_equal(double(0), std::string("Null"))); - EXPECT_FALSE(util::relaxed_equal(double(3.159385))(double(3.159383))); - EXPECT_FALSE(util::relaxed_equal(double(386))(int64_t(387))); - EXPECT_FALSE(util::relaxed_equal(double(386))(uint64_t(387))); - EXPECT_FALSE(util::relaxed_equal(double(0))(uint64_t(1))); - EXPECT_FALSE(util::relaxed_equal(double(386))(double(387))); - EXPECT_FALSE(util::relaxed_equal(double(386))(std::string("387"))); - EXPECT_FALSE(util::relaxed_equal(double(1))(bool(false))); - EXPECT_FALSE(util::relaxed_equal(double(0))(bool(true))); - EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("False"))); - EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("null"))); - EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("NULL"))); - EXPECT_FALSE(util::relaxed_equal(double(0))(std::string("true"))); - EXPECT_FALSE(util::relaxed_equal(double(0))(std::string("TRUE"))); + EXPECT_FALSE(util::relaxed_equal(double(3.159385), double(3.159383))); + EXPECT_FALSE(util::relaxed_equal(double(386), int64_t(387))); + EXPECT_FALSE(util::relaxed_equal(double(386), uint64_t(387))); + EXPECT_FALSE(util::relaxed_equal(double(0), uint64_t(1))); + EXPECT_FALSE(util::relaxed_equal(double(386), double(387))); + EXPECT_FALSE(util::relaxed_equal(double(386), std::string("387"))); + EXPECT_FALSE(util::relaxed_equal(double(1), bool(false))); + EXPECT_FALSE(util::relaxed_equal(double(0), bool(true))); + EXPECT_FALSE(util::relaxed_equal(double(1), std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(double(1), std::string("False"))); + EXPECT_FALSE(util::relaxed_equal(double(1), std::string("null"))); + EXPECT_FALSE(util::relaxed_equal(double(1), std::string("NULL"))); + EXPECT_FALSE(util::relaxed_equal(double(0), std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(double(0), std::string("TRUE"))); // Compare to string - EXPECT_TRUE(util::relaxed_equal(std::string("lord"))(std::string("lord"))); - EXPECT_TRUE(util::relaxed_equal(std::string("386"))(int64_t(386))); - EXPECT_TRUE(util::relaxed_equal(std::string("-386"))(int64_t(-386))); - EXPECT_TRUE(util::relaxed_equal(std::string("386"))(uint64_t(386))); - EXPECT_TRUE(util::relaxed_equal(std::string("386.36"))(double(386.36))); - EXPECT_TRUE(util::relaxed_equal(std::string("true"))(bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string("True"))(bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string("some string"))(bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string("false"))(bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("fAlse"))(bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("null"))(bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("NULl"))(bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(""))(bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("lord"), std::string("lord"))); + EXPECT_TRUE(util::relaxed_equal(std::string("386"), int64_t(386))); + EXPECT_TRUE(util::relaxed_equal(std::string("-386"), int64_t(-386))); + EXPECT_TRUE(util::relaxed_equal(std::string("386"), uint64_t(386))); + EXPECT_TRUE(util::relaxed_equal(std::string("386.36"), double(386.36))); + EXPECT_TRUE(util::relaxed_equal(std::string("true"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string("True"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string("some string"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string("false"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("fAlse"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("null"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("NULl"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string("lord"))(std::string("baron"))); - EXPECT_FALSE(util::relaxed_equal(std::string("386"))(int64_t(387))); - EXPECT_FALSE(util::relaxed_equal(std::string("-386"))(int64_t(-387))); - EXPECT_FALSE(util::relaxed_equal(std::string("386"))(uint64_t(387))); - EXPECT_FALSE(util::relaxed_equal(std::string("386.36"))(double(386.37))); - EXPECT_FALSE(util::relaxed_equal(std::string("true"))(bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string("TRUE"))(bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string("some string"))(bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string("false"))(bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string("FALSE"))(bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string("null"))(bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string("NULl"))(bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string(""))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("lord"), std::string("baron"))); + EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(387))); + EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-387))); + EXPECT_FALSE(util::relaxed_equal(std::string("386"), uint64_t(387))); + EXPECT_FALSE(util::relaxed_equal(std::string("386.36"), double(386.37))); + EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("TRUE"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("some string"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("FALSE"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("null"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("NULl"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string(""), bool(true))); +} + +TEST(Variant, RelaxedGreater) { + EXPECT_TRUE(util::relaxed_greater(std::string("387"), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater(uint64_t(387), int64_t(386))); } From 370c2e1d456bfdf43019cfe7c84d6687c28c9ceb Mon Sep 17 00:00:00 2001 From: Nicki Dlugash Date: Mon, 2 Jun 2014 17:38:44 -0400 Subject: [PATCH 08/11] separating scalerank 4 pois by localrank --- bin/style.js | 161 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 124 insertions(+), 37 deletions(-) diff --git a/bin/style.js b/bin/style.js index 6e17b3338..6e7a0306f 100644 --- a/bin/style.js +++ b/bin/style.js @@ -932,12 +932,28 @@ module.exports = { "size": 12, "type": "point" }, - "poi_4": { + "poi_4_4": { "source": "outdoors", "layer": "poi_label", "icon": "maki", - "field": "scalerank", - "value": 4, + "filter": [ + "and", + { "field": "scalerank", "value": 4 }, + { "field": "localrank", "operator": "<=", "value": 4 } + ], + "size": 12, + "type": "point" + }, + "poi_4_16": { + "source": "outdoors", + "layer": "poi_label", + "icon": "maki", + "filter": [ + "and", + { "field": "scalerank", "value": 4 }, + { "field": "localrank", "operator": "<=", "value": 16 }, + { "field": "localrank", "operator": ">", "value": 4 } + ], "size": 12, "type": "point" }, @@ -977,7 +993,7 @@ module.exports = { "text_field": "{{name_en}}", "path": "horizontal", "padding": 2, - "maxWidth": 10, + "maxWidth": 8, "verticalAlignment": "top", "translate": [0, -1], "font": "Open Sans Semibold, Arial Unicode MS Bold", @@ -985,15 +1001,38 @@ module.exports = { "feature_type": "point", "type": "text", }, - "poi_label_4": { + "poi_label_4_4": { "source": "outdoors", "layer": "poi_label", - "field": "scalerank", - "value": 4, + "filter": [ + "and", + { "field": "scalerank", "value": 4 }, + { "field": "localrank", "operator": "<=", "value": 4 } + ], "text_field": "{{name_en}}", "path": "horizontal", "padding": 2, - "maxWidth": 10, + "maxWidth": 8, + "verticalAlignment": "top", + "translate": [0, -1], + "font": "Open Sans Semibold, Arial Unicode MS Bold", + "fontSize": 10, + "feature_type": "point", + "type": "text", + }, + "poi_label_4_16": { + "source": "outdoors", + "layer": "poi_label", + "filter": [ + "and", + { "field": "scalerank", "value": 4 }, + { "field": "localrank", "operator": "<=", "value": 16 }, + { "field": "localrank", "operator": ">", "value": 4 } + ], + "text_field": "{{name_en}}", + "path": "horizontal", + "padding": 2, + "maxWidth": 8, "verticalAlignment": "top", "translate": [0, -1], "font": "Open Sans Semibold, Arial Unicode MS Bold", @@ -1483,10 +1522,34 @@ module.exports = { "name": "place_label_other", "bucket": "place_label_other" }, + { + "name": "water_label", + "bucket": "water_label" + }, + { + "name": "poi_aerodrome", + "bucket": "poi_aerodrome" + }, + { + "name": "poi", + "bucket": "poi" + }, + { + "name": "poi_label_1-2", + "bucket": "poi_label_1-2" + }, { "name": "road_label_1", "bucket": "road_label_1" }, + { + "name": "poi_3", + "bucket": "poi_3" + }, + { + "name": "poi_label_3", + "bucket": "poi_label_3" + }, { "name": "road_label_2", "bucket": "road_label_2" @@ -1499,41 +1562,25 @@ module.exports = { "name": "contour_label", "bucket": "contour_label" }, - { - "name": "water_label", - "bucket": "water_label" - }, { "name": "waterway_label", "bucket": "waterway_label" }, { - "name": "poi", - "bucket": "poi" + "name": "poi_4_4", + "bucket": "poi_4_4" }, { - "name": "poi_label_1-2", - "bucket": "poi_label_1-2" + "name": "poi_label_4_4", + "bucket": "poi_label_4_4" }, { - "name": "poi_3", - "bucket": "poi_3" + "name": "poi_4_16", + "bucket": "poi_4_16" }, { - "name": "poi_label_3", - "bucket": "poi_label_3" - }, - { - "name": "poi_4", - "bucket": "poi_4" - }, - { - "name": "poi_label_4", - "bucket": "poi_label_4" - }, - { - "name": "poi_aerodrome", - "bucket": "poi_aerodrome" + "name": "poi_label_4_16", + "bucket": "poi_label_4_16" } ], "constants": { @@ -2595,7 +2642,15 @@ module.exports = { {"z": 16.75, "val": 1} ] }, - "poi_4": { + "poi_4_4": { + "antialias": false, + "opacity": [ + "stops", + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} + ] + }, + "poi_4_16": { "antialias": false, "opacity": [ "stops", @@ -2622,12 +2677,24 @@ module.exports = { {"z": 16.75, "val": 1} ] }, - "poi_label_4": { + "poi_label_4_4": { "color": "#444", "size": 10, "opacity": [ "stops", - {"z": 18.5, "val": 0}, + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} + ], + "stroke": "land", + "strokeWidth": 0.3, + "strokeBlur": 1, + }, + "poi_label_4_16": { + "color": "#444", + "size": 10, + "opacity": [ + "stops", + {"z": 18.25, "val": 0}, {"z": 18.75, "val": 1} ], "stroke": "land", @@ -3402,7 +3469,15 @@ module.exports = { {"z": 16.75, "val": 1} ] }, - "poi_4": { + "poi_4_4": { + "antialias": false, + "opacity": [ + "stops", + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} + ] + }, + "poi_4_16": { "antialias": false, "opacity": [ "stops", @@ -3429,7 +3504,19 @@ module.exports = { {"z": 16.75, "val": 1} ] }, - "poi_label_4": { + "poi_label_4_4": { + "color": "#fff", + "size": 10, + "opacity": [ + "stops", + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} + ], + "stroke": "text2_stroke_night", + "strokeWidth": 0.3, + "strokeBlur": 1 + }, + "poi_label_4_16": { "color": "#fff", "size": 10, "opacity": [ From 331b726db4d4fcf5770657107b32fee8df90addb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Tue, 3 Jun 2014 00:00:15 +0200 Subject: [PATCH 09/11] fix comparison order error --- include/llmr/map/filter_expression.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/llmr/map/filter_expression.hpp b/include/llmr/map/filter_expression.hpp index bf6d41480..50e6ce1d7 100644 --- a/include/llmr/map/filter_expression.hpp +++ b/include/llmr/map/filter_expression.hpp @@ -87,17 +87,17 @@ public: inline bool compare(const Value &other) const { switch (op) { case FilterOperator::Equal: - return util::relaxed_equal(value, other); + return util::relaxed_equal(other, value); case FilterOperator::NotEqual: - return !util::relaxed_equal(value, other); + return !util::relaxed_equal(other, value); case FilterOperator::Greater: - return util::relaxed_greater(value, other); + return util::relaxed_greater(other, value); case FilterOperator::GreaterEqual: - return util::relaxed_greater_equal(value, other); + return util::relaxed_greater_equal(other, value); case FilterOperator::Less: - return util::relaxed_less(value, other); + return util::relaxed_less(other, value); case FilterOperator::LessEqual: - return util::relaxed_less_equal(value, other); + return util::relaxed_less_equal(other, value); default: return false; } From ce23e88b018f4615287678bd60d8112030bbdd61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Tue, 3 Jun 2014 00:38:49 +0200 Subject: [PATCH 10/11] add a few tests --- include/llmr/style/value.hpp | 2 +- test/variant.cpp | 293 +++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+), 1 deletion(-) diff --git a/include/llmr/style/value.hpp b/include/llmr/style/value.hpp index e1247af1d..c6d6f50b9 100644 --- a/include/llmr/style/value.hpp +++ b/include/llmr/style/value.hpp @@ -18,7 +18,7 @@ namespace detail { inline int string_to_bool(std::string str) { std::transform(str.begin(), str.end(), str.begin(), ::tolower); - if (str == "false" || str == "null" || !str.length()) return 0; + if (str == "0" || str == "0.0" || str == "false" || str == "null" || !str.length()) return 0; else if (str == "true") return 1; else return -1; } diff --git a/test/variant.cpp b/test/variant.cpp index 2cd545fe1..6512b398f 100644 --- a/test/variant.cpp +++ b/test/variant.cpp @@ -160,6 +160,299 @@ TEST(Variant, RelaxedEquality) { } TEST(Variant, RelaxedGreater) { + EXPECT_TRUE(util::relaxed_greater(std::string("387"), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater(uint64_t(387), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater(int64_t(387), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater(double(387), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater(bool(true), std::string("0"))); + + EXPECT_TRUE(util::relaxed_greater(std::string("387"), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater(uint64_t(387), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater(int64_t(387), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater(double(387), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0))); + EXPECT_TRUE(util::relaxed_greater(std::string("387"), int64_t(386))); EXPECT_TRUE(util::relaxed_greater(uint64_t(387), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater(int64_t(387), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater(double(387), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0))); + + EXPECT_TRUE(util::relaxed_greater(std::string("387"), double(386.7))); + EXPECT_TRUE(util::relaxed_greater(uint64_t(387), double(386.7))); + EXPECT_TRUE(util::relaxed_greater(int64_t(387), double(386.7))); + EXPECT_TRUE(util::relaxed_greater(double(387), double(386.7))); + EXPECT_TRUE(util::relaxed_greater(bool(true), double(0))); + + EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(false))); + EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(false))); + EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(false))); + EXPECT_TRUE(util::relaxed_greater(double(387), bool(false))); + EXPECT_TRUE(util::relaxed_greater(bool(true), double(false))); + + + + + EXPECT_FALSE(util::relaxed_greater(std::string("387"), std::string("388"))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_greater(double(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_greater(bool(true), std::string("388"))); + + EXPECT_FALSE(util::relaxed_greater(std::string("387"), uint64_t(388))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), uint64_t(388))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), uint64_t(388))); + EXPECT_FALSE(util::relaxed_greater(double(387), uint64_t(388))); + EXPECT_FALSE(util::relaxed_greater(bool(true), uint64_t(388))); + + EXPECT_FALSE(util::relaxed_greater(std::string("387"), int64_t(388))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), int64_t(388))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), int64_t(388))); + EXPECT_FALSE(util::relaxed_greater(double(387), int64_t(388))); + EXPECT_FALSE(util::relaxed_greater(bool(true), int64_t(388))); + + EXPECT_FALSE(util::relaxed_greater(std::string("387"), double(388.7))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), double(388.7))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), double(388.7))); + EXPECT_FALSE(util::relaxed_greater(double(387), double(388.7))); + EXPECT_FALSE(util::relaxed_greater(bool(true), double(388))); + + EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(true))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater(double(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater(bool(true), bool(true))); +} + + + +TEST(Variant, RelaxedGreaterEqual) { + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("387"))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("387"))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("387"))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("386"))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("387"))); + EXPECT_TRUE(util::relaxed_greater_equal(bool(true), std::string("0"))); + + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(bool(true), uint64_t(0))); + + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(386))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(387))); + EXPECT_TRUE(util::relaxed_greater_equal(bool(true), int64_t(0))); + + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(386.7))); + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(387))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(386.7))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(387))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(386.7))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(387))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(386.7))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(387))); + EXPECT_TRUE(util::relaxed_greater_equal(bool(true), double(0))); + + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(false))); + EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(true))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(false))); + EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(true))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(false))); + EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(true))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(false))); + EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(true))); + EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(false))); + EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(true))); + + + + + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), std::string("388"))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), std::string("388"))); + + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), uint64_t(388))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), uint64_t(388))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), uint64_t(388))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), uint64_t(388))); + + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), int64_t(388))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), int64_t(388))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), int64_t(388))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), int64_t(388))); + + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), double(388.7))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), double(388.7))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), double(388.7))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), double(388.7))); +} + + +TEST(Variant, RelaxedLess) { + EXPECT_TRUE(util::relaxed_less(std::string("387"), std::string("388"))); + EXPECT_TRUE(util::relaxed_less(uint64_t(387), std::string("388"))); + EXPECT_TRUE(util::relaxed_less(int64_t(387), std::string("388"))); + EXPECT_TRUE(util::relaxed_less(double(387), std::string("388"))); + EXPECT_TRUE(util::relaxed_less(bool(false), std::string("388"))); + EXPECT_TRUE(util::relaxed_less(bool(false), std::string("1"))); + + EXPECT_TRUE(util::relaxed_less(std::string("387"), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less(uint64_t(387), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less(int64_t(387), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less(double(387), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(1))); + + EXPECT_TRUE(util::relaxed_less(std::string("387"), int64_t(388))); + EXPECT_TRUE(util::relaxed_less(uint64_t(387), int64_t(388))); + EXPECT_TRUE(util::relaxed_less(int64_t(387), int64_t(388))); + EXPECT_TRUE(util::relaxed_less(double(387), int64_t(388))); + EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(388))); + EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(1))); + + EXPECT_TRUE(util::relaxed_less(std::string("387"), double(387.7))); + EXPECT_TRUE(util::relaxed_less(uint64_t(387), double(387.7))); + EXPECT_TRUE(util::relaxed_less(int64_t(387), double(387.7))); + EXPECT_TRUE(util::relaxed_less(double(387), double(387.7))); + EXPECT_TRUE(util::relaxed_less(bool(false), double(387))); + EXPECT_TRUE(util::relaxed_less(bool(false), double(1))); + + EXPECT_TRUE(util::relaxed_less(std::string("0"), bool(true))); + EXPECT_TRUE(util::relaxed_less(uint64_t(0), bool(true))); + EXPECT_TRUE(util::relaxed_less(int64_t(0), bool(true))); + EXPECT_TRUE(util::relaxed_less(double(0), bool(true))); + EXPECT_TRUE(util::relaxed_less(bool(false), bool(true))); + + + + + EXPECT_FALSE(util::relaxed_less(std::string("387"), std::string("386"))); + EXPECT_FALSE(util::relaxed_less(uint64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_less(int64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_less(double(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_less(bool(true), std::string("386"))); + + EXPECT_FALSE(util::relaxed_less(std::string("387"), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less(uint64_t(387), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less(int64_t(387), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less(double(387), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less(bool(true), uint64_t(386))); + + EXPECT_FALSE(util::relaxed_less(std::string("387"), int64_t(386))); + EXPECT_FALSE(util::relaxed_less(uint64_t(387), int64_t(386))); + EXPECT_FALSE(util::relaxed_less(int64_t(387), int64_t(386))); + EXPECT_FALSE(util::relaxed_less(double(387), int64_t(386))); + EXPECT_FALSE(util::relaxed_less(bool(true), int64_t(386))); + + EXPECT_FALSE(util::relaxed_less(std::string("387"), double(386.7))); + EXPECT_FALSE(util::relaxed_less(uint64_t(387), double(386.7))); + EXPECT_FALSE(util::relaxed_less(int64_t(387), double(386.7))); + EXPECT_FALSE(util::relaxed_less(double(387), double(386.7))); + EXPECT_FALSE(util::relaxed_less(bool(true), double(386))); + + EXPECT_FALSE(util::relaxed_less(std::string("387"), bool(true))); + EXPECT_FALSE(util::relaxed_less(uint64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_less(int64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_less(double(387), bool(true))); + EXPECT_FALSE(util::relaxed_less(bool(true), bool(true))); +} + + +TEST(Variant, RelaxedLessEqual) { + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("388"))); + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("387"))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("388"))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("387"))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("388"))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("387"))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("388"))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("387"))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("388"))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("1"))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("0"))); + + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(1))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(0))); + + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(387))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(388))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(1))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(0))); + + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387.7))); + EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387.7))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387.7))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387.7))); + EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(387))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(1))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(0))); + + EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(true))); + EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(false))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(true))); + EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(false))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(true))); + EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(false))); + EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(true))); + EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(false))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(true))); + EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(false))); + + + + + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), std::string("386"))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_less_equal(double(387), std::string("386"))); + + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less_equal(double(387), uint64_t(386))); + + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), int64_t(386))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), int64_t(386))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), int64_t(386))); + EXPECT_FALSE(util::relaxed_less_equal(double(387), int64_t(386))); + + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), double(386.7))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), double(386.7))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), double(386.7))); + EXPECT_FALSE(util::relaxed_less_equal(double(387), double(386.7))); } From 71cf4efa5ae806c34b48f42affd0b5df98fce8b1 Mon Sep 17 00:00:00 2001 From: Nicki Dlugash Date: Mon, 2 Jun 2014 18:49:14 -0400 Subject: [PATCH 11/11] finished separating scalerank 4 POIs by localrank --- bin/style.js | 108 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 18 deletions(-) diff --git a/bin/style.js b/bin/style.js index 11d5c6df3..4157e1e8f 100644 --- a/bin/style.js +++ b/bin/style.js @@ -957,6 +957,15 @@ module.exports = { "size": 12, "type": "point" }, + "poi_4_all": { + "source": "outdoors", + "layer": "poi_label", + "icon": "maki", + "field": "scalerank", + "value": 4, + "size": 12, + "type": "point" + }, "poi_aerodrome": { "source": "outdoors", "layer": "poi_label", @@ -1026,8 +1035,7 @@ module.exports = { "filter": [ "and", { "field": "scalerank", "value": 4 }, - { "field": "localrank", "operator": "<=", "value": 16 }, - { "field": "localrank", "operator": ">", "value": 4 } + { "field": "localrank", "operator": "<=", "value": 16 } ], "text_field": "{{name_en}}", "path": "horizontal", @@ -1039,6 +1047,22 @@ module.exports = { "fontSize": 10, "feature_type": "point", "type": "text", + }, + "poi_label_4_all": { + "source": "outdoors", + "layer": "poi_label", + "field": "scalerank", + "value": 4, + "text_field": "{{name_en}}", + "path": "horizontal", + "padding": 2, + "maxWidth": 8, + "verticalAlignment": "top", + "translate": [0, -1], + "font": "Open Sans Semibold, Arial Unicode MS Bold", + "fontSize": 10, + "feature_type": "point", + "type": "text", } }, "structure": [ @@ -1581,6 +1605,14 @@ module.exports = { { "name": "poi_label_4_16", "bucket": "poi_label_4_16" + }, + { + "name": "poi_4_all", + "bucket": "poi_4_all" + }, + { + "name": "poi_label_4_all", + "bucket": "poi_label_4_all" } ], "constants": { @@ -2638,16 +2670,16 @@ module.exports = { "antialias": false, "opacity": [ "stops", - {"z": 16.5, "val": 0}, - {"z": 16.75, "val": 1} + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} ] }, "poi_4_4": { "antialias": false, "opacity": [ "stops", - {"z": 17.5, "val": 0}, - {"z": 17.75, "val": 1} + {"z": 18, "val": 0}, + {"z": 18.25, "val": 1} ] }, "poi_4_16": { @@ -2658,6 +2690,14 @@ module.exports = { {"z": 18.75, "val": 1} ] }, + "poi_4_all": { + "antialias": false, + "opacity": [ + "stops", + {"z": 18.75, "val": 0}, + {"z": 19, "val": 1} + ] + }, "poi_label_1-2": { "color": "#444", "size": "poi_label_1-2_size", @@ -2673,8 +2713,8 @@ module.exports = { "strokeBlur": 1, "opacity": [ "stops", - {"z": 16.5, "val": 0}, - {"z": 16.75, "val": 1} + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} ] }, "poi_label_4_4": { @@ -2682,8 +2722,8 @@ module.exports = { "size": 10, "opacity": [ "stops", - {"z": 17.5, "val": 0}, - {"z": 17.75, "val": 1} + {"z": 18, "val": 0}, + {"z": 17.25, "val": 1} ], "stroke": "land", "strokeWidth": 0.3, @@ -2701,6 +2741,18 @@ module.exports = { "strokeWidth": 0.3, "strokeBlur": 1, }, + "poi_label_4_all": { + "color": "#444", + "size": 10, + "opacity": [ + "stops", + {"z": 18.75, "val": 0}, + {"z": 19, "val": 1} + ], + "stroke": "land", + "strokeWidth": 0.3, + "strokeBlur": 1, + }, "poi_aerodrome": { "opacity": ["stops", {"z": 13, "val": 0}, @@ -3465,16 +3517,16 @@ module.exports = { "antialias": false, "opacity": [ "stops", - {"z": 16.5, "val": 0}, - {"z": 16.75, "val": 1} + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} ] }, "poi_4_4": { "antialias": false, "opacity": [ "stops", - {"z": 17.5, "val": 0}, - {"z": 17.75, "val": 1} + {"z": 18, "val": 0}, + {"z": 17.25, "val": 1} ] }, "poi_4_16": { @@ -3485,6 +3537,14 @@ module.exports = { {"z": 18.75, "val": 1} ] }, + "poi_4_all": { + "antialias": false, + "opacity": [ + "stops", + {"z": 18.75, "val": 0}, + {"z": 19, "val": 1} + ] + }, "poi_label_1-2": { "color": "#fff", "size": "poi_label_1-2_size", @@ -3500,8 +3560,8 @@ module.exports = { "strokeBlur": 1, "opacity": [ "stops", - {"z": 16.5, "val": 0}, - {"z": 16.75, "val": 1} + {"z": 17.5, "val": 0}, + {"z": 17.75, "val": 1} ] }, "poi_label_4_4": { @@ -3509,8 +3569,8 @@ module.exports = { "size": 10, "opacity": [ "stops", - {"z": 17.5, "val": 0}, - {"z": 17.75, "val": 1} + {"z": 18, "val": 0}, + {"z": 18.25, "val": 1} ], "stroke": "text2_stroke_night", "strokeWidth": 0.3, @@ -3528,6 +3588,18 @@ module.exports = { "strokeWidth": 0.3, "strokeBlur": 1 }, + "poi_label_4_all": { + "color": "#fff", + "size": 10, + "opacity": [ + "stops", + {"z": 18.75, "val": 0}, + {"z": 19, "val": 1} + ], + "stroke": "text2_stroke_night", + "strokeWidth": 0.3, + "strokeBlur": 1 + }, "poi_aerodrome": { "opacity": ["stops", {"z": 13, "val": 0},