Skip to content

Commit 6b198c5

Browse files
tracking: tracks an attribute for a path
works via labels + entry dijkstra updates entry tracking with the label tracking useful to know if a path contains an elevator somewhere without having to actually reconstruct the whole path
1 parent 6cf0a46 commit 6b198c5

File tree

9 files changed

+103
-87
lines changed

9 files changed

+103
-87
lines changed

exe/backend/src/http_server.cc

+1-3
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,7 @@ struct http_server::impl {
137137
? 0U
138138
: to_idx(w_.way_osm_idx_[s.way_])},
139139
{"cost", s.cost_},
140-
{"distance", s.dist_},
141-
{"from_node", s.from_node_properties_},
142-
{"to_node", s.to_node_properties_}},
140+
{"distance", s.dist_}},
143141
},
144142
{"geometry", to_line_string(s.polyline_)}};
145143
}) |

include/osr/routing/dijkstra.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct dijkstra {
5757
cost_[neighbor.get_key()].update(
5858
l, neighbor, static_cast<cost_t>(total), curr)) {
5959
auto next = label{neighbor, static_cast<cost_t>(total)};
60-
next.track(r, way, neighbor.get_node());
60+
next.track(l, r, way, neighbor.get_node());
6161
pq_.push(std::move(next));
6262
}
6363
});

