diff --git a/clip.cpp b/clip.cpp index 224b5510..dad9de19 100644 --- a/clip.cpp +++ b/clip.cpp @@ -1319,7 +1319,8 @@ mvt_tile assign_to_bins(mvt_tile const &features, std::vector const & std::sort(events.begin(), events.end()); std::set active; - std::vector counters; // separate because set items can't be mutated from an iterator + std::vector counters; // separate because set items can't be mutated from an iterator + std::vector> sums; // separate because set items can't be mutated from an iterator mvt_layer outlayer; outlayer.extent = 1 << detail; @@ -1335,10 +1336,12 @@ mvt_tile assign_to_bins(mvt_tile const &features, std::vector const & outfeature.geometry = bin.geometry; outfeature.type = bin.type; a.outfeature = outlayer.features.size(); + a.counter = counters.size(); + counters.push_back(0); + sums.emplace_back(); outlayer.features.push_back(std::move(outfeature)); - counters.push_back(0); active.insert(std::move(a)); } else if (e.kind == index_event::CHECK) { auto const &feature = features.layers[e.layer].features[e.feature]; @@ -1363,6 +1366,22 @@ mvt_tile assign_to_bins(mvt_tile const &features, std::vector const & printf("\n"); #endif counters[a.counter]++; + + for (size_t i = 0; i + 1 < feature.tags.size(); i += 2) { + const mvt_value &val = features.layers[e.layer].values[feature.tags[i + 1]]; + const std::string &key = features.layers[e.layer].keys[feature.tags[i]]; + + if (val.is_numeric()) { + auto find_attr = sums[a.counter].find(key); + if (find_attr == sums[a.counter].end()) { + sums[a.counter].emplace(key, 0); + find_attr = sums[a.counter].find(key); + } + + find_attr->second += mvt_value_to_double(val); + } + } + break; } } @@ -1384,6 +1403,13 @@ mvt_tile assign_to_bins(mvt_tile const &features, std::vector const & v.type = mvt_uint; v.numeric_value.uint_value = counters[found->counter]; outlayer.tag(outfeature, "bin-count", v); + + for (auto const &kv : sums[found->counter]) { + mvt_value v2; + v2.type = mvt_double; + v2.numeric_value.double_value = kv.second; + outlayer.tag(outfeature, "tippecanoe:sum:" + kv.first, v2); + } } else { outfeature.geometry.clear(); } diff --git a/mvt.cpp b/mvt.cpp index 7c600f2d..8594fe51 100644 --- a/mvt.cpp +++ b/mvt.cpp @@ -836,6 +836,31 @@ long long mvt_value_to_long_long(mvt_value const &v) { } } +// This extracts a double value from an mvt_value +double mvt_value_to_double(mvt_value const &v) { + switch (v.type) { + case mvt_string: + return atof(v.c_str()); + case mvt_float: + return v.numeric_value.float_value; + case mvt_double: + return v.numeric_value.double_value; + case mvt_int: + return v.numeric_value.int_value; + case mvt_uint: + return v.numeric_value.uint_value; + case mvt_sint: + return v.numeric_value.sint_value; + case mvt_bool: + return v.numeric_value.bool_value; + case mvt_null: + return 0; + default: + fprintf(stderr, "unhandled mvt_type %d\n", v.type); + exit(EXIT_IMPOSSIBLE); + } +} + void get_bbox(std::vector const &geom, long long *xmin, long long *ymin, long long *xmax, long long *ymax, int z, int tx, int ty, int detail) { diff --git a/mvt.hpp b/mvt.hpp index 33f3c173..0f9ccc4a 100644 --- a/mvt.hpp +++ b/mvt.hpp @@ -118,6 +118,14 @@ struct mvt_value { s->push_back('\0'); } + bool is_numeric() const { + return type == mvt_float || + type == mvt_double || + type == mvt_int || + type == mvt_uint || + type == mvt_sint; + } + bool operator<(const mvt_value &o) const; bool operator==(const mvt_value &o) const; std::string toString() const; @@ -193,6 +201,7 @@ int dezig(unsigned n); mvt_value stringified_to_mvt_value(int type, const char *s, std::shared_ptr const &tile_stringpool); long long mvt_value_to_long_long(mvt_value const &v); +double mvt_value_to_double(mvt_value const &v); bool is_integer(const char *s, long long *v); bool is_unsigned_integer(const char *s, unsigned long long *v); diff --git a/tests/pbf/0-0-0-pop-2-0-1.pbf.out.json b/tests/pbf/0-0-0-pop-2-0-1.pbf.out.json index 8fef8b20..f96e20ee 100644 --- a/tests/pbf/0-0-0-pop-2-0-1.pbf.out.json +++ b/tests/pbf/0-0-0-pop-2-0-1.pbf.out.json @@ -1,6 +1,6 @@ { "type": "FeatureCollection", "properties": { "zoom": 2, "x": 0, "y": 1 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "ne_10m_admin_0_countries", "version": 2, "extent": 4096 }, "features": [ -{ "type": "Feature", "properties": { "bin": "8188fffffffffff", "bin-count": 1 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -154.028320, 4.258768 ], [ -150.908203, 0.790990 ], [ -152.402344, -3.425692 ], [ -156.862793, -4.258768 ], [ -159.938965, -0.944781 ], [ -158.598633, 3.337954 ], [ -154.028320, 4.258768 ] ] ] } } +{ "type": "Feature", "properties": { "bin": "8188fffffffffff", "bin-count": 1, "tippecanoe:sum:ABBREV_LEN": 4, "tippecanoe:sum:ADM0_A3_UN": -99, "tippecanoe:sum:ADM0_A3_WB": -99, "tippecanoe:sum:ADM0_DIF": 0, "tippecanoe:sum:BRK_DIFF": 0, "tippecanoe:sum:GDP_MD": 194, "tippecanoe:sum:GDP_YEAR": 2019, "tippecanoe:sum:GEOU_DIF": 0, "tippecanoe:sum:HOMEPART": 1, "tippecanoe:sum:LABELRANK": 6, "tippecanoe:sum:LABEL_X": -157.384577, "tippecanoe:sum:LABEL_Y": 1.820437, "tippecanoe:sum:LEVEL": 2, "tippecanoe:sum:LONG_LEN": 8, "tippecanoe:sum:MAPCOLOR13": 12, "tippecanoe:sum:MAPCOLOR7": 5, "tippecanoe:sum:MAPCOLOR8": 7, "tippecanoe:sum:MAPCOLOR9": 6, "tippecanoe:sum:MAX_LABEL": 10, "tippecanoe:sum:MIN_LABEL": 5, "tippecanoe:sum:MIN_ZOOM": 0, "tippecanoe:sum:NAME_LEN": 8, "tippecanoe:sum:NE_ID": 1159320981, "tippecanoe:sum:POP_EST": 117606, "tippecanoe:sum:POP_RANK": 9, "tippecanoe:sum:POP_YEAR": 2019, "tippecanoe:sum:SU_DIF": 0, "tippecanoe:sum:TINY": 2, "tippecanoe:sum:WOE_ID": 23424867, "tippecanoe:sum:WOE_ID_EH": 23424867, "tippecanoe:sum:scalerank": 3 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -154.028320, 4.258768 ], [ -150.908203, 0.790990 ], [ -152.402344, -3.425692 ], [ -156.862793, -4.258768 ], [ -159.938965, -0.944781 ], [ -158.598633, 3.337954 ], [ -154.028320, 4.258768 ] ] ] } } , { "type": "Feature", "properties": { "bin": "816f7ffffffffff", "bin-count": 0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -124.738770, 5.309766 ], [ -120.476074, 5.156599 ], [ -118.234863, 1.537901 ], [ -120.256348, -1.691649 ], [ -124.299316, -1.450040 ], [ -126.474609, 1.625758 ], [ -125.661621, 3.601142 ], [ -124.738770, 5.309766 ] ] ] } } , @@ -36,7 +36,7 @@ , { "type": "Feature", "properties": { "bin": "810ebffffffffff", "bin-count": 0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -96.437988, 63.253412 ], [ -86.440430, 62.186014 ], [ -84.550781, 57.527622 ], [ -90.659180, 54.303704 ], [ -98.569336, 55.216490 ], [ -102.128906, 59.467408 ], [ -96.437988, 63.253412 ] ] ] } } , -{ "type": "Feature", "properties": { "bin": "81137ffffffffff", "bin-count": 1 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -100.832520, 67.533772 ], [ -96.437988, 63.253412 ], [ -102.128906, 59.467408 ], [ -110.961914, 59.512029 ], [ -116.455078, 63.194018 ], [ -112.543945, 67.415927 ], [ -100.832520, 67.533772 ] ] ] } } +{ "type": "Feature", "properties": { "bin": "81137ffffffffff", "bin-count": 1, "tippecanoe:sum:ABBREV_LEN": 4, "tippecanoe:sum:ADM0_A3_UN": -99, "tippecanoe:sum:ADM0_A3_WB": -99, "tippecanoe:sum:ADM0_DIF": 0, "tippecanoe:sum:BRK_DIFF": 0, "tippecanoe:sum:GDP_MD": 1736425, "tippecanoe:sum:GDP_YEAR": 2019, "tippecanoe:sum:GEOU_DIF": 0, "tippecanoe:sum:HOMEPART": 1, "tippecanoe:sum:LABELRANK": 2, "tippecanoe:sum:LABEL_X": -101.9107, "tippecanoe:sum:LABEL_Y": 60.324287, "tippecanoe:sum:LEVEL": 2, "tippecanoe:sum:LONG_LEN": 6, "tippecanoe:sum:MAPCOLOR13": 2, "tippecanoe:sum:MAPCOLOR7": 6, "tippecanoe:sum:MAPCOLOR8": 6, "tippecanoe:sum:MAPCOLOR9": 2, "tippecanoe:sum:MAX_LABEL": 5.7, "tippecanoe:sum:MIN_LABEL": 1.7, "tippecanoe:sum:MIN_ZOOM": 0, "tippecanoe:sum:NAME_LEN": 6, "tippecanoe:sum:NE_ID": 1159320467, "tippecanoe:sum:POP_EST": 37589262, "tippecanoe:sum:POP_RANK": 15, "tippecanoe:sum:POP_YEAR": 2019, "tippecanoe:sum:SU_DIF": 0, "tippecanoe:sum:TINY": -99, "tippecanoe:sum:WOE_ID": 23424775, "tippecanoe:sum:WOE_ID_EH": 23424775, "tippecanoe:sum:scalerank": 0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -100.832520, 67.533772 ], [ -96.437988, 63.253412 ], [ -102.128906, 59.467408 ], [ -110.961914, 59.512029 ], [ -116.455078, 63.194018 ], [ -112.543945, 67.415927 ], [ -100.832520, 67.533772 ] ] ] } } , { "type": "Feature", "properties": { "bin": "810fbffffffffff", "bin-count": 0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -92.680664, 71.230221 ], [ -79.299316, 69.854762 ], [ -78.068848, 65.183030 ], [ -86.440430, 62.186014 ], [ -96.437988, 63.253412 ], [ -100.832520, 67.533772 ], [ -92.680664, 71.230221 ] ] ] } } ,