Update in-tree libosmium dependency to 2.5.4

The latest releases have some critical fixes, see the changelog:
https://github.com/osmcode/libosmium/blob/v2.5.4/CHANGELOG.md

Merge commit 'afdf8e7b21fbaf597e91d9d8a7542635e60ee9a1' into use_libosmium_2_5_4
This commit is contained in:
Daniel J. Hofmann
2016-01-05 12:00:40 +01:00
171 changed files with 7150 additions and 3988 deletions
+2 -25
View File
@@ -14,12 +14,10 @@ set(EXAMPLES
count
create_node_cache
debug
filter_discussions
index
read
serdump
toogr
toogr2
toogr2_exp
use_node_cache
CACHE STRING "Example programs"
)
@@ -30,7 +28,7 @@ set(EXAMPLES
# Examples depending on wingetopt
#
#-----------------------------------------------------------------------------
set(GETOPT_EXAMPLES area_test convert serdump toogr toogr2 toogr2_exp)
set(GETOPT_EXAMPLES area_test convert serdump)
if(NOT GETOPT_MISSING)
foreach(example ${GETOPT_EXAMPLES})
list(APPEND EXAMPLE_LIBS_${example} ${GETOPT_LIBRARY})
@@ -74,27 +72,6 @@ else()
endif()
#-----------------------------------------------------------------------------
#
# Examples depending on GDAL/PROJ.4/SparseHash
#
#-----------------------------------------------------------------------------
set(OGR_EXAMPLES toogr toogr2 toogr2_exp)
if(GDAL_FOUND AND PROJ_FOUND AND SPARSEHASH_FOUND)
foreach(example ${OGR_EXAMPLES})
list(APPEND EXAMPLE_LIBS_${example} ${GDAL_LIBRARIES})
list(APPEND EXAMPLE_LIBS_${example} ${PROJ_LIBRARIES})
endforeach()
else()
message(STATUS "Configuring examples - Skipping examples because GDAL and/or Proj.4 and/or SparseHash not found:")
foreach(example ${OGR_EXAMPLES})
message(STATUS " - osmium_${example}")
list(REMOVE_ITEM EXAMPLES ${example})
endforeach()
endif()
#-----------------------------------------------------------------------------
#
# Configure examples
@@ -0,0 +1,72 @@
/*
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).
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
// 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
#include <osmium/io/xml_output.hpp>
#include <osmium/io/output_iterator.hpp>
// we want to support any compressioon (.gz2 and .bz2)
#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);
}
// The input file, deduce file format from file suffix
osmium::io::File infile(argv[1]);
// The output file, force class XML OSM file format
osmium::io::File outfile(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);
// Get the header from the input file
osmium::io::Header header = reader.header();
// Initialize writer for the output file. Use the header from the input
// file for the output file. This will copy over some header information.
// The last parameter will tell the writer that it is allowed to overwrite
// an existing file. Without it, it will refuse to do so.
osmium::io::Writer writer(outfile, header, osmium::io::overwrite::allow);
// Create range of input iterators that will iterator over all changesets
// delivered from input file through the "reader".
auto input_range = osmium::io::make_input_iterator_range<osmium::Changeset>(reader);
// Create an output iterator writing through the "writer" object to the
// output file.
auto output_iterator = osmium::io::make_output_iterator(writer);
// Copy all changesets from input to output that have at least one comment.
std::copy_if(input_range.begin(), input_range.end(), output_iterator, [](const osmium::Changeset& changeset) {
return changeset.num_comments() > 0;
});
// 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();
}
-244
View File
@@ -1,244 +0,0 @@
/*
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>
#include <osmium/index/map/all.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::Map<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" \
<< " -l, --location_store=TYPE Set location store\n" \
<< " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n" \
<< " -L See available location stores\n";
}
int main(int argc, char* argv[]) {
const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
{"location_store", required_argument, 0, 'l'},
{"list_location_stores", no_argument, 0, 'L'},
{0, 0, 0, 0}
};
std::string output_format { "SQLite" };
std::string location_store { "sparse_mem_array" };
while (true) {
int c = getopt_long(argc, argv, "hf:l:L", long_options, 0);
if (c == -1) {
break;
}
switch (c) {
case 'h':
print_help();
exit(0);
case 'f':
output_format = optarg;
break;
case 'l':
location_store = optarg;
break;
case 'L':
std::cout << "Available map types:\n";
for (const auto& map_type : map_factory.map_types()) {
std::cout << " " << map_type << "\n";
}
exit(0);
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);
std::unique_ptr<index_pos_type> index_pos = map_factory.create_map(location_store);
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();
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);
}
-331
View File
@@ -1,331 +0,0 @@
/*
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>
// usually you only need one or two of these
#include <osmium/index/map/dummy.hpp>
#include <osmium/index/map/sparse_mem_array.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::SparseMemArray<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";
}
}
-305
View File
@@ -1,305 +0,0 @@
/*
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>
#include <osmium/index/map/sparse_mem_array.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::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
typedef osmium::handler::NodeLocationsForWays<index_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_type index_pos;
location_handler_type location_handler(index_pos);
osmium::experimental::FlexReader<location_handler_type> exr(input_filename, location_handler, 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";
}
}