From d1a0e495ce94ab3f39886a3de78937c0d9315fc4 Mon Sep 17 00:00:00 2001 From: Eric Fischer <enf@pobox.com> Date: Thu, 12 Jul 2018 11:24:30 -0700 Subject: [PATCH] Require that per-feature maxzoom and minzoom be small integers Also fixes a place in the Makefile that accidentally still used CFLAGS instead of CXXFLAGS --- Makefile | 2 +- geobuf.cpp | 5 +- geojson.cpp | 14 ++--- tests/dateline/in.json | 20 ++++++ tests/dateline/out/-z5.json | 118 +++++++++++++++++++++++++++++++++++- text.cpp | 11 ++++ text.hpp | 1 + 7 files changed, 156 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index b667c91..e2fbed4 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o pro $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread tippecanoe-enumerate: enumerate.o - $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3 + $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3 tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 diff --git a/geobuf.cpp b/geobuf.cpp index 6bfa872..8c87f10 100644 --- a/geobuf.cpp +++ b/geobuf.cpp @@ -13,6 +13,7 @@ #include "protozero/pbf_writer.hpp" #include "milo/dtoa_milo.h" #include "jsonpull/jsonpull.h" +#include "text.hpp" #define POINT 0 #define MULTIPOINT 1 @@ -397,13 +398,13 @@ void readFeature(protozero::pbf_reader &pbf, size_t dim, double e, std::vector<s json_object *min = json_hash_get(o, "minzoom"); if (min != NULL && (min->type == JSON_STRING || min->type == JSON_NUMBER)) { sf.has_tippecanoe_minzoom = true; - sf.tippecanoe_minzoom = atoi(min->string); + sf.tippecanoe_minzoom = integer_zoom(sst->fname, min->string); } json_object *max = json_hash_get(o, "maxzoom"); if (max != NULL && (max->type == JSON_STRING || max->type == JSON_NUMBER)) { sf.has_tippecanoe_maxzoom = true; - sf.tippecanoe_maxzoom = atoi(max->string); + sf.tippecanoe_maxzoom = integer_zoom(sst->fname, max->string); } json_object *tlayer = json_hash_get(o, "layer"); diff --git a/geojson.cpp b/geojson.cpp index bf106ad..09cdb6d 100644 --- a/geojson.cpp +++ b/geojson.cpp @@ -82,19 +82,13 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom if (tippecanoe != NULL) { json_object *min = json_hash_get(tippecanoe, "minzoom"); - if (min != NULL && min->type == JSON_NUMBER) { - tippecanoe_minzoom = min->number; - } - if (min != NULL && min->type == JSON_STRING) { - tippecanoe_minzoom = atoi(min->string); + if (min != NULL && (min->type == JSON_STRING || min->type == JSON_NUMBER)) { + tippecanoe_minzoom = integer_zoom(sst->fname, min->string); } json_object *max = json_hash_get(tippecanoe, "maxzoom"); - if (max != NULL && max->type == JSON_NUMBER) { - tippecanoe_maxzoom = max->number; - } - if (max != NULL && max->type == JSON_STRING) { - tippecanoe_maxzoom = atoi(max->string); + if (max != NULL && (max->type == JSON_STRING || max->type == JSON_NUMBER)) { + tippecanoe_maxzoom = integer_zoom(sst->fname, max->string); } json_object *ln = json_hash_get(tippecanoe, "layer"); diff --git a/tests/dateline/in.json b/tests/dateline/in.json index 5237282..b73acb3 100644 --- a/tests/dateline/in.json +++ b/tests/dateline/in.json @@ -52,6 +52,26 @@ ] ] } +}, + +{ + "type": "Feature", + "tippecanoe": { "minzoom": 1e1 }, + "properties": { "zoom": "nothing, since 10 > 5"}, + "geometry": { + "type": "LineString", + "coordinates": [ [ 0, 0 ], [ 1, 1 ] ] + } +}, + +{ + "type": "Feature", + "tippecanoe": { "maxzoom": 1e1}, + "properties": { "zoom": "0-5, since 10 > 5"}, + "geometry": { + "type": "LineString", + "coordinates": [ [ 0, 0 ], [ 1, 1 ] ] + } } ]} diff --git a/tests/dateline/out/-z5.json b/tests/dateline/out/-z5.json index 0f9528f..c6aca34 100644 --- a/tests/dateline/out/-z5.json +++ b/tests/dateline/out/-z5.json @@ -1,9 +1,9 @@ { "type": "FeatureCollection", "properties": { -"bounds": "-180.000000,34.885930,180.000000,68.269386", +"bounds": "-180.000000,0.000000,180.000000,68.269386", "center": "-151.875000,64.059828,5", "description": "tests/dateline/out/-z5.json.check.mbtiles", "format": "pbf", -"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 5, \"fields\": {\"\": \"String\", \"boolean\": \"Boolean\", \"escape\": \"String\", \"otherboolean\": \"Boolean\", \"prêt\": \"String\", \"stringify\": \"String\", \"zoom\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 3,\"geometry\": \"LineString\",\"attributeCount\": 7,\"attributes\": [{\"attribute\": \"\",\"count\": 1,\"type\": \"string\",\"values\": [\"something for nothing\"]},{\"attribute\": \"boolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [true]},{\"attribute\": \"escape\",\"count\": 1,\"type\": \"string\",\"values\": [\"foo\\u0001bar,ü\\\"\\\\/\\u0008\\u000c\\u000a\\u000d\\u0009→🐂🐳\"]},{\"attribute\": \"otherboolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [false]},{\"attribute\": \"prêt\",\"count\": 1,\"type\": \"string\",\"values\": [\"ready\"]},{\"attribute\": \"stringify\",\"count\": 1,\"type\": \"string\",\"values\": [\"[\\\"yes\\\",27,27,1.4e+27,{\\\"foo\\\":\\\"bar\\\"}]\"]},{\"attribute\": \"zoom\",\"count\": 2,\"type\": \"string\",\"values\": [\"3-5\",\"z0-2\"]}]}]}}", +"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 5, \"fields\": {\"\": \"String\", \"boolean\": \"Boolean\", \"escape\": \"String\", \"otherboolean\": \"Boolean\", \"prêt\": \"String\", \"stringify\": \"String\", \"zoom\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 5,\"geometry\": \"LineString\",\"attributeCount\": 7,\"attributes\": [{\"attribute\": \"\",\"count\": 1,\"type\": \"string\",\"values\": [\"something for nothing\"]},{\"attribute\": \"boolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [true]},{\"attribute\": \"escape\",\"count\": 1,\"type\": \"string\",\"values\": [\"foo\\u0001bar,ü\\\"\\\\/\\u0008\\u000c\\u000a\\u000d\\u0009→🐂🐳\"]},{\"attribute\": \"otherboolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [false]},{\"attribute\": \"prêt\",\"count\": 1,\"type\": \"string\",\"values\": [\"ready\"]},{\"attribute\": \"stringify\",\"count\": 1,\"type\": \"string\",\"values\": [\"[\\\"yes\\\",27,27,1.4e+27,{\\\"foo\\\":\\\"bar\\\"}]\"]},{\"attribute\": \"zoom\",\"count\": 4,\"type\": \"string\",\"values\": [\"0-5, since 10 > 5\",\"3-5\",\"nothing, since 10 > 5\",\"z0-2\"]}]}]}}", "maxzoom": "5", "minzoom": "0", "name": "tests/dateline/out/-z5.json.check.mbtiles", @@ -15,6 +15,14 @@ { "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -187.031250, 50.457504 ], [ -185.976562, 47.279229 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.689872 ], [ -185.976562, 58.813742 ], [ -187.031250, 56.992883 ], [ -187.031250, 65.730626 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.542167 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -184.218750, 37.160317 ], [ -187.031250, 38.891033 ], [ -187.031250, 50.457504 ] ] ], [ [ [ 187.031250, 63.704722 ], [ 182.109375, 62.593341 ], [ 180.000000, 61.689872 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 182.460938, 44.339565 ], [ 187.031250, 44.024422 ], [ 187.031250, 35.460670 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.542167 ], [ 187.031250, 68.007571 ], [ 187.031250, 63.704722 ] ] ] ] } } , { "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } } +, +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.054628 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 0, "y": 1 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } } ] } ] } , @@ -23,12 +31,22 @@ { "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -183.515625, 46.437857 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.669024 ], [ -183.515625, 60.020952 ], [ -183.515625, 66.981666 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.525373 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -183.515625, 37.055177 ], [ -183.515625, 46.437857 ] ] ] } } , { "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } } +, +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 1 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } } ] } ] } , { "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 0 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 183.515625, 62.915233 ], [ 182.109375, 62.593341 ], [ 180.000000, 61.669024 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 182.460938, 44.339565 ], [ 183.515625, 44.276671 ], [ 183.515625, 35.995785 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.525373 ], [ 183.515625, 67.776025 ], [ 183.515625, 62.915233 ] ] ] } } +, +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } } ] } ] } , @@ -46,6 +64,30 @@ ] } ] } , +{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 1, "y": 2 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 1, "y": 1 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 2, "y": 2 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 2, "y": 1 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } } +] } +] } +, { "type": "FeatureCollection", "properties": { "zoom": 2, "x": 3, "y": 1 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 181.757812, 62.441242 ], [ 180.000000, 61.658595 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 181.757812, 44.590467 ], [ 181.757812, 36.261992 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.187988, 66.513260 ], [ 177.143555, 67.204032 ], [ 181.757812, 67.204032 ], [ 181.757812, 62.441242 ] ] ] } } @@ -82,12 +124,36 @@ ] } ] } , +{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 3, "y": 4 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.867920, 0.878872 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 3, "y": 3 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.878906, 0.889857 ] ] } } +] } +] } +, { "type": "FeatureCollection", "properties": { "zoom": 3, "x": 3, "y": 2 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ], [ 0.878906, 46.619261 ] ] } } ] } ] } , +{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 4 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.867920, 0.878872 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 3 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.010690 ] ] } } +] } +] } +, { "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 2 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -0.878906, 46.012224 ], [ 0.000000, 46.316584 ], [ 16.171875, 51.618017 ] ] } } @@ -172,12 +238,36 @@ ] } ] } , +{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 7, "y": 8 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.433960, 0.439449 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 7, "y": 7 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.439453, 0.444942 ] ] } } +] } +] } +, { "type": "FeatureCollection", "properties": { "zoom": 4, "x": 7, "y": 5 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ], [ 0.439453, 46.468133 ] ] } } ] } ] } , +{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 8 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.433960, 0.439449 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 7 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.005197 ] ] } } +] } +] } +, { "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 5 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -0.439453, 46.164614 ], [ 0.000000, 46.316584 ], [ 16.171875, 51.618017 ] ] } } @@ -370,12 +460,36 @@ ] } ] } , +{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 15, "y": 16 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.216980, 0.219726 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 15, "y": 15 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.219727, 0.222473 ] ] } } +] } +] } +, { "type": "FeatureCollection", "properties": { "zoom": 5, "x": 15, "y": 11 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ], [ 0.219727, 46.392411 ] ] } } ] } ] } , +{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 16 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.216980, 0.219726 ] ] } } +] } +] } +, +{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 15 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.002451 ] ] } } +] } +] } +, { "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 11 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -0.219727, 46.240652 ], [ 0.000000, 46.316584 ], [ 7.734375, 48.922499 ], [ 8.173828, 49.066668 ] ] } } diff --git a/text.cpp b/text.cpp index dc27d21..d7473fe 100644 --- a/text.cpp +++ b/text.cpp @@ -1,5 +1,7 @@ #include "text.hpp" #include <stdio.h> +#include <math.h> +#include <stdlib.h> /** * Returns an empty string if `s` is valid utf8; @@ -122,3 +124,12 @@ std::string truncate16(std::string const &s, size_t runes) { return std::string(s, 0, lastgood - start); } + +int integer_zoom(std::string where, std::string text) { + double d = atof(text.c_str()); + if (!isnormal(d) || d != floor(d) || d < 0 || d > 32) { + fprintf(stderr, "%s: Expected integer zoom level in \"tippecanoe\" GeoJSON extension, not %s\n", where.c_str(), text.c_str()); + exit(EXIT_FAILURE); + } + return d; +} diff --git a/text.hpp b/text.hpp index 65274a3..6f339d2 100644 --- a/text.hpp +++ b/text.hpp @@ -6,5 +6,6 @@ std::string check_utf8(std::string text); const char *utf8_next(const char *s, long *c); std::string truncate16(std::string const &s, size_t runes); +int integer_zoom(std::string where, std::string text); #endif