diff --git a/mbtiles.cpp b/mbtiles.cpp index 258b7637..d52a99f4 100644 --- a/mbtiles.cpp +++ b/mbtiles.cpp @@ -276,6 +276,12 @@ void tilestats(std::map const &layermap1, size_t el state.json_write_string("attribute"); state.json_write_string(attribute.first); + double xd = attribute.second.xsum / attribute.second.count; + double yd = attribute.second.ysum / attribute.second.count; + double d = sqrt(xd * xd + yd * yd); + + printf("%s %0.6f\n", attribute.first.c_str(), d); + size_t val_count = attribute.second.sample_values.size(); if (val_count > max_tilestats_sample_values) { val_count = max_tilestats_sample_values; @@ -848,6 +854,22 @@ void add_to_file_keys(std::map &file_keys, s if (fka->second.sample_values.size() > max_tilestats_sample_values) { fka->second.sample_values.pop_back(); } + + unsigned hash = 0; + for (size_t i = 0; i < val.string.size(); i++) { + // https://en.wikipedia.org/wiki/Hash_function#Fibonacci_hashing + hash = hash * 2654435769 + val.string[i]; + } + // extra multiply so even single-byte values are distributed + // around the circle rather than clumped together on one side. + hash = hash * 2654435769; + double angle = ((double) hash) / UINT_MAX * 2 * M_PI; + double x = cos(angle); + double y = sin(angle); + + fka->second.xsum += x; + fka->second.ysum += y; + fka->second.count++; } fka->second.type |= (1 << val.type); diff --git a/mbtiles.hpp b/mbtiles.hpp index 8fcd17d6..83244b80 100644 --- a/mbtiles.hpp +++ b/mbtiles.hpp @@ -22,6 +22,11 @@ struct type_and_string_stats { double min = INFINITY; double max = -INFINITY; int type = 0; + + // for circular mean of value hashes + double xsum = 0; + double ysum = 0; + size_t count = 0; }; struct layermap_entry {