Preserve numeric property types for FlatGeobuf input (#395)

Fix FlatGeobuf numeric property types

Co-authored-by: dstadnikov <dstadnikov@SOFT-DSTADNIKOV>
This commit is contained in:
Denis Stadnikov
2026-07-16 07:42:57 -07:00
committed by GitHub
co-authored by dstadnikov
parent 7fc82a1796
commit 0c650b881a
4 changed files with 22 additions and 11 deletions
+7 -1
View File
@@ -97,7 +97,7 @@ indent:
TESTS = $(wildcard tests/*/out/*.json) TESTS = $(wildcard tests/*/out/*.json)
SPACE = $(NULL) $(NULL) 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 pmtiles-test decode-pmtiles-test overzoom-test 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 pmtiles-test decode-pmtiles-test overzoom-test flatgeobuf-test
./unit ./unit
suffixes = json json.gz suffixes = json json.gz
@@ -572,6 +572,12 @@ csv-test: tippecanoe tippecanoe-decode
cmp tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles.json cmp tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles.json
rm -f tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles rm -f tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles
flatgeobuf-test: tippecanoe tippecanoe-decode
./tippecanoe -q -f -z0 -l numeric-properties -o tests/flatgeobuf/numeric-properties.mbtiles tests/flatgeobuf/numeric-properties.fgb
./tippecanoe-decode tests/flatgeobuf/numeric-properties.mbtiles 0 0 0 > tests/flatgeobuf/numeric-properties.json.check
cmp tests/flatgeobuf/numeric-properties.json.check tests/flatgeobuf/numeric-properties.json
rm -f tests/flatgeobuf/numeric-properties.mbtiles tests/flatgeobuf/numeric-properties.json.check
layer-json-test: tippecanoe tippecanoe-decode layer-json-test: tippecanoe tippecanoe-decode
# GeoJSON with description and named layer # GeoJSON with description and named layer
./tippecanoe -q -z0 -r1 -yNAME -f -o tests/layer-json/out.mbtiles -L'{"file":"tests/ne_110m_populated_places/in.json", "description":"World cities", "layer":"places"}' ./tippecanoe -q -z0 -r1 -yNAME -f -o tests/layer-json/out.mbtiles -L'{"file":"tests/ne_110m_populated_places/in.json", "description":"World cities", "layer":"places"}'
+10 -10
View File
@@ -163,13 +163,13 @@ void readFeature(const FlatGeobuf::Feature *feature, long long feature_sequence_
serial_val sv; serial_val sv;
if (col_type == FlatGeobuf::ColumnType_Byte) { if (col_type == FlatGeobuf::ColumnType_Byte) {
sv.type = mvt_sint; sv.type = mvt_double;
int8_t byte_val; int8_t byte_val;
memcpy(&byte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(byte_val)); memcpy(&byte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(byte_val));
sv.s = std::to_string(byte_val); sv.s = std::to_string(byte_val);
p_pos += sizeof(uint16_t) + sizeof(byte_val); p_pos += sizeof(uint16_t) + sizeof(byte_val);
} else if (col_type == FlatGeobuf::ColumnType_UByte) { } else if (col_type == FlatGeobuf::ColumnType_UByte) {
sv.type = mvt_uint; sv.type = mvt_double;
uint8_t ubyte_val; uint8_t ubyte_val;
memcpy(&ubyte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ubyte_val)); memcpy(&ubyte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ubyte_val));
sv.s = std::to_string(ubyte_val); sv.s = std::to_string(ubyte_val);
@@ -185,43 +185,43 @@ void readFeature(const FlatGeobuf::Feature *feature, long long feature_sequence_
} }
p_pos += sizeof(uint16_t) + sizeof(bool_val); p_pos += sizeof(uint16_t) + sizeof(bool_val);
} else if (col_type == FlatGeobuf::ColumnType_Short) { } else if (col_type == FlatGeobuf::ColumnType_Short) {
sv.type = mvt_sint; sv.type = mvt_double;
int16_t short_val; int16_t short_val;
memcpy(&short_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(short_val)); memcpy(&short_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(short_val));
sv.s = std::to_string(short_val); sv.s = std::to_string(short_val);
p_pos += sizeof(uint16_t) + sizeof(short_val); p_pos += sizeof(uint16_t) + sizeof(short_val);
} else if (col_type == FlatGeobuf::ColumnType_UShort) { } else if (col_type == FlatGeobuf::ColumnType_UShort) {
sv.type = mvt_uint; sv.type = mvt_double;
uint16_t ushort_val; uint16_t ushort_val;
memcpy(&ushort_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ushort_val)); memcpy(&ushort_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ushort_val));
sv.s = std::to_string(ushort_val); sv.s = std::to_string(ushort_val);
p_pos += sizeof(uint16_t) + sizeof(ushort_val); p_pos += sizeof(uint16_t) + sizeof(ushort_val);
} else if (col_type == FlatGeobuf::ColumnType_Int) { } else if (col_type == FlatGeobuf::ColumnType_Int) {
sv.type = mvt_sint; sv.type = mvt_double;
int32_t int_val; int32_t int_val;
memcpy(&int_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(int_val)); memcpy(&int_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(int_val));
sv.s = std::to_string(int_val); sv.s = std::to_string(int_val);
p_pos += sizeof(uint16_t) + sizeof(int_val); p_pos += sizeof(uint16_t) + sizeof(int_val);
} else if (col_type == FlatGeobuf::ColumnType_UInt) { } else if (col_type == FlatGeobuf::ColumnType_UInt) {
sv.type = mvt_uint; sv.type = mvt_double;
uint32_t uint_val; uint32_t uint_val;
memcpy(&uint_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(uint_val)); memcpy(&uint_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(uint_val));
sv.s = std::to_string(uint_val); sv.s = std::to_string(uint_val);
p_pos += sizeof(uint16_t) + sizeof(uint_val); p_pos += sizeof(uint16_t) + sizeof(uint_val);
} else if (col_type == FlatGeobuf::ColumnType_Long) { } else if (col_type == FlatGeobuf::ColumnType_Long) {
sv.type = mvt_sint; sv.type = mvt_double;
int64_t long_val; int64_t long_val;
memcpy(&long_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(long_val)); memcpy(&long_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(long_val));
sv.s = std::to_string(long_val); sv.s = std::to_string(long_val);
p_pos += sizeof(uint16_t) + sizeof(long_val); p_pos += sizeof(uint16_t) + sizeof(long_val);
} else if (col_type == FlatGeobuf::ColumnType_ULong) { } else if (col_type == FlatGeobuf::ColumnType_ULong) {
sv.type = mvt_uint; sv.type = mvt_double;
int64_t ulong_val; uint64_t ulong_val;
memcpy(&ulong_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ulong_val)); memcpy(&ulong_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ulong_val));
sv.s = std::to_string(ulong_val); sv.s = std::to_string(ulong_val);
p_pos += sizeof(uint16_t) + sizeof(ulong_val); p_pos += sizeof(uint16_t) + sizeof(ulong_val);
} else if (col_type == FlatGeobuf::ColumnType_Float) { } else if (col_type == FlatGeobuf::ColumnType_Float) {
sv.type = mvt_float; sv.type = mvt_double;
float float_val; float float_val;
memcpy(&float_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(float_val)); memcpy(&float_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(float_val));
sv.s = milo::dtoa_milo(float_val); sv.s = milo::dtoa_milo(float_val);
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "numeric-properties", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "byte_min": -128, "ubyte_max": 255, "bool_value": true, "short_min": -32768, "ushort_max": 65535, "int_min": -2147483648, "uint_max": 4294967295, "long_min": -9223372036854775808, "ulong_max": 18446744073709551615, "float_value": 1.25, "double_value": 12345.678901234, "guid_value": "123e4567-e89b-12d3-a456-426614174000" }, "geometry": { "type": "Point", "coordinates": [ 0.000000, 0.000000 ] } }
] }
] }