Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/extract/strategy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@ class Pass {
break;
case osmium::item_type::way:
self().way(static_cast<const osmium::Way&>(object));
for (auto& e : extracts()) {
self().eway(&e, static_cast<const osmium::Way&>(object));
}
self().eway_all(extracts(), static_cast<const osmium::Way&>(object));
break;
case osmium::item_type::relation:
self().relation(static_cast<const osmium::Relation&>(object));
Expand Down Expand Up @@ -155,6 +153,15 @@ class Pass {
void erelation(extract_data*, const osmium::Relation&) {
}

// Default implementation: call eway() for each extract separately.
// Subclasses may override this to process all extracts in a single
// pass over way.nodes().
void eway_all(std::vector<extract_data>& exts, const osmium::Way& way) {
for (auto& e : exts) {
self().eway(&e, way);
}
}

public:

explicit Pass(TStrategy* strategy) :
Expand Down
50 changes: 50 additions & 0 deletions src/extract/strategy_complete_ways.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <osmium/handler/check_order.hpp>
#include <osmium/util/file.hpp>

#include <cstdint>
#include <cstdlib>
#include <memory>
#include <vector>
Expand Down Expand Up @@ -100,6 +101,55 @@ namespace strategy_complete_ways {
}
}

// Override that scans way.nodes() at most twice for all extracts
// combined instead of up to twice per extract as the default does.
// Uses a uint64_t bitmask so falls back to the default per-extract
// eway() loop when there are more than 64 extracts.
// Pass A finds which extracts claim this way.
// Pass B records all node refs into extra_node_ids for matched extracts.
void eway_all(std::vector<extract_data>& exts, const osmium::Way& way) {
const std::size_t n = exts.size();

if (n > 64) {
for (auto& e : exts) {
self().eway(&e, way);
}
return;
}
std::uint64_t found_mask = 0;
std::size_t remaining = n;

for (const auto& nr : way.nodes()) {
const auto node_id = nr.positive_ref();
for (std::size_t i = 0; i < n; ++i) {
if (!(found_mask & (std::uint64_t{1} << i)) &&
exts[i].node_ids.get(node_id)) {
found_mask |= std::uint64_t{1} << i;
exts[i].way_ids.set(way.positive_id());
if (--remaining == 0) {
break;
}
}
}
if (remaining == 0) {
break;
}
}

if (found_mask == 0) {
return;
}

for (const auto& nr : way.nodes()) {
const auto node_ref = nr.ref();
for (std::size_t i = 0; i < n; ++i) {
if (found_mask & (std::uint64_t{1} << i)) {
exts[i].extra_node_ids.set(node_ref);
}
}
}
}

void relation(const osmium::Relation& relation) {
m_check_order.relation(relation);
m_relations_map_stash.add_members(relation);
Expand Down