diff options
author | Jochen Topf <jochen@topf.org> | 2011-04-21 15:54:40 +0200 |
---|---|---|
committer | Jochen Topf <jochen@topf.org> | 2011-04-21 15:54:40 +0200 |
commit | 3b5fae193bdba7fb15413eff3ab13b128fd40c93 (patch) | |
tree | d9d3d046288ba13da159b2308b2dc63d0f0e0469 | |
parent | 30144f46591736f4d906c936d32c617a5d46226f (diff) | |
download | taginfo-3b5fae193bdba7fb15413eff3ab13b128fd40c93.tar taginfo-3b5fae193bdba7fb15413eff3ab13b128fd40c93.tar.gz |
Moved distribution map code into own class and added memory optimization.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | tagstats/Makefile | 7 | ||||
-rw-r--r-- | tagstats/geodistribution.hpp | 123 | ||||
-rw-r--r-- | tagstats/tagstats.cpp | 3 | ||||
-rw-r--r-- | tagstats/tagstats_handler.hpp | 74 |
5 files changed, 144 insertions, 64 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cbc93a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tagstats/tagstats diff --git a/tagstats/Makefile b/tagstats/Makefile index d110996..d777ed3 100644 --- a/tagstats/Makefile +++ b/tagstats/Makefile @@ -29,13 +29,16 @@ LIB_PROTOBUF = -lz -lprotobuf-lite -losmpbf all: tagstats -tagstats: tagstats.cpp tagstats_handler.hpp string_store.hpp +tagstats: tagstats.cpp tagstats_handler.hpp string_store.hpp geodistribution.hpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_GD) $(LIB_SQLITE) +check: + cppcheck --enable=all *.cpp *.hpp + install: install -m 755 -g root -o root -d $(DESTDIR)/usr/bin install -m 755 -g root -o root tagstats $(DESTDIR)/usr/bin/tagstats - + clean: rm -f *.o core tagstats diff --git a/tagstats/geodistribution.hpp b/tagstats/geodistribution.hpp new file mode 100644 index 0000000..4065b5c --- /dev/null +++ b/tagstats/geodistribution.hpp @@ -0,0 +1,123 @@ +#ifndef TAGSTATS_GEODISTRIBUTION_HPP +#define TAGSTATS_GEODISTRIBUTION_HPP + +#include <bitset> + +#include <gd.h> + +class GeoDistribution { + +public: + + static const int resolution_y = 360; + static const int resolution_x = 2 * resolution_y; + + static const int image_size_y = resolution_y; + static const int image_size_x = resolution_x; + +private: + + std::bitset<resolution_x * resolution_y> *location; + + int cells; + int loc; + + static std::bitset<resolution_x * resolution_y> location_all; + +public: + + GeoDistribution() : location(NULL), cells(0), loc(-1) { + } + + ~GeoDistribution() { + delete location; + } + + /** + * Add the given coordinate to the distribution store. + */ + void add_coordinate(double dx, double dy) { + int x = int(2 * (dx + 180)); + int y = resolution_y - int(2 * (dy + 90)); + int n = resolution_x * y + x; + if (cells == 0) { + loc = n; + cells++; + location_all[n] = true; + } else if (cells == 1) { + if (loc != n) { + location = new std::bitset<resolution_x * resolution_y>; + (*location)[loc] = true; + location_all[loc] = true; + (*location)[n] = true; + cells++; + } + } else { + (*location)[n] = true; + location_all[n] = true; + } + } + + /** + * Create PNG image. + * You have to call free_png() to free the memory allocated for the + * PNG image once you are done with it. + * + * @param size Pointer to integer thats set to the size of the created + * image. + * @returns Pointer to memory area with PNG image. + */ + void *create_png(int *size) { + gdImagePtr im = gdImageCreate(image_size_x, image_size_y); + int bgColor = gdImageColorAllocate(im, 0, 0, 0); + gdImageColorTransparent(im, bgColor); + int fgColor = gdImageColorAllocate(im, 180, 0, 0); + + if (location) { + int n=0; + for (int y=0; y < resolution_y; y++) { + for (int x=0; x < resolution_x; x++) { + if ((*location)[n]) { + cells++; + gdImageSetPixel(im, x, y, fgColor); + } + n++; + } + } + } else { + int y = loc / resolution_x; + int x = loc - y; + gdImageSetPixel(im, x, y, fgColor); + } + + void *png = gdImagePngPtr(im, size); + gdImageDestroy(im); + + return png; + } + + /** + * Call this to free the pointer returned by create_png(). + */ + void free_png(void *png) { + gdFree(png); + } + + /** + * Return the number of cells set. This is only valid after a call to create_png(). + */ + int get_cells() const { + return cells; + } + + /** + * Return the number of cells that are set in at least one GeoDistribution + * object. + */ + static int count_all_set_cells() { + return location_all.count(); + } + +}; + +#endif // TAGSTATS_GEODISTRIBUTION_HPP diff --git a/tagstats/tagstats.cpp b/tagstats/tagstats.cpp index 1845e79..88026c4 100644 --- a/tagstats/tagstats.cpp +++ b/tagstats/tagstats.cpp @@ -4,8 +4,11 @@ #include <osmium/handler/statistics.hpp> //#include <osmium/handler/node_location_store.hpp> +#include "geodistribution.hpp" #include "tagstats_handler.hpp" +std::bitset<GeoDistribution::resolution_x * GeoDistribution::resolution_y> GeoDistribution::location_all; + class MyTagStatsHandler : public Osmium::Handler::Base { Osmium::Handler::Statistics osmium_handler_stats; diff --git a/tagstats/tagstats_handler.hpp b/tagstats/tagstats_handler.hpp index 1286e32..289912d 100644 --- a/tagstats/tagstats_handler.hpp +++ b/tagstats/tagstats_handler.hpp @@ -73,6 +73,9 @@ typedef google::sparse_hash_map<osm_user_id_t, uint32_t> user_hash_map_t; typedef google::sparse_hash_map<const char *, Counter, djb2_hash, eqstr> key_combination_hash_map_t; #endif // TAGSTATS_COUNT_KEY_COMBINATIONS +/** + * A KeyStats object holds all statistics for an OSM tag key. + */ class KeyStats { public: @@ -90,16 +93,7 @@ public: user_hash_map_t user_hash; #endif // TAGSTATS_COUNT_USERS - static const int location_image_y_size = 360; - static const int location_image_x_size = 2 * location_image_y_size; - - std::bitset<location_image_x_size * location_image_y_size> location; - - int grids; - - KeyStats() { - grids = 0; - } + GeoDistribution distribution; void update(const char *value, Osmium::OSM::Object *object, StringStore *string_store) { key.count[object->get_type()]++; @@ -122,9 +116,8 @@ public: #endif // TAGSTATS_COUNT_USERS if (object->get_type() == NODE) { - int x = int(2 * (static_cast<Osmium::OSM::Node *>(object)->get_lon() + 180)); - int y = KeyStats::location_image_y_size - int(2 * (static_cast<Osmium::OSM::Node *>(object)->get_lat() + 90)); - location[KeyStats::location_image_x_size * y + x] = true; + distribution.add_coordinate(static_cast<Osmium::OSM::Node *>(object)->get_lon(), + static_cast<Osmium::OSM::Node *>(object)->get_lat()); } } @@ -180,7 +173,6 @@ class TagStatsHandler : public Osmium::Handler::Base { #endif // TAGSTATS_COUNT_KEY_COMBINATIONS void _print_images() { - std::bitset<KeyStats::location_image_x_size * KeyStats::location_image_y_size> location_all; int sum_size=0; Osmium::Sqlite::Statement *statement_insert_into_key_distributions = db->prepare("INSERT INTO key_distributions (key, png) VALUES (?, ?);"); @@ -190,61 +182,19 @@ class TagStatsHandler : public Osmium::Handler::Base { const char *key = tags_iterator->first; KeyStats *stat = tags_iterator->second; - gdImagePtr im = gdImageCreate(KeyStats::location_image_x_size, KeyStats::location_image_y_size); - int bgColor = gdImageColorAllocate(im, 0, 0, 0); - gdImageColorTransparent(im, bgColor); - int fgColor = gdImageColorAllocate(im, 180, 0, 0); - - int n=0; - for (int y=0; y < KeyStats::location_image_y_size; y++) { - for (int x=0; x < KeyStats::location_image_x_size; x++) { - if (stat->location[n]) { - stat->grids++; - gdImageSetPixel(im, x, y, fgColor); - location_all[n] = true; - } - n++; - } - } - int size; - void *ptr = gdImagePngPtr(im, &size); + void *ptr = stat->distribution.create_png(&size); sum_size += size; statement_insert_into_key_distributions ->bind_text(key) ->bind_blob(ptr, size) ->execute(); - gdFree(ptr); - gdImageDestroy(im); + stat->distribution.free_png(ptr); } - gdImagePtr im_all = gdImageCreate(KeyStats::location_image_x_size, KeyStats::location_image_y_size); - gdImageColorAllocate(im_all, 0, 0, 0); - int white_all = gdImageColorAllocate(im_all, 255, 255, 255); - int n=0, count_grid=0; - for (int y=0; y < KeyStats::location_image_y_size; y++) { - for (int x=0; x < KeyStats::location_image_x_size; x++) { - if (location_all[n]) { - gdImageSetPixel(im_all, x, y, white_all); - count_grid++; - } - n++; - } - } - std::cerr << "grids_all: " << count_grid << std::endl; - - int size; - void *ptr = gdImagePngPtr(im_all, &size); - statement_insert_into_key_distributions - ->bind_null() - ->bind_blob(ptr, size) - ->execute(); - gdFree(ptr); - - gdImageDestroy(im_all); - - std::cerr << "sum of location image sizes: " << sum_size + size << std::endl; + std::cerr << "grids_all: " << GeoDistribution::count_all_set_cells() << std::endl; + std::cerr << "sum of location image sizes: " << sum_size << std::endl; db->commit(); delete statement_insert_into_key_distributions; @@ -355,7 +305,7 @@ public: std::cerr << "sizeof(user_hash_map_t) = " << sizeof(user_hash_map_t) << std::endl; #endif // TAGSTATS_COUNT_USERS - std::cerr << "sizeof(std::bitset<x_size*y_size>) = " << sizeof(std::bitset<KeyStats::location_image_x_size * KeyStats::location_image_y_size>) << std::endl; + std::cerr << "sizeof(std::bitset<x_size*y_size>) = " << sizeof(std::bitset<GeoDistribution::resolution_x * GeoDistribution::resolution_y>) << std::endl; std::cerr << "sizeof(KeyStats) = " << sizeof(KeyStats) << std::endl << std::endl; _print_memory_usage(); @@ -445,7 +395,7 @@ public: #else ->bind_int64(0) #endif // TAGSTATS_COUNT_USERS - ->bind_int64(stat->grids) + ->bind_int64(stat->distribution.get_cells()) ->execute(); #ifdef TAGSTATS_COUNT_KEY_COMBINATIONS |