diff --git a/Makefile b/Makefile index a39ac0490..82bbe1fc9 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ tippecanoe-enumerate: enumerate.o tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.o pmtiles_file.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -tile-join: tile-join.o projection.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o pmtiles_file.o clip.o attribute.o thread.o +tile-join: tile-join.o projection.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o pmtiles_file.o clip.o attribute.o thread.o read_json.o projection.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o @@ -76,8 +76,8 @@ tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o unit: unit.o text.o sort.o mvt.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread -tippecanoe-overzoom: overzoom.o mvt.o clip.o evaluator.o jsonpull/jsonpull.o text.o attribute.o - $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread +tippecanoe-overzoom: overzoom.o mvt.o clip.o evaluator.o jsonpull/jsonpull.o text.o attribute.o read_json.o + $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread projection.o -include $(wildcard *.d) diff --git a/clip.cpp b/clip.cpp index a220e2ad6..4bd570200 100644 --- a/clip.cpp +++ b/clip.cpp @@ -10,6 +10,7 @@ #include "evaluator.hpp" #include "serial.hpp" #include "attribute.hpp" +#include "read_json.hpp" static std::vector> clip_poly1(std::vector> &geom, long long minx, long long miny, long long maxx, long long maxy, @@ -886,7 +887,11 @@ Joined values win over original values, at least for the moment. */ -void join_by_id(mvt_feature &feature, const json_object *j) { +void join_by_id(mvt_layer &layer, mvt_feature &feature, const json_object *j, std::shared_ptr tile_stringpool) { + if (!feature.has_id) { + return; + } + if (j->type != JSON_HASH) { fprintf(stderr, "list of attributes to be joined to features is not a json object\n"); exit(EXIT_JSON); @@ -894,17 +899,47 @@ void join_by_id(mvt_feature &feature, const json_object *j) { for (size_t i = 0; i < j->value.object.length; i++) { const json_object *key = j->value.object.keys[i]; + if (key->type == JSON_STRING) { + unsigned long long feature_id = atoll(j->value.object.keys[i]->value.string.string); + if (feature_id == feature.id) { + const json_object *value = j->value.object.values[i]; + + if (value->type == JSON_HASH) { + for (size_t a = 0; a < value->value.object.length; a++) { + json_object *k = value->value.object.keys[a]; + json_object *v = value->value.object.values[a]; + + if (k->type != JSON_STRING) { + fprintf(stderr, "Expected string for key in json join, not %s\n", json_stringify(k)); + exit(EXIT_JSON); + } + + serial_val sv = stringify_value(v, "joined json", 1, value); + mvt_value mv = stringified_to_mvt_value(sv.type, sv.s.c_str(), tile_stringpool); + layer.tag(feature, k->value.string.string, mv); + } + } else { + fprintf(stderr, "Expected attribute object for value in json join, not %s\n", json_stringify(value)); + exit(EXIT_JSON); + } + + break; + } + } else { + fprintf(stderr, "Expected string for key in json join, not %s\n", json_stringify(key)); + exit(EXIT_JSON); + } } } -std::string overzoom(const mvt_tile &tile, int oz, int ox, int oy, int nz, int nx, int ny, +std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny, int detail, int buffer, std::set const &keep, bool do_compress, std::vector> *next_overzoomed_tiles, bool demultiply, json_object *filter, bool preserve_input_order, std::unordered_map const &attribute_accum, std::vector const &unidecode_data, json_object *join_attributes_json) { mvt_tile outtile; std::shared_ptr tile_stringpool = std::make_shared(); - for (auto const &layer : tile.layers) { + for (auto &layer : tile.layers) { mvt_layer outlayer = mvt_layer(); int det = detail; @@ -923,7 +958,7 @@ std::string overzoom(const mvt_tile &tile, int oz, int ox, int oy, int nz, int n for (auto feature : layer.features) { if (join_attributes_json != NULL) { - join_by_id(feature, join_attributes_json); + join_by_id(layer, feature, join_attributes_json, tile_stringpool); } bool flush_multiplier_cluster = false; diff --git a/geometry.hpp b/geometry.hpp index 5d4ea1d7c..4d72cad54 100644 --- a/geometry.hpp +++ b/geometry.hpp @@ -100,7 +100,7 @@ void visvalingam(drawvec &ls, size_t start, size_t end, double threshold, size_t int pnpoly(const drawvec &vert, size_t start, size_t nvert, long long testx, long long testy); double distance_from_line(long long point_x, long long point_y, long long segA_x, long long segA_y, long long segB_x, long long segB_y); -std::string overzoom(const mvt_tile &tile, int oz, int ox, int oy, int nz, int nx, int ny, +std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny, int detail, int buffer, std::set const &keep, bool do_compress, std::vector> *next_overzoomed_tiles, bool demultiply, json_object *filter, bool preserve_input_order, diff --git a/jsonpull/jsonpull.c b/jsonpull/jsonpull.c index 04ca0f296..01ee5d8ca 100644 --- a/jsonpull/jsonpull.c +++ b/jsonpull/jsonpull.c @@ -905,7 +905,7 @@ void json_disconnect(json_object *o) { o->parent = NULL; } -static void json_print_one(struct string *val, json_object *o) { +static void json_print_one(struct string *val, const json_object *o) { if (o == NULL) { string_append_string(val, "..."); } else if (o->type == JSON_STRING) { @@ -955,7 +955,7 @@ static void json_print_one(struct string *val, json_object *o) { } } -static void json_print(struct string *val, json_object *o) { +static void json_print(struct string *val, const json_object *o) { if (o == NULL) { // Hash value in incompletely read hash string_append_string(val, "..."); @@ -987,7 +987,7 @@ static void json_print(struct string *val, json_object *o) { } } -char *json_stringify(json_object *o) { +char *json_stringify(const json_object *o) { struct string val; string_init(&val); json_print(&val, o); diff --git a/jsonpull/jsonpull.h b/jsonpull/jsonpull.h index b19e0e8e9..40ae28b15 100644 --- a/jsonpull/jsonpull.h +++ b/jsonpull/jsonpull.h @@ -89,7 +89,7 @@ void json_disconnect(json_object *j); json_object *json_hash_get(json_object *o, const char *s); -char *json_stringify(json_object *o); +char *json_stringify(const json_object *o); #ifdef __cplusplus } diff --git a/read_json.cpp b/read_json.cpp index 45e136582..2b1f3f3bf 100644 --- a/read_json.cpp +++ b/read_json.cpp @@ -42,7 +42,7 @@ int mb_geometry[GEOM_TYPES] = { VT_POLYGON, }; -void json_context(json_object *j) { +void json_context(const json_object *j) { char *s = json_stringify(j); if (strlen(s) >= 500) { @@ -121,7 +121,7 @@ void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fna // type and stringified value. All numeric values, even if they are integers, // even integers that are too large to fit in a double but will still be // stringified with their original precision, are recorded here as mvt_double. -serial_val stringify_value(json_object *value, const char *reading, int line, json_object *feature) { +serial_val stringify_value(json_object const *value, char const *reading, int line, json_object const *feature) { serial_val sv; if (value != NULL) { diff --git a/read_json.hpp b/read_json.hpp index 1d9374abd..5a16b40a8 100644 --- a/read_json.hpp +++ b/read_json.hpp @@ -10,7 +10,6 @@ extern const char *geometry_names[GEOM_TYPES]; extern int geometry_within[GEOM_TYPES]; extern int mb_geometry[GEOM_TYPES]; -void json_context(json_object *j); +void json_context(const json_object *j); void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature); - -serial_val stringify_value(json_object *value, const char *reading, int line, json_object *feature); +serial_val stringify_value(json_object const *, char const *, int, json_object const *);