diff --git a/include/osr/routing/dijkstra.h b/include/osr/routing/dijkstra.h index 9fb8098..a90b5a6 100644 --- a/include/osr/routing/dijkstra.h +++ b/include/osr/routing/dijkstra.h @@ -26,7 +26,7 @@ struct dijkstra { } void add_start(label const l) { - if (cost_[l.get_node().get_key()].update(l.get_node(), l.cost(), + if (cost_[l.get_node().get_key()].update(l, l.get_node(), l.cost(), node::invalid())) { pq_.push(l); } @@ -51,12 +51,14 @@ struct dijkstra { Profile::template adjacent( r, curr, blocked, [&](node const neighbor, std::uint32_t const cost, distance_t, - way_idx_t, std::uint16_t, std::uint16_t) { + way_idx_t const way, std::uint16_t, std::uint16_t) { auto const total = l.cost() + cost; if (total < max && cost_[neighbor.get_key()].update( - neighbor, static_cast(total), curr)) { - pq_.push(label{neighbor, static_cast(total)}); + l, neighbor, static_cast(total), curr)) { + auto next = label{neighbor, static_cast(total)}; + next.track(r, way, neighbor.get_node()); + pq_.push(std::move(next)); } }); } diff --git a/include/osr/routing/profiles/bike.h b/include/osr/routing/profiles/bike.h index 186399e..2d58f63 100644 --- a/include/osr/routing/profiles/bike.h +++ b/include/osr/routing/profiles/bike.h @@ -1,5 +1,6 @@ #pragma once +#include "osr/routing/route.h" #include "osr/ways.h" namespace osr { @@ -27,31 +28,14 @@ struct bike { using key = node; - struct entry { - constexpr std::optional pred(node) const noexcept { - return pred_ == node_idx_t::invalid() ? std::nullopt - : std::optional{node{pred_}}; - } - constexpr cost_t cost(node) const noexcept { return cost_; } - constexpr bool update(node, cost_t const c, node const pred) noexcept { - if (c < cost_) { - cost_ = c; - pred_ = pred.n_; - return true; - } - return false; - } - - node_idx_t pred_{node_idx_t::invalid()}; - cost_t cost_{kInfeasible}; - }; - struct label { label(node const n, cost_t const c) : n_{n.n_}, cost_{c} {} constexpr node get_node() const noexcept { return {n_}; } constexpr cost_t cost() const noexcept { return cost_; } + void track(ways::routing const&, way_idx_t, node_idx_t) {} + node_idx_t n_; level_t lvl_; cost_t cost_; @@ -65,6 +49,30 @@ struct bike { } }; + struct entry { + constexpr std::optional pred(node) const noexcept { + return pred_ == node_idx_t::invalid() ? std::nullopt + : std::optional{node{pred_}}; + } + constexpr cost_t cost(node) const noexcept { return cost_; } + constexpr bool update(label const&, + node, + cost_t const c, + node const pred) noexcept { + if (c < cost_) { + cost_ = c; + pred_ = pred.n_; + return true; + } + return false; + } + + void write(node, path&) const {} + + node_idx_t pred_{node_idx_t::invalid()}; + cost_t cost_{kInfeasible}; + }; + template static void resolve( ways::routing const&, way_idx_t, node_idx_t const n, level_t, Fn&& f) { diff --git a/include/osr/routing/profiles/car.h b/include/osr/routing/profiles/car.h index ac61894..788dd09 100644 --- a/include/osr/routing/profiles/car.h +++ b/include/osr/routing/profiles/car.h @@ -4,6 +4,7 @@ #include "utl/helpers/algorithm.h" +#include "osr/routing/route.h" #include "osr/ways.h" namespace osr { @@ -25,6 +26,8 @@ struct car { constexpr node_idx_t get_node() const noexcept { return n_; } constexpr node_idx_t get_key() const noexcept { return n_; } + void track(ways::routing const&, way_idx_t, node_idx_t) {} + std::ostream& print(std::ostream& out, ways const& w) const { return out << "(node=" << w.node_to_osm_[n_] << ", dir=" << to_str(dir_) << ", way=" << w.way_osm_idx_[w.r_->node_ways_[n_][way_]] @@ -36,6 +39,21 @@ struct car { direction dir_; }; + struct label { + label(node const n, cost_t const c) + : n_{n.n_}, way_{n.way_}, dir_{n.dir_}, cost_{c} {} + + constexpr node get_node() const noexcept { return {n_, way_, dir_}; } + constexpr cost_t cost() const noexcept { return cost_; } + + void track(ways::routing const&, way_idx_t, node_idx_t) {} + + node_idx_t n_; + way_pos_t way_; + direction dir_; + cost_t cost_; + }; + struct entry { static constexpr auto const kMaxWays = way_pos_t{16U}; static constexpr auto const kN = kMaxWays * 2U /* FWD+BWD */; @@ -54,7 +72,8 @@ struct car { return cost_[get_index(n)]; } - constexpr bool update(node const n, + constexpr bool update(label const&, + node const n, cost_t const c, node const pred) noexcept { auto const idx = get_index(n); @@ -68,6 +87,8 @@ struct car { return false; } + void write(node, path&) const {} + static constexpr node get_node(node_idx_t const n, std::size_t const index) { return node{n, static_cast(index % kMaxWays), @@ -92,19 +113,6 @@ struct car { std::array cost_; }; - struct label { - label(node const n, cost_t const c) - : n_{n.n_}, way_{n.way_}, dir_{n.dir_}, cost_{c} {} - - constexpr node get_node() const noexcept { return {n_, way_, dir_}; } - constexpr cost_t cost() const noexcept { return cost_; } - - node_idx_t n_; - way_pos_t way_; - direction dir_; - cost_t cost_; - }; - struct hash { using is_avalanching = void; auto operator()(key const n) const noexcept -> std::uint64_t { diff --git a/include/osr/routing/profiles/foot.h b/include/osr/routing/profiles/foot.h index ae304b8..3d62813 100644 --- a/include/osr/routing/profiles/foot.h +++ b/include/osr/routing/profiles/foot.h @@ -1,10 +1,11 @@ #pragma once +#include "osr/routing/tracking.h" #include "osr/ways.h" namespace osr { -template +template struct foot { static constexpr auto const kMaxMatchDistance = 100U; static constexpr auto const kOffroadPenalty = 3U; @@ -29,6 +30,22 @@ struct foot { using key = node; + struct label { + label(node const n, cost_t const c) : n_{n.n_}, cost_{c}, lvl_{n.lvl_} {} + + constexpr node get_node() const noexcept { return {n_, lvl_}; } + constexpr cost_t cost() const noexcept { return cost_; } + + void track(ways::routing const& r, way_idx_t const w, node_idx_t const n) { + tracking_.track(r, w, n); + } + + node_idx_t n_; + cost_t cost_; + level_t lvl_; + [[no_unique_address]] Tracking tracking_; + }; + struct entry { constexpr std::optional pred(node) const noexcept { return pred_ == node_idx_t::invalid() @@ -36,8 +53,12 @@ struct foot { : std::optional{node{pred_, pred_lvl_}}; } constexpr cost_t cost(node) const noexcept { return cost_; } - constexpr bool update(node, cost_t const c, node const pred) noexcept { + constexpr bool update(label const& l, + node, + cost_t const c, + node const pred) noexcept { if (c < cost_) { + tracking_ = l.tracking_; cost_ = c; pred_ = pred.n_; pred_lvl_ = pred.lvl_; @@ -46,20 +67,12 @@ struct foot { return false; } + void write(node, path& p) const { tracking_.write(p); } + node_idx_t pred_{node_idx_t::invalid()}; - level_t pred_lvl_; cost_t cost_{kInfeasible}; - }; - - struct label { - label(node const n, cost_t const c) : n_{n.n_}, lvl_{n.lvl_}, cost_{c} {} - - constexpr node get_node() const noexcept { return {n_, lvl_}; } - constexpr cost_t cost() const noexcept { return cost_; } - - node_idx_t n_; - level_t lvl_; - cost_t cost_; + level_t pred_lvl_; + [[no_unique_address]] Tracking tracking_; }; struct hash { diff --git a/include/osr/routing/route.h b/include/osr/routing/route.h index e348aca..35ad386 100644 --- a/include/osr/routing/route.h +++ b/include/osr/routing/route.h @@ -39,6 +39,7 @@ struct path { cost_t cost_{kInfeasible}; double dist_{0.0}; std::vector segments_{}; + bool uses_elevator_{false}; }; struct connecting_way { diff --git a/include/osr/routing/tracking.h b/include/osr/routing/tracking.h new file mode 100644 index 0000000..966893d --- /dev/null +++ b/include/osr/routing/tracking.h @@ -0,0 +1,22 @@ +#pragma once + +#include "osr/routing/route.h" +#include "osr/ways.h" + +namespace osr { + +struct elevator_tracking { + void write(path& p) const { p.uses_elevator_ = uses_elevator_; } + void track(ways::routing const& r, way_idx_t, node_idx_t const n) { + uses_elevator_ |= r.node_properties_[n].is_elevator(); + } + + bool uses_elevator_{false}; +}; + +struct noop_tracking { + void write(path&) const {} + void track(ways::routing const&, way_idx_t, node_idx_t) {} +}; + +} // namespace osr \ No newline at end of file diff --git a/src/route.cc b/src/route.cc index 89f43c3..e0164c1 100644 --- a/src/route.cc +++ b/src/route.cc @@ -155,9 +155,11 @@ path reconstruct(ways const& w, .to_level_ = start_node.lvl_, .way_ = way_idx_t::invalid()}); std::reverse(begin(segments), end(segments)); - return {.cost_ = cost, - .dist_ = start_node.dist_to_node_ + dist + dest.dist_to_node_, - .segments_ = segments}; + auto p = path{.cost_ = cost, + .dist_ = start_node.dist_to_node_ + dist + dest.dist_to_node_, + .segments_ = segments}; + d.cost_.at(dest_node.get_key()).write(dest_node, p); + return p; } template @@ -370,8 +372,8 @@ std::optional route(ways const& w, return route(w, l, get_dijkstra>(), from, to, max, dir, max_match_distance, blocked); case search_profile::kWheelchair: - return route(w, l, get_dijkstra>(), from, to, max, dir, - max_match_distance, blocked); + return route(w, l, get_dijkstra>(), from, + to, max, dir, max_match_distance, blocked); case search_profile::kBike: return route(w, l, get_dijkstra(), from, to, max, dir, max_match_distance, blocked);