Once features can't possibly fit in a tile, stop trying (#9)

* Stop adding features to a tile if it can't possibly work

* Add --integer and --fraction options to tippecanoe-decode

* Carry the strategies field from tileset metadata through tile-join

* Update changelog

* Assign different codes to different kinds of error exits
This commit is contained in:
Erica Fischer
2022-09-23 20:01:13 -04:00
committed by GitHub
parent ed31b9ac84
commit af1a7ed7ae
44 changed files with 782 additions and 488 deletions
+23 -22
View File
@@ -4,6 +4,7 @@
#include <map>
#include "mvt.hpp"
#include "evaluator.hpp"
#include "errors.hpp"
int compare(mvt_value one, json_object *two, bool &fail) {
if (one.type == mvt_string) {
@@ -34,7 +35,7 @@ int compare(mvt_value one, json_object *two, bool &fail) {
v = one.numeric_value.sint_value;
} else {
fprintf(stderr, "Internal error: bad mvt type %d\n", one.type);
exit(EXIT_FAILURE);
exit(EXIT_IMPOSSIBLE);
}
if (v < two->value.number.number) {
@@ -66,36 +67,36 @@ int compare(mvt_value one, json_object *two, bool &fail) {
}
fprintf(stderr, "Internal error: bad mvt type %d\n", one.type);
exit(EXIT_FAILURE);
exit(EXIT_IMPOSSIBLE);
}
bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::set<std::string> &exclude_attributes) {
if (f == NULL || f->type != JSON_ARRAY) {
fprintf(stderr, "Filter is not an array: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
if (f->value.array.length < 1) {
fprintf(stderr, "Array too small in filter: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
if (f->value.array.array[0]->type != JSON_STRING) {
fprintf(stderr, "Filter operation is not a string: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
if (strcmp(f->value.array.array[0]->value.string.string, "has") == 0 ||
strcmp(f->value.array.array[0]->value.string.string, "!has") == 0) {
if (f->value.array.length != 2) {
fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
if (strcmp(f->value.array.array[0]->value.string.string, "has") == 0) {
if (f->value.array.array[1]->type != JSON_STRING) {
fprintf(stderr, "\"has\" key is not a string: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
return feature.count(std::string(f->value.array.array[1]->value.string.string)) != 0;
}
@@ -103,7 +104,7 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::
if (strcmp(f->value.array.array[0]->value.string.string, "!has") == 0) {
if (f->value.array.array[1]->type != JSON_STRING) {
fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
return feature.count(std::string(f->value.array.array[1]->value.string.string)) == 0;
}
@@ -117,11 +118,11 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::
strcmp(f->value.array.array[0]->value.string.string, "<=") == 0) {
if (f->value.array.length != 3) {
fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
if (f->value.array.array[1]->type != JSON_STRING) {
fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
fprintf(stderr, "comparison key is not a string: %s\n", json_stringify(f));
exit(EXIT_FILTER);
}
auto ff = feature.find(std::string(f->value.array.array[1]->value.string.string));
@@ -176,7 +177,7 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::
}
fprintf(stderr, "Internal error: can't happen: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_IMPOSSIBLE);
}
if (strcmp(f->value.array.array[0]->value.string.string, "all") == 0 ||
@@ -217,12 +218,12 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::
strcmp(f->value.array.array[0]->value.string.string, "!in") == 0) {
if (f->value.array.length < 2) {
fprintf(stderr, "Array too small in filter: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
if (f->value.array.array[1]->type != JSON_STRING) {
fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
fprintf(stderr, "\"!in\" key is not a string: %s\n", json_stringify(f));
exit(EXIT_FILTER);
}
auto ff = feature.find(std::string(f->value.array.array[1]->value.string.string));
@@ -272,12 +273,12 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::
if (strcmp(f->value.array.array[0]->value.string.string, "attribute-filter") == 0) {
if (f->value.array.length != 3) {
fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
if (f->value.array.array[1]->type != JSON_STRING) {
fprintf(stderr, "\"attribute-filter\" key is not a string: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
bool ok = eval(feature, f->value.array.array[2], exclude_attributes);
@@ -289,13 +290,13 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::
}
fprintf(stderr, "Unknown filter %s\n", json_stringify(f));
exit(EXIT_FAILURE);
exit(EXIT_FILTER);
}
bool evaluate(std::map<std::string, mvt_value> const &feature, std::string const &layer, json_object *filter, std::set<std::string> &exclude_attributes) {
if (filter == NULL || filter->type != JSON_HASH) {
fprintf(stderr, "Error: filter is not a hash: %s\n", json_stringify(filter));
exit(EXIT_FAILURE);
exit(EXIT_JSON);
}
bool ok = true;
@@ -318,14 +319,14 @@ json_object *read_filter(const char *fname) {
FILE *fp = fopen(fname, "r");
if (fp == NULL) {
perror(fname);
exit(EXIT_FAILURE);
exit(EXIT_OPEN);
}
json_pull *jp = json_begin_file(fp);
json_object *filter = json_read_tree(jp);
if (filter == NULL) {
fprintf(stderr, "%s: %s\n", fname, jp->error);
exit(EXIT_FAILURE);
exit(EXIT_JSON);
}
json_disconnect(filter);
json_end(jp);
@@ -339,7 +340,7 @@ json_object *parse_filter(const char *s) {
if (filter == NULL) {
fprintf(stderr, "Could not parse filter %s\n", s);
fprintf(stderr, "%s\n", jp->error);
exit(EXIT_FAILURE);
exit(EXIT_JSON);
}
json_disconnect(filter);
json_end(jp);