/** * @deprecated * Use osmium::builder::add_way_node_list() instead. */ OSMIUM_DEPRECATED inline const osmium::WayNodeList& build_way_node_list(osmium::memory::Buffer& buffer, const std::initializer_list<osmium::NodeRef>& nodes) { const size_t pos = buffer.committed(); { osmium::builder::WayNodeListBuilder wnl_builder(buffer); for (const auto& node_ref : nodes) { wnl_builder.add_node_ref(node_ref); } } buffer.commit(); return buffer.get<const osmium::WayNodeList>(pos); }
osmium_builder_t::wkbs_t osmium_builder_t::get_wkb_multiline(osmium::memory::Buffer const &ways, double split_at) { // make a list of all endpoints using endpoint_t = std::tuple<osmium::object_id_type, size_t, bool>; std::vector<endpoint_t> endpoints; // and a list of way connections enum lmt : size_t { NOCONN = -1UL }; std::vector<std::tuple<size_t, osmium::Way const *, size_t>> conns; // initialise the two lists for (auto const &w : ways.select<osmium::Way>()) { if (w.nodes().size() > 1) { endpoints.emplace_back(w.nodes().front().ref(), conns.size(), true); endpoints.emplace_back(w.nodes().back().ref(), conns.size(), false); conns.emplace_back(NOCONN, &w, NOCONN); } } // sort by node id std::sort(endpoints.begin(), endpoints.end()); // now fill the connection list based on the sorted list { endpoint_t const *prev = nullptr; for (auto const &pt : endpoints) { if (prev) { if (std::get<0>(*prev) == std::get<0>(pt)) { auto previd = std::get<1>(*prev); auto ptid = std::get<1>(pt); if (std::get<2>(*prev)) { std::get<0>(conns[previd]) = ptid; } else { std::get<2>(conns[previd]) = ptid; } if (std::get<2>(pt)) { std::get<0>(conns[ptid]) = previd; } else { std::get<2>(conns[ptid]) = previd; } prev = nullptr; continue; } } prev = &pt; } } wkbs_t ret; size_t done_ways = 0; size_t todo_ways = conns.size(); for (size_t i = 0; i < todo_ways; ++i) { if (!std::get<1>(conns[i]) || (std::get<0>(conns[i]) != NOCONN && std::get<2>(conns[i]) != NOCONN)) { continue; // way already done or not the beginning of a segment } m_buffer.clear(); { osmium::builder::WayNodeListBuilder wnl_builder(m_buffer); size_t prev = NOCONN; size_t cur = i; do { auto &conn = conns[cur]; assert(std::get<1>(conn)); auto &nl = std::get<1>(conn)->nodes(); bool skip_first = prev != NOCONN; bool forward = std::get<0>(conn) == prev; prev = cur; // add way nodes if (forward) { add_nodes_to_builder(wnl_builder, nl.cbegin(), nl.cend(), skip_first); cur = std::get<2>(conn); } else { add_nodes_to_builder(wnl_builder, nl.crbegin(), nl.crend(), skip_first); cur = std::get<0>(conn); } // mark way as done std::get<1>(conns[prev]) = nullptr; ++done_ways; } while (cur != NOCONN); } // found a line end, create the wkbs m_buffer.commit(); auto linewkbs = get_wkb_line(m_buffer.get<osmium::WayNodeList>(0), split_at); std::move(linewkbs.begin(), linewkbs.end(), std::inserter(ret, ret.end())); } if (done_ways < todo_ways) { // oh dear, there must be circular ways without an end // need to do the same shebang again for (size_t i = 0; i < todo_ways; ++i) { if (!std::get<1>(conns[i])) { continue; // way already done } m_buffer.clear(); { osmium::builder::WayNodeListBuilder wnl_builder(m_buffer); size_t prev = std::get<0>(conns[i]); size_t cur = i; bool skip_first = false; do { auto &conn = conns[cur]; assert(std::get<1>(conn)); auto &nl = std::get<1>(conn)->nodes(); bool forward = std::get<0>(conn) == prev; prev = cur; if (forward) { // add way forwards add_nodes_to_builder(wnl_builder, nl.cbegin(), nl.cend(), skip_first); cur = std::get<2>(conn); } else { // add way backwards add_nodes_to_builder(wnl_builder, nl.crbegin(), nl.crend(), skip_first); cur = std::get<0>(conn); } // mark way as done std::get<1>(conns[prev]) = nullptr; skip_first = true; } while (cur != i); } // found a line end, create the wkbs m_buffer.commit(); auto linewkbs = get_wkb_line(m_buffer.get<osmium::WayNodeList>(0), split_at); std::move(linewkbs.begin(), linewkbs.end(), std::inserter(ret, ret.end())); } } if (split_at <= 0.0 && !ret.empty()) { auto num_lines = ret.size(); m_writer.multilinestring_start(); for (auto const &line : ret) { m_writer.add_sub_geometry(line); } ret.clear(); ret.push_back(m_writer.multilinestring_finish(num_lines)); } return ret; }