diff --git a/CHANGELOG.md b/CHANGELOG.md index ce7b61d..10e4a5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.3 + +* Encode numeric attributes as integers instead of floating point if possible + ## 1.4.2 * Bug fix for problem that would occasionally produce empty point geometries diff --git a/tile.cc b/tile.cc index 93f5273..8784a58 100644 --- a/tile.cc +++ b/tile.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -241,6 +242,37 @@ void decode_meta(char **meta, char *stringpool, struct pool *keys, struct pool * } } +static int is_integer(const char *s, long long *v) { + errno = 0; + char *endptr; + + *v = strtoll(s, &endptr, 0); + if (*v == 0 && errno != 0) { + return 0; + } + if ((*v == LLONG_MIN || *v == LLONG_MAX) && (errno == ERANGE)) { + return 0; + } + if (*endptr != '\0') { + // Special case: If it is an integer followed by .0000 or similar, + // it is still an integer + + if (*endptr != '.') { + return 0; + } + endptr++; + for (; *endptr != '\0'; endptr++) { + if (*endptr != '0') { + return 0; + } + } + + return 1; + } + + return 1; +} + mapnik::vector::tile create_tile(char **layernames, int line_detail, std::vector > &features, long long *count, struct pool **keys, struct pool **values, int nlayers) { mapnik::vector::tile tile; @@ -291,7 +323,16 @@ mapnik::vector::tile create_tile(char **layernames, int line_detail, std::vector mapnik::vector::tile_value *tv = layer->add_values(); if (pv->type == VT_NUMBER) { - tv->set_double_value(atof(pv->s)); + long long v; + if (is_integer(pv->s, &v)) { + if (v >= 0) { + tv->set_int_value(v); + } else { + tv->set_sint_value(v); + } + } else { + tv->set_double_value(atof(pv->s)); + } } else if (pv->type == VT_BOOLEAN) { tv->set_bool_value(pv->s[0] == 't'); } else { diff --git a/version.h b/version.h index bcab1a6..5adfc75 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define VERSION "tippecanoe v1.4.2\n" +#define VERSION "tippecanoe v1.4.3\n"