Merge branch 'object-attributes' into blake-properties

This commit is contained in:
Eric Fischer 2018-08-14 16:16:26 -07:00
commit f31024d97e
5 changed files with 111 additions and 74 deletions

View File

@ -82,7 +82,7 @@ indent:
TESTS = $(wildcard tests/*/out/*.json)
SPACE = $(NULL) $(NULL)
test: tippecanoe tippecanoe-decode $(addsuffix .check,$(TESTS)) raw-tiles-test parallel-test pbf-test join-test enumerate-test decode-test join-filter-test unit json-tool-test allow-existing-test csv-test layer-json-test join-test-object
test: tippecanoe tippecanoe-decode $(addsuffix .check,$(TESTS)) raw-tiles-test parallel-test pbf-test join-test enumerate-test decode-test join-filter-test unit json-tool-test allow-existing-test csv-test layer-json-test join-object-test
./unit
suffixes = json json.gz
@ -305,7 +305,7 @@ csv-test:
cmp tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles.json
rm -f tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles
join-test-object:
join-object-test:
./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.jsontmp

69
mvt.cpp
View File

@ -13,6 +13,7 @@
#include "protozero/pbf_reader.hpp"
#include "protozero/pbf_writer.hpp"
#include "milo/dtoa_milo.h"
#include "jsonpull/jsonpull.h"
int mvt_format = mvt_blake;
@ -607,6 +608,55 @@ size_t mvt_layer::tag_key(std::string const &key) {
return ko;
}
size_t tag_object(mvt_layer &layer, json_object *j) {
mvt_value tv;
if (j->type == JSON_NUMBER) {
long long v;
if (is_integer(j->string, &v)) {
if (v >= 0) {
tv.type = mvt_int;
tv.numeric_value.int_value = v;
} else {
tv.type = mvt_sint;
tv.numeric_value.sint_value = v;
}
} else {
tv.type = mvt_double;
tv.numeric_value.double_value = atof(j->string);
}
} else if (j->type == JSON_TRUE) {
tv.type = mvt_bool;
tv.numeric_value.bool_value = 1;
} else if (j->type == JSON_FALSE) {
tv.type = mvt_bool;
tv.numeric_value.bool_value = 0;
} else if (j->type == JSON_STRING) {
tv.type = mvt_string;
tv.string_value = std::string(j->string);
} else if (j->type == JSON_NULL) {
tv.type = mvt_null;
tv.numeric_value.null_value = 0;
} else if (j->type == JSON_HASH) {
tv.type = mvt_hash;
tv.list_value = std::vector<size_t>();
for (size_t i = 0; i < j->length; i++) {
tv.list_value.push_back(layer.tag_key(std::string(j->keys[i]->string)));
tv.list_value.push_back(tag_object(layer, j->values[i]));
}
} else if (j->type == JSON_ARRAY) {
tv.type = mvt_list;
tv.list_value = std::vector<size_t>();
for (size_t i = 0; i < j->length; i++) {
tv.list_value.push_back(tag_object(layer, j->array[i]));
}
}
return layer.tag_value(tv);
}
size_t mvt_layer::tag_value(mvt_value const &value) {
size_t vo;
@ -624,8 +674,23 @@ size_t mvt_layer::tag_value(mvt_value const &value) {
}
void mvt_layer::tag(mvt_feature &feature, std::string key, mvt_value value) {
feature.tags.push_back(tag_key(key));
feature.tags.push_back(tag_value(value));
if (value.type == mvt_hash) {
json_pull *jp = json_begin_string((char *) value.string_value.c_str());
json_object *jo = json_read_tree(jp);
if (jo == NULL) {
fprintf(stderr, "Internal error: failed to reconstruct JSON %s\n", value.string_value.c_str());
exit(EXIT_FAILURE);
}
size_t ko = tag_key(key);
size_t vo = tag_object(*this, jo);
feature.tags.push_back(ko);
feature.tags.push_back(vo);
json_free(jo);
json_end(jp);
} else {
feature.tags.push_back(tag_key(key));
feature.tags.push_back(tag_value(value));
}
}
void mvt_layer::tag_v3(mvt_feature &feature, std::string key, mvt_value value) {

View File

@ -0,0 +1,18 @@
{ "type": "FeatureCollection", "properties": {
"bounds": "0.000000,0.000000,0.000000,0.000000",
"center": "0.000000,0.000000,0",
"description": "tests/object/out/-Ccat_-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\\\"}],\\\"emptylist\\\":[],\\\"emptyhash\\\":{},\\\"nest\\\":{\\\"something\\\":\\\"else\\\"}}\"]}]}]}}",
"maxzoom": "0",
"minzoom": "0",
"name": "tests/object/out/-Ccat_-z0.json.check.mbtiles",
"type": "overlay",
"version": "2"
}, "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"}],"emptylist":[],"emptyhash":{},"nest":{"something":"else"}} }, "geometry": { "type": "Point", "coordinates": [ 0.000000, 0.000000 ] } }
] }
] }
] }

View File

@ -0,0 +1,18 @@
{ "type": "FeatureCollection", "properties": {
"bounds": "0.000000,0.000000,0.000000,0.000000",
"center": "0.000000,0.000000,0",
"description": "tests/object/out/-z0_-ccat.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\\\"}],\\\"emptylist\\\":[],\\\"emptyhash\\\":{},\\\"nest\\\":{\\\"something\\\":\\\"else\\\"}}\"]}]}]}}",
"maxzoom": "0",
"minzoom": "0",
"name": "tests/object/out/-z0_-ccat.json.check.mbtiles",
"type": "overlay",
"version": "2"
}, "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"}],"emptylist":[],"emptyhash":{},"nest":{"something":"else"}} }, "geometry": { "type": "Point", "coordinates": [ 0.000000, 0.000000 ] } }
] }
] }
] }

View File

@ -199,55 +199,6 @@ mvt_value retrieve_string(long long off, char *stringpool, int *otype) {
return stringified_to_mvt_value(type, s);
}
size_t tag_object(mvt_layer &layer, json_object *j) {
mvt_value tv;
if (j->type == JSON_NUMBER) {
long long v;
if (is_integer(j->string, &v)) {
if (v >= 0) {
tv.type = mvt_int;
tv.numeric_value.int_value = v;
} else {
tv.type = mvt_sint;
tv.numeric_value.sint_value = v;
}
} else {
tv.type = mvt_double;
tv.numeric_value.double_value = atof(j->string);
}
} else if (j->type == JSON_TRUE) {
tv.type = mvt_bool;
tv.numeric_value.bool_value = 1;
} else if (j->type == JSON_FALSE) {
tv.type = mvt_bool;
tv.numeric_value.bool_value = 0;
} else if (j->type == JSON_STRING) {
tv.type = mvt_string;
tv.string_value = std::string(j->string);
} else if (j->type == JSON_NULL) {
tv.type = mvt_null;
tv.numeric_value.null_value = 0;
} else if (j->type == JSON_HASH) {
tv.type = mvt_hash;
tv.list_value = std::vector<size_t>();
for (size_t i = 0; i < j->length; i++) {
tv.list_value.push_back(layer.tag_key(std::string(j->keys[i]->string)));
tv.list_value.push_back(tag_object(layer, j->values[i]));
}
} else if (j->type == JSON_ARRAY) {
tv.type = mvt_list;
tv.list_value = std::vector<size_t>();
for (size_t i = 0; i < j->length; i++) {
tv.list_value.push_back(tag_object(layer, j->array[i]));
}
}
return layer.tag_value(tv);
}
void decode_meta(std::vector<long long> const &metakeys, std::vector<long long> const &metavals, char *stringpool, mvt_layer &layer, mvt_feature &feature, bool suppress_null) {
size_t i;
for (i = 0; i < metakeys.size(); i++) {
@ -255,27 +206,11 @@ void decode_meta(std::vector<long long> const &metakeys, std::vector<long long>
mvt_value key = retrieve_string(metakeys[i], stringpool, NULL);
mvt_value value = retrieve_string(metavals[i], stringpool, &otype);
if (value.type == mvt_hash) {
json_pull *jp = json_begin_string((char *) value.string_value.c_str());
json_object *j = json_read_tree(jp);
if (j == NULL) {
fprintf(stderr, "Internal error: failed to reconstruct JSON %s\n", value.string_value.c_str());
exit(EXIT_FAILURE);
}
// XXX blake tag
size_t ko = layer.tag_key(key.string_value);
size_t vo = tag_object(layer, j);
feature.tags.push_back(ko);
feature.tags.push_back(vo);
json_free(j);
json_end(jp);
} else {
if (!suppress_null || value.type != mvt_null) {
if (mvt_format == mvt_blake || mvt_format == mvt_blake_float) {
layer.tag_v3(feature, key.string_value, value);
} else {
layer.tag(feature, key.string_value, value);
}
if (!suppress_null || value.type != mvt_null) {
if (mvt_format == mvt_blake || mvt_format == mvt_blake_float) {
layer.tag_v3(feature, key.string_value, value);
} else {
layer.tag(feature, key.string_value, value);
}
}
}
@ -2282,6 +2217,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
feature.has_id = layer_features[x].has_id;
decode_meta(layer_features[x].keys, layer_features[x].values, layer_features[x].stringpool, layer, feature, true);
for (size_t a = 0; a < layer_features[x].full_keys.size(); a++) {
serial_val sv = layer_features[x].full_values[a];
mvt_value v = stringified_to_mvt_value(sv.type, sv.s.c_str());