summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJochen Topf <jochen@topf.org>2011-04-21 15:54:40 +0200
committerJochen Topf <jochen@topf.org>2011-04-21 15:54:40 +0200
commit3b5fae193bdba7fb15413eff3ab13b128fd40c93 (patch)
treed9d3d046288ba13da159b2308b2dc63d0f0e0469
parent30144f46591736f4d906c936d32c617a5d46226f (diff)
downloadtaginfo-3b5fae193bdba7fb15413eff3ab13b128fd40c93.tar
taginfo-3b5fae193bdba7fb15413eff3ab13b128fd40c93.tar.gz
Moved distribution map code into own class and added memory optimization.
-rw-r--r--.gitignore1
-rw-r--r--tagstats/Makefile7
-rw-r--r--tagstats/geodistribution.hpp123
-rw-r--r--tagstats/tagstats.cpp3
-rw-r--r--tagstats/tagstats_handler.hpp74
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