From 74a6f174b6ab17e73f405bbdaedd05ee1e5bae92 Mon Sep 17 00:00:00 2001 From: Michael Kopp <kopp.michael@yahoo.de> Date: Thu, 5 Oct 2023 21:23:06 +0200 Subject: [PATCH] introduce binary operators for aggregation --- README.md | 3 ++- main.cpp | 6 +++++- tile.cpp | 36 ++++++++++++++++++++++++++++++++++++ tile.hpp | 2 ++ 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5744d5623..906737b10 100644 --- a/README.md +++ b/README.md @@ -422,8 +422,9 @@ resolution is obtained than by using a smaller _maxzoom_ or _detail_. * `-Y`_attribute_`:`_description_ or `--attribute-description=`_attribute_`:`_description_: Set the `description` for the specified attribute in the tileset metadata to _description_ instead of the usual `String`, `Number`, or `Boolean`. * `-E`_attribute_`:`_operation_ or `--accumulate-attribute=`_attribute_`:`_operation_: Preserve the named _attribute_ from features that are dropped, coalesced-as-needed, or clustered. The _operation_ may be - `sum`, `product`, `mean`, `max`, `min`, `concat`, or `comma` + `sum`, `product`, `mean`, `max`, `min`, `and`, `or`, `concat`, or `comma` to specify how the named _attribute_ is accumulated onto the attribute of the same name in a feature that does survive. + Note, that `and` and `or` are only intended for boolean input. * `-pe` or `--empty-csv-columns-are-null`: Treat empty CSV columns as nulls rather than as empty strings. * `-aI` or `--convert-stringified-ids-to-numbers`: If a feature ID is the string representation of a number, convert it to a plain number to use as the feature ID. * `--use-attribute-for-id=`*name*: Use the attribute with the specified *name* as if it were specified as the feature ID. (If this attribute is a stringified number, you must also use `-aI` to convert it to a number.) diff --git a/main.cpp b/main.cpp index ae41d8254..3957c9a2a 100644 --- a/main.cpp +++ b/main.cpp @@ -2392,12 +2392,16 @@ void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, c t = op_max; } else if (type == "min") { t = op_min; + } else if (type == "or") { + t = op_or; + } else if (type == "and") { + t = op_and; } else if (type == "concat") { t = op_concat; } else if (type == "comma") { t = op_comma; } else { - fprintf(stderr, "Attribute method (%s) must be sum, product, mean, max, min, concat, or comma\n", type.c_str()); + fprintf(stderr, "Attribute method (%s) must be sum, product, mean, max, min, or, and, concat, or comma\n", type.c_str()); exit(EXIT_FAILURE); } diff --git a/tile.cpp b/tile.cpp index cf419825a..22bea7b5a 100644 --- a/tile.cpp +++ b/tile.cpp @@ -1566,6 +1566,32 @@ void add_tilestats(std::string const &layername, int z, std::vector<std::map<std add_to_file_keys(fk->second.file_keys, key, attrib); } +// parse boolean values +// "true" -> true +// "false" -> false +// Anything else is parsed as numeric value using atof; +// - if it is not 0 -> true +// - if it is 0 (including somethign not parsable, e.g. "foo" or "True") -> false +bool atob(const char* str) { + if (0 == strcmp(str, "true")) { + return true; + } + if (0 == strcmp(str, "false")) { + return false; + } + const double floating_point_value = atof(str); + return floating_point_value != 0; +} + +std::string btoa(bool value) { + if (value) { + return "true"; + } + else { + return "false"; + } +} + void preserve_attribute(attribute_op op, serial_feature &, char *stringpool, long long *pool_off, std::string &key, serial_val &val, partial &p) { if (p.need_tilestats.count(key) == 0) { p.need_tilestats.insert(key); @@ -1623,6 +1649,16 @@ void preserve_attribute(attribute_op op, serial_feature &, char *stringpool, lon break; } + case op_or: + p.full_values[i].s = btoa(atob(p.full_values[i].s.c_str()) || atob(val.s.c_str())); + p.full_values[i].type = mvt_bool; + break; + + case op_and: + p.full_values[i].s = btoa(atob(p.full_values[i].s.c_str()) && atob(val.s.c_str())); + p.full_values[i].type = mvt_bool; + break; + case op_mean: { auto state = p.attribute_accum_state.find(key); if (state == p.attribute_accum_state.end()) { diff --git a/tile.hpp b/tile.hpp index 32fb22772..e057e6f38 100644 --- a/tile.hpp +++ b/tile.hpp @@ -17,6 +17,8 @@ enum attribute_op { op_comma, op_max, op_min, + op_or, + op_and, }; long long write_tile(char **geom, char *metabase, char *stringpool, unsigned *file_bbox, int z, unsigned x, unsigned y, int detail, int min_detail, int basezoom, sqlite3 *outdb, const char *outdir, double droprate, int buffer, const char *fname, FILE **geomfile, int file_minzoom, int file_maxzoom, double todo, char *geomstart, long long along, double gamma, int nlayers);