diff --git a/.gitignore b/.gitignore index 620d3dc..400c1ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,11 @@ +# Binaries +osmstats +count_addresses +osmgrep +*.osm +*.pbf + + # Compiled Object files *.slo *.lo @@ -11,3 +19,60 @@ *.lai *.la *.a + + +# Created by https://www.gitignore.io/api/eclipse + +### Eclipse ### + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + diff --git a/Makefile b/Makefile index acd372d..140ecb3 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,13 @@ CXX = g++ #CXX = clang++ -#CXXFLAGS = -g -CXXFLAGS = -O3 +#CXXFLAGS += -g +CXXFLAGS += -O3 CXXFLAGS += -Wall -Wextra -Wdisabled-optimization -pedantic -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wno-long-long +CXXFLAGS += -std=c++11 + CXXFLAGS_GEOS = $(shell geos-config --cflags) CXXFLAGS_LIBXML2 = $(shell xml2-config --cflags) CXXFLAGS_OGR = $(shell gdal-config --cflags) @@ -26,54 +28,32 @@ LIB_EXPAT = -lexpat LIB_GD = -lgd -lz -lm LIB_GEOS = $(shell geos-config --libs) LIB_OGR = $(shell gdal-config --libs) -LIB_PBF = -lz -lpthread -lprotobuf-lite -losmpbf +LIB_PBF = -lz -lpthread #-lprotobuf-lite -losmpbf LIB_SHAPE = -lshp $(LIB_GEOS) LIB_SQLITE = -lsqlite3 LIB_XML2 = $(shell xml2-config --libs) +LIB_BZ2 = -lbz2 LDFLAGS = $(LIB_EXPAT) $(LIB_PBF) PROGRAMS = \ - noderef \ count_addresses \ - count \ osmgrep \ - grep-user-from-history \ - history-cleartext \ - add_timestamp \ - osmstats \ - lastnode + osmstats .PHONY: all clean all: $(PROGRAMS) count_addresses: count_addresses.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) - -noderef: noderef.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) - -count: count.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) + $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_BZ2) osmgrep: osmgrep.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) - -grep-user-from-history: grep-user-from-history.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) - -history-cleartext: history-cleartext.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) - -add_timestamp: add_timestamp.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) + $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_BZ2) osmstats: osmstats.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) $(LIB_GEOS) + $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_BZ2) $(LIB_GEOS) -lastnode: lastnode.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_XML2) clean: rm -f *.o core $(PROGRAMS) diff --git a/README b/README deleted file mode 100644 index 8163149..0000000 --- a/README +++ /dev/null @@ -1,9 +0,0 @@ -A collection of Osmium-based utilities for doing things -with OSM data files. - -Note: - -These tools are based on the old version of Osmium, not the new one found in the osmcode/libosmium repo. -The osmcode/osmtool repo has a command line utility that can be used to replace some of these programs: - -* As a lastnode.cpp replacement, use `osmium fileinfo x.osm.pbf -eg data.maxid.nodes diff --git a/README.md b/README.md new file mode 100644 index 0000000..64d8d62 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# A collection of osmium-based utilities for doing things with OSM data files. + + +## Note: + +The osmcode/osmtool repo has a command line utility that can be used to replace some of these programs: + +* As a lastnode.cpp replacement, use `osmium fileinfo x.osm.pbf -eg data.maxid.nodes`. + For more information call `osmium help fileinfo`. + +## Updated +* osmgrep.cpp +* osmstats.cpp +* count_addresses.cpp + + +## Replacements + +### count.cpp + + $ osmium fileinfo -e karlsruhe-regbez.osm.pbf | grep Number | grep -v changesets + Number of nodes: 8291451 + Number of ways: 1424970 + Number of relations: 26632 + +--- +### Dropped + +* noderef.cpp +* add_timestamp.cpp diff --git a/add_timestamp.cpp b/add_timestamp.cpp deleted file mode 100644 index 4cf16b4..0000000 --- a/add_timestamp.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - - Add a synthesized timestamp tag to all objects in the output file. - - This makes little sense *except* if you are using some kind of - OSM file processor that cannot use the timestamp attribute; - using this program you can transform the timestamp attributo - into a proper tag which can then be used. - - Written by Frederik Ramm , public domain. - -*/ - -#include -#include - -#define OSMIUM_WITH_PBF_INPUT -#define OSMIUM_WITH_XML_INPUT -#include -#include -#include - -void print_help() -{ - std::cout << "add_timestamp \n\nadds a synthesized timestamp tag to all OSM objects.\n"; -} - -class AddTimestampHandler : public Osmium::Output::Handler -{ - public: - - AddTimestampHandler(Osmium::OSMFile& outfile) : Osmium::Output::Handler(outfile) - { - } - - void node(const shared_ptr& node) - { - node->tags().add("timestamp", node->timestamp_as_string().c_str()); - Osmium::Output::Handler::node(node); - } - void way(const shared_ptr& way) - { - way->tags().add("timestamp", way->timestamp_as_string().c_str()); - Osmium::Output::Handler::way(way); - } - void relation(const shared_ptr& relation) - { - relation->tags().add("timestamp", relation->timestamp_as_string().c_str()); - Osmium::Output::Handler::relation(relation); - } -}; - - -int main(int argc, char* argv[]) -{ - static struct option long_options[] = - { - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0} - }; - - std::string input_format; - std::string output_format; - - while (true) - { - int c = getopt_long(argc, argv, "h", long_options, 0); - if (c == -1) - { - break; - } - - switch (c) - { - case 'h': - print_help(); - exit(0); - default: - exit(1); - } - } - - std::string input; - std::string output; - int remaining_args = argc - optind; - if (remaining_args != 2) - { - print_help(); - exit(1); - } - - input = argv[optind]; - output = argv[optind+1]; - - Osmium::OSMFile infile(input); - Osmium::OSMFile outfile(output); - - AddTimestampHandler ats(outfile); - ats.set_generator("add_timestamp"); - - Osmium::Input::read(infile, ats); -} - diff --git a/count.cpp b/count.cpp deleted file mode 100644 index 69266a6..0000000 --- a/count.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - Osmium-based tool that counts the number of nodes/ways/relations - in the input file. -*/ - -/* - -Written 2013 by Frederik Ramm - -Public Domain. - -*/ - -#include -#include - -#define OSMIUM_WITH_PBF_INPUT -#define OSMIUM_WITH_XML_INPUT - -#include - -class CountHandler : public Osmium::Handler::Base { - - uint64_t nodes; - uint64_t ways; - uint64_t rels; - -public: - - CountHandler() - { - nodes = 0; - ways = 0; - rels = 0; - } - - void node(__attribute__((__unused__)) const shared_ptr& node) - { - nodes++; - } - - void after_nodes() - { - std::cerr << "nodes: " << nodes << "\n"; - } - void way(__attribute__((__unused__)) const shared_ptr& way) - { - ways++; - } - - void after_ways() - { - std::cerr << "ways: " << ways << "\n"; - } - - void relation(__attribute__((__unused__)) const shared_ptr& relation) - { - rels++; - } - - void after_relations() - { - std::cerr << "relations: " << rels << "\n"; - } - -}; - - -int main(int argc, char *argv[]) -{ - if (argc != 2) - { - std::cerr << "usage: " << argv[0] << " osmfile" << std::endl; - exit(1); - } - Osmium::OSMFile infile(argv[1]); - CountHandler handler; - Osmium::Input::read(infile, handler); - - google::protobuf::ShutdownProtobufLibrary(); -} - diff --git a/count_addresses.cpp b/count_addresses.cpp index cfd2a04..19509c1 100644 --- a/count_addresses.cpp +++ b/count_addresses.cpp @@ -1,11 +1,12 @@ /* - Osmium-based tool that counts the number of addresses + osmium-based tool that counts the number of addresses (house numbers) in the input file. */ /* Written 2012 by Frederik Ramm +Ported 2016 to libosmium 2.9 by Philip Beelmann Public Domain. @@ -18,89 +19,68 @@ Public Domain. #include -#include -#include -#include -#include -#include -#include + +#include +#include +#include +#include #include -class AddressCountHandler : public Osmium::Handler::Base +class AddressCountHandler : public osmium::handler::Handler { private: - std::map housenumberMap; - size_t numbers_nodes_overall; - size_t numbers_nodes_withstreet; - size_t numbers_nodes_withcity; - size_t numbers_nodes_withcountry; - size_t numbers_nodes_withpostcode; - size_t numbers_ways_overall; - size_t numbers_ways_withstreet; - size_t numbers_ways_withcity; - size_t numbers_ways_withcountry; - size_t numbers_ways_withpostcode; - size_t postcode_boundaries; - size_t interpolation_count; - size_t interpolation_error; - size_t numbers_through_interpolation; + std::map housenumberMap; + size_t numbers_nodes_overall = 0; + size_t numbers_nodes_withstreet = 0; + size_t numbers_nodes_withcity = 0; + size_t numbers_nodes_withcountry = 0; + size_t numbers_nodes_withpostcode = 0; + size_t numbers_ways_overall = 0; + size_t numbers_ways_withstreet = 0; + size_t numbers_ways_withcity = 0; + size_t numbers_ways_withcountry = 0; + size_t numbers_ways_withpostcode = 0; + size_t postcode_boundaries = 0; + size_t interpolation_count = 0; + size_t interpolation_error = 0; + size_t numbers_through_interpolation = 0; std::map postcode; bool debug; public: - AddressCountHandler(bool dbg) - { - numbers_nodes_overall = 0; - numbers_nodes_withstreet = 0; - numbers_nodes_withcity = 0; - numbers_nodes_withcountry = 0; - numbers_nodes_withpostcode = 0; - numbers_ways_overall = 0; - numbers_ways_withstreet = 0; - numbers_ways_withcity = 0; - numbers_ways_withcountry = 0; - numbers_ways_withpostcode = 0; - postcode_boundaries = 0; - interpolation_count = 0; - interpolation_error = 0; - numbers_through_interpolation = 0; - debug = dbg; - } - - ~AddressCountHandler() - { + AddressCountHandler(bool debug) : debug(debug){ } - void node(const shared_ptr& node) + void node(const osmium::Node& node) { - const char *hno = node->tags().get_value_by_key("addr:housenumber"); + const char *hno = node.tags().get_value_by_key("addr:housenumber"); if (hno) { - housenumberMap[node->id()] = atoi(hno); + housenumberMap[node.id()] = atoi(hno); numbers_nodes_overall ++; - if (node->tags().get_value_by_key("addr:street")) numbers_nodes_withstreet ++; - if (node->tags().get_value_by_key("addr:city")) numbers_nodes_withcity ++; - if (node->tags().get_value_by_key("addr:country")) numbers_nodes_withcountry ++; - if (node->tags().get_value_by_key("addr:postcode")) + if (node.tags().get_value_by_key("addr:street")) numbers_nodes_withstreet ++; + if (node.tags().get_value_by_key("addr:city")) numbers_nodes_withcity ++; + if (node.tags().get_value_by_key("addr:country")) numbers_nodes_withcountry ++; + if (node.tags().get_value_by_key("addr:postcode")) { numbers_nodes_withpostcode ++; - postcode[node->tags().get_value_by_key("addr:postcode")] = true; + postcode[node.tags().get_value_by_key("addr:postcode")] = true; } } } - void way(const shared_ptr& way) + void way(const osmium::Way& way) { - const char* inter = way->tags().get_value_by_key("addr:interpolation"); + const char* inter = way.tags().get_value_by_key("addr:interpolation"); if (inter) { interpolation_count ++; - osm_object_id_t fromnode = way->get_first_node_id(); - osm_object_id_t tonode = way->get_last_node_id(); + osmium::unsigned_object_id_type fromnode = way.nodes().front().ref(); + osmium::unsigned_object_id_type tonode = way.nodes().back().ref(); uint16_t fromhouse = housenumberMap[fromnode]; uint16_t tohouse = housenumberMap[tonode]; @@ -110,8 +90,9 @@ class AddressCountHandler : public Osmium::Handler::Base interpolation_error++; if (debug) { - if (!fromhouse) std::cerr << "interpolation way " << way->id() << " references node " << fromnode << " which has no addr:housenumber" << std::endl; - if (!tohouse) std::cerr << "interpolation way " << way->id() << " references node " << tonode << " which has no addr:housenumber" << std::endl; + + if (!fromhouse) std::cerr << "interpolation way " << way.id() << " references node " << fromnode << " which has no addr:housenumber" << std::endl; + if (!tohouse) std::cerr << "interpolation way " << way.id() << " references node " << tonode << " which has no addr:housenumber" << std::endl; } return; } @@ -129,8 +110,8 @@ class AddressCountHandler : public Osmium::Handler::Base { if (debug) { - if (fromhouse%2==1) std::cerr << "interpolation way " << way->id() << " (addr:interpolation=even) references node " << fromnode << " which has an odd house number of " << fromhouse << std::endl; - if (tohouse%2==1) std::cerr << "interpolation way " << way->id() << " (addr:interpolation=even) references node " << tonode << " which has an odd house number of " << tohouse << std::endl; + if (fromhouse%2==1) std::cerr << "interpolation way " << way.id() << " (addr:interpolation=even) references node " << fromnode << " which has an odd house number of " << fromhouse << std::endl; + if (tohouse%2==1) std::cerr << "interpolation way " << way.id() << " (addr:interpolation=even) references node " << tonode << " which has an odd house number of " << tohouse << std::endl; } interpolation_error++; return; @@ -143,8 +124,8 @@ class AddressCountHandler : public Osmium::Handler::Base { if (debug) { - if (fromhouse%2==1) std::cerr << "interpolation way " << way->id() << " (addr:interpolation=odd) references node " << fromnode << " which has an even house number of " << fromhouse << std::endl; - if (tohouse%2==1) std::cerr << "interpolation way " << way->id() << " (addr:interpolation=odd) references node " << tonode << " which has an even house number of " << tohouse << std::endl; + if (fromhouse%2==1) std::cerr << "interpolation way " << way.id() << " (addr:interpolation=odd) references node " << fromnode << " which has an even house number of " << fromhouse << std::endl; + if (tohouse%2==1) std::cerr << "interpolation way " << way.id() << " (addr:interpolation=odd) references node " << tonode << " which has an even house number of " << tohouse << std::endl; } interpolation_error++; return; @@ -159,7 +140,7 @@ class AddressCountHandler : public Osmium::Handler::Base { if (debug) { - std::cerr << "interpolation way " << way->id() << " has invalid interpolation mode '" << inter << "'" << std::endl; + std::cerr << "interpolation way " << way.id() << " has invalid interpolation mode '" << inter << "'" << std::endl; } interpolation_error++; } @@ -167,58 +148,55 @@ class AddressCountHandler : public Osmium::Handler::Base } else { - const char *hno = way->tags().get_value_by_key("addr:housenumber"); + const char *hno = way.tags().get_value_by_key("addr:housenumber"); if (hno) { numbers_ways_overall ++; - if (way->tags().get_value_by_key("addr:street")) numbers_ways_withstreet ++; - if (way->tags().get_value_by_key("addr:city")) numbers_ways_withcity ++; - if (way->tags().get_value_by_key("addr:country")) numbers_ways_withcountry ++; - if (way->tags().get_value_by_key("addr:postcode")) + if (way.tags().get_value_by_key("addr:street")) numbers_ways_withstreet ++; + if (way.tags().get_value_by_key("addr:city")) numbers_ways_withcity ++; + if (way.tags().get_value_by_key("addr:country")) numbers_ways_withcountry ++; + if (way.tags().get_value_by_key("addr:postcode")) { numbers_ways_withpostcode ++; - postcode[way->tags().get_value_by_key("addr:postcode")] = true; + postcode[way.tags().get_value_by_key("addr:postcode")] = true; } } else { - const char *bdy = way->tags().get_value_by_key("boundary"); + const char *bdy = way.tags().get_value_by_key("boundary"); if (bdy && !strcmp(bdy, "postal_code")) { postcode_boundaries++; - const char *ref = way->tags().get_value_by_key("ref"); + const char *ref = way.tags().get_value_by_key("ref"); if (ref) postcode[ref]=true; } } } } - void relation(const shared_ptr& rel) + void relation(const osmium::Relation& rel) { - const char *bdy = rel->tags().get_value_by_key("boundary"); + const char *bdy = rel.tags().get_value_by_key("boundary"); if (bdy && !strcmp(bdy, "postal_code")) { postcode_boundaries++; - const char *ref = rel->tags().get_value_by_key("ref"); + const char *ref = rel.tags().get_value_by_key("ref"); if (ref) postcode[ref]=true; } } - void after_ways() - { - printf(" nodes ways total\n"); - printf("with house number %8ld %8ld %8ld\n", numbers_nodes_overall, numbers_ways_overall, numbers_nodes_overall + numbers_ways_overall); - printf("... and street %8ld %8ld %8ld\n", numbers_nodes_withstreet, numbers_ways_withstreet, numbers_nodes_withstreet + numbers_ways_withstreet); - printf("... and city %8ld %8ld %8ld\n", numbers_nodes_withcity, numbers_ways_withcity, numbers_nodes_withcity + numbers_ways_withcity); - printf("... and post code %8ld %8ld %8ld\n", numbers_nodes_withpostcode, numbers_ways_withpostcode, numbers_nodes_withpostcode + numbers_ways_withpostcode); - printf("... and country %8ld %8ld %8ld\n", numbers_nodes_withcountry, numbers_ways_withcountry, numbers_nodes_withcountry + numbers_ways_withcountry); - printf("\ntotal interpolations: %ld (%ld ignored)\n", interpolation_count, interpolation_error); - printf("\nhouse numbers added through interpolation: %ld\n", numbers_through_interpolation); - printf("\ngrand total (interpolation, ways, nodes): %ld\n", numbers_through_interpolation + numbers_nodes_overall + numbers_ways_overall); - printf("\nnumber of different post codes: %ld\n", postcode.size()); - printf("\nnumber of post code boundaries: %ld\n", postcode_boundaries); - - throw Osmium::Handler::StopReading(); + void print() { + std::cout << " nodes ways total" << std::endl; + std::cout << "with house number " << numbers_ways_overall << " " << numbers_nodes_overall << " " << numbers_ways_overall << std::endl; + std::cout << "... and street " << numbers_nodes_withstreet << " " << numbers_ways_withstreet << " " << numbers_nodes_withstreet + numbers_ways_withstreet << std::endl; + std::cout << "... and city " << numbers_nodes_withcity << " " << numbers_ways_withcity << " " << numbers_nodes_withcity + numbers_ways_withcity << std::endl; + std::cout << "... and post code " << numbers_nodes_withpostcode << " " << numbers_ways_withpostcode << " " << numbers_nodes_withpostcode + numbers_ways_withcountry << std::endl; + std::cout << "... and country " << numbers_nodes_withcountry << " " << numbers_ways_withcountry << " " << numbers_nodes_withcountry + numbers_ways_withcountry << std::endl; + std::cout << "\ntotal interpolations: " << interpolation_count << " (" << interpolation_error << " ignored)" << std::endl; + std::cout << "\nhouse numbers added through interpolation: " << numbers_through_interpolation << std::endl; + std::cout << "\ngrand total (interpolation, ways, nodes): " << numbers_through_interpolation + numbers_nodes_overall + numbers_ways_overall << std::endl; + std::cout << "\nnumber of different post codes: " << postcode.size() << std::endl; + std::cout << "\nnumber of post code boundaries: " << postcode_boundaries << std::endl; } }; @@ -228,9 +206,10 @@ class AddressCountHandler : public Osmium::Handler::Base void usage(const char *prg) { std::cerr << "Usage: " << prg << " [-d] [-h] OSMFILE" << std::endl; + } -int main(int argc, char* argv[]) +int main(int argc, char* argv[]) { static struct option long_options[] = { {"debug", no_argument, 0, 'd'}, @@ -258,14 +237,22 @@ int main(int argc, char* argv[]) } } - if (argc != 2) - { + std::string input; + int remaining_args = argc - optind; + if (remaining_args == 1) { + input = argv[optind]; + } else { usage(argv[0]); exit(1); } - Osmium::OSMFile infile(argv[1]); + + osmium::io::File infile(input); + osmium::io::Reader reader(infile); + AddressCountHandler handler(debug); - Osmium::Input::read(infile, handler); + osmium::apply(reader, handler); + reader.close(); + handler.print(); } diff --git a/lastnode.cpp b/lastnode.cpp deleted file mode 100644 index 4bda4de..0000000 --- a/lastnode.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - -Osmium-based tool that finds the last node ID in the input file. - -Written 2013 by Frederik Ramm - -Public Domain. - -*/ - -#include - -#define OSMIUM_WITH_PBF_INPUT -#define OSMIUM_WITH_XML_INPUT - -#include - -class LastIdHandler : public Osmium::Handler::Base { - -osm_object_id_t lastid; - -public: - - LastIdHandler() - { - lastid = 0; - } - - void node(const shared_ptr& node) - { - lastid = node->id(); - } - - void after_nodes() - { - std::cout << lastid << std::endl; - throw Osmium::Handler::StopReading(); - } -}; - -int main(int argc, char* argv[]) -{ - if (argc != 2) - { - std::cerr << "usage: lastnode inputfile.pbf" << std::endl; - exit(1); - } - - Osmium::OSMFile infile(argv[1]); - LastIdHandler handler; - Osmium::Input::read(infile, handler); -} diff --git a/noderef.cpp b/noderef.cpp deleted file mode 100644 index b4e1cd3..0000000 --- a/noderef.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - Osmium-based tool that counts how often nodes are referenced. -*/ - -/* - -Written 2013 by Frederik Ramm - -Public Domain. - -*/ - -#include -#include - -#define OSMIUM_WITH_PBF_INPUT -#define OSMIUM_WITH_XML_INPUT - -#define MAX_NODE_ID 4000000000 - -#include - -class RefHandler : public Osmium::Handler::Base { - - unsigned char *ref; - uint64_t max_node_id; - -public: - - RefHandler() - { - ref = (unsigned char *) malloc(MAX_NODE_ID); - memset(ref, 0, MAX_NODE_ID); - max_node_id = 0; - } - - void node(const shared_ptr& node) - { - max_node_id = node->id(); - } - - void way(const shared_ptr& way) - { - for (Osmium::OSM::WayNodeList::const_iterator i = way->nodes().begin(); i!= way->nodes().end(); i++) - { - if (ref[i->ref()] < 255) ref[i->ref()]++; - } - } - - void after_ways() - { - uint64_t count[256]; - for (int i=0; i<256; i++) count[i]=0; - for (uint64_t i = 0; i <= max_node_id; i++) - { - count[ref[i]]++; - } - for (int i=0; i<256; i++) printf("%d,%ld\n", i, count[i]); - throw Osmium::Handler::StopReading(); - } - - void relation(__attribute__((__unused__)) const shared_ptr& relation) - { - } - -}; - - -int main(int argc, char *argv[]) -{ - if (argc != 2) - { - std::cerr << "usage: " << argv[0] << " osmfile" << std::endl; - exit(1); - } - Osmium::OSMFile infile(argv[1]); - RefHandler handler; - Osmium::Input::read(infile, handler); - - google::protobuf::ShutdownProtobufLibrary(); -} - diff --git a/osmgrep.cpp b/osmgrep.cpp index 73b5da5..369d3bc 100644 --- a/osmgrep.cpp +++ b/osmgrep.cpp @@ -1,423 +1,288 @@ /* - Osmium-based tool which to grep an OSM File with a faster C++-Code + osmium-based tool which to grep an OSM File with a faster C++-Code */ /* Written 2013 by Dietmar Sauer + Ported 2016 to libosmium 2.9 by Philip Beelmann Public Domain. */ +#include #include #include #include #include -#include -#include +#include // for std::copy_if +#include +#include +#include +#include +#include -#define OSMIUM_WITH_PBF_INPUT -#define OSMIUM_WITH_XML_INPUT -#define OSMIUM_WITH_PBF_OUTPUT +// Get access to isatty utility function and progress bar utility class. +#include +#include -#include - -struct SearchTag -{ - std::string key; - std::string value; - SearchTag(const char *k, const char *v) { key.assign(k); value.assign(v); } -}; - -class CountHandler: public Osmium::Handler::Base -{ - - uint64_t nodes; - uint64_t ways; - uint64_t rels; - - std::vector searchTags; - std::vector usernames; - std::vector userid; - std::vector objectid; - - uint64_t version; - short int version_sign; - - Osmium::Output::Handler *outHandler; - - bool process_nodes; - bool process_ways; - bool process_rels; - - -public: - - CountHandler() - { - nodes = 0; - ways = 0; - rels = 0; - outHandler = NULL; - process_nodes = false; - process_ways = false; - process_rels = false; - version = 0; - version_sign = 0; - } - - void setTypes(bool nodes, bool ways, bool rels) - { - process_nodes = nodes; - process_ways = ways; - process_rels = rels; - } - - bool setOutputfile(const char *filename) - { - Osmium::OSMFile *outfile = new Osmium::OSMFile(filename); - outHandler = new Osmium::Output::Handler(*outfile); - try - { - outHandler = new Osmium::Output::Handler(*outfile); - } - catch (Osmium::OSMFile::IOError *e) - { - std::cerr << "IOError: " << e << std::endl; - return false; - } - return true; - } - - bool addSearchTag(char *t) - { - char *equal = strchr(t, '='); - if (!equal) return false; - *equal++ = 0; - if (!strlen(t)) return false; - if (!strlen(equal)) return false; - searchTags.push_back(new SearchTag(t, equal)); - return true; - } - - bool addUserID(char *i) - { - int a=atoi(i); - if(a==0) return false; - userid.push_back(a); - return true; - } - - bool addObjectID(char *i) - { - int a=atoi(i); - if(a==0) return false; - objectid.push_back(a); - return true; - } - - bool setVersion(char *v) - { - if (*v == '+' || *v == '-') - { - version_sign = (*v == '-') ? -1 : 1; - v++; - } - version = atoi(v); - return (version > 0); - } - - void addUserName(char *u) - { - usernames.push_back(u); - } - - void init(Osmium::OSM::Meta& meta) - { - if (outHandler) outHandler->init(meta); - } - - void node(const shared_ptr& node) - { - if (!process_nodes) return; - if (!tagmatch(node->tags())) return; - if (!usermatch(node->user())) return; - if (!uidmatch(node->uid())) return; - if (!oidmatch(node->id())) return; - if (!versionmatch(node->version())) return; - if (outHandler) outHandler->node(node); - nodes++; - } - - void after_nodes() - { - if (process_nodes) - { - std::cerr << "nodes: "<< nodes << std::endl; - } - } - - void way(const shared_ptr& way) - { - if (!process_ways) return; - if (!tagmatch(way->tags())) return; - if (!usermatch(way->user())) return; - if (!uidmatch(way->uid())) return; - if (!oidmatch(way->id())) return; - if (!versionmatch(way->version())) return; - if (outHandler) outHandler->way(way); - ways++; - } - - void after_ways() - { - if (process_ways) - { - std::cerr << "ways: " << ways << "\n"; - } - } - - void relation(const shared_ptr& relation) - { - if (!process_rels) return; - if (!tagmatch(relation->tags())) return; - if (!usermatch(relation->user())) return; - if (!uidmatch(relation->uid())) return; - if (!oidmatch(relation->id())) return; - if (!versionmatch(relation->version())) return; - if (outHandler) outHandler->relation(relation); - rels++; - } - - void after_relations() - { - if (process_rels) - { - std::cerr << "relations: " << rels << "\n"; - } - std::cerr << "total: " << nodes + ways + rels << std::endl; - } - - void final() - { - if (outHandler) outHandler->final(); - } - -private: - - bool uidmatch(uint32_t id) - { - if (userid.empty()) return true; - for (unsigned int i=0; i < userid.size(); i++) - { - if (userid[i]==id) - { - return true; - } - } - return false; - } - - bool oidmatch(uint64_t id) - { - if (objectid.empty()) return true; - for (unsigned int i=0; i < objectid.size(); i++) - { - if (objectid[i]==id) - { - return true; - } - } - return false; - } - - bool usermatch(const char* user) - { - if (usernames.empty()) return true; - for (unsigned int i=0; i < usernames.size(); i++) - { - if (usernames[i]==user) - { - return true; - } - } - return false; - } - - bool tagmatch(const Osmium::OSM::TagList& tags) - { - if (searchTags.empty()) return true; - for (unsigned int i=0; i < searchTags.size(); i++) - { - const char *tagvalue = tags.get_value_by_key(searchTags[i]->key.c_str()); - if (tagvalue) - { - if (searchTags[i]->value == "*") - { - return true; - } - else if (searchTags[i]->value == tagvalue) - { - return true; - } - } - } - return false; - } - - bool versionmatch(uint64_t v) - { - if (version == 0) return true; - if (version_sign == -1 && v < version) return true; - if (version_sign == 1 && v > version) return true; - return (v==version); - } - -}; +#include +#include void print_help(const char *progname) { - std::cerr << "\n" << progname << " [OPTIONS] \n" + std::cerr << "\n" << progname << " [OPTIONS] \n" << "\nFinds and counts (optionally outputs) matching objects in an OSM file.\n" - << "\nOptions:\n" - << " --help this help message\n" - << " --type match objects of type t (node, way, relation)\n" - << " --oid match object ID i\n" - << " --uid match user ID i\n" - << " --version match verison i (+i = larger than i, -i = smaller than i)\n" - << " --user match user name u\n" - << " --expr match objects with given tag (e can be type=value or type=*)\n" - << " --output write output to file o (without, just displays counts)\n" - << "\nIf multiple selectors are given, objects have to match all conditions.\n" + << "\nOptions:\n" + << " --help this help message\n" + << " --type match objects of type t (node, way, relation)\n" + << " --oid match object ID i\n" + << " --uid match user ID i\n" + << " --version match verison i (+i = larger than i, -i = smaller than i)\n" + << " --user match user name u\n" + << " --expr match objects with given tag (e can be type=value or type=*)\n" + << " --output write output to file o (without, just displays counts)\n" + << " --progress

