[OSM-dev] libosmium and missing multipolygons
Sylvain Melin
s.melin at alsim.com
Thu Apr 21 14:03:31 UTC 2016
Hi everyone.
I wrote a C++ program using libosmium to read an osm file, filter the
data and extract the result to different target shapefiles.
I have a problem with some features not being written in shapefiles.
For example, I want to extract all water bodies in the bounding box
latmin=44 latmax=45 lonmin=-1 lonmax=0.
In the resulting shapefile, the relation 2988 "Lit de la Dordogne" is
missing : https://www.openstreetmap.org/relation/2988
The osmium::Area built from this relation seems to be empty.
area.num_rings() gives 0
area.tags() is empty
Trying to create a multipolygon from this area throws an
osmium::geometry_error :
"Ignoring illegal geometry for area 5977 created from relation with id=2988.
area contains no rings (area_id=5977)"
Importing my osm file in QGis or converting it with ogr2ogr gives the
appropriate result and the relation 2988 is correctly exported into the
shapefile.
Do you have any idea of what's causing this problem and how it can be
solved ?
Thank you for your help.
Here's the code of my osmium test program (it's a slight modification of
https://github.com/osmcode/osm-gis-export/blob/master/src/osmium_toogr2.cpp)
:
template <class TProjection>
class MyOGRHandler : public osmium::handler::Handler
{
gdalcpp::Layer m_layer;
osmium::geom::OGRFactory<TProjection>& m_factory;
public:
MyOGRHandler(gdalcpp::Dataset& dataset,
osmium::geom::OGRFactory<TProjection>& factory) :
m_layer(dataset, "toto", wkbMultiPolygon),
m_factory(factory)
{
m_layer.add_field("id", OFTReal, 10);
m_layer.add_field("type", OFTString, 30);
}
void area(const osmium::Area& area)
{
try
{
gdalcpp::Feature feature(m_Output.m_layer,
m_factory.create_multipolygon(area));
feature.set_field("id", static_cast<double>(area.id()));
feature.set_field("type", "toto");
feature.add_to_layer();
}
catch (osmium::geometry_error& e)
{
std::cerr << "Ignoring illegal geometry for area "
<< area.id()
<< " created from "
<< (area.from_way() ? "way" : "relation")
<< " with id="
<< area.orig_id() << ".\n";
printf("%s\n\n",e.what());
}
}
};
int main(int argc, char* argv[])
{
...
osmium::area::Assembler::config_type assembler_config;
assembler_config.enable_debug_output(debug);
osmium::area::MultipolygonCollector<osmium::area::Assembler>
collector(assembler_config);
bool error = false;
std::cerr << "Pass 1...\n";
try
{
osmium::io::Reader reader1(szIn);
collector.read_relations(reader1);
reader1.close();
printf("%s\n",collector.members_buffer().data());
}
catch(osmium::xml_error&)
{
printf("Error reading file\n");
error = true;
}
std::cerr << "Pass 1 done\n";
if(!error)
{
index_type index_pos;
location_handler_type location_handler(index_pos);
location_handler.ignore_errors();
osmium::geom::OGRFactory<> factory {};
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
gdalcpp::Dataset dataset{output_format, szOut,
gdalcpp::SRS{factory.proj_string()}, { "SPATIALITE=TRUE" }};
MyOGRHandler<decltype(factory)::projection_type> ogr_handler(dataset,
factory);
std::cerr << "Pass 2...\n";
osmium::io::Reader reader2(szIn);
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";
}
}
}
More information about the dev
mailing list