Merge commit '879f7eb04200d7d2c28af565229bf6e3d54274fd' into retry/libosmium

This commit is contained in:
karenzshea
2016-10-03 13:08:59 -04:00
208 changed files with 11590 additions and 4051 deletions
+7 -33
View File
@@ -12,13 +12,17 @@ set(EXAMPLES
area_test
convert
count
create_node_cache
debug
filter_discussions
index
location_cache_create
location_cache_use
pub_names
read
read_with_progress
road_length
serdump
use_node_cache
tiles
CACHE STRING "Example programs"
)
@@ -28,7 +32,7 @@ set(EXAMPLES
# Examples depending on wingetopt
#
#-----------------------------------------------------------------------------
set(GETOPT_EXAMPLES area_test convert serdump)
set(GETOPT_EXAMPLES area_test convert index serdump)
if(NOT GETOPT_MISSING)
foreach(example ${GETOPT_EXAMPLES})
list(APPEND EXAMPLE_LIBS_${example} ${GETOPT_LIBRARY})
@@ -42,36 +46,6 @@ else()
endif()
#-----------------------------------------------------------------------------
#
# Examples depending on SparseHash
#
#-----------------------------------------------------------------------------
if(NOT SPARSEHASH_FOUND)
list(REMOVE_ITEM EXAMPLES area_test)
message(STATUS "Configuring examples - Skipping examples because Google SparseHash not found:")
message(STATUS " - osmium_area_test")
endif()
#-----------------------------------------------------------------------------
#
# Examples depending on Boost Program Options
#
#-----------------------------------------------------------------------------
unset(Boost_LIBRARIES)
unset(Boost_FOUND)
find_package(Boost 1.38 COMPONENTS program_options)
if(Boost_PROGRAM_OPTIONS_FOUND)
list(APPEND EXAMPLE_LIBS_index ${Boost_PROGRAM_OPTIONS_LIBRARY})
else()
list(REMOVE_ITEM EXAMPLES index)
message(STATUS "Configuring examples - Skipping examples because Boost program_options not found:")
message(STATUS " - osmium_index")
endif()
#-----------------------------------------------------------------------------
#
# Configure examples
+32
View File
@@ -0,0 +1,32 @@
# Osmium example programs
The programs in this directory are intended as examples for developers. They
contain extensive comments explaining what's going on. Note that the examples
only cover a small part of what Osmium can do, you should also read the
documentation and API documentation.
All programs can be run without arguments and they will tell you how to run
them.
## Very simple examples
* `osmium_read`
* `osmium_count`
* `osmium_debug`
* `osmium_tiles`
## Still reasonably simple examples
* `osmium_filter_discussions`
* `osmium_convert`
## More advanced examples
* `osmium_area_test`
## License
The code in these example files is released into the Public Domain. Feel free
to copy the code and build on it.
+97 -32
View File
@@ -1,48 +1,81 @@
/*
This is an example tool that creates multipolygons from OSM data
and dumps them to stdout.
EXAMPLE osmium_area_test
Create multipolygons from OSM data and dump them to stdout in one of two
formats: WKT or using the built-in Dump format.
DEMONSTRATES USE OF:
* file input
* location indexes and the NodeLocationsForWays handler
* the MultipolygonCollector and Assembler to assemble areas (multipolygons)
* your own handler that works with areas (multipolygons)
* the WKTFactory to write geometries in WKT format
* the Dump handler
* the DynamicHandler
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
* osmium_count
* osmium_debug
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <getopt.h>
#include <cstdlib> // for std::exit
#include <getopt.h> // for getopt_long
#include <iostream> // for std::cout, std::cerr
// For assembling multipolygons
#include <osmium/area/assembler.hpp>
#include <osmium/area/multipolygon_collector.hpp>
// For the DynamicHandler class
#include <osmium/dynamic_handler.hpp>
// For the WKT factory
#include <osmium/geom/wkt.hpp>
// For the Dump handler
#include <osmium/handler/dump.hpp>
// For the NodeLocationForWays handler
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/sparse_mem_array.hpp>
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// For osmium::apply()
#include <osmium/visitor.hpp>
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
// For the location index. There are different types of indexes available.
// This will work for small and medium sized input files.
#include <osmium/index/map/sparse_mem_array.hpp>
// The type of index used. This must match the include file above
using index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
// The location handler always depends on the index type
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
// This handler writes all area geometries out in WKT (Well Known Text) format.
class WKTDump : public osmium::handler::Handler {
osmium::geom::WKTFactory<> m_factory ;
std::ostream& m_out;
// This factory is used to create a geometry in WKT format from OSM
// objects. The template parameter is empty here, because we output WGS84
// coordinates, but could be used for a projection.
osmium::geom::WKTFactory<> m_factory;
public:
WKTDump(std::ostream& out) :
m_out(out) {
}
// This callback is called by osmium::apply for each area in the data.
void area(const osmium::Area& area) {
try {
m_out << m_factory.create_multipolygon(area) << "\n";
} catch (osmium::geometry_error& e) {
m_out << "GEOMETRY ERROR: " << e.what() << "\n";
std::cout << m_factory.create_multipolygon(area) << "\n";
} catch (const osmium::geometry_error& e) {
std::cout << "GEOMETRY ERROR: " << e.what() << "\n";
}
}
@@ -65,8 +98,13 @@ int main(int argc, char* argv[]) {
{0, 0, 0, 0}
};
// 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;
// Read options from command line.
while (true) {
int c = getopt_long(argc, argv, "hwo", long_options, 0);
if (c == -1) {
@@ -76,54 +114,81 @@ int main(int argc, char* argv[]) {
switch (c) {
case 'h':
print_help();
exit(0);
std::exit(0);
case 'w':
handler.set<WKTDump>(std::cout);
handler.set<WKTDump>();
break;
case 'o':
handler.set<osmium::handler::Dump>(std::cout);
break;
default:
exit(1);
std::exit(1);
}
}
int remaining_args = argc - optind;
if (remaining_args != 1) {
std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE\n";
exit(1);
std::exit(1);
}
osmium::io::File infile(argv[optind]);
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;
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector(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<osmium::area::Assembler> collector{assembler_config};
// We read the input file twice. In the first pass, only relations are
// read and fed into the multipolygon collector.
std::cerr << "Pass 1...\n";
osmium::io::Reader reader1(infile, osmium::osm_entity_bits::relation);
osmium::io::Reader reader1{input_file, osmium::osm_entity_bits::relation};
collector.read_relations(reader1);
reader1.close();
std::cerr << "Pass 1 done\n";
// Output the amount of main memory used so far. All multipolygon relations
// are in memory now.
std::cerr << "Memory:\n";
collector.used_memory();
index_pos_type index_pos;
index_neg_type index_neg;
location_handler_type location_handler(index_pos, index_neg);
location_handler.ignore_errors(); // XXX
// 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".
std::cerr << "Pass 2...\n";
osmium::io::Reader reader2(infile);
osmium::io::Reader reader2{input_file};
osmium::apply(reader2, location_handler, collector.handler([&handler](osmium::memory::Buffer&& buffer) {
osmium::apply(buffer, handler);
}));
reader2.close();
std::cerr << "Pass 2 done\n";
// Output the amount of main memory used so far. All complete multipolygon
// relations have been cleaned up.
std::cerr << "Memory:\n";
collector.used_memory();
// If there were multipolgyon relations in the input, but some of their
// members are not in the input file (which often happens for extracts)
// this will write the IDs of the incomplete relations to stderr.
std::vector<const osmium::Relation*> incomplete_relations = collector.get_incomplete_relations();
if (!incomplete_relations.empty()) {
std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
+68 -24
View File
@@ -1,16 +1,32 @@
/*
EXAMPLE osmium_convert
Convert OSM files from one format into another.
DEMONSTRATES USE OF:
* file input and output
* file types
* Osmium buffers
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <getopt.h>
#include <cstdlib> // for std::exit
#include <exception> // for std::exception
#include <getopt.h> // for getopt_long
#include <iostream> // for std::cout, std::cerr
#include <string> // for std::string
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// Allow any format of output files (XML, PBF, ...)
#include <osmium/io/any_output.hpp>
void print_help() {
@@ -43,9 +59,13 @@ int main(int argc, char* argv[]) {
{0, 0, 0, 0}
};
// Input and output format are empty by default. Later this will mean that
// the format should be taken from the input and output file suffix,
// respectively.
std::string input_format;
std::string output_format;
// Read options from command line.
while (true) {
int c = getopt_long(argc, argv, "dhf:t:", long_options, 0);
if (c == -1) {
@@ -55,7 +75,7 @@ int main(int argc, char* argv[]) {
switch (c) {
case 'h':
print_help();
exit(0);
std::exit(0);
case 'f':
input_format = optarg;
break;
@@ -63,49 +83,73 @@ int main(int argc, char* argv[]) {
output_format = optarg;
break;
default:
exit(1);
std::exit(1);
}
}
std::string input;
std::string output;
int remaining_args = argc - optind;
if (remaining_args > 2) {
std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]" << std::endl;
exit(1);
} else if (remaining_args == 2) {
input = argv[optind];
output = argv[optind+1];
} else if (remaining_args == 1) {
input = argv[optind];
std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n";
std::exit(1);
}
osmium::io::File infile(input, input_format);
// Get input file name from command line.
std::string input_file_name;
if (remaining_args >= 1) {
input_file_name = argv[optind];
}
osmium::io::File outfile(output, output_format);
// Get output file name from command line.
std::string output_file_name;
if (remaining_args == 2) {
output_file_name = argv[optind+1];
}
if (infile.has_multiple_object_versions() && !outfile.has_multiple_object_versions()) {
// This declares the input and output files using either the suffix of
// the file names or the format in the 2nd argument. It does not yet open
// the files.
osmium::io::File input_file{input_file_name, input_format};
osmium::io::File output_file{output_file_name, output_format};
// Input and output files can be OSM data files (without history) or
// OSM history files. History files are detected if they use the '.osh'
// file suffix.
if ( input_file.has_multiple_object_versions() &&
!output_file.has_multiple_object_versions()) {
std::cerr << "Warning! You are converting from an OSM file with (potentially) several versions of the same object to one that is not marked as such.\n";
}
int exit_code = 0;
try {
osmium::io::Reader reader(infile);
// Initialize Reader
osmium::io::Reader reader{input_file};
// Get header from input file and change the "generator" setting to
// outselves.
osmium::io::Header header = reader.header();
header.set("generator", "osmium_convert");
osmium::io::Writer writer(outfile, header, osmium::io::overwrite::allow);
// Initialize Writer using the header from above and tell it that it
// is allowed to overwrite a possibly existing file.
osmium::io::Writer writer(output_file, header, osmium::io::overwrite::allow);
// Copy the contents from the input to the output file one buffer at
// a time. This is much easier and faster than copying each object
// in the file. Buffers are moved around, so there is no cost for
// copying in memory.
while (osmium::memory::Buffer buffer = reader.read()) {
writer(std::move(buffer));
}
// 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();
reader.close();
} catch (std::exception& e) {
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << "\n";
exit_code = 1;
std::exit(1);
}
return exit_code;
}
+54 -15
View File
@@ -1,56 +1,95 @@
/*
This is a small tool that counts the number of nodes, ways, and relations in
the input file.
EXAMPLE osmium_count
Counts the number of nodes, ways, and relations in the input file.
DEMONSTRATES USE OF:
* OSM file input
* your own handler
* the memory usage utility class
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <cstdint>
#include <iostream>
#include <cstdint> // for std::uint64_t
#include <cstdlib> // for std::exit
#include <iostream> // for std::cout, std::cerr
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// We want to use the handler interface
#include <osmium/handler.hpp>
// Utility class gives us access to memory usage information
#include <osmium/util/memory.hpp>
// For osmium::apply()
#include <osmium/visitor.hpp>
// Handler derive from the osmium::handler::Handler base class. Usually you
// overwrite functions node(), way(), and relation(). Other functions are
// available, too. Read the API documentation for details.
struct CountHandler : public osmium::handler::Handler {
uint64_t nodes = 0;
uint64_t ways = 0;
uint64_t relations = 0;
std::uint64_t nodes = 0;
std::uint64_t ways = 0;
std::uint64_t relations = 0;
void node(osmium::Node&) {
// This callback is called by osmium::apply for each node in the data.
void node(const osmium::Node&) noexcept {
++nodes;
}
void way(osmium::Way&) {
// This callback is called by osmium::apply for each way in the data.
void way(const osmium::Way&) noexcept {
++ways;
}
void relation(osmium::Relation&) {
// This callback is called by osmium::apply for each relation in the data.
void relation(const osmium::Relation&) noexcept {
++relations;
}
};
}; // struct CountHandler
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
exit(1);
std::exit(1);
}
osmium::io::File infile(argv[1]);
osmium::io::Reader reader(infile);
// The Reader is initialized here with an osmium::io::File, but could
// also be directly initialized with a file name.
osmium::io::File input_file{argv[1]};
osmium::io::Reader reader{input_file};
// Create an instance of our own CountHandler and push the data from the
// input file through it.
CountHandler handler;
osmium::apply(reader, handler);
// You do not have to close the Reader explicitly, but because the
// destructor can't throw, you will not see any errors otherwise.
reader.close();
std::cout << "Nodes: " << handler.nodes << "\n";
std::cout << "Ways: " << handler.ways << "\n";
std::cout << "Relations: " << handler.relations << "\n";
// Because of the huge amount of OSM data, some Osmium-based programs
// (though not this one) can use huge amounts of data. So checking actual
// memore usage is often useful and can be done easily with this class.
// (Currently only works on Linux, not OSX and Windows.)
osmium::MemoryUsage memory;
std::cout << "\nMemory used: " << memory.peak() << " MBytes\n";
}
@@ -1,55 +0,0 @@
/*
This reads an OSM file and writes out the node locations to a cache
file.
The code in this example file is released into the Public Domain.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <osmium/io/any_input.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/dense_mmap_array.hpp>
#include <osmium/index/map/dense_file_array.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/visitor.hpp>
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
return 1;
}
std::string input_filename(argv[1]);
osmium::io::Reader reader(input_filename, osmium::osm_entity_bits::node);
int fd = open(argv[2], O_RDWR | O_CREAT, 0666);
if (fd == -1) {
std::cerr << "Can not open node cache file '" << argv[2] << "': " << strerror(errno) << "\n";
return 1;
}
index_pos_type index_pos {fd};
index_neg_type index_neg;
location_handler_type location_handler(index_pos, index_neg);
location_handler.ignore_errors();
osmium::apply(reader, location_handler);
reader.close();
return 0;
}
+36 -10
View File
@@ -1,27 +1,46 @@
/*
This is a small tool to dump the contents of the input file.
EXAMPLE osmium_debug
Dump the contents of the input file in a debug format.
DEMONSTRATES USE OF:
* file input reading only some types
* the dump handler
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
* osmium_count
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <cstdlib> // for std::exit
#include <iostream> // for std::cout, std::cerr
#include <string> // for std::string
// The Dump handler
#include <osmium/handler/dump.hpp>
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
int main(int argc, char* argv[]) {
// Speed up output (not Osmium-specific)
std::ios_base::sync_with_stdio(false);
if (argc < 2 || argc > 3) {
std::cerr << "Usage: " << argv[0] << " OSMFILE [TYPES]\n";
std::cerr << "TYPES can be any combination of 'n', 'w', 'r', and 'c' to indicate what types of OSM entities you want (default: all).\n";
exit(1);
std::exit(1);
}
// Default is all entity types: nodes, ways, relations, and changesets
osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all;
// Get entity types from command line if there is a 2nd argument.
if (argc == 3) {
read_types = osmium::osm_entity_bits::nothing;
std::string types = argv[2];
@@ -31,20 +50,27 @@ int main(int argc, char* argv[]) {
if (types.find('c') != std::string::npos) read_types |= osmium::osm_entity_bits::changeset;
}
osmium::io::Reader reader(argv[1], read_types);
osmium::io::Header header = reader.header();
// Initialize Reader with file name and the types of entities we want to
// read.
osmium::io::Reader reader{argv[1], read_types};
// The file header can contain metadata such as the program that generated
// the file and the bounding box of the data.
osmium::io::Header header = reader.header();
std::cout << "HEADER:\n generator=" << header.get("generator") << "\n";
for (auto& bbox : header.boxes()) {
for (const auto& bbox : header.boxes()) {
std::cout << " bbox=" << bbox << "\n";
}
osmium::handler::Dump dump(std::cout);
while (osmium::memory::Buffer buffer = reader.read()) {
osmium::apply(buffer, dump);
}
// Initialize Dump handler.
osmium::handler::Dump dump{std::cout};
// Read from input and send everything to Dump handler.
osmium::apply(reader, dump);
// You do not have to close the Reader explicitly, but because the
// destructor can't throw, you will not see any errors otherwise.
reader.close();
}
+34 -14
View File
@@ -1,53 +1,73 @@
/*
EXAMPLE osmium_filter_discussions
Read OSM changesets with discussions from a changeset dump like the one
you get from http://planet.osm.org/planet/discussions-latest.osm.bz2
and write out only those changesets which have discussions (ie comments).
DEMONSTRATES USE OF:
* file input and output
* setting file formats using the osmium::io::File class
* OSM file headers
* input and output iterators
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
* osmium_count
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <algorithm> // for std::copy_if
#include <iostream> // for std::cout, std::cerr
#include <cstdlib> // for std::exit
#include <iostream> // for std::cout, std::cerr
// we want to read OSM files in XML format
// (other formats don't support full changesets, so only XML is needed here)
// We want to read OSM files in XML format
// (other formats don't support full changesets, so only XML is needed here).
#include <osmium/io/xml_input.hpp>
#include <osmium/io/input_iterator.hpp>
// we want to write OSM files in XML format
// We want to write OSM files in XML format.
#include <osmium/io/xml_output.hpp>
// We want to use input and output iterators for easy integration with the
// algorithms of the standard library.
#include <osmium/io/input_iterator.hpp>
#include <osmium/io/output_iterator.hpp>
// we want to support any compressioon (.gz2 and .bz2)
// We want to support any compression (none, gzip, and bzip2).
#include <osmium/io/any_compression.hpp>
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cout << "Usage: " << argv[0] << " INFILE OUTFILE\n";
exit(1);
std::exit(1);
}
// The input file, deduce file format from file suffix
osmium::io::File infile(argv[1]);
// The input file, deduce file format from file suffix.
osmium::io::File input_file{argv[1]};
// The output file, force class XML OSM file format
osmium::io::File outfile(argv[2], "osm");
// The output file, force XML OSM file format.
osmium::io::File output_file{argv[2], "osm"};
// Initialize Reader for the input file.
// Read only changesets (will ignore nodes, ways, and
// relations if there are any).
osmium::io::Reader reader(infile, osmium::osm_entity_bits::changeset);
osmium::io::Reader reader{input_file, osmium::osm_entity_bits::changeset};
// Get the header from the input file
// Get the header from the input file.
osmium::io::Header header = reader.header();
// Set the "generator" on the header to ourselves.
header.set("generator", "osmium_filter_discussions");
// 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);
osmium::io::Writer writer(output_file, header, osmium::io::overwrite::allow);
// Create range of input iterators that will iterator over all changesets
// delivered from input file through the "reader".
+85 -62
View File
@@ -12,7 +12,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <boost/program_options.hpp>
#include <getopt.h>
#include <osmium/index/map/dense_file_array.hpp>
#include <osmium/index/map/sparse_file_array.hpp>
@@ -31,7 +31,7 @@ class IndexSearch {
void dump_dense() {
dense_index_type index(m_fd);
for (size_t i = 0; i < index.size(); ++i) {
for (std::size_t i = 0; i < index.size(); ++i) {
if (index.get(i) != TValue()) {
std::cout << i << " " << index.get(i) << "\n";
}
@@ -51,9 +51,9 @@ class IndexSearch {
try {
TValue value = index.get(key);
std::cout << key << " " << value << std::endl;
std::cout << key << " " << value << "\n";
} catch (...) {
std::cout << key << " not found" << std::endl;
std::cout << key << " not found\n";
return false;
}
@@ -69,7 +69,7 @@ class IndexSearch {
return lhs.first < rhs.first;
});
if (positions.first == positions.second) {
std::cout << key << " not found" << std::endl;
std::cout << key << " not found\n";
return false;
}
@@ -103,7 +103,7 @@ public:
}
}
bool search(std::vector<TKey> keys) {
bool search(const std::vector<TKey>& keys) {
bool found_all = true;
for (const auto key : keys) {
@@ -124,82 +124,105 @@ enum return_code : int {
fatal = 3
};
namespace po = boost::program_options;
class Options {
po::variables_map vm;
std::vector<osmium::unsigned_object_id_type> m_ids;
std::string m_type;
std::string m_filename;
bool m_dump = false;
bool m_array_format = false;
bool m_list_format = false;
void print_help() {
std::cout << "Usage: osmium_index [OPTIONS]\n\n"
<< "-h, --help Print this help message\n"
<< "-a, --array=FILE Read given index file in array format\n"
<< "-l, --list=FILE Read given index file in list format\n"
<< "-d, --dump Dump contents of index file to STDOUT\n"
<< "-s, --search=ID Search for given id (Option can appear multiple times)\n"
<< "-t, --type=TYPE Type of value ('location' or 'offset')\n"
;
}
public:
Options(int argc, char* argv[]) {
try {
po::options_description desc("Allowed options");
desc.add_options()
("help,h", "Print this help message")
("array,a", po::value<std::string>(), "Read given index file in array format")
("list,l", po::value<std::string>(), "Read given index file in list format")
("dump,d", "Dump contents of index file to STDOUT")
("search,s", po::value<std::vector<osmium::unsigned_object_id_type>>(), "Search for given id (Option can appear multiple times)")
("type,t", po::value<std::string>(), "Type of value ('location' or 'offset')")
;
static struct option long_options[] = {
{"array", required_argument, 0, 'a'},
{"dump", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"list", required_argument, 0, 'l'},
{"search", required_argument, 0, 's'},
{"type", required_argument, 0, 't'},
{0, 0, 0, 0}
};
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << "\n";
exit(return_code::okay);
while (true) {
int c = getopt_long(argc, argv, "a:dhl:s:t:", long_options, 0);
if (c == -1) {
break;
}
if (vm.count("array") && vm.count("list")) {
std::cerr << "Only option --array or --list allowed." << std::endl;
exit(return_code::fatal);
switch (c) {
case 'a':
m_array_format = true;
m_filename = optarg;
break;
case 'd':
m_dump = true;
break;
case 'h':
print_help();
std::exit(return_code::okay);
case 'l':
m_list_format = true;
m_filename = optarg;
break;
case 's':
m_ids.push_back(std::atoll(optarg));
break;
case 't':
m_type = optarg;
if (m_type != "location" && m_type != "offset") {
std::cerr << "Unknown type '" << m_type << "'. Must be 'location' or 'offset'.\n";
std::exit(return_code::fatal);
}
break;
default:
std::exit(return_code::fatal);
}
if (!vm.count("array") && !vm.count("list")) {
std::cerr << "Need one of option --array or --list." << std::endl;
exit(return_code::fatal);
}
if (!vm.count("type")) {
std::cerr << "Need --type argument." << std::endl;
exit(return_code::fatal);
}
const std::string& type = vm["type"].as<std::string>();
if (type != "location" && type != "offset") {
std::cerr << "Unknown type '" << type << "'. Must be 'location' or 'offset'." << std::endl;
exit(return_code::fatal);
}
} catch (boost::program_options::error& e) {
std::cerr << "Error parsing command line: " << e.what() << std::endl;
exit(return_code::fatal);
}
}
const std::string& filename() const {
if (vm.count("array")) {
return vm["array"].as<std::string>();
} else {
return vm["list"].as<std::string>();
if (m_array_format == m_list_format) {
std::cerr << "Need option --array or --list, but not both\n";
std::exit(return_code::fatal);
}
if (m_type.empty()) {
std::cerr << "Need --type argument.\n";
std::exit(return_code::fatal);
}
}
bool dense_format() const {
return vm.count("array") != 0;
const std::string& filename() const noexcept {
return m_filename;
}
bool do_dump() const {
return vm.count("dump") != 0;
bool dense_format() const noexcept {
return m_array_format;
}
std::vector<osmium::unsigned_object_id_type> search_keys() const {
return vm["search"].as<std::vector<osmium::unsigned_object_id_type>>();
bool do_dump() const noexcept {
return m_dump;
}
bool type_is(const char* type) const {
return vm["type"].as<std::string>() == type;
const std::vector<osmium::unsigned_object_id_type>& search_keys() const noexcept {
return m_ids;
}
bool type_is(const char* type) const noexcept {
return m_type == type;
}
}; // class Options
@@ -232,6 +255,6 @@ int main(int argc, char* argv[]) {
}
}
exit(result_okay ? return_code::okay : return_code::not_found);
std::exit(result_okay ? return_code::okay : return_code::not_found);
}
@@ -0,0 +1,87 @@
/*
EXAMPLE osmium_location_cache_create
Reads nodes from an OSM file and writes out their locations to a cache
file. The cache file can then be read with osmium_location_cache_use.
Warning: The locations cache file will get huge (>32GB) if you are using
the DenseFileArray index even if the input file is small, because
it depends on the *largest* node ID, not the number of nodes.
DEMONSTRATES USE OF:
* file input
* location indexes and the NodeLocationsForWays handler
* location indexes on disk
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
* osmium_count
* osmium_road_length
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <cerrno> // for errno
#include <cstdlib> // for std::exit
#include <cstring> // for strerror
#include <fcntl.h> // for open
#include <iostream> // for std::cout, std::cerr
#include <string> // for std::string
#include <sys/stat.h> // for open
#include <sys/types.h> // for open
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// For the location index. There are different types of index implementation
// available. These implementations put the index on disk. See below.
#include <osmium/index/map/sparse_file_array.hpp>
#include <osmium/index/map/dense_file_array.hpp>
// For the NodeLocationForWays handler
#include <osmium/handler/node_locations_for_ways.hpp>
// For osmium::apply()
#include <osmium/visitor.hpp>
// Chose one of these two. "sparse" is best used for small and medium extracts,
// the "dense" index for large extracts or the whole planet.
using index_type = osmium::index::map::SparseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
//using index_type = osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
// The location handler always depends on the index type
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
std::exit(1);
}
const std::string input_filename{argv[1]};
const std::string cache_filename{argv[2]};
// Construct Reader reading only nodes
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::node};
// Initialize location index on disk creating a new file.
const int fd = open(cache_filename.c_str(), O_RDWR | O_CREAT, 0666);
if (fd == -1) {
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n";
std::exit(1);
}
index_type index{fd};
// The handler that stores all node locations in the index.
location_handler_type location_handler{index};
// Feed all nodes through the location handler.
osmium::apply(reader, location_handler);
// Explicitly close input so we get notified of any errors.
reader.close();
}
@@ -0,0 +1,101 @@
/*
EXAMPLE osmium_location_cache_use
This reads ways from an OSM file and writes out the way node locations
it got from a location cache generated with osmium_location_cache_create.
Warning: The locations cache file will get huge (>32GB) if you are using
the DenseFileArray index even if the input file is small, because
it depends on the *largest* node ID, not the number of nodes.
DEMONSTRATES USE OF:
* file input
* location indexes and the NodeLocationsForWays handler
* location indexes on disk
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
* osmium_count
* osmium_road_length
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <cerrno> // for errno
#include <cstdlib> // for std::exit
#include <cstring> // for strerror
#include <fcntl.h> // for open
#include <iostream> // for std::cout, std::cerr
#include <string> // for std::string
#include <sys/stat.h> // for open
#include <sys/types.h> // for open
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// For the location index. There are different types of index implementation
// available. These implementations put the index on disk. See below.
#include <osmium/index/map/dense_file_array.hpp>
#include <osmium/index/map/sparse_file_array.hpp>
// For the NodeLocationForWays handler
#include <osmium/handler/node_locations_for_ways.hpp>
// For osmium::apply()
#include <osmium/visitor.hpp>
// Chose one of these two. "sparse" is best used for small and medium extracts,
// the "dense" index for large extracts or the whole planet.
using index_type = osmium::index::map::SparseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
//using index_type = osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
// The location handler always depends on the index type
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
// This handler only implements the way() function which prints out the way
// ID and all nodes IDs and locations in those ways.
struct MyHandler : public osmium::handler::Handler {
void way(const osmium::Way& way) {
std::cout << "way " << way.id() << "\n";
for (const auto& nr : way.nodes()) {
std::cout << " node " << nr.ref() << " " << nr.location() << "\n";
}
}
}; // struct MyHandler
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
std::exit(1);
}
const std::string input_filename{argv[1]};
const std::string cache_filename{argv[2]};
// Construct Reader reading only ways
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::way};
// Initialize location index on disk using an existing file
const int fd = open(cache_filename.c_str(), O_RDWR);
if (fd == -1) {
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n";
return 1;
}
index_type index{fd};
// The handler that adds node locations from the index to the ways.
location_handler_type location_handler{index};
// Feed all ways through the location handler and then our own handler.
MyHandler handler;
osmium::apply(reader, location_handler, handler);
// Explicitly close input so we get notified of any errors.
reader.close();
}
+89
View File
@@ -0,0 +1,89 @@
/*
EXAMPLE osmium_pub_names
Show the names and addresses of all pubs found in an OSM file.
DEMONSTRATES USE OF:
* file input
* your own handler
* access to tags
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
* osmium_count
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <cstdlib> // for std::exit
#include <cstring> // for std::strncmp
#include <iostream> // for std::cout, std::cerr
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// We want to use the handler interface
#include <osmium/handler.hpp>
// For osmium::apply()
#include <osmium/visitor.hpp>
class NamesHandler : public osmium::handler::Handler {
void output_pubs(const osmium::OSMObject& object) {
const osmium::TagList& tags = object.tags();
if (tags.has_tag("amenity", "pub")) {
// Print name of the pub if it is set.
const char* name = tags["name"];
if (name) {
std::cout << name << "\n";
} else {
std::cout << "pub with unknown name\n";
}
// Iterate over all tags finding those which start with "addr:"
// and print them.
for (const osmium::Tag& tag : tags) {
if (!std::strncmp(tag.key(), "addr:", 5)) {
std::cout << " " << tag.key() << ": " << tag.value() << "\n";
}
}
}
}
public:
// Nodes can be tagged amenity=pub.
void node(const osmium::Node& node) {
output_pubs(node);
}
// Ways can be tagged amenity=pub, too (typically buildings).
void way(const osmium::Way& way) {
output_pubs(way);
}
}; // class NamesHandler
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
std::exit(1);
}
// Construct the handler defined above
NamesHandler names_handler;
// Initialize the reader with the filename from the command line and
// tell it to only read nodes and ways. We are ignoring multipolygon
// relations in this simple example.
osmium::io::Reader reader{argv[1], osmium::osm_entity_bits::node | osmium::osm_entity_bits::way};
// Apply input data to our own handler
osmium::apply(reader, names_handler);
}
+19 -7
View File
@@ -1,30 +1,42 @@
/*
This is a small tool that reads and discards the contents of the input file.
(Used for timing.)
EXAMPLE osmium_read
Reads and discards the contents of the input file.
(It can be used for timing.)
DEMONSTRATES USE OF:
* file input
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <cstdlib> // for std::exit
#include <iostream> // for std::cerr
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
exit(1);
std::exit(1);
}
osmium::io::File infile(argv[1]);
osmium::io::Reader reader(infile);
// The Reader is initialized here with an osmium::io::File, but could
// also be directly initialized with a file name.
osmium::io::File input_file{argv[1]};
osmium::io::Reader reader{input_file};
// OSM data comes in buffers, read until there are no more.
while (osmium::memory::Buffer buffer = reader.read()) {
// do nothing
}
// You do not have to close the Reader explicitly, but because the
// destructor can't throw, you will not see any errors otherwise.
reader.close();
}
@@ -0,0 +1,56 @@
/*
EXAMPLE osmium_read_with_progress
Reads the contents of the input file showing a progress bar.
DEMONSTRATES USE OF:
* file input
* ProgressBar utility function
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <cstdlib> // for std::exit
#include <iostream> // for std::cerr
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// Get access to isatty utility function and progress bar utility class.
#include <osmium/util/file.hpp>
#include <osmium/util/progress_bar.hpp>
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
std::exit(1);
}
// The Reader is initialized here with an osmium::io::File, but could
// also be directly initialized with a file name.
osmium::io::File input_file{argv[1]};
osmium::io::Reader reader{input_file};
// Initialize progress bar, enable it only if STDERR is a TTY.
osmium::ProgressBar progress{reader.file_size(), osmium::util::isatty(2)};
// OSM data comes in buffers, read until there are no more.
while (osmium::memory::Buffer buffer = reader.read()) {
// Update progress bar for each buffer.
progress.update(reader.offset());
}
// Progress bar is done.
progress.done();
// You do not have to close the Reader explicitly, but because the
// destructor can't throw, you will not see any errors otherwise.
reader.close();
}
+92
View File
@@ -0,0 +1,92 @@
/*
EXAMPLE osmium_road_length
Calculate the length of the road network (everything tagged `highway=*`)
from the given OSM file.
DEMONSTRATES USE OF:
* file input
* location indexes and the NodeLocationsForWays handler
* length calculation on the earth using the haversine function
SIMPLER EXAMPLES you might want to understand first:
* osmium_read
* osmium_count
* osmium_pub_names
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <cstdlib> // for std::exit
#include <iostream> // for std::cout, std::cerr
// Allow any format of input files (XML, PBF, ...)
#include <osmium/io/any_input.hpp>
// For the osmium::geom::haversine::distance() function
#include <osmium/geom/haversine.hpp>
// For osmium::apply()
#include <osmium/visitor.hpp>
// For the location index. There are different types of indexes available.
// This will work for small and medium sized input files.
#include <osmium/index/map/sparse_mem_array.hpp>
// For the NodeLocationForWays handler
#include <osmium/handler/node_locations_for_ways.hpp>
// The type of index used. This must match the include file above
using index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
// The location handler always depends on the index type
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
// This handler only implements the way() function, we are not interested in
// any other objects.
struct RoadLengthHandler : public osmium::handler::Handler {
double length = 0;
// If the way has a "highway" tag, find its length and add it to the
// overall length.
void way(const osmium::Way& way) {
const char* highway = way.tags()["highway"];
if (highway) {
length += osmium::geom::haversine::distance(way.nodes());
}
}
}; // struct RoadLengthHandler
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
std::exit(1);
}
// Initialize the reader with the filename from the command line and
// tell it to only read nodes and ways.
osmium::io::Reader reader{argv[1], osmium::osm_entity_bits::node | osmium::osm_entity_bits::way};
// The index to hold node locations.
index_type index;
// The location handler will add the node locations to the index and then
// to the ways
location_handler_type location_handler{index};
// Our handler defined above
RoadLengthHandler road_length_handler;
// Apply input data to first the location handler and then our own handler
osmium::apply(reader, location_handler, road_length_handler);
// Output the length. The haversine function calculates it in meters,
// so we first devide by 1000 to get kilometers.
std::cout << "Length: " << road_length_handler.length / 1000 << " km\n";
}
+12 -12
View File
@@ -69,9 +69,9 @@ int main(int argc, char* argv[]) {
switch (c) {
case 'h':
print_help();
exit(0);
std::exit(0);
default:
exit(2);
std::exit(2);
}
}
@@ -79,7 +79,7 @@ int main(int argc, char* argv[]) {
if (remaining_args != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE DIR\n";
exit(2);
std::exit(2);
}
std::string dir(argv[optind+1]);
@@ -90,14 +90,14 @@ int main(int argc, char* argv[]) {
#endif
if (result == -1 && errno != EEXIST) {
std::cerr << "Problem creating directory '" << dir << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
std::string data_file(dir + "/data.osm.ser");
int data_fd = ::open(data_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (data_fd < 0) {
std::cerr << "Can't open data file '" << data_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
offset_index_type node_index;
@@ -127,7 +127,7 @@ int main(int argc, char* argv[]) {
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
std::cerr << "Can't open nodes index file '" << index_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
node_index.dump_as_list(fd);
close(fd);
@@ -138,7 +138,7 @@ int main(int argc, char* argv[]) {
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
std::cerr << "Can't open ways index file '" << index_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
way_index.dump_as_list(fd);
close(fd);
@@ -149,7 +149,7 @@ int main(int argc, char* argv[]) {
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
std::cerr << "Can't open relations index file '" << index_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
relation_index.dump_as_list(fd);
close(fd);
@@ -161,7 +161,7 @@ int main(int argc, char* argv[]) {
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
std::cerr << "Can't open node->way map file '" << index_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
map_node2way.dump_as_list(fd);
close(fd);
@@ -173,7 +173,7 @@ int main(int argc, char* argv[]) {
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
std::cerr << "Can't open node->rel map file '" << index_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
map_node2relation.dump_as_list(fd);
close(fd);
@@ -185,7 +185,7 @@ int main(int argc, char* argv[]) {
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
std::cerr << "Can't open way->rel map file '" << index_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
map_way2relation.dump_as_list(fd);
close(fd);
@@ -197,7 +197,7 @@ int main(int argc, char* argv[]) {
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
std::cerr << "Can't open rel->rel map file '" << index_file << "': " << strerror(errno) << "\n";
exit(2);
std::exit(2);
}
map_relation2relation.dump_as_list(fd);
close(fd);
+72
View File
@@ -0,0 +1,72 @@
/*
EXAMPLE osmium_tiles
Convert WGS84 longitude and latitude to Mercator coordinates and tile
coordinates.
DEMONSTRATES USE OF:
* the Location and Coordinates classes
* the Mercator projection function
* the Tile class
LICENSE
The code in this example file is released into the Public Domain.
*/
#include <cstdlib> // for std::exit, std::atoi, std::atof
#include <iostream> // for std::cout, std::cerr
// The Location contains a longitude and latitude and is usually used inside
// a node to store its location in the world.
#include <osmium/osm/location.hpp>
// Needed for the Mercator projection function. Osmium supports the Mercator
// projection out of the box, or pretty much any projection using the Proj.4
// library (with the osmium::geom::Projection class).
#include <osmium/geom/mercator_projection.hpp>
// The Tile class handles tile coordinates and zoom levels.
#include <osmium/geom/tile.hpp>
int main(int argc, char* argv[]) {
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " ZOOM LON LAT\n";
std::exit(1);
}
const int zoom = std::atoi(argv[1]);
if (zoom < 0 || zoom > 30) {
std::cerr << "ERROR: Zoom must be between 0 and 30\n";
std::exit(1);
}
const double lon = std::atof(argv[2]);
const double lat = std::atof(argv[3]);
// Create location from WGS84 coordinates. In Osmium the order of
// coordinate values is always x/longitude first, then y/latitude.
const osmium::Location location{lon, lat};
std::cout << "WGS84: lon=" << lon << " lat=" << lat << "\n";
// A location can store some invalid locations, ie locations outside the
// -180 to 180 and -90 to 90 degree range. This function checks for that.
if (!location.valid()) {
std::cerr << "ERROR: Location is invalid\n";
std::exit(1);
}
// Project the coordinates using a helper function. You can also use the
// osmium::geom::MercatorProjection class.
const osmium::geom::Coordinates c = osmium::geom::lonlat_to_mercator(location);
std::cout << "Mercator: x=" << c.x << " y=" << c.y << "\n";
// Create a tile at this location. This will also internally use the
// Mercator projection and then calculate the tile coordinates.
const osmium::geom::Tile tile{uint32_t(zoom), location};
std::cout << "Tile: zoom=" << tile.z << " x=" << tile.x << " y=" << tile.y << "\n";
}
@@ -1,68 +0,0 @@
/*
This reads ways from an OSM file and writes out the node locations
it got from a node cache generated with osmium_create_node_cache.
The code in this example file is released into the Public Domain.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <osmium/io/any_input.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/dense_file_array.hpp>
#include <osmium/index/map/dense_mmap_array.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/visitor.hpp>
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
class MyHandler : public osmium::handler::Handler {
public:
void way(osmium::Way& way) {
for (auto& nr : way.nodes()) {
std::cout << nr << "\n";
}
}
}; // class MyHandler
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
return 1;
}
std::string input_filename(argv[1]);
osmium::io::Reader reader(input_filename, osmium::osm_entity_bits::way);
int fd = open(argv[2], O_RDWR);
if (fd == -1) {
std::cerr << "Can not open node cache file '" << argv[2] << "': " << strerror(errno) << "\n";
return 1;
}
index_pos_type index_pos {fd};
index_neg_type index_neg;
location_handler_type location_handler(index_pos, index_neg);
location_handler.ignore_errors();
MyHandler handler;
osmium::apply(reader, location_handler, handler);
reader.close();
return 0;
}