From 9319f2e1b2022f3a537138b30a54c081cb5d7f8b Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Tue, 14 Aug 2018 13:27:56 -0700 Subject: [PATCH] Add a way to represent empty hashes and lists in attributes --- Makefile | 8 ++++---- mvt.cpp | 24 ++++++++++++++++++++++-- tests/object/out/-z0.json | 4 ++-- vector_tile.proto | 5 ++++- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index d818272..c754b69 100644 --- a/Makefile +++ b/Makefile @@ -308,10 +308,10 @@ csv-test: join-test-object: ./tippecanoe -z0 -f -o tests/object/out/before.mbtiles tests/object/in.json ./tile-join -f -o tests/object/out/after.mbtiles tests/object/out/before.mbtiles - ./tippecanoe-decode -x generator tests/object/out/before.mbtiles | grep -v '"bounds"' > tests/object/out/before.mbtiles.json - ./tippecanoe-decode -x generator tests/object/out/after.mbtiles | grep -v '"bounds"' > tests/object/out/after.mbtiles.json - cmp tests/object/out/before.mbtiles.json tests/object/out/after.mbtiles.json - rm -f tests/object/out/before.mbtiles.json tests/object/out/after.mbtiles.json tests/object/out/before.mbtiles tests/object/out/after.mbtiles + ./tippecanoe-decode -x generator tests/object/out/before.mbtiles | grep -v '"bounds"' > tests/object/out/before.mbtiles.jsontmp + ./tippecanoe-decode -x generator tests/object/out/after.mbtiles | grep -v '"bounds"' > tests/object/out/after.mbtiles.jsontmp + cmp tests/object/out/before.mbtiles.jsontmp tests/object/out/after.mbtiles.jsontmp + rm -f tests/object/out/before.mbtiles.jsontmp tests/object/out/after.mbtiles.jsontmp tests/object/out/before.mbtiles tests/object/out/after.mbtiles layer-json-test: # GeoJSON with description and named layer diff --git a/mvt.cpp b/mvt.cpp index 87111ab..7d7207f 100644 --- a/mvt.cpp +++ b/mvt.cpp @@ -208,6 +208,18 @@ bool mvt_tile::decode(std::string &message, bool &was_compressed) { } break; + case 10: /* empty */ + { + unsigned type = value_reader.get_uint64(); + if (type == 0) { + value.type = mvt_hash; + value.list_value.clear(); + } else if (type == 1) { + value.type = mvt_list; + value.list_value.clear(); + } + } break; + default: value_reader.skip(); break; @@ -353,9 +365,17 @@ std::string mvt_tile::encode() { } else if (pbv.type == mvt_bool) { value_writer.add_bool(7, pbv.numeric_value.bool_value); } else if (pbv.type == mvt_hash) { - value_writer.add_packed_uint32(8, std::begin(layers[i].values[v].list_value), std::end(layers[i].values[v].list_value)); + if (pbv.list_value.size() > 0) { + value_writer.add_packed_uint32(8, std::begin(layers[i].values[v].list_value), std::end(layers[i].values[v].list_value)); + } else { + value_writer.add_uint64(10, 0); + } } else if (pbv.type == mvt_list) { - value_writer.add_packed_uint32(9, std::begin(layers[i].values[v].list_value), std::end(layers[i].values[v].list_value)); + if (pbv.list_value.size() > 0) { + value_writer.add_packed_uint32(9, std::begin(layers[i].values[v].list_value), std::end(layers[i].values[v].list_value)); + } else { + value_writer.add_uint64(10, 1); + } } else if (pbv.type == mvt_null) { // empty value represents null } else { diff --git a/tests/object/out/-z0.json b/tests/object/out/-z0.json index 9cf021c..5f08fd2 100644 --- a/tests/object/out/-z0.json +++ b/tests/object/out/-z0.json @@ -3,7 +3,7 @@ "center": "0.000000,0.000000,0", "description": "tests/object/out/-z0.json.check.mbtiles", "format": "pbf", -"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {\"compound\": \"Mixed\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 1,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"compound\",\"count\": 1,\"type\": \"mixed\",\"values\": [\"{\\\"string\\\":\\\"string\\\",\\\"number\\\":10,\\\"null\\\":null,\\\"true\\\":true,\\\"false\\\":false,\\\"array\\\":[\\\"string\\\",10,null,true,false,[1,2,3],{\\\"this\\\":\\\"that\\\"}],\\\"nest\\\":{\\\"something\\\":\\\"else\\\"}}\"]}]}]}}", +"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {\"compound\": \"Mixed\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 1,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"compound\",\"count\": 1,\"type\": \"mixed\",\"values\": [\"{\\\"string\\\":\\\"string\\\",\\\"number\\\":10,\\\"null\\\":null,\\\"true\\\":true,\\\"false\\\":false,\\\"array\\\":[\\\"string\\\",10,null,true,false,[1,2,3],{\\\"this\\\":\\\"that\\\"}],\\\"emptylist\\\":[],\\\"emptyhash\\\":{},\\\"nest\\\":{\\\"something\\\":\\\"else\\\"}}\"]}]}]}}", "maxzoom": "0", "minzoom": "0", "name": "tests/object/out/-z0.json.check.mbtiles", @@ -12,7 +12,7 @@ }, "features": [ { "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ -{ "type": "Feature", "properties": { "compound": {"string":"string","number":10,"null":null,"true":true,"false":false,"array":["string",10,null,true,false,[1,2,3],{"this":"that"}],"nest":{"something":"else"}} }, "geometry": { "type": "Point", "coordinates": [ 0.000000, 0.000000 ] } } +{ "type": "Feature", "properties": { "compound": {"string":"string","number":10,"null":null,"true":true,"false":false,"array":["string",10,null,true,false,[1,2,3],{"this":"that"}],"emptylist":[],"emptyhash":{},"nest":{"something":"else"}} }, "geometry": { "type": "Point", "coordinates": [ 0.000000, 0.000000 ] } } ] } ] } ] } diff --git a/vector_tile.proto b/vector_tile.proto index 05e2db4..1377c85 100644 --- a/vector_tile.proto +++ b/vector_tile.proto @@ -32,7 +32,10 @@ message tile { // Each element refers to the nth value in the layer's values list repeated uint32 list_value = 9 [ packed = true ]; - extensions 10 to max; + // 0 signifies an empty hash, 1 signifies an empty list + optional uint64 empty_value = 10; + + extensions 11 to max; } message feature {