From 19b79d0d5c97970f744269b752ef6e608445c6db Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Tue, 26 Mar 2024 16:26:52 -0700 Subject: [PATCH 1/4] Scaffolding --- clip.cpp | 8 ++++---- geometry.hpp | 6 ++++-- overzoom.cpp | 8 +++++++- tile-join.cpp | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/clip.cpp b/clip.cpp index 4b11a3dd8..d4c1ab308 100644 --- a/clip.cpp +++ b/clip.cpp @@ -758,7 +758,7 @@ static std::vector> clip_poly1(std::vector 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) { + 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 tile; try { @@ -772,7 +772,7 @@ std::string overzoom(const std::string &s, int oz, int ox, int oy, int nz, int n exit(EXIT_PROTOBUF); } - return overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order, attribute_accum, unidecode_data); + return overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order, attribute_accum, unidecode_data, join_attributes_json); } struct tile_feature { @@ -873,7 +873,7 @@ static struct preservecmp { std::string overzoom(const 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) { + 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(); @@ -1046,7 +1046,7 @@ std::string overzoom(const mvt_tile &tile, int oz, int ox, int oy, int nz, int n std::string child = overzoom(outtile, nz, nx, ny, nz + 1, nx * 2 + x, ny * 2 + y, detail, buffer, keep, false, NULL, - demultiply, filter, preserve_input_order, attribute_accum, unidecode_data); + demultiply, filter, preserve_input_order, attribute_accum, unidecode_data, join_attributes_json); if (child.size() > 0) { next_overzoomed_tiles->emplace_back(nx * 2 + x, ny * 2 + y); } diff --git a/geometry.hpp b/geometry.hpp index f847afd15..5d4ea1d7c 100644 --- a/geometry.hpp +++ b/geometry.hpp @@ -105,13 +105,15 @@ std::string overzoom(const mvt_tile &tile, int oz, int ox, int oy, int nz, int n 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); + std::vector const &unidecode_data, + json_object *join_attributes_json); std::string overzoom(const std::string &s, 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); + std::vector const &unidecode_data, + json_object *join_attributes_json); #endif diff --git a/overzoom.cpp b/overzoom.cpp index 67037f918..b8f553367 100644 --- a/overzoom.cpp +++ b/overzoom.cpp @@ -20,6 +20,7 @@ std::string filter; bool preserve_input_order = false; std::unordered_map attribute_accum; std::vector unidecode_data; +json_object *join_attributes_json = NULL; std::set keep; @@ -43,6 +44,7 @@ int main(int argc, char **argv) { {"preserve-input-order", no_argument, 0, 'o' & 0x1F}, {"accumulate-attribute", required_argument, 0, 'E'}, {"unidecode-data", required_argument, 0, 'u' & 0x1F}, + {"join-attributes-json", required_argument, 0, 'c' & 0x1F}, {0, 0, 0, 0}, }; @@ -97,6 +99,10 @@ int main(int argc, char **argv) { unidecode_data = read_unidecode(optarg); break; + case 'c' & 0x1F: + join_attributes_json = read_filter(optarg); + break; + default: fprintf(stderr, "Unrecognized flag -%c\n", i); usage(argv); @@ -151,7 +157,7 @@ int main(int argc, char **argv) { json_filter = parse_filter(filter.c_str()); } - std::string out = overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, true, NULL, demultiply, json_filter, preserve_input_order, attribute_accum, unidecode_data); + std::string out = overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, true, NULL, demultiply, json_filter, preserve_input_order, attribute_accum, unidecode_data, join_attributes_json); fwrite(out.c_str(), sizeof(char), out.size(), f); fclose(f); diff --git a/tile-join.cpp b/tile-join.cpp index be33a7e44..9dfbcd4e0 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -704,7 +704,7 @@ struct tileset_reader { } if (source.layers.size() != 0) { - std::string ret = overzoom(source, parent_tile.z, parent_tile.x, parent_tile.y, tile.z, tile.x, tile.y, -1, buffer, std::set(), false, &next_overzoomed_tiles, false, NULL, false, std::unordered_map(), unidecode_data); + std::string ret = overzoom(source, parent_tile.z, parent_tile.x, parent_tile.y, tile.z, tile.x, tile.y, -1, buffer, std::set(), false, &next_overzoomed_tiles, false, NULL, false, std::unordered_map(), unidecode_data, NULL /* XXX join_attributes_json */); return ret; } From 2e0f099b7c5ce57e75b8c6affc161ca4a5e3b184 Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Tue, 26 Mar 2024 16:59:02 -0700 Subject: [PATCH 2/4] Figuring out a little more --- clip.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/clip.cpp b/clip.cpp index d4c1ab308..a220e2ad6 100644 --- a/clip.cpp +++ b/clip.cpp @@ -870,6 +870,33 @@ static struct preservecmp { } } preservecmp; +/* Format looks like: + +{ + "id": { + "1234": { "name": "Rome", "population", 567890 }, + "15": { "name": "New York", "population": 32, "fictional": false } + } +} + +IDs are really unsigned ints, not strings, but it feels like the keys +and values should be written as keys instead of in some other way. + +Joined values win over original values, at least for the moment. + +*/ + +void join_by_id(mvt_feature &feature, const json_object *j) { + if (j->type != JSON_HASH) { + fprintf(stderr, "list of attributes to be joined to features is not a json object\n"); + exit(EXIT_JSON); + } + + for (size_t i = 0; i < j->value.object.length; i++) { + const json_object *key = j->value.object.keys[i]; + } +} + std::string overzoom(const 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, @@ -895,6 +922,10 @@ std::string overzoom(const mvt_tile &tile, int oz, int ox, int oy, int nz, int n static const std::string retain_points_multiplier_sequence = "tippecanoe:retain_points_multiplier_sequence"; for (auto feature : layer.features) { + if (join_attributes_json != NULL) { + join_by_id(feature, join_attributes_json); + } + bool flush_multiplier_cluster = false; if (demultiply) { for (ssize_t i = feature.tags.size() - 2; i >= 0; i -= 2) { From 1d48570e26dbd12b5942d0bbe77d286a521b53d3 Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Mon, 8 Apr 2024 14:01:17 -0700 Subject: [PATCH 3/4] Most of the rest of joining JSON attributes onto features in overzoom --- Makefile | 6 +++--- clip.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- geometry.hpp | 2 +- jsonpull/jsonpull.c | 6 +++--- jsonpull/jsonpull.h | 2 +- read_json.cpp | 4 ++-- read_json.hpp | 5 ++--- 7 files changed, 51 insertions(+), 17 deletions(-) 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 *); From 20ca3140acc7dc6ff6a37c4615ff741fa72cddda Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Mon, 8 Apr 2024 14:34:00 -0700 Subject: [PATCH 4/4] Test attribute joining in overzoom --- Makefile | 5 +++ tests/pbf/name-fr.json | 1 + tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json | 35 +++++++++++++++++++++ tests/pbf/ne-110m-z3-0-0-0.pbf | Bin 0 -> 453 bytes 4 files changed, 41 insertions(+) create mode 100644 tests/pbf/name-fr.json create mode 100644 tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json create mode 100644 tests/pbf/ne-110m-z3-0-0-0.pbf diff --git a/Makefile b/Makefile index 82bbe1fc9..cf7073866 100644 --- a/Makefile +++ b/Makefile @@ -345,6 +345,11 @@ overzoom-test: tippecanoe-overzoom ./tippecanoe-decode tests/pbf/12-2145-1391-filter2.pbf 12 2145 1391 > tests/pbf/12-2145-1391-filter2.pbf.json.check cmp tests/pbf/12-2145-1391-filter2.pbf.json.check tests/pbf/12-2145-1391-filter2.pbf.json rm tests/pbf/12-2145-1391-filter2.pbf.json.check tests/pbf/12-2145-1391-filter2.pbf + # Test joining attributes from JSON + ./tippecanoe-overzoom -o tests/pbf/ne-110m-z3-0-0-0-joined.pbf --join-attributes-json tests/pbf/name-fr.json tests/pbf/ne-110m-z3-0-0-0.pbf 0/0/0 0/0/0 + ./tippecanoe-decode tests/pbf/ne-110m-z3-0-0-0-joined.pbf 0 0 0 > tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json.check + cmp tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json.check tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json + rm tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json.check tests/pbf/ne-110m-z3-0-0-0-joined.pbf join-test: tippecanoe tippecanoe-decode tile-join ./tippecanoe -q -f -z12 -o tests/join-population/tabblock_06001420.mbtiles -YALAND10:'Land area' -L'{"file": "tests/join-population/tabblock_06001420.json", "description": "population"}' diff --git a/tests/pbf/name-fr.json b/tests/pbf/name-fr.json new file mode 100644 index 000000000..9d60b9cc9 --- /dev/null +++ b/tests/pbf/name-fr.json @@ -0,0 +1 @@ +{"6691831": {"NAME_FR": "Cit\u00e9 du Vatican", "SCALERANK": 8, "NAME_RU": "\u0412\u0430\u0442\u0438\u043a\u0430\u043d"}, "3168070": {"NAME_FR": "Saint-Marin", "SCALERANK": 7, "NAME_RU": "\u0421\u0430\u043d-\u041c\u0430\u0440\u0438\u043d\u043e"}, "3042030": {"NAME_FR": "Vaduz", "SCALERANK": 7, "NAME_RU": "\u0412\u0430\u0434\u0443\u0446"}, "935048": {"NAME_FR": "Lobamba", "SCALERANK": 6, "NAME_RU": "\u041b\u043e\u0431\u0430\u043c\u0431\u0430"}, "2960316": {"NAME_FR": "Luxembourg", "SCALERANK": 6, "NAME_RU": "\u041b\u044e\u043a\u0441\u0435\u043c\u0431\u0443\u0440\u0433"}, "2081986": {"NAME_FR": "Palikir", "SCALERANK": 6, "NAME_RU": "\u041f\u0430\u043b\u0438\u043a\u0438\u0440"}, "2113779": {"NAME_FR": "Majuro", "SCALERANK": 6, "NAME_RU": "\u041c\u0430\u0434\u0436\u0443\u0440\u043e"}, "2110394": {"NAME_FR": "Funafuti", "SCALERANK": 6, "NAME_RU": "\u0424\u0443\u043d\u0430\u0444\u0443\u0442\u0438"}, "1559804": {"NAME_FR": "Melekeok", "SCALERANK": 6, "NAME_RU": "\u041c\u0435\u043b\u0435\u043a\u0435\u043e\u043a"}, "-1": {"NAME_FR": "Tripoli", "SCALERANK": 2, "NAME_RU": "\u0422\u0440\u0438\u043f\u043e\u043b\u0438"}, "2993458": {"NAME_FR": "Monaco", "SCALERANK": 6, "NAME_RU": "\u041c\u043e\u043d\u0430\u043a\u043e"}, "2110079": {"NAME_FR": "Tarawa-Sud", "SCALERANK": 6, "NAME_RU": "\u042e\u0436\u043d\u0430\u044f \u0422\u0430\u0440\u0430\u0432\u0430"}, "921772": {"NAME_FR": "Moroni", "SCALERANK": 6, "NAME_RU": "\u041c\u043e\u0440\u043e\u043d\u0438"}, "3130067": {"NAME_FR": "Andorre-la-Vieille", "SCALERANK": 6, "NAME_RU": "\u0410\u043d\u0434\u043e\u0440\u0440\u0430-\u043b\u0430-\u0412\u0435\u043b\u044c\u044f"}, "3573890": {"NAME_FR": "Port-d'Espagne", "SCALERANK": 4, "NAME_RU": "\u041f\u043e\u0440\u0442-\u043e\u0444-\u0421\u043f\u0435\u0439\u043d"}, "202061": {"NAME_FR": "Kigali", "SCALERANK": 4, "NAME_RU": "\u041a\u0438\u0433\u0430\u043b\u0438"}, "934985": {"NAME_FR": "Mbabane", "SCALERANK": 4, "NAME_RU": "\u041c\u0431\u0430\u0431\u0430\u043d\u0435"}, "373303": {"NAME_FR": "Djouba", "SCALERANK": 4, "NAME_RU": "\u0414\u0436\u0443\u0431\u0430"}, "2747373": {"NAME_FR": "La Haye", "SCALERANK": 4, "NAME_RU": "\u0413\u0430\u0430\u0433\u0430"}, "3196359": {"NAME_FR": "Ljubljana", "SCALERANK": 4, "NAME_RU": "\u041b\u044e\u0431\u043b\u044f\u043d\u0430"}, "3060972": {"NAME_FR": "Bratislava", "SCALERANK": 4, "NAME_RU": "\u0411\u0440\u0430\u0442\u0438\u0441\u043b\u0430\u0432\u0430"}, "290030": {"NAME_FR": "Doha", "SCALERANK": 4, "NAME_RU": "\u0414\u043e\u0445\u0430"}, "3193044": {"NAME_FR": "Podgorica", "SCALERANK": 4, "NAME_RU": "\u041f\u043e\u0434\u0433\u043e\u0440\u0438\u0446\u0430"}, "1238992": {"NAME_FR": "Sri Jayawardenapura", "SCALERANK": 4, "NAME_RU": "\u0428\u0440\u0438-\u0414\u0436\u0430\u044f\u0432\u0430\u0440\u0434\u0435\u043d\u0435\u043f\u0443\u0440\u0430-\u041a\u043e\u0442\u0442\u0435"}, "1728930": {"NAME_FR": "Baguio", "SCALERANK": 4, "NAME_RU": "\u0411\u0430\u0433\u0438\u043e"}, "160196": {"NAME_FR": "Dodoma", "SCALERANK": 4, "NAME_RU": "\u0414\u043e\u0434\u043e\u043c\u0430"}, "2661552": {"NAME_FR": "Berne", "SCALERANK": 4, "NAME_RU": "\u0411\u0435\u0440\u043d"}, "2462881": {"NAME_FR": "La\u00e2youne", "SCALERANK": 4, "NAME_RU": "\u042d\u043b\u044c-\u0410\u044e\u043d"}, "786714": {"NAME_FR": "Pristina", "SCALERANK": 4, "NAME_RU": "\u041f\u0440\u0438\u0448\u0442\u0438\u043d\u0430"}, "3575635": {"NAME_FR": "Roseau", "SCALERANK": 4, "NAME_RU": "\u0420\u043e\u0437\u043e"}, "223817": {"NAME_FR": "Djibouti", "SCALERANK": 4, "NAME_RU": "\u0414\u0436\u0438\u0431\u0443\u0442\u0438"}, "6697380": {"NAME_FR": "Putrajaya", "SCALERANK": 4, "NAME_RU": "\u041f\u0443\u0442\u0440\u0430\u0434\u0436\u0430\u044f"}, "1857910": {"NAME_FR": "Kyoto", "SCALERANK": 4, "NAME_RU": "\u041a\u0438\u043e\u0442\u043e"}, "2413876": {"NAME_FR": "Banjul", "SCALERANK": 4, "NAME_RU": "\u0411\u0430\u043d\u0436\u0443\u043b"}, "785842": {"NAME_FR": "Skopje", "SCALERANK": 4, "NAME_RU": "\u0421\u043a\u043e\u043f\u044c\u0435"}, "2075807": {"NAME_FR": "Bridgetown", "SCALERANK": 4, "NAME_RU": "\u0411\u0440\u0438\u0434\u0436\u0442\u0430\u0443\u043d"}, "2392087": {"NAME_FR": "Porto-Novo", "SCALERANK": 4, "NAME_RU": "\u041f\u043e\u0440\u0442\u043e-\u041d\u043e\u0432\u043e"}, "425378": {"NAME_FR": "Bujumbura", "SCALERANK": 4, "NAME_RU": "\u0411\u0443\u0436\u0443\u043c\u0431\u0443\u0440\u0430"}, "4359981": {"NAME_FR": "Kingstown", "SCALERANK": 4, "NAME_RU": "\u041a\u0438\u043d\u0433\u0441\u0442\u0430\u0443\u043d"}, "3028258": {"NAME_FR": "Castries", "SCALERANK": 4, "NAME_RU": "\u041a\u0430\u0441\u0442\u0440\u0438"}, "3575551": {"NAME_FR": "Basseterre", "SCALERANK": 4, "NAME_RU": "\u0411\u0430\u0441\u0442\u0435\u0440"}, "934154": {"NAME_FR": "Port-Louis", "SCALERANK": 4, "NAME_RU": "\u041f\u043e\u0440\u0442-\u041b\u0443\u0438"}, "3579925": {"NAME_FR": "Saint-Georges", "SCALERANK": 4, "NAME_RU": "\u0421\u0435\u043d\u0442-\u0414\u0436\u043e\u0440\u0434\u0436\u0435\u0441"}, "290340": {"NAME_FR": "Manama", "SCALERANK": 4, "NAME_RU": "\u041c\u0430\u043d\u0430\u043c\u0430"}, "3576022": {"NAME_FR": "Saint John's", "SCALERANK": 4, "NAME_RU": "\u0421\u0435\u043d\u0442-\u0414\u0436\u043e\u043d\u0441"}, "5038018": {"NAME_FR": "Montevideo", "SCALERANK": 3, "NAME_RU": "\u041c\u043e\u043d\u0442\u0435\u0432\u0438\u0434\u0435\u043e"}, "2365267": {"NAME_FR": "Lom\u00e9", "SCALERANK": 3, "NAME_RU": "\u041b\u043e\u043c\u0435"}, "2464470": {"NAME_FR": "Tunis", "SCALERANK": 3, "NAME_RU": "\u0422\u0443\u043d\u0438\u0441"}, "292968": {"NAME_FR": "Abou Dabi", "SCALERANK": 3, "NAME_RU": "\u0410\u0431\u0443-\u0414\u0430\u0431\u0438"}, "162183": {"NAME_FR": "Achgabat", "SCALERANK": 3, "NAME_RU": "\u0410\u0448\u0445\u0430\u0431\u0430\u0434"}, "909137": {"NAME_FR": "Lusaka", "SCALERANK": 3, "NAME_RU": "\u041b\u0443\u0441\u0430\u043a\u0430"}, "890299": {"NAME_FR": "Harare", "SCALERANK": 3, "NAME_RU": "\u0425\u0430\u0440\u0430\u0440\u0435"}, "1645457": {"NAME_FR": "Dili", "SCALERANK": 3, "NAME_RU": "\u0414\u0438\u043b\u0438"}, "2135171": {"NAME_FR": "Port-Vila", "SCALERANK": 3, "NAME_RU": "\u041f\u043e\u0440\u0442-\u0412\u0438\u043b\u0430"}, "3600949": {"NAME_FR": "Tegucigalpa", "SCALERANK": 3, "NAME_RU": "\u0422\u0435\u0433\u0443\u0441\u0438\u0433\u0430\u043b\u044c\u043f\u0430"}, "3378644": {"NAME_FR": "Georgetown", "SCALERANK": 3, "NAME_RU": "\u0414\u0436\u043e\u0440\u0434\u0436\u0442\u0430\u0443\u043d"}, "3413829": {"NAME_FR": "Reykjavik", "SCALERANK": 3, "NAME_RU": "\u0420\u0435\u0439\u043a\u044c\u044f\u0432\u0438\u043a"}, "3718426": {"NAME_FR": "Port-au-Prince", "SCALERANK": 3, "NAME_RU": "\u041f\u043e\u0440\u0442-\u043e-\u041f\u0440\u0435\u043d\u0441"}, "232422": {"NAME_FR": "Kampala", "SCALERANK": 3, "NAME_RU": "\u041a\u0430\u043c\u043f\u0430\u043b\u0430"}, "3383330": {"NAME_FR": "Paramaribo", "SCALERANK": 3, "NAME_RU": "\u041f\u0430\u0440\u0430\u043c\u0430\u0440\u0438\u0431\u043e"}, "2440485": {"NAME_FR": "Niamey", "SCALERANK": 3, "NAME_RU": "\u041d\u0438\u0430\u043c\u0435\u0439"}, "1221874": {"NAME_FR": "Douchanb\u00e9", "SCALERANK": 3, "NAME_RU": "\u0414\u0443\u0448\u0430\u043d\u0431\u0435"}, "1730025": {"NAME_FR": "Asuncion", "SCALERANK": 3, "NAME_RU": "\u0410\u0441\u0443\u043d\u0441\u044c\u043e\u043d"}, "3617763": {"NAME_FR": "Managua", "SCALERANK": 3, "NAME_RU": "\u041c\u0430\u043d\u0430\u0433\u0443\u0430"}, "2408770": {"NAME_FR": "Freetown", "SCALERANK": 3, "NAME_RU": "\u0424\u0440\u0438\u0442\u0430\u0443\u043d"}, "1176615": {"NAME_FR": "Islamabad", "SCALERANK": 3, "NAME_RU": "\u0418\u0441\u043b\u0430\u043c\u0430\u0431\u0430\u0434"}, "1283240": {"NAME_FR": "Katmandou", "SCALERANK": 3, "NAME_RU": "\u041a\u0430\u0442\u043c\u0430\u043d\u0434\u0443"}, "1018725": {"NAME_FR": "Bloemfontein", "SCALERANK": 3, "NAME_RU": "\u0411\u043b\u0443\u043c\u0444\u043e\u043d\u0442\u0435\u0439\u043d"}, "964137": {"NAME_FR": "Pretoria", "SCALERANK": 3, "NAME_RU": "\u041f\u0440\u0435\u0442\u043e\u0440\u0438\u044f"}, "2088122": {"NAME_FR": "Port Moresby", "SCALERANK": 3, "NAME_RU": "\u041f\u043e\u0440\u0442-\u041c\u043e\u0440\u0441\u0431\u0438"}, "2108502": {"NAME_FR": "Honiara", "SCALERANK": 3, "NAME_RU": "\u0425\u043e\u043d\u0438\u0430\u0440\u0430"}, "3703443": {"NAME_FR": "Panama", "SCALERANK": 3, "NAME_RU": "\u041f\u0430\u043d\u0430\u043c\u0430"}, "2538475": {"NAME_FR": "Rabat", "SCALERANK": 3, "NAME_RU": "\u0420\u0430\u0431\u0430\u0442"}, "618426": {"NAME_FR": "Chi\u0219in\u0103u", "SCALERANK": 3, "NAME_RU": "\u041a\u0438\u0448\u0438\u043d\u0451\u0432"}, "1040652": {"NAME_FR": "Maputo", "SCALERANK": 3, "NAME_RU": "\u041c\u0430\u043f\u0443\u0442\u0443"}, "53654": {"NAME_FR": "Mogadiscio", "SCALERANK": 3, "NAME_RU": "\u041c\u043e\u0433\u0430\u0434\u0438\u0448\u043e"}, "287286": {"NAME_FR": "Mascate", "SCALERANK": 3, "NAME_RU": "\u041c\u0430\u0441\u043a\u0430\u0442"}, "3465927": {"NAME_FR": "Colombo", "SCALERANK": 3, "NAME_RU": "\u041a\u043e\u043b\u043e\u043c\u0431\u043e"}, "2028462": {"NAME_FR": "Oulan-Bator", "SCALERANK": 3, "NAME_RU": "\u0423\u043b\u0430\u043d-\u0411\u0430\u0442\u043e\u0440"}, "3352136": {"NAME_FR": "Windhoek", "SCALERANK": 3, "NAME_RU": "\u0412\u0438\u043d\u0434\u0445\u0443\u043a"}, "2322794": {"NAME_FR": "Abuja", "SCALERANK": 3, "NAME_RU": "\u0410\u0431\u0443\u0434\u0436\u0430"}, "2374775": {"NAME_FR": "Bissau", "SCALERANK": 3, "NAME_RU": "\u0411\u0438\u0441\u0430\u0443"}, "250441": {"NAME_FR": "Amman", "SCALERANK": 3, "NAME_RU": "\u0410\u043c\u043c\u0430\u043d"}, "593116": {"NAME_FR": "Vilnius", "SCALERANK": 3, "NAME_RU": "\u0412\u0438\u043b\u044c\u043d\u044e\u0441"}, "456172": {"NAME_FR": "Riga", "SCALERANK": 3, "NAME_RU": "\u0420\u0438\u0433\u0430"}, "1528675": {"NAME_FR": "Bichkek", "SCALERANK": 3, "NAME_RU": "\u0411\u0438\u0448\u043a\u0435\u043a"}, "932505": {"NAME_FR": "Maseru", "SCALERANK": 3, "NAME_RU": "\u041c\u0430\u0441\u0435\u0440\u0443"}, "1070940": {"NAME_FR": "Antananarivo", "SCALERANK": 3, "NAME_RU": "\u0410\u043d\u0442\u0430\u043d\u0430\u043d\u0430\u0440\u0438\u0432\u0443"}, "3652462": {"NAME_FR": "Quito", "SCALERANK": 3, "NAME_RU": "\u041a\u0438\u0442\u043e"}, "3669623": {"NAME_FR": "San Jos\u00e9", "SCALERANK": 3, "NAME_RU": "\u0421\u0430\u043d-\u0425\u043e\u0441\u0435"}, "1690681": {"NAME_FR": "San Salvador", "SCALERANK": 3, "NAME_RU": "\u0421\u0430\u043d-\u0421\u0430\u043b\u044c\u0432\u0430\u0434\u043e\u0440"}, "3489854": {"NAME_FR": "Kingston", "SCALERANK": 3, "NAME_RU": "\u041a\u0438\u043d\u0433\u0441\u0442\u043e\u043d"}, "2427123": {"NAME_FR": "N'Djam\u00e9na", "SCALERANK": 3, "NAME_RU": "\u041d\u0434\u0436\u0430\u043c\u0435\u043d\u0430"}, "2309527": {"NAME_FR": "Malabo", "SCALERANK": 3, "NAME_RU": "\u041c\u0430\u043b\u0430\u0431\u043e"}, "343300": {"NAME_FR": "Asmara", "SCALERANK": 3, "NAME_RU": "\u0410\u0441\u043c\u044d\u0440\u0430"}, "3186886": {"NAME_FR": "Zagreb", "SCALERANK": 3, "NAME_RU": "\u0417\u0430\u0433\u0440\u0435\u0431"}, "588409": {"NAME_FR": "Tallinn", "SCALERANK": 3, "NAME_RU": "\u0422\u0430\u043b\u043b\u0438\u043d"}, "927967": {"NAME_FR": "Lilongwe", "SCALERANK": 3, "NAME_RU": "\u041b\u0438\u043b\u043e\u043d\u0433\u0432\u0435"}, "3598132": {"NAME_FR": "Guatemala-Ville", "SCALERANK": 3, "NAME_RU": "\u0413\u0432\u0430\u0442\u0435\u043c\u0430\u043b\u0430"}, "2399697": {"NAME_FR": "Libreville", "SCALERANK": 3, "NAME_RU": "\u041b\u0438\u0431\u0440\u0435\u0432\u0438\u043b\u044c"}, "2198148": {"NAME_FR": "Suva", "SCALERANK": 3, "NAME_RU": "\u0421\u0443\u0432\u0430"}, "3445575": {"NAME_FR": "Valpara\u00edso", "SCALERANK": 3, "NAME_RU": "\u0412\u0430\u043b\u044c\u043f\u0430\u0440\u0430\u0438\u0441\u043e"}, "2377450": {"NAME_FR": "Nouakchott", "SCALERANK": 3, "NAME_RU": "\u041d\u0443\u0430\u043a\u0448\u043e\u0442"}, "2460596": {"NAME_FR": "Bamako", "SCALERANK": 3, "NAME_RU": "\u0411\u0430\u043c\u0430\u043a\u043e"}, "276781": {"NAME_FR": "Beyrouth", "SCALERANK": 3, "NAME_RU": "\u0411\u0435\u0439\u0440\u0443\u0442"}, "611717": {"NAME_FR": "Tbilissi", "SCALERANK": 3, "NAME_RU": "\u0422\u0431\u0438\u043b\u0438\u0441\u0438"}, "1526273": {"NAME_FR": "Noursoultan", "SCALERANK": 3, "NAME_RU": "\u041d\u0443\u0440-\u0421\u0443\u043b\u0442\u0430\u043d"}, "1651944": {"NAME_FR": "Vientiane", "SCALERANK": 3, "NAME_RU": "\u0412\u044c\u0435\u043d\u0442\u044c\u044f\u043d"}, "2260535": {"NAME_FR": "Brazzaville", "SCALERANK": 3, "NAME_RU": "\u0411\u0440\u0430\u0437\u0437\u0430\u0432\u0438\u043b\u044c"}, "2422465": {"NAME_FR": "Conakry", "SCALERANK": 3, "NAME_RU": "\u041a\u043e\u043d\u0430\u043a\u0440\u0438"}, "2279755": {"NAME_FR": "Yamoussoukro", "SCALERANK": 3, "NAME_RU": "\u042f\u043c\u0443\u0441\u0443\u043a\u0440\u043e"}, "6094817": {"NAME_FR": "Ottawa", "SCALERANK": 3, "NAME_RU": "\u041e\u0442\u0442\u0430\u0432\u0430"}, "792680": {"NAME_FR": "Belgrade", "SCALERANK": 3, "NAME_RU": "\u0411\u0435\u043b\u0433\u0440\u0430\u0434"}, "1820906": {"NAME_FR": "Bandar Seri Begawan", "SCALERANK": 3, "NAME_RU": "\u0411\u0430\u043d\u0434\u0430\u0440-\u0421\u0435\u0440\u0438-\u0411\u0435\u0433\u0430\u0432\u0430\u043d"}, "3903987": {"NAME_FR": "Sucre", "SCALERANK": 3, "NAME_RU": "\u0421\u0443\u043a\u0440\u0435"}, "3582672": {"NAME_FR": "Belmopan", "SCALERANK": 3, "NAME_RU": "\u0411\u0435\u043b\u044c\u043c\u043e\u043f\u0430\u043d"}, "2389853": {"NAME_FR": "Bangui", "SCALERANK": 3, "NAME_RU": "\u0411\u0430\u043d\u0433\u0438"}, "2220957": {"NAME_FR": "Yaound\u00e9", "SCALERANK": 3, "NAME_RU": "\u042f\u0443\u043d\u0434\u0435"}, "3183875": {"NAME_FR": "Tirana", "SCALERANK": 3, "NAME_RU": "\u0422\u0438\u0440\u0430\u043d\u0430"}, "616052": {"NAME_FR": "Erevan", "SCALERANK": 3, "NAME_RU": "\u0415\u0440\u0435\u0432\u0430\u043d"}, "587084": {"NAME_FR": "Bakou", "SCALERANK": 3, "NAME_RU": "\u0411\u0430\u043a\u0443"}, "1821306": {"NAME_FR": "Phnom Penh", "SCALERANK": 3, "NAME_RU": "\u041f\u043d\u043e\u043c\u043f\u0435\u043d\u044c"}, "3911925": {"NAME_FR": "La Paz", "SCALERANK": 3, "NAME_RU": "\u041b\u0430-\u041f\u0430\u0441"}, "2394819": {"NAME_FR": "Cotonou", "SCALERANK": 3, "NAME_RU": "\u041a\u043e\u0442\u043e\u043d\u0443"}, "727011": {"NAME_FR": "Sofia", "SCALERANK": 3, "NAME_RU": "\u0421\u043e\u0444\u0438\u044f"}, "625144": {"NAME_FR": "Minsk", "SCALERANK": 3, "NAME_RU": "\u041c\u0438\u043d\u0441\u043a"}, "1252416": {"NAME_FR": "Thimphou", "SCALERANK": 3, "NAME_RU": "\u0422\u0445\u0438\u043c\u043f\u0445\u0443"}, "933773": {"NAME_FR": "Gaborone", "SCALERANK": 3, "NAME_RU": "\u0413\u0430\u0431\u043e\u0440\u043e\u043d\u0435"}, "2172517": {"NAME_FR": "Canberra", "SCALERANK": 3, "NAME_RU": "\u041a\u0430\u043d\u0431\u0435\u0440\u0440\u0430"}, "2357048": {"NAME_FR": "Ouagadougou", "SCALERANK": 3, "NAME_RU": "\u0423\u0430\u0433\u0430\u0434\u0443\u0433\u0443"}, "3191281": {"NAME_FR": "Sarajevo", "SCALERANK": 3, "NAME_RU": "\u0421\u0430\u0440\u0430\u0435\u0432\u043e"}, "6611854": {"NAME_FR": "Naypyidaw", "SCALERANK": 3, "NAME_RU": "\u041d\u0435\u0439\u043f\u044c\u0438\u0434\u043e"}, "4032402": {"NAME_FR": "Nuku\u02bbalofa", "SCALERANK": 3, "NAME_RU": "\u041d\u0443\u043a\u0443\u0430\u043b\u043e\u0444\u0430"}, "57289": {"NAME_FR": "Hargeisa", "SCALERANK": 3, "NAME_RU": "\u0425\u0430\u0440\u0433\u0435\u0439\u0441\u0430"}, "241131": {"NAME_FR": "Victoria", "SCALERANK": 3, "NAME_RU": "\u0412\u0438\u043a\u0442\u043e\u0440\u0438\u044f"}, "3388092": {"NAME_FR": "S\u00e3o Tom\u00e9", "SCALERANK": 3, "NAME_RU": "\u0421\u0430\u043d-\u0422\u043e\u043c\u0435"}, "3689793": {"NAME_FR": "Apia", "SCALERANK": 3, "NAME_RU": "\u0410\u043f\u0438\u0430"}, "2562305": {"NAME_FR": "La Valette", "SCALERANK": 3, "NAME_RU": "\u0412\u0430\u043b\u043b\u0435\u0442\u0442\u0430"}, "3174186": {"NAME_FR": "Mal\u00e9", "SCALERANK": 3, "NAME_RU": "\u041c\u0430\u043b\u0435"}, "281184": {"NAME_FR": "J\u00e9rusalem", "SCALERANK": 3, "NAME_RU": "\u0418\u0435\u0440\u0443\u0441\u0430\u043b\u0438\u043c"}, "3374333": {"NAME_FR": "Praia", "SCALERANK": 3, "NAME_RU": "\u041f\u0440\u0430\u044f"}, "3571824": {"NAME_FR": "Nassau", "SCALERANK": 3, "NAME_RU": "\u041d\u0430\u0441\u0441\u0430\u0443"}, "146268": {"NAME_FR": "Nicosie", "SCALERANK": 3, "NAME_RU": "\u041d\u0438\u043a\u043e\u0441\u0438\u044f"}, "2144168": {"NAME_FR": "Wellington", "SCALERANK": 3, "NAME_RU": "\u0412\u0435\u043b\u043b\u0438\u043d\u0433\u0442\u043e\u043d"}, "1581130": {"NAME_FR": "Hano\u00ef", "SCALERANK": 2, "NAME_RU": "\u0425\u0430\u043d\u043e\u0439"}, "323786": {"NAME_FR": "Ankara", "SCALERANK": 2, "NAME_RU": "\u0410\u043d\u043a\u0430\u0440\u0430"}, "3054643": {"NAME_FR": "Budapest", "SCALERANK": 2, "NAME_RU": "\u0411\u0443\u0434\u0430\u043f\u0435\u0448\u0442"}, "71137": {"NAME_FR": "Sanaa", "SCALERANK": 2, "NAME_RU": "\u0421\u0430\u043d\u0430"}, "683506": {"NAME_FR": "Bucarest", "SCALERANK": 2, "NAME_RU": "\u0411\u0443\u0445\u0430\u0440\u0435\u0441\u0442"}, "170654": {"NAME_FR": "Damas", "SCALERANK": 2, "NAME_RU": "\u0414\u0430\u043c\u0430\u0441\u043a"}, "2267057": {"NAME_FR": "Lisbonne", "SCALERANK": 2, "NAME_RU": "\u041b\u0438\u0441\u0441\u0430\u0431\u043e\u043d"}, "379252": {"NAME_FR": "Khartoum", "SCALERANK": 2, "NAME_RU": "\u0425\u0430\u0440\u0442\u0443\u043c"}, "3143244": {"NAME_FR": "Oslo", "SCALERANK": 2, "NAME_RU": "\u041e\u0441\u043b\u043e"}, "756135": {"NAME_FR": "Varsovie", "SCALERANK": 2, "NAME_RU": "\u0412\u0430\u0440\u0448\u0430\u0432\u0430"}, "1871859": {"NAME_FR": "Pyongyang", "SCALERANK": 2, "NAME_RU": "\u041f\u0445\u0435\u043d\u044c\u044f\u043d"}, "160263": {"NAME_FR": "Dar es Salam", "SCALERANK": 2, "NAME_RU": "\u0414\u0430\u0440-\u044d\u0441-\u0421\u0430\u043b\u0430\u043c"}, "2964574": {"NAME_FR": "Dublin", "SCALERANK": 2, "NAME_RU": "\u0414\u0443\u0431\u043b\u0438\u043d"}, "2274895": {"NAME_FR": "Monrovia", "SCALERANK": 2, "NAME_RU": "\u041c\u043e\u043d\u0440\u043e\u0432\u0438\u044f"}, "1735161": {"NAME_FR": "Kuala Lumpur", "SCALERANK": 2, "NAME_RU": "\u041a\u0443\u0430\u043b\u0430-\u041b\u0443\u043c\u043f\u0443\u0440"}, "3553478": {"NAME_FR": "La Havane", "SCALERANK": 2, "NAME_RU": "\u0413\u0430\u0432\u0430\u043d\u0430"}, "4548393": {"NAME_FR": "Prague", "SCALERANK": 2, "NAME_RU": "\u041f\u0440\u0430\u0433\u0430"}, "285787": {"NAME_FR": "Kowe\u00eft", "SCALERANK": 2, "NAME_RU": "\u042d\u043b\u044c-\u041a\u0443\u0432\u0435\u0439\u0442"}, "3668373": {"NAME_FR": "Saint-Domingue", "SCALERANK": 2, "NAME_RU": "\u0421\u0430\u043d\u0442\u043e-\u0414\u043e\u043c\u0438\u043d\u0433\u043e"}, "2306104": {"NAME_FR": "Accra", "SCALERANK": 2, "NAME_RU": "\u0410\u043a\u043a\u0440\u0430"}, "293394": {"NAME_FR": "Tel Aviv", "SCALERANK": 2, "NAME_RU": "\u0422\u0435\u043b\u044c-\u0410\u0432\u0438\u0432"}, "658225": {"NAME_FR": "Helsinki", "SCALERANK": 2, "NAME_RU": "\u0425\u0435\u043b\u044c\u0441\u0438\u043d\u043a\u0438"}, "2618425": {"NAME_FR": "Copenhague", "SCALERANK": 2, "NAME_RU": "\u041a\u043e\u043f\u0435\u043d\u0433\u0430\u0433\u0435\u043d"}, "2293538": {"NAME_FR": "Abidjan", "SCALERANK": 2, "NAME_RU": "\u0410\u0431\u0438\u0434\u0436\u0430\u043d"}, "3469058": {"NAME_FR": "Brasilia", "SCALERANK": 2, "NAME_RU": "\u0411\u0440\u0430\u0437\u0438\u043b\u0438\u0430"}, "2800866": {"NAME_FR": "Bruxelles", "SCALERANK": 2, "NAME_RU": "\u0411\u0440\u044e\u0441\u0441\u0435\u043b\u044c"}, "1185241": {"NAME_FR": "Dacca", "SCALERANK": 2, "NAME_RU": "\u0414\u0430\u043a\u043a\u0430"}, "2240449": {"NAME_FR": "Luanda", "SCALERANK": 2, "NAME_RU": "\u041b\u0443\u0430\u043d\u0434\u0430"}, "2507480": {"NAME_FR": "Alger", "SCALERANK": 2, "NAME_RU": "\u0410\u043b\u0436\u0438\u0440"}, "1298824": {"NAME_FR": "Rangoun", "SCALERANK": 2, "NAME_RU": "\u042f\u043d\u0433\u043e\u043d"}, "5391959": {"NAME_FR": "San Francisco", "SCALERANK": 1, "NAME_RU": "\u0421\u0430\u043d-\u0424\u0440\u0430\u043d\u0446\u0438\u0441\u043a\u043e"}, "5419384": {"NAME_FR": "Denver", "SCALERANK": 1, "NAME_RU": "\u0414\u0435\u043d\u0432\u0435\u0440"}, "4699066": {"NAME_FR": "Houston", "SCALERANK": 1, "NAME_RU": "\u0425\u044c\u044e\u0441\u0442\u043e\u043d"}, "4164138": {"NAME_FR": "Miami", "SCALERANK": 1, "NAME_RU": "\u041c\u0430\u0439\u0430\u043c\u0438"}, "4180439": {"NAME_FR": "Atlanta", "SCALERANK": 1, "NAME_RU": "\u0410\u0442\u043b\u0430\u043d\u0442\u0430"}, "4887398": {"NAME_FR": "Chicago", "SCALERANK": 1, "NAME_RU": "\u0427\u0438\u043a\u0430\u0433\u043e"}, "3646738": {"NAME_FR": "Caracas", "SCALERANK": 1, "NAME_RU": "\u041a\u0430\u0440\u0430\u043a\u0430\u0441"}, "703448": {"NAME_FR": "Kiev", "SCALERANK": 1, "NAME_RU": "\u041a\u0438\u0435\u0432"}, "292223": {"NAME_FR": "Duba\u00ef", "SCALERANK": 1, "NAME_RU": "\u0414\u0443\u0431\u0430\u0439"}, "1512569": {"NAME_FR": "Tachkent", "SCALERANK": 1, "NAME_RU": "\u0422\u0430\u0448\u043a\u0435\u043d\u0442"}, "3117735": {"NAME_FR": "Madrid", "SCALERANK": 1, "NAME_RU": "\u041c\u0430\u0434\u0440\u0438\u0434"}, "2660646": {"NAME_FR": "Gen\u00e8ve", "SCALERANK": 1, "NAME_RU": "\u0416\u0435\u043d\u0435\u0432\u0430"}, "2673730": {"NAME_FR": "Stockholm", "SCALERANK": 1, "NAME_RU": "\u0421\u0442\u043e\u043a\u0433\u043e\u043b\u044c\u043c"}, "1609350": {"NAME_FR": "Bangkok", "SCALERANK": 1, "NAME_RU": "\u0411\u0430\u043d\u0433\u043a\u043e\u043a"}, "3936456": {"NAME_FR": "Lima", "SCALERANK": 1, "NAME_RU": "\u041b\u0438\u043c\u0430"}, "2253354": {"NAME_FR": "Dakar", "SCALERANK": 1, "NAME_RU": "\u0414\u0430\u043a\u0430\u0440"}, "993800": {"NAME_FR": "Johannesbourg", "SCALERANK": 1, "NAME_RU": "\u0419\u043e\u0445\u0430\u043d\u043d\u0435\u0441\u0431\u0443\u0440\u0433"}, "2759794": {"NAME_FR": "Amsterdam", "SCALERANK": 1, "NAME_RU": "\u0410\u043c\u0441\u0442\u0435\u0440\u0434\u0430\u043c"}, "2553604": {"NAME_FR": "Casablanca", "SCALERANK": 1, "NAME_RU": "\u041a\u0430\u0441\u0430\u0431\u043b\u0430\u043d\u043a\u0430"}, "1835848": {"NAME_FR": "S\u00e9oul", "SCALERANK": 1, "NAME_RU": "\u0421\u0435\u0443\u043b"}, "1701668": {"NAME_FR": "Manille", "SCALERANK": 1, "NAME_RU": "\u041c\u0430\u043d\u0438\u043b\u0430"}, "3995465": {"NAME_FR": "Monterrey", "SCALERANK": 1, "NAME_RU": "\u041c\u043e\u043d\u0442\u0435\u0440\u0440\u0435\u0439"}, "2950159": {"NAME_FR": "Berlin", "SCALERANK": 1, "NAME_RU": "\u0411\u0435\u0440\u043b\u0438\u043d"}, "1529102": {"NAME_FR": "\u00dcr\u00fcmqi", "SCALERANK": 1, "NAME_RU": "\u0423\u0440\u0443\u043c\u0447\u0438"}, "1815286": {"NAME_FR": "Chengdu", "SCALERANK": 1, "NAME_RU": "\u0427\u044d\u043d\u0434\u0443"}, "1853909": {"NAME_FR": "Osaka", "SCALERANK": 1, "NAME_RU": "\u041e\u0441\u0430\u043a\u0430"}, "2314302": {"NAME_FR": "Kinshasa", "SCALERANK": 1, "NAME_RU": "\u041a\u0438\u043d\u0448\u0430\u0441\u0430"}, "1261481": {"NAME_FR": "New Delhi", "SCALERANK": 1, "NAME_RU": "\u041d\u044c\u044e-\u0414\u0435\u043b\u0438"}, "1277333": {"NAME_FR": "Bangalore", "SCALERANK": 1, "NAME_RU": "\u0411\u0430\u043d\u0433\u0430\u043b\u043e\u0440"}, "264371": {"NAME_FR": "Ath\u00e8nes", "SCALERANK": 1, "NAME_RU": "\u0410\u0444\u0438\u043d\u044b"}, "98182": {"NAME_FR": "Bagdad", "SCALERANK": 1, "NAME_RU": "\u0411\u0430\u0433\u0434\u0430\u0434"}, "344979": {"NAME_FR": "Addis-Abeba", "SCALERANK": 1, "NAME_RU": "\u0410\u0434\u0434\u0438\u0441-\u0410\u0431\u0435\u0431\u0430"}, "112931": {"NAME_FR": "T\u00e9h\u00e9ran", "SCALERANK": 1, "NAME_RU": "\u0422\u0435\u0433\u0435\u0440\u0430\u043d"}, "6173331": {"NAME_FR": "Vancouver", "SCALERANK": 1, "NAME_RU": "\u0412\u0430\u043d\u043a\u0443\u0432\u0435\u0440"}, "6167865": {"NAME_FR": "Toronto", "SCALERANK": 1, "NAME_RU": "\u0422\u043e\u0440\u043e\u043d\u0442\u043e"}, "3435910": {"NAME_FR": "Buenos Aires", "SCALERANK": 1, "NAME_RU": "\u0411\u0443\u044d\u043d\u043e\u0441-\u0410\u0439\u0440\u0435\u0441"}, "1138958": {"NAME_FR": "Kaboul", "SCALERANK": 1, "NAME_RU": "\u041a\u0430\u0431\u0443\u043b"}, "2761369": {"NAME_FR": "Vienne", "SCALERANK": 1, "NAME_RU": "\u0412\u0435\u043d\u0430"}, "2158177": {"NAME_FR": "Melbourne", "SCALERANK": 1, "NAME_RU": "\u041c\u0435\u043b\u044c\u0431\u0443\u0440\u043d"}, "1668341": {"NAME_FR": "Taipei", "SCALERANK": 1, "NAME_RU": "\u0422\u0430\u0439\u0431\u044d\u0439"}, "2193733": {"NAME_FR": "Auckland", "SCALERANK": 1, "NAME_RU": "\u041e\u043a\u043b\u0435\u043d\u0434"}, "5368361": {"NAME_FR": "Los Angeles", "SCALERANK": 0, "NAME_RU": "\u041b\u043e\u0441-\u0410\u043d\u0434\u0436\u0435\u043b\u0435\u0441"}, "4140963": {"NAME_FR": "Washington", "SCALERANK": 0, "NAME_RU": "\u0412\u0430\u0448\u0438\u043d\u0433\u0442\u043e\u043d"}, "5128581": {"NAME_FR": "New York", "SCALERANK": 0, "NAME_RU": "\u041d\u044c\u044e-\u0419\u043e\u0440\u043a"}, "2643743": {"NAME_FR": "Londres", "SCALERANK": 0, "NAME_RU": "\u041b\u043e\u043d\u0434\u043e\u043d"}, "745044": {"NAME_FR": "Istanbul", "SCALERANK": 0, "NAME_RU": "\u0421\u0442\u0430\u043c\u0431\u0443\u043b"}, "108410": {"NAME_FR": "Riyad", "SCALERANK": 0, "NAME_RU": "\u042d\u0440-\u0420\u0438\u044f\u0434"}, "3369157": {"NAME_FR": "Le Cap", "SCALERANK": 0, "NAME_RU": "\u041a\u0435\u0439\u043f\u0442\u0430\u0443\u043d"}, "524901": {"NAME_FR": "Moscou", "SCALERANK": 0, "NAME_RU": "\u041c\u043e\u0441\u043a\u0432\u0430"}, "3530597": {"NAME_FR": "Mexico", "SCALERANK": 0, "NAME_RU": "\u041c\u0435\u0445\u0438\u043a\u043e"}, "2332459": {"NAME_FR": "Lagos", "SCALERANK": 0, "NAME_RU": "\u041b\u0430\u0433\u043e\u0441"}, "3169070": {"NAME_FR": "Rome", "SCALERANK": 0, "NAME_RU": "\u0420\u0438\u043c"}, "1816670": {"NAME_FR": "P\u00e9kin", "SCALERANK": 0, "NAME_RU": "\u041f\u0435\u043a\u0438\u043d"}, "184745": {"NAME_FR": "Nairobi", "SCALERANK": 0, "NAME_RU": "\u041d\u0430\u0439\u0440\u043e\u0431\u0438"}, "1642911": {"NAME_FR": "Jakarta", "SCALERANK": 0, "NAME_RU": "\u0414\u0436\u0430\u043a\u0430\u0440\u0442\u0430"}, "3688689": {"NAME_FR": "Bogota", "SCALERANK": 0, "NAME_RU": "\u0411\u043e\u0433\u043e\u0442\u0430"}, "360630": {"NAME_FR": "Le Caire", "SCALERANK": 0, "NAME_RU": "\u041a\u0430\u0438\u0440"}, "1796236": {"NAME_FR": "Shanghai", "SCALERANK": 0, "NAME_RU": "\u0428\u0430\u043d\u0445\u0430\u0439"}, "1850147": {"NAME_FR": "Tokyo", "SCALERANK": 0, "NAME_RU": "\u0422\u043e\u043a\u0438\u043e"}, "1275339": {"NAME_FR": "Bombay", "SCALERANK": 0, "NAME_RU": "\u041c\u0443\u043c\u0431\u0430\u0438"}, "2988507": {"NAME_FR": "Paris", "SCALERANK": 0, "NAME_RU": "\u041f\u0430\u0440\u0438\u0436"}, "3449741": {"NAME_FR": "Santiago", "SCALERANK": 0, "NAME_RU": "\u0421\u0430\u043d\u0442\u044c\u044f\u0433\u043e"}, "1275004": {"NAME_FR": "Calcutta", "SCALERANK": 0, "NAME_RU": "\u041a\u0430\u043b\u044c\u043a\u0443\u0442\u0442\u0430"}, "3451190": {"NAME_FR": "Rio de Janeiro", "SCALERANK": 0, "NAME_RU": "\u0420\u0438\u043e-\u0434\u0435-\u0416\u0430\u043d\u0435\u0439\u0440\u043e"}, "3448439": {"NAME_FR": "S\u00e3o Paulo", "SCALERANK": 0, "NAME_RU": "\u0421\u0430\u043d-\u041f\u0430\u0443\u043b\u0443"}, "2147714": {"NAME_FR": "Sydney", "SCALERANK": 0, "NAME_RU": "\u0421\u0438\u0434\u043d\u0435\u0439"}, "1880252": {"NAME_FR": "Singapour", "SCALERANK": 0, "NAME_RU": "\u0421\u0438\u043d\u0433\u0430\u043f\u0443\u0440"}, "1819729": {"NAME_FR": "Hong Kong", "SCALERANK": 0, "NAME_RU": "\u0413\u043e\u043d\u043a\u043e\u043d\u0433"}} diff --git a/tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json b/tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json new file mode 100644 index 000000000..435d49eb4 --- /dev/null +++ b/tests/pbf/ne-110m-z3-0-0-0-joined.pbf.json @@ -0,0 +1,35 @@ +{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "11", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "id": 6173331, "properties": { "NAME": "Vancouver", "NAME_FR": "Vancouver", "SCALERANK": 1, "NAME_RU": "Ванкувер" }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.267805 ] } } +, +{ "type": "Feature", "id": 1690681, "properties": { "NAME": "San Salvador", "NAME_FR": "San Salvador", "SCALERANK": 3, "NAME_RU": "Сан-Сальвадор" }, "geometry": { "type": "Point", "coordinates": [ -89.208984, 13.667338 ] } } +, +{ "type": "Feature", "id": 3579925, "properties": { "NAME": "Saint George's", "NAME_FR": "Saint-Georges", "SCALERANK": 4, "NAME_RU": "Сент-Джорджес" }, "geometry": { "type": "Point", "coordinates": [ -61.699219, 12.039321 ] } } +, +{ "type": "Feature", "id": 2422465, "properties": { "NAME": "Conakry", "NAME_FR": "Conakry", "SCALERANK": 3, "NAME_RU": "Конакри" }, "geometry": { "type": "Point", "coordinates": [ -13.710938, 9.535749 ] } } +, +{ "type": "Feature", "id": 3652462, "properties": { "NAME": "Quito", "NAME_FR": "Quito", "SCALERANK": 3, "NAME_RU": "Кито" }, "geometry": { "type": "Point", "coordinates": [ -78.486328, -0.175781 ] } } +, +{ "type": "Feature", "id": 2660646, "properties": { "NAME": "Geneva", "NAME_FR": "Genève", "SCALERANK": 1, "NAME_RU": "Женева" }, "geometry": { "type": "Point", "coordinates": [ 6.152344, 46.195042 ] } } +, +{ "type": "Feature", "id": 6691831, "properties": { "NAME": "Vatican City", "NAME_FR": "Cité du Vatican", "SCALERANK": 8, "NAME_RU": "Ватикан" }, "geometry": { "type": "Point", "coordinates": [ 12.480469, 41.902277 ] } } +, +{ "type": "Feature", "id": 618426, "properties": { "NAME": "Chișinău", "NAME_FR": "Chișinău", "SCALERANK": 3, "NAME_RU": "Кишинёв" }, "geometry": { "type": "Point", "coordinates": [ 28.828125, 46.980252 ] } } +, +{ "type": "Feature", "id": 2309527, "properties": { "NAME": "Malabo", "NAME_FR": "Malabo", "SCALERANK": 3, "NAME_RU": "Малабо" }, "geometry": { "type": "Point", "coordinates": [ 8.789062, 3.776559 ] } } +, +{ "type": "Feature", "id": 373303, "properties": { "NAME": "Juba", "NAME_FR": "Djouba", "SCALERANK": 4, "NAME_RU": "Джуба" }, "geometry": { "type": "Point", "coordinates": [ 31.552734, 4.828260 ] } } +, +{ "type": "Feature", "id": 285787, "properties": { "NAME": "Kuwait City", "NAME_FR": "Koweït", "SCALERANK": 2, "NAME_RU": "Эль-Кувейт" }, "geometry": { "type": "Point", "coordinates": [ 47.988281, 29.382175 ] } } +, +{ "type": "Feature", "id": 1238992, "properties": { "NAME": "Sri Jayawardenepura Kotte", "NAME_FR": "Sri Jayawardenapura", "SCALERANK": 4, "NAME_RU": "Шри-Джаяварденепура-Котте" }, "geometry": { "type": "Point", "coordinates": [ 79.980469, 6.926427 ] } } +, +{ "type": "Feature", "id": 1735161, "properties": { "NAME": "Kuala Lumpur", "NAME_FR": "Kuala Lumpur", "SCALERANK": 2, "NAME_RU": "Куала-Лумпур" }, "geometry": { "type": "Point", "coordinates": [ 101.689453, 3.162456 ] } } +, +{ "type": "Feature", "id": 2314302, "properties": { "NAME": "Kinshasa", "NAME_FR": "Kinshasa", "SCALERANK": 1, "NAME_RU": "Киншаса" }, "geometry": { "type": "Point", "coordinates": [ 15.292969, -4.302591 ] } } +, +{ "type": "Feature", "id": 921772, "properties": { "NAME": "Moroni", "NAME_FR": "Moroni", "SCALERANK": 6, "NAME_RU": "Морони" }, "geometry": { "type": "Point", "coordinates": [ 43.242188, -11.695273 ] } } +, +{ "type": "Feature", "id": 2108502, "properties": { "NAME": "Honiara", "NAME_FR": "Honiara", "SCALERANK": 3, "NAME_RU": "Хониара" }, "geometry": { "type": "Point", "coordinates": [ 159.960938, -9.449062 ] } } +] } +] } diff --git a/tests/pbf/ne-110m-z3-0-0-0.pbf b/tests/pbf/ne-110m-z3-0-0-0.pbf new file mode 100644 index 0000000000000000000000000000000000000000..7b731a5c08bba5e9e1f3529b42fe5ba8426f69bc GIT binary patch literal 453 zcmV;$0XqI4iwFP!000006E)61NLx`925|GtpOc#y^?}+()SC-IC&5k~x|C2XzDAIM z`%xcyslF#K??tl-l@29JQHly3Y=#V_Qx{VQsS?CVol2-;LF}eoTB_2e_dag6bAEh$ z=OoL)MU7}fLjy}R8616@ea6BhIO0tpi;&Qm$6cEN2@ji=SwJ~uaTX_h%i4}@aTX99B4b^Sp=*O~y<6kR2MI`nqm;_zj2TF_eCVULO>;N92n0b$D> z*9{B7{>{3yqn=8yvH<-0dm-($zD$*AQ2AVzR!W_BDr}T`6p5z`&6t6cCI=F9jDhCMBuF2E~qw8ODbxG(-TAX4_@{vioyMFF6hmp vYM<(lz~1(X>_2ChRKBD0|_5Ko5u`qnAFUeT-Nj>!+I(KTyB?15dibUI_ literal 0 HcmV?d00001