diff --git a/geojson.cpp b/geojson.cpp index 0697e9c..7aae06a 100644 --- a/geojson.cpp +++ b/geojson.cpp @@ -429,14 +429,12 @@ int serialize_geometry(json_object *geometry, json_object *properties, json_obje } } - // XXX tilestats: tas.type shouldn't be used since, type is also tracked as variant inside it - if (tas.type >= 0) { auto fk = layermap->find(layername); - fk->second.file_keys.insert(std::pair(tas, type_and_string_stats())); + fk->second.file_keys.insert(std::pair(tas.string, type_and_string_stats())); if (track) { - auto fka = fk->second.file_keys.find(tas); + auto fka = fk->second.file_keys.find(tas.string); if (fka == fk->second.file_keys.end()) { fprintf(stderr, "Can't happen (tilestats)\n"); exit(EXIT_FAILURE); diff --git a/main.cpp b/main.cpp index 467fd5d..1f55959 100644 --- a/main.cpp +++ b/main.cpp @@ -1176,8 +1176,10 @@ int read_input(std::vector &sources, char *fname, int &maxzoom, int minz std::map layermap; for (size_t l = 0; l < nlayers; l++) { - layermap.insert(std::pair(sources[l].layer, layermap_entry(l))); + layermap_entry e = layermap_entry(l); + layermap.insert(std::pair(sources[l].layer, e)); } + std::vector > layermaps; for (size_t l = 0; l < CPUS; l++) { layermaps.push_back(layermap); @@ -1962,18 +1964,24 @@ int read_input(std::vector &sources, char *fname, int &maxzoom, int minz } std::map merged_lm = merge_layermaps(layermaps); - if (additional[A_CALCULATE_FEATURE_DENSITY]) { - for (auto ai = merged_lm.begin(); ai != merged_lm.end(); ++ai) { - type_and_string tas; - tas.type = mvt_double; - tas.string = "tippecanoe_feature_density"; - ai->second.file_keys.insert(std::pair(tas, type_and_string_stats())); - } - } for (auto ai = merged_lm.begin(); ai != merged_lm.end(); ++ai) { ai->second.minzoom = minzoom; ai->second.maxzoom = maxzoom; + + if (additional[A_CALCULATE_FEATURE_DENSITY]) { + type_and_string_stats tss; + + for (size_t i = 0; i < 256; i++) { + type_and_string tas; + tas.type = mvt_double; + tas.string = std::to_string(i); + + tss.sample_values.insert(tas); + } + + ai->second.file_keys.insert(std::pair("tippecanoe_feature_density", tss)); + } } mbtiles_write_metadata(outdb, outdir, fname, minzoom, maxzoom, minlat, minlon, maxlat, maxlon, midlat, midlon, forcetable, attribution, merged_lm, true, description); diff --git a/mbtiles.cpp b/mbtiles.cpp index 535b613..ecfa50d 100644 --- a/mbtiles.cpp +++ b/mbtiles.cpp @@ -266,18 +266,21 @@ void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fnam } aprintf(&buf, "\""); - quote(&buf, j->first.string.c_str()); + quote(&buf, j->first.c_str()); - if (j->first.type == mvt_double || - j->first.type == mvt_float || - j->first.type == mvt_double || - j->first.type == mvt_uint || - j->first.type == mvt_sint) { + int type = 0; + for (auto s : j->second.sample_values) { + type |= (1 << s.type); + } + + if (type == (1 << mvt_double)) { aprintf(&buf, "\": \"Number\""); - } else if (j->first.type == mvt_bool) { + } else if (type == (1 << mvt_bool)) { aprintf(&buf, "\": \"Boolean\""); - } else { + } else if (type == (1 << mvt_string)) { aprintf(&buf, "\": \"String\""); + } else { + aprintf(&buf, "\": \"Composite\""); // XXX tilestats: composite? } } @@ -367,10 +370,25 @@ std::map merge_layermaps(std::vectorsecond.file_keys.begin(); fk != map->second.file_keys.end(); ++fk) { - out_entry->second.file_keys.insert(*fk); + auto fk2 = out_entry->second.file_keys.find(fk->first); + + if (fk2 == out_entry->second.file_keys.end()) { + out_entry->second.file_keys.insert(*fk); + } else { + for (auto s : fk->second.sample_values) { + fk2->second.sample_values.insert(s); + } + + fk2->second.type |= fk->second.type; + + if (fk->second.min < fk2->second.min) { + fk2->second.min = fk->second.min; + } + if (fk->second.max > fk2->second.max) { + fk2->second.max = fk->second.max; + } + } } if (map->second.minzoom < out_entry->second.minzoom) { diff --git a/mbtiles.hpp b/mbtiles.hpp index 67e85e5..b482e5e 100644 --- a/mbtiles.hpp +++ b/mbtiles.hpp @@ -21,7 +21,7 @@ struct type_and_string_stats { struct layermap_entry { size_t id; - std::map file_keys; + std::map file_keys; int minzoom; int maxzoom; diff --git a/tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json b/tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json index 2be4ed0..c075500 100644 --- a/tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json +++ b/tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json @@ -3,7 +3,7 @@ "center": "0.000000,0.000000,0", "description": "tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json.check.mbtiles", "format": "pbf", -"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {\"booltype\": \"Boolean\", \"expect\": \"String\", \"expect\": \"Number\", \"expect\": \"Boolean\", \"floattype\": \"Number\", \"inttype\": \"Number\", \"stringtype\": \"String\"} } ] }", +"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {\"booltype\": \"Boolean\", \"expect\": \"Composite\", \"floattype\": \"Number\", \"inttype\": \"Number\", \"stringtype\": \"String\"} } ] }", "maxzoom": "0", "minzoom": "0", "name": "tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json.check.mbtiles", diff --git a/tile-join.cpp b/tile-join.cpp index 0095f85..100fa56 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -206,11 +206,17 @@ void handle(std::string message, int z, unsigned x, unsigned y, std::mapsecond.file_keys.insert(std::pair(tas, type_and_string_stats())); + if (st.sample_values.size() < 1000) { + type_and_string tas; + tas.type = tp.second; + tas.string = "XXX"; // XXX tilestats: provide actual values + st.sample_values.insert(tas); + } + + file_keys->second.file_keys.insert(std::pair(tp.first, st)); } // To keep attributes in their original order instead of alphabetical