diff --git a/CHANGELOG.md b/CHANGELOG.md index c2f11413b..9a27c9a19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 2.25.0 + +* Add `--include`/`-y` option to tile-join + # 2.24.0 * Add --cluster-maxzoom option to limit zoom levels that receive clustering diff --git a/README.md b/README.md index 8359738b3..3220ab980 100644 --- a/README.md +++ b/README.md @@ -784,8 +784,9 @@ The options are: ### Filtering features and feature attributes - * `-x` *key* or `--exclude=`*key*: Remove attributes of type *key* from the output. You can use this to remove the field you are matching against if you no longer need it after joining, or to remove any other attributes you don't want. + * `-x` *key* or `--exclude=`*key*: Remove attributes named *key* from the output. You can use this to remove the field you are matching against if you no longer need it after joining, or to remove any other attributes you don't want. You can use multiple `-x` options to remove multiple attributes. * `-X` or `--exclude-all`: Remove all attributes from the output. + * `-y` *key* or `--include=`*key*: Remove all attributes except for those named *key* from the output. You can use multiple `-y` options to retain multiple attributes. * `-i` or `--if-matched`: Only include features that matched the CSV. * `-j` *filter* or `--feature-filter`=*filter*: Check features against a per-layer filter (as defined in the [Mapbox GL Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/#other-filter)) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer `"*"` apply to all layers. * `-J` *filter-file* or `--feature-filter-file`=*filter-file*: Like `-j`, but read the filter from a file. diff --git a/man/tippecanoe.1 b/man/tippecanoe.1 index 265c82c82..7736e6d8a 100644 --- a/man/tippecanoe.1 +++ b/man/tippecanoe.1 @@ -992,10 +992,12 @@ The options are: .SS Filtering features and feature attributes .RS .IP \(bu 2 -\fB\fC\-x\fR \fIkey\fP or \fB\fC\-\-exclude=\fR\fIkey\fP: Remove attributes of type \fIkey\fP from the output. You can use this to remove the field you are matching against if you no longer need it after joining, or to remove any other attributes you don't want. +\fB\fC\-x\fR \fIkey\fP or \fB\fC\-\-exclude=\fR\fIkey\fP: Remove attributes named \fIkey\fP from the output. You can use this to remove the field you are matching against if you no longer need it after joining, or to remove any other attributes you don't want. You can use multiple \fB\fC\-x\fR options to remove multiple attributes. .IP \(bu 2 \fB\fC\-X\fR or \fB\fC\-\-exclude\-all\fR: Remove all attributes from the output. .IP \(bu 2 +\fB\fC\-y\fR \fIkey\fP or \fB\fC\-\-include=\fR\fIkey\fP: Remove all attributes except for those named \fIkey\fP from the output. You can use multiple \fB\fC\-y\fR options to retain multiple attributes. +.IP \(bu 2 \fB\fC\-i\fR or \fB\fC\-\-if\-matched\fR: Only include features that matched the CSV. .IP \(bu 2 \fB\fC\-j\fR \fIfilter\fP or \fB\fC\-\-feature\-filter\fR=\fIfilter\fP: Check features against a per\-layer filter (as defined in the Mapbox GL Style Specification \[la]https://docs.mapbox.com/mapbox-gl-js/style-spec/#other-filter\[ra]) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer \fB\fC"*"\fR apply to all layers. diff --git a/tile-join.cpp b/tile-join.cpp index cc5c7bd68..5372b959a 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -76,7 +76,7 @@ void aprintf(std::string *buf, const char *format, ...) { free(tmp); } -void handle(std::string message, int z, unsigned x, unsigned y, std::map &layermap, std::vector &header, std::map> &mapping, std::set &exclude, std::set &keep_layers, std::set &remove_layers, int ifmatched, mvt_tile &outtile, json_object *filter) { +void handle(std::string message, int z, unsigned x, unsigned y, std::map &layermap, std::vector &header, std::map> &mapping, std::set &exclude, std::set &include, std::set &keep_layers, std::set &remove_layers, int ifmatched, mvt_tile &outtile, json_object *filter) { mvt_tile tile; int features_added = 0; bool was_compressed; @@ -225,7 +225,7 @@ void handle(std::string message, int z, unsigned x, unsigned y, std::map *header = NULL; std::map> *mapping = NULL; std::set *exclude = NULL; + std::set *include = NULL; std::set *keep_layers = NULL; std::set *remove_layers = NULL; int ifmatched = 0; @@ -525,7 +526,7 @@ void *join_worker(void *v) { mvt_tile tile; for (size_t i = 0; i < ai->second.size(); i++) { - handle(ai->second[i], ai->first.z, ai->first.x, ai->first.y, *(a->layermap), *(a->header), *(a->mapping), *(a->exclude), *(a->keep_layers), *(a->remove_layers), a->ifmatched, tile, a->filter); + handle(ai->second[i], ai->first.z, ai->first.x, ai->first.y, *(a->layermap), *(a->header), *(a->mapping), *(a->exclude), *(a->include), *(a->keep_layers), *(a->remove_layers), a->ifmatched, tile, a->filter); } ai->second.clear(); @@ -560,7 +561,7 @@ void *join_worker(void *v) { return NULL; } -void handle_tasks(std::map> &tasks, std::vector> &layermaps, sqlite3 *outdb, const char *outdir, std::vector &header, std::map> &mapping, std::set &exclude, int ifmatched, std::set &keep_layers, std::set &remove_layers, json_object *filter) { +void handle_tasks(std::map> &tasks, std::vector> &layermaps, sqlite3 *outdb, const char *outdir, std::vector &header, std::map> &mapping, std::set &exclude, std::set &include, int ifmatched, std::set &keep_layers, std::set &remove_layers, json_object *filter) { pthread_t pthreads[CPUS]; std::vector args; @@ -571,6 +572,7 @@ void handle_tasks(std::map> &tasks, std::vector &layermap, sqlite3 *outdb, const char *outdir, struct stats *st, std::vector &header, std::map> &mapping, std::set &exclude, int ifmatched, std::string &attribution, std::string &description, std::set &keep_layers, std::set &remove_layers, std::string &name, json_object *filter, std::map &attribute_descriptions, std::string &generator_options, std::vector *strategies) { +void decode(struct reader *readers, std::map &layermap, sqlite3 *outdb, const char *outdir, struct stats *st, std::vector &header, std::map> &mapping, std::set &exclude, std::set &include, int ifmatched, std::string &attribution, std::string &description, std::set &keep_layers, std::set &remove_layers, std::string &name, json_object *filter, std::map &attribute_descriptions, std::string &generator_options, std::vector *strategies) { std::vector> layermaps; for (size_t i = 0; i < CPUS; i++) { layermaps.push_back(std::map()); @@ -761,7 +763,7 @@ void decode(struct reader *readers, std::map &layer if (readers == NULL || readers->zoom != r->zoom || readers->x != r->x || readers->y != r->y) { if (tasks.size() > 100 * CPUS) { - handle_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, ifmatched, keep_layers, remove_layers, filter); + handle_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, include, ifmatched, keep_layers, remove_layers, filter); tasks.clear(); } } @@ -827,7 +829,7 @@ void decode(struct reader *readers, std::map &layer st->minlat2 = min(minlat, st->minlat2); st->maxlat2 = max(maxlat, st->maxlat2); - handle_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, ifmatched, keep_layers, remove_layers, filter); + handle_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, include, ifmatched, keep_layers, remove_layers, filter); layermap = merge_layermaps(layermaps); struct reader *next; @@ -974,7 +976,7 @@ void decode(struct reader *readers, std::map &layer } void usage(char **argv) { - fprintf(stderr, "Usage: %s [-f] [-i] [-pk] [-pC] [-c joins.csv] [-X] [-x exclude ...] [-r inputfile.txt ] -o new.mbtiles source.mbtiles ...\n", argv[0]); + fprintf(stderr, "Usage: %s [-f] [-i] [-pk] [-pC] [-c joins.csv] [-X] [-x exclude ...] [-y include ...] [-r inputfile.txt ] -o new.mbtiles source.mbtiles ...\n", argv[0]); exit(EXIT_ARGS); } @@ -1004,6 +1006,7 @@ int main(int argc, char **argv) { std::map> mapping; std::set exclude; + std::set include; std::set keep_layers; std::set remove_layers; @@ -1021,6 +1024,7 @@ int main(int argc, char **argv) { {"csv", required_argument, 0, 'c'}, {"exclude", required_argument, 0, 'x'}, {"exclude-all", no_argument, 0, 'X'}, + {"include", required_argument, 0, 'y'}, {"layer", required_argument, 0, 'l'}, {"exclude-layer", required_argument, 0, 'L'}, {"quiet", no_argument, 0, 'q'}, @@ -1142,6 +1146,11 @@ int main(int argc, char **argv) { exclude_all = true; break; + case 'y': + exclude_all = true; + include.insert(std::string(optarg)); + break; + case 'l': keep_layers.insert(std::string(optarg)); break; @@ -1274,7 +1283,7 @@ int main(int argc, char **argv) { std::string generator_options; std::vector strategies; - decode(readers, layermap, outdb, out_dir, &st, header, mapping, exclude, ifmatched, attribution, description, keep_layers, remove_layers, name, filter, attribute_descriptions, generator_options, &strategies); + decode(readers, layermap, outdb, out_dir, &st, header, mapping, exclude, include, ifmatched, attribution, description, keep_layers, remove_layers, name, filter, attribute_descriptions, generator_options, &strategies); if (set_attribution.size() != 0) { attribution = set_attribution; diff --git a/version.hpp b/version.hpp index 0936bfa8b..c9c384640 100644 --- a/version.hpp +++ b/version.hpp @@ -1,6 +1,6 @@ #ifndef VERSION_HPP #define VERSION_HPP -#define VERSION "v2.24.0" +#define VERSION "v2.25.0" #endif