shows progress bar\n" + << "\nIf multiple selectors are given, objects have to match all conditions.\n" << "Multiple occurrences of same selector mean the object has to match one of them.\n" << "Example: --type node --expr amenity=restaurant --expr tourism=hotem will match\n" << "only nodes that have at least one of the given tags.\n\n"; } -int main(int argc, char *argv[]) -{ - static struct option long_options[] = - { - {"help", no_argument, 0, 'h'}, - {"type", required_argument, 0, 't'}, - {"oid", required_argument, 0, 'd'}, - {"version", required_argument, 0, 'v'}, - {"uid", required_argument, 0, 'i'}, - {"user", required_argument, 0, 'u'}, - {"expr", required_argument, 0, 'e'}, - {"output", required_argument, 0, 'o'}, - {0, 0, 0, 0} - }; - bool node=false; - bool way=false; - bool relation=false; - CountHandler handler; - - while (true) - { - int c = getopt_long(argc, argv, "ht:d:i:u:e:o:v:", long_options, 0); - if (c == -1) - { +int main(int argc, char* argv[]) +{ + uint64_t node_count = 0; + uint64_t way_count = 0; + uint64_t relation_count = 0; + + bool node = false; + bool way = false; + bool relation = false; + + bool enable_progress_bar = false; + + osmium::user_id_type user_id = 0; + osmium::object_version_type version = 0; + osmium::object_id_type object_id = 0; + const char* user_name = nullptr; + const char* search_key = nullptr; + const char* search_value = nullptr; + const char* output_file = nullptr; + + static struct option long_options[] = { + { "help", no_argument, 0, 'h' }, + { "type", required_argument, 0, 't' }, + { "oid", required_argument, 0, 'd' }, + { "version", required_argument, 0, 'v' }, + { "uid", required_argument, 0, 'i' }, + { "user", required_argument, 0, 'u' }, + { "expr", required_argument, 0, 'e' }, + { "output", required_argument, 0, 'o' }, + { "progress", no_argument, 0, 'p' }, + { 0, 0, 0, 0 } }; + while (true) { + int c = getopt_long(argc, argv, "ht:d:i:u:e:o:v:p", long_options, 0); + if (c == -1) { break; } - - switch (c) - { + switch (c) { case 'h': print_help(argv[0]); exit(0); case 't': - if (!strcmp(optarg, "node")) - { - node=true; - } - else if (!strcmp(optarg, "way")) - { - way=true; - } - else if (!strcmp(optarg, "relation")) - { - relation=true; - } - else - { + if (!strcmp(optarg, "node")) { + node = true; + } else if (!strcmp(optarg, "way")) { + way = true; + } else if (!strcmp(optarg, "relation")) { + relation = true; + } else { std::cerr << "-t flag requires a type node like -tnode for node -tway for way ...\n" << std::endl; print_help(argv[0]); exit(1); } + break; case 'i': - if (!handler.addUserID(optarg)) - { - std::cerr << "--uid flag requires a number for ID like --uid23232\n" << std::endl; + if (optarg) { + user_id = strtol(optarg, NULL, 0); + } else { + std::cerr << "--uid flag requires a number for ID like --uid23232\n" << std::endl; print_help(argv[0]); exit(1); } break; case 'v': - if (!handler.setVersion(optarg)) - { - std::cerr << "--version flag requires a number: --version [+-)]5\n" << std::endl; + if (optarg) { + version = strtol(optarg, NULL, 0); + } else { + std::cerr << "--version flag requires a number: --version [+-)]5\n" << std::endl; print_help(argv[0]); exit(1); } break; case 'd': - if (!handler.addObjectID(optarg)) - { - std::cerr << "--oid flag requires a number for ID like --oid 23232\n" << std::endl; + if (optarg) { + object_id = strtol(optarg, NULL, 0); + } else { + std::cerr << "--oid flag requires a number for ID like --oid 23232\n" << std::endl; print_help(argv[0]); exit(1); } break; case 'u': - handler.addUserName(optarg); + if (optarg) { + user_name = optarg; + } else { + std::cerr << "--user flag requires a string like --user foobar\n" << std::endl; + print_help(argv[0]); + exit(1); + } break; case 'e': - if (!handler.addSearchTag(optarg)) - { + if (optarg) { + std::string tag(optarg); + std::size_t delim = tag.find("="); + if (delim != std::string::npos && tag.find("=", delim + 1) != std::string::npos) { + std::cerr << "-e flag requires key=value style argument" << std::endl; + exit(1); + } + search_key = strdup(tag.substr(0, delim).c_str()); + if (delim != std::string::npos) { + search_value = strdup(tag.substr(delim + 1).c_str()); + } + } else { std::cerr << "-e flag requires key=value style argument" << std::endl; exit(1); } break; case 'o': - if(!handler.setOutputfile(optarg)) - { + if (optarg) { + output_file = optarg; + } else { std::cerr << "-o flag requires a suitable filename" << std::endl; exit(1); } break; + case 'p': + enable_progress_bar = true; + break; default: print_help(argv[0]); exit(1); } } - - if (node||way||relation) - { - handler.setTypes(node,way,relation); - } - else - { - handler.setTypes(true,true,true); - } - std::string input; int remaining_args = argc - optind; - if (remaining_args > 1) - { + if (remaining_args > 1) { std::cerr << "extra arguments on command line" << std::endl; print_help(argv[0]); exit(1); - } - else if (remaining_args == 1) { + } else if (remaining_args == 1) { input = argv[optind]; + } else { + std::cerr << "Usage: " << argv[0] << " OSMFILE OPTIONS" << std::endl; + std::cerr << " " << argv[0] << " --help" << std::endl; + exit(1); + } + + // The input file, deduce file format from file suffix + osmium::io::File infile{input}; + + + osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nothing; + if (node) entities |= osmium::osm_entity_bits::node; + if (way) entities |= osmium::osm_entity_bits::way; + if (relation) entities |= osmium::osm_entity_bits::relation; + + if(entities == osmium::osm_entity_bits::nothing) + entities = osmium::osm_entity_bits::all; + + // Initialize Reader for the input file. + // Read only changesets (will ignore nodes, ways, and + // relations if there are any). + osmium::io::Reader reader{infile, entities}; + + // Initialize progress bar, enable it only if STDERR is a TTY. + osmium::ProgressBar progress{reader.file_size(), osmium::util::isatty(2) && enable_progress_bar}; + + // Get the header from the input file + osmium::io::Header header = reader.header(); + + header.set("generator", "osmgrep"); + + // Create range of input iterators that will iterator over all objects + // delivered from input file through the "reader". + auto input_range = osmium::io::make_input_iterator_range(reader); + + + auto condition = [&](const osmium::OSMObject& object) { + progress.update(reader.offset()); + + if(user_id && object.uid() != user_id) return false; + if(version && object.version() != version) return false; + if(object_id && object.id() != object_id) return false; + if(user_name && strcmp(object.user(), user_name)) return false; + if(search_key) { + const char* value = object.tags()[search_key]; + if (!value) return false; + if (search_value){ + if(strcmp(search_value, value) && strcmp(search_value, "*")) return false; + } + } + if (!output_file){ + switch (object.type()) { + case osmium::item_type::node: + node_count++; + break; + case osmium::item_type::way: + way_count++; + break; + case osmium::item_type::relation: + relation_count++; + break; + default: + break; + } + } + return true; + }; + + if (output_file) { + osmium::io::File outfile { output_file }; + + // Initialize writer for the output file. Use the header from the input + // file for the output file. This will copy over some header information. + // The last parameter will tell the writer that it is allowed to overwrite + // an existing file. Without it, it will refuse to do so. + osmium::io::Writer writer(outfile, header, osmium::io::overwrite::allow); + + // Create an output iterator writing through the "writer" object to the + // output file. + auto output_iterator = osmium::io::make_output_iterator(writer); + + // Copy all objects from input to output that fit criteria + std::copy_if(input_range.begin(), input_range.end(), output_iterator, condition); + + + // Explicitly close the writer and reader. Will throw an exception if + // there is a problem. If you wait for the destructor to close the writer + // and reader, you will not notice the problem, because destructors must + // not throw. + writer.close(); + } else { + std::for_each(input_range.begin(), input_range.end(), condition); + std::cout << std::endl; + std::cout << " #nodes matching = " << node_count << std::endl; + std::cout << " #ways matching = " << way_count << std::endl; + std::cout << " #relations matching = " << relation_count << std::endl; + } + // Progress bar is done. + progress.done(); + reader.close(); - Osmium::OSMFile infile(input); - Osmium::Input::read(infile, handler); - google::protobuf::ShutdownProtobufLibrary(); } diff --git a/osmstats.cpp b/osmstats.cpp index 24469eb..22ad012 100644 --- a/osmstats.cpp +++ b/osmstats.cpp @@ -4,6 +4,7 @@ Osmium-based program that displays a couple statistics about the date in the input file. Frederik Ramm , public domain +Ported 2016 to libosmium 2.9 by Philip Beelmann Handling of areas is still missing. @@ -14,140 +15,61 @@ Handling of areas is still missing. #define OSMIUM_WITH_PBF_INPUT #define OSMIUM_WITH_XML_INPUT -#include -#include -#include -#include -#include -#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* ================================================== */ -class StatisticsHandler : public Osmium::Handler::Base +class StatisticsHandler : public osmium::handler::Handler { private: - double motorway_trunk_length; - double primary_secondary_length; - double other_road_length; - double residential_road_with_name_length; - double residential_road_length; - double path_length; - - double river_length; - double railway_length; - double powerline_length; - double water_area; - double forest_area; - - int building_count; - int poi_count; - int housenumber_count; - int place_count; - - int poi_power_count; - int poi_traffic_count; - int poi_other_count; - int poi_public_count; - int poi_hospitality_count; - int poi_shop_count; - int poi_religion_count; - - int landuse_green_count; - int landuse_blue_count; - int landuse_zone_count; - int landuse_agri_count; - + double motorway_trunk_length = 0; + double primary_secondary_length = 0; + double other_road_length = 0; + double residential_road_with_name_length = 0; + double residential_road_length = 0; + double path_length = 0; + + double river_length = 0; + double railway_length = 0; + double powerline_length = 0; + double water_area = 0; + double forest_area = 0; + + int building_count = 0; + int housenumber_count = 0; + int place_count = 0; + + int poi_power_count = 0; + int poi_traffic_count = 0; + int poi_other_count = 0; + int poi_public_count = 0; + int poi_hospitality_count = 0; + int poi_shop_count = 0; + int poi_religion_count = 0; + + int landuse_green_count = 0; + int landuse_blue_count = 0; + int landuse_zone_count = 0; + int landuse_agri_count = 0; public: - StatisticsHandler() : Osmium::Handler::Base() - { - motorway_trunk_length = 0; - primary_secondary_length = 0; - other_road_length = 0; - residential_road_length = 0; - residential_road_with_name_length = 0; - path_length = 0; - - river_length = 0; - railway_length = 0; - powerline_length = 0; - water_area = 0; - forest_area = 0; - - building_count = 0; - poi_count = 0; - housenumber_count = 0; - place_count = 0; - - poi_power_count = 0; - poi_traffic_count = 0; - poi_other_count = 0; - poi_public_count = 0; - poi_hospitality_count = 0; - poi_shop_count = 0; - poi_religion_count = 0; - poi_traffic_count = 0; - - landuse_green_count = 0; - landuse_blue_count = 0; - landuse_zone_count = 0; - landuse_agri_count = 0; - } - - ~StatisticsHandler() { - } - -#define PI 3.14159265358979323846 -#define rad(DEG) ((DEG)*((PI)/(180.0))) - double lsarea(const geos::geom::LineString *ls) - { - const geos::geom::CoordinateSequence *cs = ls->getCoordinatesRO(); - double area = 0; - size_t len = cs->getSize(); - if (len < 3) return 0; - for (size_t i = 0; i < len-1; i++) - { - const geos::geom::Coordinate &p1 = cs->getAt(i); - const geos::geom::Coordinate &p2 = cs->getAt(i+1); - area += rad(p2.x - p1.x) * - (2 + sin(rad(p1.y)) + - sin(rad(p2.y))); - } - area = area * 6378137.0 * 6378137.0 / 2.0; - } - - // unused, not properly working - double comparea(const shared_ptr& area) - { - double sum; - const geos::geom::Geometry *a = Osmium::Geometry::MultiPolygon(*area).borrow_geos_geometry(); - if (a) - { - for (size_t i = 0; i < a->getNumGeometries(); i++) - { - const geos::geom::Polygon *p = dynamic_cast(a->getGeometryN(i)); - if (p) - { - const geos::geom::LineString *er = p->getExteriorRing(); - sum += lsarea(er); - for (size_t j = 0; j < p->getNumInteriorRing(); j++) - { - sum -= lsarea(p->getInteriorRingN(j)); - } - } - } - } - else - { - std::cout << "none" << std::endl; - } - return 0.0; - } - - void count_misc(Osmium::OSM::TagList tags) + void count_misc(const osmium::TagList& tags) { const char *t = tags.get_value_by_key("landuse"); if (t) @@ -257,22 +179,22 @@ class StatisticsHandler : public Osmium::Handler::Base } - void area(const shared_ptr& area) + void area(const osmium::Area& area) { - if (area->tags().get_value_by_key("building")) + if (area.tags().get_value_by_key("building")) { building_count++; } - if (area->tags().get_value_by_key("addr_housenumber")) + if (area.tags().get_value_by_key("addr_housenumber")) { housenumber_count++; } - count_misc(area->tags()); + count_misc(area.tags()); } - void way(const shared_ptr& way) + void way(const osmium::Way& way) { - const char *hwy = way->tags().get_value_by_key("highway"); + const char *hwy = way.tags().get_value_by_key("highway"); if (hwy) { if (!strcmp(hwy, "motorway") || !strcmp(hwy, "trunk")) @@ -291,7 +213,7 @@ class StatisticsHandler : public Osmium::Handler::Base { double l = waylen(way); residential_road_length += l; - if (way->tags().get_value_by_key("name")) residential_road_with_name_length += l; + if (way.tags().get_value_by_key("name")) residential_road_with_name_length += l; } else if (!strcmp(hwy, "service") || !strcmp(hwy, "path") || !strcmp(hwy, "footway") || !strcmp(hwy, "cycleway") || !strcmp(hwy, "track")) { @@ -299,7 +221,7 @@ class StatisticsHandler : public Osmium::Handler::Base } return; } - const char *wwy = way->tags().get_value_by_key("waterway"); + const char *wwy = way.tags().get_value_by_key("waterway"); if (wwy) { if (!strcmp(wwy, "river")) @@ -308,7 +230,7 @@ class StatisticsHandler : public Osmium::Handler::Base } return; } - const char *rwy = way->tags().get_value_by_key("railway"); + const char *rwy = way.tags().get_value_by_key("railway"); if (rwy) { if (!strcmp(rwy, "rail") || !strcmp(rwy, "light_rail")) @@ -317,7 +239,7 @@ class StatisticsHandler : public Osmium::Handler::Base } return; } - const char *pwr = way->tags().get_value_by_key("power"); + const char *pwr = way.tags().get_value_by_key("power"); if (pwr) { if (!strcmp(pwr, "line") || !strcmp(pwr, "minor_line")) @@ -326,28 +248,28 @@ class StatisticsHandler : public Osmium::Handler::Base } return; } - count_misc(way->tags()); + count_misc(way.tags()); } - void node(const shared_ptr& node) + void node(const osmium::Node& node) { - if (node->tags().get_value_by_key("place")) + if (node.tags().get_value_by_key("place")) { - if (node->tags().get_value_by_key("name")) place_count++; + if (node.tags().get_value_by_key("name")) place_count++; } - else if (node->tags().get_value_by_key("addr:housenumber")) + else if (node.tags().get_value_by_key("addr:housenumber")) { housenumber_count++; } else { - count_misc(node->tags()); + count_misc(node.tags()); } } - void final() + void print() { - bool csv = true; + bool csv = false; if (csv) { std::cout << @@ -355,6 +277,7 @@ class StatisticsHandler : public Osmium::Handler::Base "primary and secondary roads km," "other connecting roads km," "residential roads km," + "residential roads with names km," "tracks/paths km," "rivers km," "railways km," @@ -379,6 +302,7 @@ class StatisticsHandler : public Osmium::Handler::Base (int) (primary_secondary_length / 1000) << "," << (int) (other_road_length / 1000) << "," << (int) (residential_road_length / 1000) << "," << + (int) (residential_road_with_name_length / 1000) << "," << (int) (path_length / 1000) << "," << (int) (river_length / 1000) << "," << (int) (railway_length / 1000) << "," << @@ -396,66 +320,54 @@ class StatisticsHandler : public Osmium::Handler::Base poi_hospitality_count << "," << poi_shop_count << "," << poi_religion_count << "," << - poi_other_count << - std::endl; + poi_other_count << std::endl; } else { - printf("motorways and trunk roads ....... %5.0f km\n", motorway_trunk_length / 1000); - printf("primary and secondary roads ..... %5.0f km\n", primary_secondary_length / 1000); - printf("other connecting roads .......... %5.0f km\n", other_road_length / 1000); - printf("residential roads ............... %5.0f km\n", residential_road_length / 1000); - printf(" thereof, with names .......... %5.0f%%\n", residential_road_with_name_length * 100 / residential_road_length); - printf("tracks, service ways, paths ..... %5.0f km\n", path_length / 1000); - printf("rivers .......................... %5.0f km\n", river_length / 1000); - printf("railways ........................ %5.0f km\n", railway_length / 1000); - printf("power lines ..................... %5.0f km\n", powerline_length / 1000); - printf("\n"); - printf("buildings ....................... %5d\n", building_count); - printf("house numbers ................... %5d\n", housenumber_count); - printf("named places .................... %5d\n", place_count); - printf("various POIs .................... %5d\n", poi_count); + std::cout << "motorways and trunk roads km........" << (int) (motorway_trunk_length / 1000) << std::endl; + std::cout << "primary and secondary roads km......" << (int) (primary_secondary_length / 1000) << std::endl; + std::cout << "other connecting roads km..........." << (int) (other_road_length / 1000) << std::endl; + std::cout << "residential roads km................" << (int) (residential_road_length / 1000) << std::endl; + std::cout << "residential roads with names km....." << (int) (residential_road_with_name_length / 1000) << std::endl; + std::cout << "tracks/paths km....................." << (int) (path_length / 1000) << std::endl; + std::cout << "rivers km..........................." << (int) (river_length / 1000) << std::endl; + std::cout << "railways km........................." << (int) (railway_length / 1000) << std::endl; + std::cout << "power lines km......................" << (int) (powerline_length / 1000) << std::endl; + std::cout << "buildings..........................." << building_count << std::endl; + std::cout << "house numbers......................." << housenumber_count << std::endl; + std::cout << "named places........................" << place_count << std::endl; + std::cout << "forest/meadow landcover count......." << landuse_green_count << std::endl; + std::cout << "water area landcover count.........." << landuse_blue_count << std::endl; + std::cout << "residential/industrial zone count..." << landuse_zone_count << std::endl; + std::cout << "agricultural landuse count.........." << landuse_agri_count << std::endl; + std::cout << "POIs power.........................." << poi_power_count << std::endl; + std::cout << "POIs transport......................" << poi_traffic_count << std::endl; + std::cout << "POIs public........................." << poi_public_count << std::endl; + std::cout << "POIs hospitality...................." << poi_hospitality_count << std::endl; + std::cout << "POIs shop/bank......................" << poi_shop_count << std::endl; + std::cout << "POIs religion......................." << poi_religion_count << std::endl; + std::cout << "POIs other.........................." << poi_other_count << std::endl; } + } private: -double waylen(const shared_ptr& way) +double waylen(const osmium::Way& way) { - return Osmium::Geometry::Haversine::distance(way->nodes()); -} -double wayarea(const shared_ptr& area) -{ - /* - double len = 0; - double lastlat = 0; - double lastlon = 0; - bool init = true; - for (Osmium::OSM::WayNodeList::const_iterator i = way->nodes().begin(); i!= way->nodes().end(); i++) - { - double thislon = i->lon(); - double thislat = i->lat(); - if (!init) - { - len += dist(lastlat, lastlon, thislat, thislon); - } - else - { - init = false; - } - lastlat = thislat; - lastlon = thislon; - } - */ - return 0.0; + return osmium::geom::haversine::distance(way.nodes()); } + }; /* ================================================== */ -typedef Osmium::Storage::ById::SparseTable storage_sparsetable_t; -typedef Osmium::Storage::ById::MmapFile storage_mmap_t; +// The type of index used. This must match the include file above +using index_type = osmium::index::map::SparseMemArray; + +// The location handler always depends on the index type +using location_handler_type = osmium::handler::NodeLocationsForWays; int main(int argc, char* argv[]) { @@ -464,29 +376,54 @@ int main(int argc, char* argv[]) exit(1); } - Osmium::OSMFile infile(argv[1]); - - storage_sparsetable_t store_pos; - storage_mmap_t store_neg; - StatisticsHandler stat_handler; - typedef Osmium::MultiPolygon::Assembler assembler_t; - assembler_t assembler(stat_handler, false); - assembler.set_debug_level(1); - - typedef Osmium::Handler::CoordinatesForWays cfw_handler_t; - cfw_handler_t cfw_handler(store_pos, store_neg); - - typedef Osmium::Handler::Sequence sequence_handler_t; - sequence_handler_t sequence_handler(cfw_handler, assembler.handler_pass2()); - - std::cerr << "First pass...\n"; - Osmium::Input::read(infile, assembler.handler_pass1()); - - std::cerr << "Second pass...\n"; - Osmium::Input::read(infile, sequence_handler); - - google::protobuf::ShutdownProtobufLibrary(); + // Initialize an empty DynamicHandler. Later it will be associated + // with one of the handlers. You can think of the DynamicHandler as + // a kind of "variant handler" or a "pointer handler" pointing to the + // real handler. + osmium::handler::DynamicHandler handler; + + osmium::io::File input_file{argv[optind]}; + + // Configuration for the multipolygon assembler. Here the default settings + // are used, but you could change multiple settings. + osmium::area::Assembler::config_type assembler_config; + + // Initialize the MultipolygonCollector. Its job is to collect all + // relations and member ways needed for each area. It then calls an + // instance of the osmium::area::Assembler class (with the given config) + // to actually assemble one area. + osmium::area::MultipolygonCollector collector{assembler_config}; + + // We read the input file twice. In the first pass, only relations are + // read and fed into the multipolygon collector. + osmium::io::Reader reader1{input_file, osmium::osm_entity_bits::relation}; + collector.read_relations(reader1); + reader1.close(); + + // The index storing all node locations. + index_type index; + + // The handler that stores all node locations in the index and adds them + // to the ways. + location_handler_type location_handler{index}; + + // If a location is not available in the index, we ignore it. It might + // not be needed (if it is not part of a multipolygon relation), so why + // create an error? + location_handler.ignore_errors(); + + // On the second pass we read all objects and run them first through the + // node location handler and then the multipolygon collector. The collector + // will put the areas it has created into the "buffer" which are then + // fed through our "handler". + osmium::io::Reader reader2{input_file}; + osmium::apply(reader2, location_handler, stat_handler, collector.handler([&stat_handler](osmium::memory::Buffer&& buffer) { + osmium::apply(buffer, stat_handler); + })); + reader2.close(); + + stat_handler.print(); }