Merge commit '73efcc6b0ccedf8c1b6d95abdba8340cc9adf100' as 'third_party/libosmium'

This commit is contained in:
Dennis Luxen
2015-01-13 16:54:25 +01:00
235 changed files with 53733 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
message(STATUS "Configuring examples...")
if(GETOPT_MISSING)
message(FATAL_ERROR "On Visual Studio the wingetopt library is needed to compile examples")
endif()
set(SIMPLE_EXAMPLES
osmium_convert
osmium_count
osmium_create_node_cache
osmium_debug
osmium_read
osmium_serdump
osmium_use_node_cache
)
if(SPARSEHASH_FOUND)
list(APPEND SIMPLE_EXAMPLES osmium_area_test)
else()
message("Skipped osmium_area_test example - needed Google SparseHash")
endif()
# In 'Dev' mode: compile with very strict warnings and turn them into errors.
if(CMAKE_BUILD_TYPE STREQUAL "Dev")
add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS})
endif()
foreach(example ${SIMPLE_EXAMPLES})
message(STATUS "Configuring example ${example}...")
add_executable(${example} "${example}.cpp")
target_link_libraries(${example} ${OSMIUM_LIBRARIES})
endforeach(example)
unset(Boost_LIBRARIES)
unset(Boost_FOUND)
find_package(Boost 1.38 COMPONENTS program_options)
if(Boost_PROGRAM_OPTIONS_FOUND)
set(example
osmium_index
)
message(STATUS "Configuring example ${example}...")
add_executable(${example} "${example}.cpp")
target_link_libraries(${example} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${OSMIUM_LIBRARIES})
else()
message("Can not build osmium_index example without Boost program_options")
endif()
set(OGR_EXAMPLES
osmium_toogr
osmium_toogr2
osmium_toogr2_exp
)
if(GDAL_FOUND AND GEOS_FOUND AND SPARSEHASH_FOUND)
foreach(example ${OGR_EXAMPLES})
message(STATUS "Configuring example ${example}...")
add_executable(${example} "${example}.cpp")
target_link_libraries(${example} ${OSMIUM_LIBRARIES})
endforeach(example)
else()
message("GDAL+GEOS+SparseHash not found, skipping OGR examples")
endif()
+138
View File
@@ -0,0 +1,138 @@
/*
This is an example tool that creates multipolygons from OSM data
and dumps them to stdout.
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <getopt.h>
#include <osmium/area/assembler.hpp>
#include <osmium/area/multipolygon_collector.hpp>
#include <osmium/dynamic_handler.hpp>
#include <osmium/geom/wkt.hpp>
#include <osmium/handler/dump.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/sparse_table.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/visitor.hpp>
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
typedef osmium::index::map::SparseTable<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
class WKTDump : public osmium::handler::Handler {
osmium::geom::WKTFactory<> m_factory ;
std::ostream& m_out;
public:
WKTDump(std::ostream& out) :
m_out(out) {
}
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";
}
}
}; // class WKTDump
void print_help() {
std::cout << "osmium_area_test [OPTIONS] OSMFILE\n\n"
<< "Read OSMFILE and build multipolygons from it.\n"
<< "\nOptions:\n"
<< " -h, --help This help message\n"
<< " -w, --dump-wkt Dump area geometries as WKT\n"
<< " -o, --dump-objects Dump area objects\n";
}
int main(int argc, char* argv[]) {
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"dump-wkt", no_argument, 0, 'w'},
{"dump-objects", no_argument, 0, 'o'},
{0, 0, 0, 0}
};
osmium::handler::DynamicHandler handler;
while (true) {
int c = getopt_long(argc, argv, "hwo", long_options, 0);
if (c == -1) {
break;
}
switch (c) {
case 'h':
print_help();
exit(0);
case 'w':
handler.set<WKTDump>(std::cout);
break;
case 'o':
handler.set<osmium::handler::Dump>(std::cout);
break;
default:
exit(1);
}
}
int remaining_args = argc - optind;
if (remaining_args != 1) {
std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE\n";
exit(1);
}
osmium::io::File infile(argv[optind]);
osmium::area::Assembler::config_type assembler_config;
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector(assembler_config);
std::cout << "Pass 1...\n";
osmium::io::Reader reader1(infile, osmium::osm_entity_bits::relation);
collector.read_relations(reader1);
reader1.close();
std::cout << "Pass 1 done\n";
std::cout << "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
std::cout << "Pass 2...\n";
osmium::io::Reader reader2(infile);
osmium::apply(reader2, location_handler, collector.handler([&handler](osmium::memory::Buffer&& buffer) {
osmium::apply(buffer, handler);
}));
reader2.close();
std::cout << "Pass 2 done\n";
std::cout << "Memory:\n";
collector.used_memory();
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:";
for (const auto* relation : incomplete_relations) {
std::cerr << " " << relation->id();
}
std::cerr << "\n";
}
google::protobuf::ShutdownProtobufLibrary();
}
+112
View File
@@ -0,0 +1,112 @@
/*
Convert OSM files from one format into another.
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <getopt.h>
#include <osmium/io/any_input.hpp>
#include <osmium/io/any_output.hpp>
void print_help() {
std::cout << "osmium_convert [OPTIONS] [INFILE [OUTFILE]]\n\n" \
<< "If INFILE or OUTFILE is not given stdin/stdout is assumed.\n" \
<< "File format is autodetected from file name suffix.\n" \
<< "Use -f and -t options to force file format.\n" \
<< "\nFile types:\n" \
<< " osm normal OSM file\n" \
<< " osc OSM change file\n" \
<< " osh OSM file with history information\n" \
<< "\nFile format:\n" \
<< " (default) XML encoding\n" \
<< " pbf binary PBF encoding\n" \
<< " opl OPL encoding\n" \
<< "\nFile compression\n" \
<< " gz compressed with gzip\n" \
<< " bz2 compressed with bzip2\n" \
<< "\nOptions:\n" \
<< " -h, --help This help message\n" \
<< " -f, --from-format=FORMAT Input format\n" \
<< " -t, --to-format=FORMAT Output format\n";
}
int main(int argc, char* argv[]) {
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"from-format", required_argument, 0, 'f'},
{"to-format", required_argument, 0, 't'},
{0, 0, 0, 0}
};
std::string input_format;
std::string output_format;
while (true) {
int c = getopt_long(argc, argv, "dhf:t:", long_options, 0);
if (c == -1) {
break;
}
switch (c) {
case 'h':
print_help();
exit(0);
case 'f':
input_format = optarg;
break;
case 't':
output_format = optarg;
break;
default:
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];
}
osmium::io::File infile(input, input_format);
osmium::io::File outfile(output, output_format);
if (infile.has_multiple_object_versions() && !outfile.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);
osmium::io::Header header = reader.header();
header.set("generator", "osmium_convert");
osmium::io::Writer writer(outfile, header, osmium::io::overwrite::allow);
while (osmium::memory::Buffer buffer = reader.read()) {
writer(std::move(buffer));
}
writer.close();
reader.close();
} catch (std::exception& e) {
std::cerr << e.what() << "\n";
exit_code = 1;
}
google::protobuf::ShutdownProtobufLibrary();
return exit_code;
}
+57
View File
@@ -0,0 +1,57 @@
/*
This is a small tool that counts the number of nodes, ways, and relations in
the input file.
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <osmium/io/any_input.hpp>
#include <osmium/handler.hpp>
#include <osmium/visitor.hpp>
struct CountHandler : public osmium::handler::Handler {
int nodes = 0;
int ways = 0;
int relations = 0;
void node(osmium::Node&) {
++nodes;
}
void way(osmium::Way&) {
++ways;
}
void relation(osmium::Relation&) {
++relations;
}
};
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
exit(1);
}
osmium::io::File infile(argv[1]);
osmium::io::Reader reader(infile);
CountHandler handler;
osmium::apply(reader, handler);
reader.close();
std::cout << "Nodes: " << handler.nodes << "\n";
std::cout << "Ways: " << handler.ways << "\n";
std::cout << "Relations: " << handler.relations << "\n";
google::protobuf::ShutdownProtobufLibrary();
}
@@ -0,0 +1,58 @@
/*
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/pbf_input.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/mmap_vector_anon.hpp>
#include <osmium/index/map/mmap_vector_file.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::DenseMapMmap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::index::map::DenseMapFile<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();
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
/*
This is a small tool to dump the contents of the input file.
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <osmium/handler/dump.hpp>
#include <osmium/io/any_input.hpp>
int main(int argc, char* argv[]) {
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);
}
osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all;
if (argc == 3) {
read_types = osmium::osm_entity_bits::nothing;
std::string types = argv[2];
if (types.find('n') != std::string::npos) read_types |= osmium::osm_entity_bits::node;
if (types.find('w') != std::string::npos) read_types |= osmium::osm_entity_bits::way;
if (types.find('r') != std::string::npos) read_types |= osmium::osm_entity_bits::relation;
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();
std::cout << "HEADER:\n generator=" << header.get("generator") << "\n";
for (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);
}
reader.close();
google::protobuf::ShutdownProtobufLibrary();
}
+236
View File
@@ -0,0 +1,236 @@
/*
Example program to look at Osmium indexes on disk.
The code in this example file is released into the Public Domain.
*/
#include <fcntl.h>
#include <iomanip>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <boost/program_options.hpp>
#include <osmium/index/map/mmap_vector_file.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/types.hpp>
template <typename TKey, typename TValue>
class IndexSearch {
typedef typename osmium::index::map::DenseMapFile<TKey, TValue> dense_index_type;
typedef typename osmium::index::map::SparseMapFile<TKey, TValue> sparse_index_type;
int m_fd;
bool m_dense_format;
void dump_dense() {
dense_index_type index(m_fd);
for (size_t i = 0; i < index.size(); ++i) {
if (index.get(i) != TValue()) {
std::cout << i << " " << index.get(i) << "\n";
}
}
}
void dump_sparse() {
sparse_index_type index(m_fd);
for (auto& element : index) {
std::cout << element.first << " " << element.second << "\n";
}
}
bool search_dense(TKey key) {
dense_index_type index(m_fd);
try {
TValue value = index.get(key);
std::cout << key << " " << value << std::endl;
} catch (...) {
std::cout << key << " not found" << std::endl;
return false;
}
return true;
}
bool search_sparse(TKey key) {
typedef typename sparse_index_type::element_type element_type;
sparse_index_type index(m_fd);
element_type elem {key, TValue()};
auto positions = std::equal_range(index.begin(), index.end(), elem, [](const element_type& lhs, const element_type& rhs) {
return lhs.first < rhs.first;
});
if (positions.first == positions.second) {
std::cout << key << " not found" << std::endl;
return false;
}
for (auto& it = positions.first; it != positions.second; ++it) {
std::cout << it->first << " " << it->second << "\n";
}
return true;
}
public:
IndexSearch(int fd, bool dense_format) :
m_fd(fd),
m_dense_format(dense_format) {
}
void dump() {
if (m_dense_format) {
dump_dense();
} else {
dump_sparse();
}
}
bool search(TKey key) {
if (m_dense_format) {
return search_dense(key);
} else {
return search_sparse(key);
}
}
bool search(std::vector<TKey> keys) {
bool found_all = true;
for (const auto key : keys) {
if (!search(key)) {
found_all = false;
}
}
return found_all;
}
}; // class IndexSearch
enum return_code : int {
okay = 0,
not_found = 1,
error = 2,
fatal = 3
};
namespace po = boost::program_options;
class Options {
po::variables_map vm;
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')")
;
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);
}
if (vm.count("array") && vm.count("list")) {
std::cerr << "Only option --array or --list allowed." << std::endl;
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>();
}
}
bool dense_format() const {
return vm.count("array");
}
bool do_dump() const {
return vm.count("dump");
}
std::vector<osmium::unsigned_object_id_type> search_keys() const {
return vm["search"].as<std::vector<osmium::unsigned_object_id_type>>();
}
bool type_is(const char* type) const {
return vm["type"].as<std::string>() == type;
}
}; // class Options
int main(int argc, char* argv[]) {
std::ios_base::sync_with_stdio(false);
Options options(argc, argv);
std::cout << std::fixed << std::setprecision(7);
int fd = open(options.filename().c_str(), O_RDWR);
bool result_okay = true;
if (options.type_is("location")) {
IndexSearch<osmium::unsigned_object_id_type, osmium::Location> is(fd, options.dense_format());
if (options.do_dump()) {
is.dump();
} else {
result_okay = is.search(options.search_keys());
}
} else {
IndexSearch<osmium::unsigned_object_id_type, size_t> is(fd, options.dense_format());
if (options.do_dump()) {
is.dump();
} else {
result_okay = is.search(options.search_keys());
}
}
exit(result_okay ? return_code::okay : return_code::not_found);
}
+32
View File
@@ -0,0 +1,32 @@
/*
This is a small tool that reads and discards the contents of the input file.
(Used for timing.)
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <osmium/io/any_input.hpp>
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
exit(1);
}
osmium::io::File infile(argv[1]);
osmium::io::Reader reader(infile);
while (osmium::memory::Buffer buffer = reader.read()) {
// do nothing
}
reader.close();
google::protobuf::ShutdownProtobufLibrary();
}
+210
View File
@@ -0,0 +1,210 @@
/*
This is a small tool to dump the contents of the input file
in serialized format to stdout.
The code in this example file is released into the Public Domain.
*/
#include <cerrno>
#include <cstring>
#include <getopt.h>
#include <iostream>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef _MSC_VER
# include <direct.h>
#endif
#include <osmium/io/pbf_input.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/handler/disk_store.hpp>
#include <osmium/handler/object_relations.hpp>
#include <osmium/index/map/stl_vector.hpp>
#include <osmium/index/multimap/stl_multimap.hpp>
#include <osmium/index/multimap/stl_vector.hpp>
#include <osmium/index/multimap/hybrid.hpp>
// ==============================================================================
// Choose the following depending on the size of the input OSM files:
// ==============================================================================
// for smaller OSM files (extracts)
typedef osmium::index::map::SparseMapMem<osmium::unsigned_object_id_type, size_t> offset_index_type;
//typedef osmium::index::map::SparseMapMmap<osmium::unsigned_object_id_type, size_t> offset_index_type;
//typedef osmium::index::map::SparseMapFile<osmium::unsigned_object_id_type, size_t> offset_index_type;
typedef osmium::index::multimap::SparseMultimapMem<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
//typedef osmium::index::multimap::StlMultimap<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
//typedef osmium::index::multimap::Hybrid<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
// ==============================================================================
// for very large OSM files (planet)
//typedef osmium::index::map::DenseMapMmap<osmium::unsigned_object_id_type, size_t> offset_index_type;
//typedef osmium::index::map::DenseMapMem map_type;
// ==============================================================================
void print_help() {
std::cout << "osmium_serdump OSMFILE DIR\n" \
<< "Serialize content of OSMFILE into data file in DIR.\n" \
<< "\nOptions:\n" \
<< " -h, --help This help message\n";
}
int main(int argc, char* argv[]) {
std::ios_base::sync_with_stdio(false);
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
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(2);
}
}
int remaining_args = argc - optind;
if (remaining_args != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE DIR\n";
exit(2);
}
std::string dir(argv[optind+1]);
#ifndef _WIN32
int result = ::mkdir(dir.c_str(), 0777);
#else
int result = mkdir(dir.c_str());
#endif
if (result == -1 && errno != EEXIST) {
std::cerr << "Problem creating directory '" << dir << "': " << strerror(errno) << "\n";
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);
}
offset_index_type node_index;
offset_index_type way_index;
offset_index_type relation_index;
osmium::handler::DiskStore disk_store_handler(data_fd, node_index, way_index, relation_index);
map_type map_node2way;
map_type map_node2relation;
map_type map_way2relation;
map_type map_relation2relation;
osmium::handler::ObjectRelations object_relations_handler(map_node2way, map_node2relation, map_way2relation, map_relation2relation);
osmium::io::Reader reader(argv[1]);
while (osmium::memory::Buffer buffer = reader.read()) {
disk_store_handler(buffer); // XXX
osmium::apply(buffer, object_relations_handler);
}
reader.close();
{
std::string index_file(dir + "/nodes.idx");
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);
}
node_index.dump_as_list(fd);
close(fd);
}
{
std::string index_file(dir + "/ways.idx");
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);
}
way_index.dump_as_list(fd);
close(fd);
}
{
std::string index_file(dir + "/relations.idx");
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);
}
relation_index.dump_as_list(fd);
close(fd);
}
{
map_node2way.sort();
std::string index_file(dir + "/node2way.map");
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);
}
map_node2way.dump_as_list(fd);
close(fd);
}
{
map_node2relation.sort();
std::string index_file(dir + "/node2rel.map");
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);
}
map_node2relation.dump_as_list(fd);
close(fd);
}
{
map_way2relation.sort();
std::string index_file(dir + "/way2rel.map");
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);
}
map_way2relation.dump_as_list(fd);
close(fd);
}
{
map_relation2relation.sort();
std::string index_file(dir + "/rel2rel.map");
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);
}
map_relation2relation.dump_as_list(fd);
close(fd);
}
google::protobuf::ShutdownProtobufLibrary();
}
+251
View File
@@ -0,0 +1,251 @@
/*
This is an example tool that converts OSM data to some output format
like Spatialite or Shapefiles using the OGR library.
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <getopt.h>
#pragma GCC diagnostic push
#ifdef __clang__
# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
#endif
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wshadow"
# include <ogr_api.h>
# include <ogrsf_frmts.h>
#pragma GCC diagnostic pop
// usually you only need one or two of these
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/sparse_table.hpp>
#include <osmium/index/map/stl_map.hpp>
#include <osmium/index/map/mmap_vector_anon.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/visitor.hpp>
#include <osmium/geom/ogr.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/handler.hpp>
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
//typedef osmium::index::map::StlMap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
//typedef osmium::index::map::SparseMapMmap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::index::map::SparseTable<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
class MyOGRHandler : public osmium::handler::Handler {
OGRDataSource* m_data_source;
OGRLayer* m_layer_point;
OGRLayer* m_layer_linestring;
osmium::geom::OGRFactory<> m_factory;
public:
MyOGRHandler(const std::string& driver_name, const std::string& filename) {
OGRRegisterAll();
OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str());
if (!driver) {
std::cerr << driver_name << " driver not available.\n";
exit(1);
}
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
const char* options[] = { "SPATIALITE=TRUE", nullptr };
m_data_source = driver->CreateDataSource(filename.c_str(), const_cast<char**>(options));
if (!m_data_source) {
std::cerr << "Creation of output file failed.\n";
exit(1);
}
OGRSpatialReference sparef;
sparef.SetWellKnownGeogCS("WGS84");
m_layer_point = m_data_source->CreateLayer("postboxes", &sparef, wkbPoint, nullptr);
if (!m_layer_point) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_id("id", OFTReal);
layer_point_field_id.SetWidth(10);
if (m_layer_point->CreateField(&layer_point_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_operator("operator", OFTString);
layer_point_field_operator.SetWidth(30);
if (m_layer_point->CreateField(&layer_point_field_operator) != OGRERR_NONE) {
std::cerr << "Creating operator field failed.\n";
exit(1);
}
/* Transactions might make things faster, then again they might not.
Feel free to experiment and benchmark and report back. */
m_layer_point->StartTransaction();
m_layer_linestring = m_data_source->CreateLayer("roads", &sparef, wkbLineString, nullptr);
if (!m_layer_linestring) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_id("id", OFTReal);
layer_linestring_field_id.SetWidth(10);
if (m_layer_linestring->CreateField(&layer_linestring_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_type("type", OFTString);
layer_linestring_field_type.SetWidth(30);
if (m_layer_linestring->CreateField(&layer_linestring_field_type) != OGRERR_NONE) {
std::cerr << "Creating type field failed.\n";
exit(1);
}
m_layer_linestring->StartTransaction();
}
~MyOGRHandler() {
m_layer_linestring->CommitTransaction();
m_layer_point->CommitTransaction();
OGRDataSource::DestroyDataSource(m_data_source);
OGRCleanupAll();
}
void node(const osmium::Node& node) {
const char* amenity = node.tags().get_value_by_key("amenity");
if (amenity && !strcmp(amenity, "post_box")) {
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn());
std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
feature->SetGeometry(ogr_point.get());
feature->SetField("id", static_cast<double>(node.id()));
feature->SetField("operator", node.tags().get_value_by_key("operator"));
if (m_layer_point->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
}
}
void way(const osmium::Way& way) {
const char* highway = way.tags().get_value_by_key("highway");
if (highway) {
try {
std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn());
feature->SetGeometry(ogr_linestring.get());
feature->SetField("id", static_cast<double>(way.id()));
feature->SetField("type", highway);
if (m_layer_linestring->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n";
}
}
}
};
/* ================================================== */
void print_help() {
std::cout << "osmium_toogr [OPTIONS] [INFILE [OUTFILE]]\n\n" \
<< "If INFILE is not given stdin is assumed.\n" \
<< "If OUTFILE is not given 'ogr_out' is used.\n" \
<< "\nOptions:\n" \
<< " -h, --help This help message\n" \
<< " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n";
}
int main(int argc, char* argv[]) {
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
std::string output_format("SQLite");
while (true) {
int c = getopt_long(argc, argv, "hf:", long_options, 0);
if (c == -1) {
break;
}
switch (c) {
case 'h':
print_help();
exit(0);
case 'f':
output_format = optarg;
break;
default:
exit(1);
}
}
std::string input_filename;
std::string output_filename("ogr_out");
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_filename = argv[optind];
output_filename = argv[optind+1];
} else if (remaining_args == 1) {
input_filename = argv[optind];
} else {
input_filename = "-";
}
osmium::io::Reader reader(input_filename);
index_pos_type index_pos;
index_neg_type index_neg;
location_handler_type location_handler(index_pos, index_neg);
location_handler.ignore_errors();
MyOGRHandler ogr_handler(output_format, output_filename);
osmium::apply(reader, location_handler, ogr_handler);
reader.close();
google::protobuf::ShutdownProtobufLibrary();
int locations_fd = open("locations.dump", O_WRONLY | O_CREAT, 0644);
if (locations_fd < 0) {
throw std::system_error(errno, std::system_category(), "Open failed");
}
index_pos.dump_as_list(locations_fd);
close(locations_fd);
}
+350
View File
@@ -0,0 +1,350 @@
/*
This is an example tool that converts OSM data to some output format
like Spatialite or Shapefiles using the OGR library.
This version does multipolygon handling (in contrast to the osmium_toogr
example which doesn't).
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <getopt.h>
#pragma GCC diagnostic push
#ifdef __clang__
# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
#endif
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wshadow"
# include <ogr_api.h>
# include <ogrsf_frmts.h>
#pragma GCC diagnostic pop
// usually you only need one or two of these
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/sparse_table.hpp>
#include <osmium/index/map/stl_map.hpp>
#include <osmium/index/map/mmap_vector_anon.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/visitor.hpp>
#include <osmium/area/multipolygon_collector.hpp>
#include <osmium/area/assembler.hpp>
#include <osmium/geom/mercator_projection.hpp>
//#include <osmium/geom/projection.hpp>
#include <osmium/geom/ogr.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/handler.hpp>
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
//typedef osmium::index::map::StlMap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
//typedef osmium::index::map::SparseMapMmap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::index::map::SparseTable<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
class MyOGRHandler : public osmium::handler::Handler {
OGRDataSource* m_data_source;
OGRLayer* m_layer_point;
OGRLayer* m_layer_linestring;
OGRLayer* m_layer_polygon;
// Choose one of the following:
// 1. Use WGS84, do not project coordinates.
//osmium::geom::OGRFactory<> m_factory {};
// 2. Project coordinates into "Web Mercator".
osmium::geom::OGRFactory<osmium::geom::MercatorProjection> m_factory;
// 3. Use any projection that the proj library can handle.
// (Initialize projection with EPSG code or proj string).
// In addition you need to link with "-lproj" and add
// #include <osmium/geom/projection.hpp>.
//osmium::geom::OGRFactory<osmium::geom::Projection> m_factory {osmium::geom::Projection(3857)};
public:
MyOGRHandler(const std::string& driver_name, const std::string& filename) {
OGRRegisterAll();
OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str());
if (!driver) {
std::cerr << driver_name << " driver not available.\n";
exit(1);
}
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
const char* options[] = { "SPATIALITE=TRUE", nullptr };
m_data_source = driver->CreateDataSource(filename.c_str(), const_cast<char**>(options));
if (!m_data_source) {
std::cerr << "Creation of output file failed.\n";
exit(1);
}
OGRSpatialReference sparef;
sparef.importFromProj4(m_factory.proj_string().c_str());
m_layer_point = m_data_source->CreateLayer("postboxes", &sparef, wkbPoint, nullptr);
if (!m_layer_point) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_id("id", OFTReal);
layer_point_field_id.SetWidth(10);
if (m_layer_point->CreateField(&layer_point_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_operator("operator", OFTString);
layer_point_field_operator.SetWidth(30);
if (m_layer_point->CreateField(&layer_point_field_operator) != OGRERR_NONE) {
std::cerr << "Creating operator field failed.\n";
exit(1);
}
/* Transactions might make things faster, then again they might not.
Feel free to experiment and benchmark and report back. */
m_layer_point->StartTransaction();
m_layer_linestring = m_data_source->CreateLayer("roads", &sparef, wkbLineString, nullptr);
if (!m_layer_linestring) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_id("id", OFTReal);
layer_linestring_field_id.SetWidth(10);
if (m_layer_linestring->CreateField(&layer_linestring_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_type("type", OFTString);
layer_linestring_field_type.SetWidth(30);
if (m_layer_linestring->CreateField(&layer_linestring_field_type) != OGRERR_NONE) {
std::cerr << "Creating type field failed.\n";
exit(1);
}
m_layer_linestring->StartTransaction();
m_layer_polygon = m_data_source->CreateLayer("buildings", &sparef, wkbMultiPolygon, nullptr);
if (!m_layer_polygon) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_polygon_field_id("id", OFTInteger);
layer_polygon_field_id.SetWidth(10);
if (m_layer_polygon->CreateField(&layer_polygon_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_polygon_field_type("type", OFTString);
layer_polygon_field_type.SetWidth(30);
if (m_layer_polygon->CreateField(&layer_polygon_field_type) != OGRERR_NONE) {
std::cerr << "Creating type field failed.\n";
exit(1);
}
m_layer_polygon->StartTransaction();
}
~MyOGRHandler() {
m_layer_polygon->CommitTransaction();
m_layer_linestring->CommitTransaction();
m_layer_point->CommitTransaction();
OGRDataSource::DestroyDataSource(m_data_source);
OGRCleanupAll();
}
void node(const osmium::Node& node) {
const char* amenity = node.tags()["amenity"];
if (amenity && !strcmp(amenity, "post_box")) {
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn());
std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
feature->SetGeometry(ogr_point.get());
feature->SetField("id", static_cast<double>(node.id()));
feature->SetField("operator", node.tags()["operator"]);
if (m_layer_point->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
}
}
void way(const osmium::Way& way) {
const char* highway = way.tags()["highway"];
if (highway) {
try {
std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn());
feature->SetGeometry(ogr_linestring.get());
feature->SetField("id", static_cast<double>(way.id()));
feature->SetField("type", highway);
if (m_layer_linestring->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n";
}
}
}
void area(const osmium::Area& area) {
const char* building = area.tags()["building"];
if (building) {
try {
std::unique_ptr<OGRMultiPolygon> ogr_polygon = m_factory.create_multipolygon(area);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_polygon->GetLayerDefn());
feature->SetGeometry(ogr_polygon.get());
feature->SetField("id", static_cast<int>(area.id()));
feature->SetField("type", building);
std::string type = "";
if (area.from_way()) {
type += "w";
} else {
type += "r";
}
feature->SetField("type", type.c_str());
if (m_layer_polygon->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for area " << area.id() << " created from " << (area.from_way() ? "way" : "relation") << " with id=" << area.orig_id() << ".\n";
}
}
}
};
/* ================================================== */
void print_help() {
std::cout << "osmium_toogr [OPTIONS] [INFILE [OUTFILE]]\n\n" \
<< "If INFILE is not given stdin is assumed.\n" \
<< "If OUTFILE is not given 'ogr_out' is used.\n" \
<< "\nOptions:\n" \
<< " -h, --help This help message\n" \
<< " -d, --debug Enable debug output\n" \
<< " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n";
}
int main(int argc, char* argv[]) {
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"debug", no_argument, 0, 'd'},
{"format", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
std::string output_format("SQLite");
bool debug = false;
while (true) {
int c = getopt_long(argc, argv, "hdf:", long_options, 0);
if (c == -1) {
break;
}
switch (c) {
case 'h':
print_help();
exit(0);
case 'd':
debug = true;
break;
case 'f':
output_format = optarg;
break;
default:
exit(1);
}
}
std::string input_filename;
std::string output_filename("ogr_out");
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_filename = argv[optind];
output_filename = argv[optind+1];
} else if (remaining_args == 1) {
input_filename = argv[optind];
} else {
input_filename = "-";
}
osmium::area::Assembler::config_type assembler_config;
assembler_config.enable_debug_output(debug);
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector(assembler_config);
std::cerr << "Pass 1...\n";
osmium::io::Reader reader1(input_filename);
collector.read_relations(reader1);
reader1.close();
std::cerr << "Pass 1 done\n";
index_pos_type index_pos;
index_neg_type index_neg;
location_handler_type location_handler(index_pos, index_neg);
location_handler.ignore_errors();
MyOGRHandler ogr_handler(output_format, output_filename);
std::cerr << "Pass 2...\n";
osmium::io::Reader reader2(input_filename);
osmium::apply(reader2, location_handler, ogr_handler, collector.handler([&ogr_handler](const osmium::memory::Buffer& area_buffer) {
osmium::apply(area_buffer, ogr_handler);
}));
reader2.close();
std::cerr << "Pass 2 done\n";
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:";
for (const auto* relation : incomplete_relations) {
std::cerr << " " << relation->id();
}
std::cerr << "\n";
}
google::protobuf::ShutdownProtobufLibrary();
}
+330
View File
@@ -0,0 +1,330 @@
/*
This is an example tool that converts OSM data to some output format
like Spatialite or Shapefiles using the OGR library.
This version does multipolygon handling (in contrast to the osmium_toogr
example which doesn't).
This version (..._exp) uses a new experimental unsupported interface.
The code in this example file is released into the Public Domain.
*/
#include <iostream>
#include <getopt.h>
#pragma GCC diagnostic push
#ifdef __clang__
# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
#endif
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wshadow"
# include <ogr_api.h>
# include <ogrsf_frmts.h>
#pragma GCC diagnostic pop
// usually you only need one or two of these
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/sparse_table.hpp>
#include <osmium/index/map/stl_map.hpp>
#include <osmium/index/map/mmap_vector_anon.hpp>
#include <osmium/visitor.hpp>
#include <osmium/geom/mercator_projection.hpp>
//#include <osmium/geom/projection.hpp>
#include <osmium/geom/ogr.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/handler.hpp>
#include <osmium/experimental/flex_reader.hpp>
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
//typedef osmium::index::map::StlMap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
//typedef osmium::index::map::SparseMapMmap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::index::map::SparseTable<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
class MyOGRHandler : public osmium::handler::Handler {
OGRDataSource* m_data_source;
OGRLayer* m_layer_point;
OGRLayer* m_layer_linestring;
OGRLayer* m_layer_polygon;
// Choose one of the following:
// 1. Use WGS84, do not project coordinates.
//osmium::geom::OGRFactory<> m_factory {};
// 2. Project coordinates into "Web Mercator".
osmium::geom::OGRFactory<osmium::geom::MercatorProjection> m_factory;
// 3. Use any projection that the proj library can handle.
// (Initialize projection with EPSG code or proj string).
// In addition you need to link with "-lproj" and add
// #include <osmium/geom/projection.hpp>.
//osmium::geom::OGRFactory<osmium::geom::Projection> m_factory {osmium::geom::Projection(3857)};
public:
MyOGRHandler(const std::string& driver_name, const std::string& filename) {
OGRRegisterAll();
OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str());
if (!driver) {
std::cerr << driver_name << " driver not available.\n";
exit(1);
}
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
const char* options[] = { "SPATIALITE=TRUE", nullptr };
m_data_source = driver->CreateDataSource(filename.c_str(), const_cast<char**>(options));
if (!m_data_source) {
std::cerr << "Creation of output file failed.\n";
exit(1);
}
OGRSpatialReference sparef;
sparef.importFromProj4(m_factory.proj_string().c_str());
m_layer_point = m_data_source->CreateLayer("postboxes", &sparef, wkbPoint, nullptr);
if (!m_layer_point) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_id("id", OFTReal);
layer_point_field_id.SetWidth(10);
if (m_layer_point->CreateField(&layer_point_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_operator("operator", OFTString);
layer_point_field_operator.SetWidth(30);
if (m_layer_point->CreateField(&layer_point_field_operator) != OGRERR_NONE) {
std::cerr << "Creating operator field failed.\n";
exit(1);
}
/* Transactions might make things faster, then again they might not.
Feel free to experiment and benchmark and report back. */
m_layer_point->StartTransaction();
m_layer_linestring = m_data_source->CreateLayer("roads", &sparef, wkbLineString, nullptr);
if (!m_layer_linestring) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_id("id", OFTReal);
layer_linestring_field_id.SetWidth(10);
if (m_layer_linestring->CreateField(&layer_linestring_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_type("type", OFTString);
layer_linestring_field_type.SetWidth(30);
if (m_layer_linestring->CreateField(&layer_linestring_field_type) != OGRERR_NONE) {
std::cerr << "Creating type field failed.\n";
exit(1);
}
m_layer_linestring->StartTransaction();
m_layer_polygon = m_data_source->CreateLayer("buildings", &sparef, wkbMultiPolygon, nullptr);
if (!m_layer_polygon) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_polygon_field_id("id", OFTInteger);
layer_polygon_field_id.SetWidth(10);
if (m_layer_polygon->CreateField(&layer_polygon_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_polygon_field_type("type", OFTString);
layer_polygon_field_type.SetWidth(30);
if (m_layer_polygon->CreateField(&layer_polygon_field_type) != OGRERR_NONE) {
std::cerr << "Creating type field failed.\n";
exit(1);
}
m_layer_polygon->StartTransaction();
}
~MyOGRHandler() {
m_layer_polygon->CommitTransaction();
m_layer_linestring->CommitTransaction();
m_layer_point->CommitTransaction();
OGRDataSource::DestroyDataSource(m_data_source);
OGRCleanupAll();
}
void node(const osmium::Node& node) {
const char* amenity = node.tags()["amenity"];
if (amenity && !strcmp(amenity, "post_box")) {
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn());
std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
feature->SetGeometry(ogr_point.get());
feature->SetField("id", static_cast<double>(node.id()));
feature->SetField("operator", node.tags()["operator"]);
if (m_layer_point->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
}
}
void way(const osmium::Way& way) {
const char* highway = way.tags()["highway"];
if (highway) {
try {
std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn());
feature->SetGeometry(ogr_linestring.get());
feature->SetField("id", static_cast<double>(way.id()));
feature->SetField("type", highway);
if (m_layer_linestring->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n";
}
}
}
void area(const osmium::Area& area) {
const char* building = area.tags()["building"];
if (building) {
try {
std::unique_ptr<OGRMultiPolygon> ogr_polygon = m_factory.create_multipolygon(area);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_polygon->GetLayerDefn());
feature->SetGeometry(ogr_polygon.get());
feature->SetField("id", static_cast<int>(area.id()));
feature->SetField("type", building);
std::string type = "";
if (area.from_way()) {
type += "w";
} else {
type += "r";
}
feature->SetField("type", type.c_str());
if (m_layer_polygon->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for area " << area.id() << " created from " << (area.from_way() ? "way" : "relation") << " with id=" << area.orig_id() << ".\n";
}
}
}
};
/* ================================================== */
void print_help() {
std::cout << "osmium_toogr [OPTIONS] [INFILE [OUTFILE]]\n\n" \
<< "If INFILE is not given stdin is assumed.\n" \
<< "If OUTFILE is not given 'ogr_out' is used.\n" \
<< "\nOptions:\n" \
<< " -h, --help This help message\n" \
<< " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n";
}
int main(int argc, char* argv[]) {
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
std::string output_format("SQLite");
while (true) {
int c = getopt_long(argc, argv, "hf:", long_options, 0);
if (c == -1) {
break;
}
switch (c) {
case 'h':
print_help();
exit(0);
case 'f':
output_format = optarg;
break;
default:
exit(1);
}
}
std::string input_filename;
std::string output_filename("ogr_out");
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_filename = argv[optind];
output_filename = argv[optind+1];
} else if (remaining_args == 1) {
input_filename = argv[optind];
} else {
input_filename = "-";
}
index_pos_type index_pos;
index_neg_type index_neg;
location_handler_type location_handler(index_pos, index_neg);
osmium::experimental::FlexReader<location_handler_type> exr(input_filename, osmium::osm_entity_bits::object);
MyOGRHandler ogr_handler(output_format, output_filename);
while (auto buffer = exr.read()) {
osmium::apply(buffer, ogr_handler);
}
exr.close();
std::vector<const osmium::Relation*> incomplete_relations = exr.collector().get_incomplete_relations();
if (!incomplete_relations.empty()) {
std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
for (const auto* relation : incomplete_relations) {
std::cerr << " " << relation->id();
}
std::cerr << "\n";
}
google::protobuf::ShutdownProtobufLibrary();
}
@@ -0,0 +1,71 @@
/*
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/pbf_input.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/mmap_vector_anon.hpp>
#include <osmium/index/map/mmap_vector_file.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::DenseMapMmap<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
typedef osmium::index::map::DenseMapFile<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();
google::protobuf::ShutdownProtobufLibrary();
return 0;
}