Skip to content

Commit 62d71c5

Browse files
authored
Separate reader for node/way/area and relation to fix missing relation geometries (ad-freiburg#129)
Adds separate readers for nwa (node/way/area) and relation to fix an issue where way member geometries may not have been seen at the time a relation arrives at the RelationHandler when using multiple threads. Fixes ad-freiburg#128. On the side, add hasCompleteGeometry true triples to relation areas for consistency (because the same triple is present for non-area relations) (fixes ad-freiburg#130), and fix a subtle issue with the area classification for ways. Because of this issue, untagged closed ways (of which there are few, if any, in OSM) had no geometry object. Fixes ad-freiburg#131, see there for details.
1 parent cd127f4 commit 62d71c5

File tree

7 files changed

+76
-6
lines changed

7 files changed

+76
-6
lines changed

include/osm2rdf/osm/OsmiumHandler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class OsmiumHandler : public osmium::handler::Handler {
8888
void handleBuffers(
8989
osmium::memory::Buffer& buffer,
9090
osmium::area::MultipolygonManager<osmium::area::Assembler>& mp_manager);
91+
void handleRelBuffers(
92+
osmium::memory::Buffer& buffer);
9193
void handleAreaBuffers(osmium::memory::Buffer& areaBuffer);
9294
};
9395
} // namespace osm2rdf::osm

src/osm/FactHandler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ void osm2rdf::osm::FactHandler<W>::area(const osm2rdf::osm::Area& area) {
161161
_writer->writeLiteralTripleUnsafe(
162162
subj, _areaIRI, ::util::formatFloat(area.geomArea(), AREA_PRECISION),
163163
_iriXSDDouble);
164+
165+
if (!area.fromWay()) {
166+
// for areas from relations, always write hasCompleteGeometry true for
167+
// consistency with non-area relations
168+
_writer->writeTriple(
169+
subj,
170+
_writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "hasCompleteGeometry"),
171+
osm2rdf::ttl::constants::LITERAL__TRUE
172+
);
173+
}
164174
}
165175

166176
// ____________________________________________________________________________

src/osm/OsmiumHandler.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ void osm2rdf::osm::OsmiumHandler<W>::handle() {
138138
prepReader.close();
139139
_locationHandler->finalizeNodes();
140140

141-
osmium::io::Reader dumpReader{input_file, osmium::osm_entity_bits::object,
141+
osmium::io::Reader dumpReader{input_file, osmium::osm_entity_bits::nwa,
142142
osmium::io::read_meta::yes};
143143

144144
#pragma omp parallel
@@ -153,6 +153,21 @@ void osm2rdf::osm::OsmiumHandler<W>::handle() {
153153

154154
dumpReader.close();
155155

156+
osmium::io::Reader relReader{input_file, osmium::osm_entity_bits::relation,
157+
osmium::io::read_meta::yes};
158+
159+
#pragma omp parallel
160+
{
161+
#pragma omp single
162+
{
163+
while (auto buf = relReader.read()) {
164+
handleRelBuffers(buf);
165+
}
166+
}
167+
}
168+
169+
relReader.close();
170+
156171
delete _locationHandler;
157172
_progressBar.done();
158173

@@ -219,6 +234,17 @@ void osm2rdf::osm::OsmiumHandler<W>::handleBuffers(
219234
}));
220235
}
221236