include/osr/routing/profiles/bike.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct bike {
3939
constexpr node get_node() const noexcept { return {n_}; }
4040
constexpr cost_t cost() const noexcept { return cost_; }
4141

42-
void track(ways::routing const&, way_idx_t, node_idx_t) {}
42+
void track(label const&, ways::routing const&, way_idx_t, node_idx_t) {}
4343

4444
node_idx_t n_;
4545
level_t lvl_;

include/osr/routing/profiles/car.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ struct car {
3333

3434
constexpr node_idx_t get_key() const noexcept { return n_; }
3535

36-
void track(ways::routing const&, way_idx_t, node_idx_t) {}
37-
3836
std::ostream& print(std::ostream& out, ways const& w) const {
3937
return out << "(node=" << w.node_to_osm_[n_] << ", dir=" << to_str(dir_)
4038
<< ", way=" << w.way_osm_idx_[w.r_->node_ways_[n_][way_]]
@@ -53,7 +51,7 @@ struct car {
5351
constexpr node get_node() const noexcept { return {n_, way_, dir_}; }
5452
constexpr cost_t cost() const noexcept { return cost_; }
5553

56-
void track(ways::routing const&, way_idx_t, node_idx_t) {}
54+
void track(label const&, ways::routing const&, way_idx_t, node_idx_t) {}
5755

5856
node_idx_t n_;
5957
way_pos_t way_;

include/osr/routing/profiles/car_parking.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ struct car_parking {
9393

9494
constexpr cost_t cost() const noexcept { return cost_; }
9595

96-
void track(ways::routing const&, way_idx_t, node_idx_t) {}
96+
void track(label const&, ways::routing const&, way_idx_t, node_idx_t) {}
9797

9898
node_idx_t n_;
9999
cost_t cost_;

include/osr/routing/profiles/foot.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ struct foot {
4141
constexpr node get_node() const noexcept { return {n_, lvl_}; }
4242
constexpr cost_t cost() const noexcept { return cost_; }
4343

44-
void track(ways::routing const& r, way_idx_t const w, node_idx_t const n) {
45-
tracking_.track(r, w, n);
44+
void track(label const& l,
45+
ways::routing const& r,
46+
way_idx_t const w,
47+
node_idx_t const n) {
48+
tracking_.track(l.tracking_, r, w, n);
4649
}
4750

4851
node_idx_t n_;

include/osr/routing/route.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ struct path {
3131
std::vector<geo::latlng> polyline_;
3232
level_t from_level_;
3333
level_t to_level_;
34+
node_idx_t from_, to_;
3435
way_idx_t way_;
3536
cost_t cost_{kInfeasible};
3637
distance_t dist_{0};
37-
boost::json::object from_node_properties_{};
38-
boost::json::object to_node_properties_{};
3938
};
4039

4140
cost_t cost_{kInfeasible};
@@ -56,7 +55,10 @@ std::vector<std::optional<path>> route(
5655
cost_t max,
5756
direction,
5857
double max_match_distance,
59-
bitvec<node_idx_t> const* blocked = nullptr);
58+
bitvec<node_idx_t> const* blocked = nullptr,
59+
std::function<bool(path const&)> const& = [](path const&) {
60+
return false;
61+
});
6062

6163
std::optional<path> route(ways const&,
6264
lookup const&,

include/osr/routing/tracking.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@ namespace osr {
77

88
struct elevator_tracking {
99
void write(path& p) const { p.uses_elevator_ = uses_elevator_; }
10-
void track(ways::routing const& r, way_idx_t, node_idx_t const n) {
11-
uses_elevator_ |= r.node_properties_[n].is_elevator();
10+
void track(elevator_tracking const& l,
11+
ways::routing const& r,
12+
way_idx_t,
13+
node_idx_t const n) {
14+
uses_elevator_ = l.uses_elevator_ || r.node_properties_[n].is_elevator();
1215
}
1316

1417
bool uses_elevator_{false};
1518
};
1619

1720
struct noop_tracking {
1821
void write(path&) const {}
19-
void track(ways::routing const&, way_idx_t, node_idx_t) {}
22+
void track(noop_tracking const&,
23+
ways::routing const&,
24+
way_idx_t,
25+
node_idx_t) {}
2026
};
2127

2228
} // namespace osr

src/route.cc

+79-70
Original file line numberDiff line numberDiff line change
@@ -112,22 +112,10 @@ double add_path(ways const& w,
112112
segment.way_ = way;
113113
segment.dist_ = distance;
114114
segment.cost_ = expected_cost;
115-
116-
// when going backwards we have to swap the properties, since we will be
117-
// traversing the way in the opposite direction.
118-
if (dir == direction::kForward) {
119-
segment.from_level_ = r.way_properties_[way].from_level();
120-
segment.to_level_ = r.way_properties_[way].to_level();
121-
122-
segment.from_node_properties_ = from.geojson_properties(w);
123-
segment.to_node_properties_ = to.geojson_properties(w);
124-
} else {
125-
segment.from_level_ = r.way_properties_[way].to_level();
126-
segment.to_level_ = r.way_properties_[way].from_level();
127-
128-
segment.from_node_properties_ = to.geojson_properties(w);
129-
segment.to_node_properties_ = from.geojson_properties(w);
130-
}
115+
segment.from_level_ = r.way_properties_[way].from_level();
116+
segment.to_level_ = r.way_properties_[way].to_level();
117+
segment.from_ = r.way_nodes_[way][from_idx];
118+
segment.to_ = r.way_nodes_[way][to_idx];
131119

132120
for (auto const [osm_idx, coord] :
133121
infinite(reverse(utl::zip(w.way_osm_nodes_[way], w.way_polylines_[way]),
@@ -183,14 +171,16 @@ path reconstruct(ways const& w,
183171

184172
auto const& start_node =
185173
n.get_node() == start.left_.node_ ? start.left_ : start.right_;
186-
segments.push_back({.polyline_ = start_node.path_,
187-
.from_level_ = start_node.lvl_,
188-
.to_level_ = start_node.lvl_,
189-
.way_ = way_idx_t::invalid(),
190-
.cost_ = kInfeasible,
191-
.dist_ = 0,
192-
.from_node_properties_ = {},
193-
.to_node_properties_ = {}});
174+
segments.push_back(
175+
{.polyline_ = start_node.path_,
176+
.from_level_ = start_node.lvl_,
177+
.to_level_ = start_node.lvl_,
178+
.from_ =
179+
dir == direction::kBackward ? n.get_node() : node_idx_t::invalid(),
180+
.to_ = dir == direction::kForward ? n.get_node() : node_idx_t::invalid(),
181+
.way_ = way_idx_t::invalid(),
182+
.cost_ = kInfeasible,
183+
.dist_ = 0});
194184
std::reverse(begin(segments), end(segments));
195185
auto p = path{.cost_ = cost,
196186
.dist_ = start_node.dist_to_node_ + dist + dest.dist_to_node_,
@@ -203,7 +193,7 @@ template <typename Profile>
203193
std::optional<std::tuple<node_candidate const*,
204194
way_candidate const*,
205195
typename Profile::node,
206-
cost_t>>
196+
path>>
207197
best_candidate(ways const& w,
208198
dijkstra<Profile>& d,
209199
level_t const lvl,
@@ -213,7 +203,7 @@ best_candidate(ways const& w,
213203
auto const get_best = [&](way_candidate const& dest,
214204
node_candidate const* x) {
215205
auto best_node = typename Profile::node{};
216-
auto best_cost = std::numeric_limits<cost_t>::max();
206+
auto best_cost = path{.cost_ = std::numeric_limits<cost_t>::max()};
217207
Profile::resolve_all(*w.r_, x->node_, lvl, [&](auto&& node) {
218208
if (!Profile::is_dest_reachable(*w.r_, node, dest.way_,
219209
flip(opposite(dir), x->way_dir_),
@@ -227,26 +217,26 @@ best_candidate(ways const& w,
227217
}
228218

229219
auto const total_cost = target_cost + x->cost_;
230-
if (total_cost < max && total_cost < best_cost) {
220+
if (total_cost < max && total_cost < best_cost.cost_) {
231221
best_node = node;
232-
best_cost = static_cast<cost_t>(total_cost);
222+
best_cost.cost_ = static_cast<cost_t>(total_cost);
233223
}
234224
});
235225
return std::pair{best_node, best_cost};
236226
};
237227

238228
for (auto const& dest : m) {
239229
auto best_node = typename Profile::node{};
240-
auto best_cost = std::numeric_limits<cost_t>::max();
230+
auto best_cost = path{.cost_ = std::numeric_limits<cost_t>::max()};
241231
auto best = static_cast<node_candidate const*>(nullptr);
242232

243233
for (auto const x : {&dest.left_, &dest.right_}) {
244234
if (x->valid() && x->cost_ < max) {
245235
auto const [x_node, x_cost] = get_best(dest, x);
246-
if (x_cost < max && x_cost < best_cost) {
236+
if (x_cost.cost_ < max && x_cost.cost_ < best_cost.cost_) {
247237
best = x;
248238
best_node = x_node;
249-
best_cost = static_cast<cost_t>(x_cost);
239+
best_cost = x_cost;
250240
}
251241
}
252242
}
@@ -282,10 +272,9 @@ std::optional<path> route(ways const& w,
282272
for (auto const& start : from_match) {
283273
for (auto const* nc : {&start.left_, &start.right_}) {
284274
if (nc->valid() && nc->cost_ < max) {
285-
Profile::resolve_start_node(*w.r_, start.way_, nc->node_, from.lvl_,
286-
dir, [&](auto const node) {
287-
d.add_start({node, nc->cost_});
288-
});
275+
Profile::resolve_start_node(
276+
*w.r_, start.way_, nc->node_, from.lvl_, dir,
277+
[&](auto const node) { d.add_start({node, nc->cost_}); });
289278
}
290279
}
291280

@@ -297,24 +286,27 @@ std::optional<path> route(ways const& w,
297286

298287
auto const c = best_candidate(w, d, to.lvl_, to_match, max, dir);
299288
if (c.has_value()) {
300-
auto const [nc, wc, node, cost] = *c;
301-
return reconstruct<Profile>(w, blocked, d, start, *nc, node, cost, dir);
289+
auto const [nc, wc, node, p] = *c;
290+
return reconstruct<Profile>(w, blocked, d, start, *nc, node, p.cost_,
291+
dir);
302292
}
303293
}
304294

305295
return std::nullopt;
306296
}
307297

308298
template <typename Profile>
309-
std::vector<std::optional<path>> route(ways const& w,
310-
lookup const& l,
311-
dijkstra<Profile>& d,
312-
location const& from,
313-
std::vector<location> const& to,
314-
cost_t const max,
315-
direction const dir,
316-
double const max_match_distance,
317-
bitvec<node_idx_t> const* blocked) {
299+
std::vector<std::optional<path>> route(
300+
ways const& w,
301+
lookup const& l,
302+
dijkstra<Profile>& d,
303+
location const& from,
304+
std::vector<location> const& to,
305+
cost_t const max,
306+
direction const dir,
307+
double const max_match_distance,
308+
bitvec<node_idx_t> const* blocked,
309+
std::function<bool(path const&)> const& do_reconstruct) {
318310
auto const from_match =
319311
l.match<Profile>(from, false, dir, max_match_distance, blocked);
320312
auto const to_match = utl::to_vec(to, [&](auto&& x) {
@@ -332,10 +324,12 @@ std::vector<std::optional<path>> route(ways const& w,
332324
for (auto const& start : from_match) {
333325
for (auto const* nc : {&start.left_, &start.right_}) {
334326
if (nc->valid() && nc->cost_ < max) {
335-
Profile::resolve_start_node(*w.r_, start.way_, nc->node_, from.lvl_,
336-
dir, [&](auto const node) {
337-
d.add_start({node, nc->cost_});
338-
});
327+
Profile::resolve_start_node(
328+
*w.r_, start.way_, nc->node_, from.lvl_, dir, [&](auto const node) {
329+
auto label = typename Profile::label{node, nc->cost_};
330+
label.track(label, *w.r_, start.way_, node.get_node());
331+
d.add_start(label);
332+
});
339333
}
340334
}
341335

@@ -348,7 +342,14 @@ std::vector<std::optional<path>> route(ways const& w,
348342
} else {
349343
auto const c = best_candidate(w, d, t.lvl_, m, max, dir);
350344
if (c.has_value()) {
351-
r = std::make_optional(path{.cost_ = std::get<3>(*c)});
345+
auto [nc, wc, n, p] = *c;
346+
d.cost_.at(n.get_key()).write(n, p);
347+
if (do_reconstruct(p)) {
348+
p = reconstruct<Profile>(w, blocked, d, start, *nc, n, p.cost_,
349+
dir);
350+
p.uses_elevator_ = true;
351+
}
352+
r = std::make_optional(p);
352353
++found;
353354
}
354355
}
@@ -371,34 +372,36 @@ dijkstra<Profile>& get_dijkstra() {
371372
return *s.get();
372373
}
373374

374-
std::vector<std::optional<path>> route(ways const& w,
375-
lookup const& l,
376-
search_profile const profile,
377-
location const& from,
378-
std::vector<location> const& to,
379-
cost_t const max,
380-
direction const dir,
381-
double const max_match_distance,
382-
bitvec<node_idx_t> const* blocked) {
375+
std::vector<std::optional<path>> route(
376+
ways const& w,
377+
lookup const& l,
378+
search_profile const profile,
379+
location const& from,
380+
std::vector<location> const& to,
381+
cost_t const max,
382+
direction const dir,
383+
double const max_match_distance,
384+
bitvec<node_idx_t> const* blocked,
385+
std::function<bool(path const&)> const& do_reconstruct) {
383386
switch (profile) {
384387
case search_profile::kFoot:
385-
return route(w, l, get_dijkstra<foot<false>>(), from, to, max, dir,
386-
max_match_distance, blocked);
388+
return route(w, l, get_dijkstra<foot<false, elevator_tracking>>(), from,
389+
to, max, dir, max_match_distance, blocked, do_reconstruct);
387390
case search_profile::kWheelchair:
388-
return route(w, l, get_dijkstra<foot<true>>(), from, to, max, dir,
389-
max_match_distance, blocked);
391+
return route(w, l, get_dijkstra<foot<true, elevator_tracking>>(), from,
392+
to, max, dir, max_match_distance, blocked, do_reconstruct);
390393
case search_profile::kBike:
391394
return route(w, l, get_dijkstra<bike>(), from, to, max, dir,
392-
max_match_distance, blocked);
395+
max_match_distance, blocked, do_reconstruct);
393396
case search_profile::kCar:
394397
return route(w, l, get_dijkstra<car>(), from, to, max, dir,
395-
max_match_distance, blocked);
398+
max_match_distance, blocked, do_reconstruct);
396399
case search_profile::kCarParking:
397400
return route(w, l, get_dijkstra<car_parking<false>>(), from, to, max, dir,
398-
max_match_distance, blocked);
401+
max_match_distance, blocked, do_reconstruct);
399402
case search_profile::kCarParkingWheelchair:
400403
return route(w, l, get_dijkstra<car_parking<true>>(), from, to, max, dir,
401-
max_match_distance, blocked);
404+
max_match_distance, blocked, do_reconstruct);
402405
}
403406
throw utl::fail("not implemented");
404407
}
@@ -414,8 +417,8 @@ std::optional<path> route(ways const& w,
414417
bitvec<node_idx_t> const* blocked) {
415418
switch (profile) {
416419
case search_profile::kFoot:
417-
return route(w, l, get_dijkstra<foot<false>>(), from, to, max, dir,
418-
max_match_distance, blocked);
420+
return route(w, l, get_dijkstra<foot<false, elevator_tracking>>(), from,
421+
to, max, dir, max_match_distance, blocked);
419422
case search_profile::kWheelchair:
420423
return route(w, l, get_dijkstra<foot<true, elevator_tracking>>(), from,
421424
to, max, dir, max_match_distance, blocked);
@@ -435,4 +438,10 @@ std::optional<path> route(ways const& w,
435438
throw utl::fail("not implemented");
436439
}
437440

441+
template dijkstra<foot<true, osr::noop_tracking>>&
442+
get_dijkstra<foot<true, osr::noop_tracking>>();
443+
444+
template dijkstra<foot<false, osr::noop_tracking>>&
445+
get_dijkstra<foot<false, osr::noop_tracking>>();
446+
438447
} // namespace osr

0 commit comments

Comments
 (0)