Skip to content

Commit 6ad5829

Browse files
committed
Better handling of areas with duplicate segments.
If the duplicate segments are not in inner rings, they will now always be reported. Also if complete ways are removed due to the detection of duplicate segments, the entire area will be marked as invalid.
1 parent f5985ed commit 6ad5829

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

include/osmium/area/assembler.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ namespace osmium {
266266
// Statistics
267267
area_stats m_stats;
268268

269+
// The number of members the multipolygon relation has
270+
size_t m_num_members = 0;
271+
269272
bool debug() const noexcept {
270273
return m_config.debug_level > 1;
271274
}
@@ -1168,6 +1171,20 @@ namespace osmium {
11681171
return true;
11691172
}
11701173

1174+
/**
1175+
* Checks if any ways were completely removed in the
1176+
* erase_duplicate_segments step.
1177+
*/
1178+
bool ways_were_lost() {
1179+
std::unordered_set<const osmium::Way*> ways_in_segments;
1180+
1181+
for (const auto& segment : m_segment_list) {
1182+
ways_in_segments.insert(segment.way());
1183+
}
1184+
1185+
return ways_in_segments.size() < m_num_members;
1186+
}
1187+
11711188
/**
11721189
* Create rings from segments.
11731190
*/
@@ -1196,6 +1213,15 @@ namespace osmium {
11961213
return false;
11971214
}
11981215

1216+
// If one or more complete ways was removed because of
1217+
// duplicate segments, this isn't a valid area.
1218+
if (ways_were_lost()) {
1219+
if (debug()) {
1220+
std::cerr << " Complete ways removed because of duplicate segments\n";
1221+
}
1222+
return false;
1223+
}
1224+
11991225
if (m_config.debug_level >= 3) {
12001226
std::cerr << "Sorted de-duplicated segment list:\n";
12011227
for (const auto& s : m_segment_list) {
@@ -1355,6 +1381,7 @@ namespace osmium {
13551381
}
13561382

13571383
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
1384+
m_num_members = members.size();
13581385
osmium::builder::AreaBuilder builder(out_buffer);
13591386
builder.initialize_from_object(relation);
13601387

include/osmium/area/detail/segment_list.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,13 @@ namespace osmium {
261261
}
262262

263263
// Only count and report duplicate segments if they
264-
// belong to the same way. Those cases are definitely
265-
// wrong. If the duplicate segments belong to
266-
// different ways, they could be touching inner rings
267-
// which are perfectly okay.
268-
if (it->way() == std::next(it)->way()) {
264+
// belong to the same way or if they don't both have
265+
// the role "inner". Those cases are definitely wrong.
266+
// If the duplicate segments belong to different
267+
// "inner" ways, they could be touching inner rings
268+
// which are perfectly okay. Note that for this check
269+
// the role has to be correct in the member data.
270+
if (it->way() == std::next(it)->way() || !it->role_inner() || !std::next(it)->role_inner()) {
269271
++duplicate_segments;
270272
if (problem_reporter) {
271273
problem_reporter->report_duplicate_segment(it->first(), it->second());

0 commit comments

Comments
 (0)