237+
// ____________________________________________________________________________
238+
template <typename W>
239+
void osm2rdf::osm::OsmiumHandler<W>::handleRelBuffers(
240+
osmium::memory::Buffer& buffer) {
241+
// handlers which do not care about the order in which the
242+
// elements are given to them
243+
const auto buff = std::make_shared<osmium::memory::Buffer>(std::move(buffer));
244+
#pragma omp task
245+
{ osmium::apply(*buff, _relationHandler, *this); }
246+
}
247+
222248
// ____________________________________________________________________________
223249
template <typename W>
224250
void osm2rdf::osm::OsmiumHandler<W>::handleAreaBuffers(

src/osm/Way.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include "osm2rdf/osm/Way.h"
2121

22+
#include <osmium/tags/taglist.hpp>
23+
#include <osmium/tags/tags_filter.hpp>
2224
#include <vector>
2325

2426
#include "osm2rdf/osm/Box.h"
@@ -104,6 +106,13 @@ bool osm2rdf::osm::Way::isArea() const noexcept {
104106
if (!closed()) {
105107
return false;
106108
}
107-
auto areaTag = _w->tags()["area"];
108-
return areaTag == nullptr || strcmp(areaTag, "no") != 0;
109+
if (_w->tags().has_tag("area", "no")) {
110+
return false;
111+
}
112+
113+
if (osmium::tags::match_none_of(_w->tags(), osmium::TagsFilter{true})) {
114+
return false;
115+
}
116+
117+
return true;
109118
}

tests/issues/Issue24.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ TEST(Issue24, areaFromRelationHasGeometryAsGeoSPARQL) {
131131
"osmrel:10 geo:hasGeometry osm2rdfgeom:osmrel_10 "
132132
".\nosm2rdfgeom:osmrel_10 geo:asWKT \"POLYGON((48 7.5,48 "
133133
"7.6,48.1 7.6,48.1 7.5,48 7.5))\"^^geo:wktLiteral .\nosmrel:10 "
134-
"osm2rdf:area \"122568687.4654\"^^xsd:double .\n",
134+
"osm2rdf:area \"122568687.4654\"^^xsd:double .\nosmrel:10 "
135+
"osm2rdf:hasCompleteGeometry \"true\"^^xsd:boolean .\n",
135136
buffer.str());
136137

137138
// Cleanup

tests/osm/FactHandler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ TEST(OSM_FactHandler, areaFromRelation) {
164164
"osm2rdfgeom:obb \"POLYGON((48.1 7.5,48.1 7.6,48 7.6,48 7.5,48.1 "
165165
"7.5))\"^^geo:wktLiteral .\nosmrel:10 osm2rdf:area "
166166
"\"122568687.4654\"^^xsd:double "
167-
".\n",
167+
".\nosmrel:10 osm2rdf:hasCompleteGeometry \"true\"^^xsd:boolean .\n",
168168
buffer.str());
169169

170170
// Cleanup

tests/osm/Way.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ TEST(OSM_Way, isAreaFalseForOpenWay) {
200200
}
201201

202202
// ____________________________________________________________________________
203-
TEST(OSM_Way, isAreaTrueForTriangle) {
203+
TEST(OSM_Way, isAreaFalseForTriangleWithoutTags) {
204204
// Create osmium object
205205
const size_t initial_buffer_size = 10000;
206206
osmium::memory::Buffer buffer{initial_buffer_size,
@@ -217,6 +217,28 @@ TEST(OSM_Way, isAreaTrueForTriangle) {
217217
osm2rdf::osm::Way w{buffer.get<osmium::Way>(0)};
218218
ASSERT_TRUE(w.closed());
219219

220+
ASSERT_FALSE(w.isArea());
221+
}
222+
223+
// ____________________________________________________________________________
224+
TEST(OSM_Way, isAreaFTrueForTriangleWithTags) {
225+
// Create osmium object
226+
const size_t initial_buffer_size = 10000;
227+
osmium::memory::Buffer buffer{initial_buffer_size,
228+
osmium::memory::Buffer::auto_grow::yes};
229+
osmium::builder::add_way(buffer, osmium::builder::attr::_id(42),
230+
osmium::builder::attr::_nodes({
231+
{1, {48.0, 7.51}},
232+
{2, {48.0, 7.61}},
233+
{1, {48.1, 7.61}},
234+
{1, {48.0, 7.51}},
235+
}),
236+
osmium::builder::attr::_tag("some", "tag"));
237+
238+
// Create osm2rdf object from osmium object
239+
const osm2rdf::osm::Way w{buffer.get<osmium::Way>(0)};
240+
ASSERT_TRUE(w.closed());
241+
220242
ASSERT_TRUE(w.isArea());
221243
}
222244

0 commit comments

Comments
 (0)