Skip to content

Commit

Permalink
no level = wildcard (can transition to any level) (#23)
Browse files Browse the repository at this point in the history
* custom level struct

* wip
  • Loading branch information
felixguendling authored Nov 1, 2024
1 parent 6c7f593 commit 03de6b4
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 49 deletions.
6 changes: 3 additions & 3 deletions exe/backend/src/http_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ location parse_location(json::value const& v) {
auto const& obj = v.as_object();
return {obj.at("lat").as_double(), obj.at("lng").as_double(),
obj.contains("level") ? to_level(obj.at("level").to_number<float>())
: level_t::invalid()};
: kNoLevel};
}

json::value to_json(std::vector<geo::latlng> const& polyline) {
Expand Down Expand Up @@ -230,7 +230,7 @@ struct http_server::impl {
auto const query = boost::json::parse(req.body()).as_object();
auto const level = query.contains("level")
? to_level(query.at("level").to_number<float>())
: level_t::invalid();
: kNoLevel;
auto const waypoints = query.at("waypoints").as_array();
auto const min = point::from_latlng(
{waypoints[1].as_double(), waypoints[0].as_double()});
Expand All @@ -239,7 +239,7 @@ struct http_server::impl {

auto gj = geojson_writer{.w_ = w_, .platforms_ = pl_};
pl_->find(min, max, [&](platform_idx_t const i) {
if (level == level_t::invalid() || pl_->get_level(w_, i) == level) {
if (level == kNoLevel || pl_->get_level(w_, i) == level) {
gj.write_platform(i);
}
});
Expand Down
17 changes: 8 additions & 9 deletions include/osr/geojson.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,14 @@ struct geojson_writer {
auto const p = w_.r_->node_properties_[n];

auto ss = std::stringstream{};
Dijkstra::profile_t::resolve_all(*w_.r_, n, level_t::invalid(),
[&](auto const x) {
auto const cost = s->get_cost(x);
if (cost != kInfeasible) {
ss << "{";
x.print(ss, w_);
ss << ", " << cost << "}\n";
}
});
Dijkstra::profile_t::resolve_all(*w_.r_, n, kNoLevel, [&](auto const x) {
auto const cost = s->get_cost(x);
if (cost != kInfeasible) {
ss << "{";
x.print(ss, w_);
ss << ", " << cost << "}\n";
}
});

auto levels = std::vector<float>();
foot<true>::for_each_elevator_level(
Expand Down
2 changes: 1 addition & 1 deletion include/osr/lookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void till_the_end(T const& start,
struct node_candidate {
bool valid() const { return node_ != node_idx_t::invalid(); }

level_t lvl_{level_t::invalid()};
level_t lvl_{kNoLevel};
direction way_dir_{direction::kForward};
node_idx_t node_{node_idx_t::invalid()};
double dist_to_node_{0.0};
Expand Down
2 changes: 1 addition & 1 deletion include/osr/routing/profiles/bike_sharing.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ struct bike_sharing {
entry() {
utl::fill(pred_, node_idx_t::invalid());
utl::fill(cost_, kInfeasible);
utl::fill(pred_lvl_, level_t::invalid());
utl::fill(pred_lvl_, kNoLevel);
utl::fill(pred_type_, node_type::kInvalid);
}

Expand Down
17 changes: 8 additions & 9 deletions include/osr/routing/profiles/car_parking.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ struct car_parking {
w, n, lvl, [&](footp::node const neighbor) { f(to_node(neighbor)); });
car::resolve_all(w, n, lvl, [&](car::node const neighbor) {
auto const p = w.way_properties_[w.node_ways_[n][neighbor.way_]];
auto const node_level = lvl == level_t::invalid() ? p.from_level() : lvl;
auto const node_level = lvl == kNoLevel ? p.from_level() : lvl;
f(to_node(neighbor, node_level));
});
}
Expand Down Expand Up @@ -277,14 +277,13 @@ struct car_parking {
Fn&& f) {
auto const way_properties = w.way_properties_[way];
search_dir == direction::kForward
? car::resolve_start_node(w, way, n, lvl, search_dir,
[&](car::node const cn) {
auto const node_level =
lvl == level_t::invalid()
? way_properties.from_level()
: lvl;
f(to_node(cn, node_level));
})
? car::resolve_start_node(
w, way, n, lvl, search_dir,
[&](car::node const cn) {
auto const node_level =
lvl == kNoLevel ? way_properties.from_level() : lvl;
f(to_node(cn, node_level));
})
: footp::resolve_start_node(
w, way, n, lvl, search_dir,
[&](footp::node const fn) { f(to_node(fn)); });
Expand Down
30 changes: 16 additions & 14 deletions include/osr/routing/profiles/foot.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct foot {
friend bool operator==(node, node) = default;

static constexpr node invalid() noexcept {
return {.n_ = node_idx_t::invalid(), .lvl_{level_t::invalid()}};
return {.n_ = node_idx_t::invalid(), .lvl_{kNoLevel}};
}
constexpr node_idx_t get_node() const noexcept { return n_; }

Expand Down Expand Up @@ -104,10 +104,12 @@ struct foot {
direction,
Fn&& f) {
auto const p = w.way_properties_[way];
if (lvl == level_t::invalid() ||
if (lvl == kNoLevel ||
(p.from_level() == lvl || p.to_level() == lvl ||
can_use_elevator(w, n, lvl))) {
f(node{n, lvl == level_t::invalid() ? p.from_level() : lvl});
can_use_elevator(w, n, lvl)) ||
(lvl == to_level(0.F) &&
(p.from_level() == kNoLevel && p.to_level() == kNoLevel))) {
f(node{n, lvl == kNoLevel ? p.from_level() : lvl});
}
}

Expand All @@ -121,15 +123,15 @@ struct foot {
for (auto i = way_pos_t{0U}; i != ways.size(); ++i) {
// TODO what's with stairs? need to resolve to from_level or to_level?
auto const p = w.way_properties_[w.node_ways_[n][i]];
if (lvl == level_t::invalid()) {
if (lvl == kNoLevel) {
if (levels.emplace(p.from_level()).second) {
f(node{n, p.from_level()});
}
if (levels.emplace(p.to_level()).second) {
f(node{n, p.to_level()});
}
} else if ((p.from_level() == lvl || p.to_level() == lvl ||
can_use_elevator(w, n, lvl)) &&
p.from_level() == kNoLevel || can_use_elevator(w, n, lvl)) &&
levels.emplace(lvl).second) {
f(node{n, lvl});
}
Expand Down Expand Up @@ -239,7 +241,8 @@ struct foot {
} else if (can_use_elevator(w, from_node, way_prop.from_level(),
from_level)) {
return way_prop.from_level();
} else if (way_prop.from_level() == from_level) {
} else if (way_prop.from_level() == from_level ||
way_prop.from_level() == kNoLevel || from_level == kNoLevel) {
return from_level;
} else {
return std::nullopt;
Expand All @@ -249,7 +252,7 @@ struct foot {
static bool can_use_elevator(ways::routing const& w,
way_idx_t const way,
level_t const a,
level_t const b = level_t::invalid()) {
level_t const b = kNoLevel) {
return w.way_properties_[way].is_elevator() &&
can_use_elevator(w, w.way_nodes_[way][0], a, b);
}
Expand All @@ -271,20 +274,19 @@ struct foot {
static bool can_use_elevator(ways::routing const& w,
node_idx_t const n,
level_t const a,
level_t const b = level_t::invalid()) {
level_t const b = kNoLevel) {
auto const p = w.node_properties_[n];
if (!p.is_elevator()) {
return false;
}

if (p.is_multi_level()) {
auto const levels = get_elevator_multi_levels(w, n);
return utl::has_bit_set(levels, to_idx(a)) &&
(b == level_t::invalid() || utl::has_bit_set(levels, to_idx(b)));
return (a == kNoLevel || utl::has_bit_set(levels, to_idx(a))) &&
(b == kNoLevel || utl::has_bit_set(levels, to_idx(b)));
} else {
return (a == p.from_level() || a == p.to_level()) &&
(b == level_t::invalid() || b == p.from_level() ||
b == p.to_level());
return (a == kNoLevel || a == p.from_level() || a == p.to_level()) &&
(b == kNoLevel || b == p.from_level() || b == p.to_level());
}
}

Expand Down
4 changes: 2 additions & 2 deletions include/osr/routing/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ struct sharing_data;
struct path {
struct segment {
geo::polyline polyline_;
level_t from_level_{level_t::invalid()};
level_t to_level_{level_t::invalid()};
level_t from_level_{kNoLevel};
level_t to_level_{kNoLevel};
node_idx_t from_{node_idx_t::invalid()};
node_idx_t to_{node_idx_t::invalid()};
way_idx_t way_{way_idx_t::invalid()};
Expand Down
45 changes: 35 additions & 10 deletions include/osr/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ enum class direction : std::uint8_t {
kBackward,
};

inline std::ostream& operator<<(std::ostream& out, direction const d) {
return out << (d == direction::kBackward ? "bwd" : "fwd");
}

constexpr direction opposite(direction const dir) {
return dir == direction::kForward ? direction::kBackward
: direction::kForward;
Expand Down Expand Up @@ -134,37 +138,58 @@ constexpr direction to_direction(std::string_view s) {
}

// level
using level_t = cista::strong<std::uint8_t, struct level_>;
struct level_t {
friend constexpr std::uint8_t to_idx(level_t l) { return l.v_; }

friend std::ostream& operator<<(std::ostream& out, level_t const l) {
if (to_idx(l) == 0) {
return out << "-";
} else {
return out << (-4.0 + ((to_idx(l) - 1U) / 4.0F));
}
}

template <std::integral X>
explicit constexpr level_t(X x) : v_{static_cast<std::uint8_t>(x)} {}

constexpr level_t() = default;

auto operator<=>(level_t const&) const = default;

constexpr cista::hash_t hash() const { return v_; }

std::uint8_t v_;
};

constexpr auto const kNoLevel = level_t{0U};
constexpr auto const kMinLevel = -4.0F;
constexpr auto const kMaxLevel = 3.75F;
constexpr auto const kMaxLevel = 3.5F;

constexpr level_t to_level(float const f) {
return level_t{static_cast<std::uint8_t>((f - kMinLevel) / 0.25F)};
return level_t{static_cast<std::uint8_t>((f - kMinLevel) / 0.25F + 1U)};
}

constexpr float to_float(level_t const l) {
return l == level_t::invalid() ? 0.0F : (kMinLevel + (to_idx(l) / 4.0F));
return (l == kNoLevel) ? 0.0F : (kMinLevel + ((to_idx(l) - 1U) / 4.0F));
}

constexpr auto const kLevelBits = cista::constexpr_trailing_zeros(
cista::next_power_of_two(to_idx(to_level(kMaxLevel))));
cista::next_power_of_two(to_idx(to_level(kMaxLevel)) + 1U));

using level_bits_t = std::uint32_t;

constexpr std::tuple<level_t, level_t, bool> get_levels(
bool const has_level, level_bits_t const levels) noexcept {
if (!has_level) {
return {level_t{to_level(0.F)}, level_t{to_level(0.F)}, false};
return {level_t{kNoLevel}, level_t{kNoLevel}, false};
}
auto from = level_t::invalid(), to = level_t::invalid();
auto from = kNoLevel, to = kNoLevel;
utl::for_each_set_bit(levels, [&](auto&& bit) {
from == level_t::invalid() //
from == kNoLevel //
? from = level_t{bit}
: to = level_t{bit};
});
return {from, to == level_t::invalid() ? from : to,
std::popcount(levels) > 2};
return {from, to == kNoLevel ? from : to, std::popcount(levels) > 2};
}

static_assert(kLevelBits == 5U);
Expand Down

0 comments on commit 03de6b4

Please sign in to comment.