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
38 changes: 37 additions & 1 deletion include/osr/extract/tags.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@

namespace osr {

enum class indoor : std::uint8_t {
kNone,
kRoom,
kArea,
kWall,
kCorridor,
kDoor,
kLevel,
kYes,
kOther
};

enum class osm_obj_type : std::uint8_t { kWay, kNode };

enum class override : std::uint8_t { kNone, kWhitelist, kBlacklist };
Expand Down Expand Up @@ -67,6 +79,23 @@ struct tags {
is_platform_ = true;
}
break;
case cista::hash("indoor"):
switch (cista::hash(std::string_view{t.value()})) {
case cista::hash("room"): indoor_ = indoor::kRoom; break;
case cista::hash("area"): indoor_ = indoor::kArea; break;
case cista::hash("wall"): indoor_ = indoor::kWall; break;
case cista::hash("corridor"): indoor_ = indoor::kCorridor; break;
case cista::hash("door"): indoor_ = indoor::kDoor; break;
case cista::hash("level"): indoor_ = indoor::kLevel; break;
case cista::hash("yes"): indoor_ = indoor::kYes; break;
default: indoor_ = indoor::kOther;
}
break;
case cista::hash("room"):
switch (cista::hash(std::string_view{t.value()})) {
case cista::hash("stairs"): is_stairs_room_ = true; break;
}
break;
case cista::hash("indoor:level"): [[fallthrough]];
case cista::hash("level"):
has_level_ = true;
Expand Down Expand Up @@ -198,6 +227,12 @@ struct tags {
// https://wiki.openstreetmap.org/wiki/Tag:highway=elevator
bool is_elevator_{false};

// https://wiki.openstreetmap.org/wiki/Tag:indoor=corridor
indoor indoor_{indoor::kNone};

// https://wiki.openstreetmap.org/wiki/Key:room
bool is_stairs_room_{false};

// https://wiki.openstreetmap.org/wiki/Key:entrance
bool is_entrance_{false};

Expand Down Expand Up @@ -242,7 +277,8 @@ struct foot_profile {
case cista::hash("designated"): return override::kWhitelist;
}

if (t.is_platform_ || t.is_parking_) {
if (t.is_platform_ || t.is_parking_ || t.indoor_ == indoor::kCorridor ||
(t.indoor_ == indoor::kRoom && t.is_stairs_room_)) {
return override::kWhitelist;
}

Expand Down
8 changes: 6 additions & 2 deletions include/osr/geojson.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ struct geojson_writer {
{"is_elevator", p.is_elevator()},
{"is_steps", p.is_steps()},
{"is_parking", p.is_parking()},
{"is_ramp", p.is_ramp()}}},
{"is_ramp", p.is_ramp()},
{"indoor", p.is_indoor_},
{"corridor", p.is_corridor_}}},
{"geometry", to_line_string(std::initializer_list<geo::latlng>{
w_.get_node_pos(from), w_.get_node_pos(to)})}});
}
Expand All @@ -120,7 +122,9 @@ struct geojson_writer {
{"is_elevator", p.is_elevator()},
{"is_steps", p.is_steps()},
{"is_parking", p.is_parking()},
{"is_ramp", p.is_ramp()}}},
{"is_ramp", p.is_ramp()},
{"indoor", p.is_indoor_},
{"corridor", p.is_corridor_}}},
{"geometry", to_line_string(w_.way_polylines_[i])}});

nodes_.insert(begin(nodes), end(nodes));
Expand Down
8 changes: 6 additions & 2 deletions include/osr/routing/profiles/bike_sharing.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ struct bike_sharing {
.is_platform_ = 0,
.is_parking_ = 0,
.is_ramp_ = 0,
.is_sidewalk_separate_ = false};
.is_sidewalk_separate_ = false,
.is_indoor_ = false,
.is_corridor_ = false};

static constexpr auto const kAdditionalNodeProperties =
node_properties{.from_level_ = 0,
Expand Down Expand Up @@ -84,6 +86,7 @@ struct bike_sharing {

node_idx_t n_{node_idx_t::invalid()};
level_t lvl_{};
bool indoor_{};
};

using hash = footp::hash;
Expand Down Expand Up @@ -145,6 +148,7 @@ struct bike_sharing {
node_idx_t n_{node_idx_t::invalid()};
node_type type_{node_type::kInvalid};
level_t lvl_{};
bool indoor_{false};
};

struct label {
Expand Down Expand Up @@ -217,7 +221,7 @@ struct bike_sharing {
};

static footp::node to_foot(node const n) {
return {.n_ = n.n_, .lvl_ = n.lvl_};
return {.n_ = n.n_, .lvl_ = n.lvl_, .indoor_ = false};
}

static bike<kElevationNoCost>::node to_bike(node const n) {
Expand Down
2 changes: 1 addition & 1 deletion include/osr/routing/profiles/car_parking.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ struct car_parking {
}

static footp::node to_foot(node const n) {
return {.n_ = n.n_, .lvl_ = n.lvl_};
return {.n_ = n.n_, .lvl_ = n.lvl_, .indoor_ = false};
}

static node to_node(car::node const n, level_t const lvl) {
Expand Down
43 changes: 31 additions & 12 deletions include/osr/routing/profiles/foot.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ struct foot {
return l == kNoLevel || l == level_t{0.F};
};
return a.n_ == b.n_ &&
(a.lvl_ == b.lvl_ || (is_zero(a.lvl_) && is_zero(b.lvl_)));
(a.lvl_ == b.lvl_ || (is_zero(a.lvl_) && is_zero(b.lvl_))) &&
a.indoor_ == b.indoor_;
}

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

Expand All @@ -40,14 +41,15 @@ struct foot {

node_idx_t n_;
level_t lvl_;
bool indoor_;
};

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 node get_node() const noexcept { return {n_, lvl_, indoor_}; }
constexpr cost_t cost() const noexcept { return cost_; }

void track(label const& l,
Expand All @@ -60,14 +62,15 @@ struct foot {
node_idx_t n_;
cost_t cost_;
level_t lvl_;
bool indoor_;
[[no_unique_address]] Tracking tracking_;
};

struct entry {
constexpr std::optional<node> pred(node) const noexcept {
return pred_ == node_idx_t::invalid()
? std::nullopt
: std::optional{node{pred_, pred_lvl_}};
: std::optional{node{pred_, pred_lvl_, pred_indoor_}};
}
constexpr cost_t cost(node) const noexcept { return cost_; }
constexpr bool update(label const& l,
Expand All @@ -89,6 +92,7 @@ struct foot {
node_idx_t pred_{node_idx_t::invalid()};
cost_t cost_{kInfeasible};
level_t pred_lvl_;
bool pred_indoor_;
[[no_unique_address]] Tracking tracking_;
};

Expand All @@ -99,7 +103,8 @@ struct foot {
return wyhash::mix(
wyhash::hash(static_cast<std::uint64_t>(
to_idx(n.lvl_ == kNoLevel ? level_t{0.F} : n.lvl_))),
wyhash::hash(static_cast<std::uint64_t>(to_idx(n.n_))));
wyhash::mix(wyhash::hash(static_cast<std::uint64_t>(to_idx(n.n_))),
wyhash::hash(n.indoor_)));
}
};

Expand All @@ -111,12 +116,15 @@ struct foot {
direction,
Fn&& f) {
auto const p = w.way_properties_[way];
if (p.is_corridor_) {
return;
}
if (lvl == kNoLevel ||
(p.from_level() == lvl || p.to_level() == lvl ||
can_use_elevator(w, n, lvl)) ||
(lvl == level_t{0.F} &&
(p.from_level() == kNoLevel && p.to_level() == kNoLevel))) {
f(node{n, p.from_level()});
f(node{n, p.from_level(), false});
}
}

Expand All @@ -132,15 +140,15 @@ struct foot {
auto const p = w.way_properties_[w.node_ways_[n][i]];
if (lvl == kNoLevel) {
if (levels.emplace(p.from_level()).second) {
f(node{n, p.from_level()});
f(node{n, p.from_level(), p.is_indoor_});
}
if (levels.emplace(p.to_level()).second) {
f(node{n, p.to_level()});
f(node{n, p.to_level(), p.is_indoor_});
}
} else if ((p.from_level() == lvl || p.to_level() == lvl ||
p.from_level() == kNoLevel || can_use_elevator(w, n, lvl)) &&
levels.emplace(lvl).second) {
f(node{n, lvl});
f(node{n, lvl, p.is_indoor_});
}
}
}
Expand Down Expand Up @@ -174,13 +182,23 @@ struct foot {
return;
}

if (target_way_prop.is_corridor_ && !n.indoor_ &&
!w.node_properties_[n.n_].is_entrance_) {
return;
}

if (!n.indoor_ && target_way_prop.is_corridor_ &&
!w.node_properties_[n.n_].is_entrance_) {
return;
}

if (can_use_elevator(w, target_node, n.lvl_)) {
for_each_elevator_level(
w, target_node, [&](level_t const target_lvl) {
auto const dist = w.way_node_dist_[way][std::min(from, to)];
auto const cost = way_cost(target_way_prop, way_dir, dist) +
node_cost(target_node_prop);
fn(node{target_node, target_lvl},
fn(node{target_node, target_lvl, target_way_prop.is_indoor_},
static_cast<std::uint32_t>(cost), dist, way, from, to,
elevation_storage::elevation{});
});
Expand All @@ -193,8 +211,9 @@ struct foot {
auto const dist = w.way_node_dist_[way][std::min(from, to)];
auto const cost = way_cost(target_way_prop, way_dir, dist) +
node_cost(target_node_prop);
fn(node{target_node, *target_lvl}, static_cast<std::uint32_t>(cost),
dist, way, from, to, elevation_storage::elevation{});
fn(node{target_node, *target_lvl, target_way_prop.is_indoor_},
static_cast<std::uint32_t>(cost), dist, way, from, to,
elevation_storage::elevation{});
}
};

Expand Down
2 changes: 2 additions & 0 deletions include/osr/ways.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ struct way_properties {

bool is_ramp_ : 1;
bool is_sidewalk_separate_ : 1;
bool is_indoor_ : 1;
bool is_corridor_ : 1;
};

static_assert(sizeof(way_properties) == 4);
Expand Down
20 changes: 13 additions & 7 deletions src/extract.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,16 @@ way_properties get_way_properties(tags const& t) {
p.is_oneway_car_ = t.oneway_;
p.is_oneway_bike_ = t.oneway_ && !t.not_oneway_bike_;
p.is_elevator_ = t.is_elevator_;
p.is_steps_ = (t.highway_ == "steps"sv);
p.is_steps_ = (t.highway_ == "steps"sv) || t.is_stairs_room_;
p.is_parking_ = t.is_parking_;
p.speed_limit_ = get_speed_limit(t);
p.from_level_ = to_idx(from);
p.to_level_ = to_idx(to);
p.is_platform_ = t.is_platform_;
p.is_ramp_ = t.is_ramp_;
p.is_sidewalk_separate_ = t.sidewalk_separate_;
p.is_indoor_ = t.indoor_ != indoor::kNone;
p.is_corridor_ = t.indoor_ == indoor::kCorridor;
return p;
}

Expand Down Expand Up @@ -198,15 +200,19 @@ struct way_handler : public osm::handler::Handler {

if (!t.is_elevator_ && // elevators tagged as building would be landuse
!t.is_parking_ &&
((it == end(rel_ways_) && t.highway_.empty() && !t.is_platform_) ||
(t.highway_.empty() && !t.is_platform_ && it != end(rel_ways_) &&
t.landuse_))) {
t.indoor_ != indoor::kCorridor && // enable routing for indoor=corridor
!t.is_stairs_room_ // enable routing for and room=stairs
&& ((it == end(rel_ways_) && t.highway_.empty() && !t.is_platform_) ||
(t.highway_.empty() && !t.is_platform_ && it != end(rel_ways_) &&
t.landuse_))) {
return;
}

auto p = (t.is_platform_ || t.is_parking_ || !t.highway_.empty())
? get_way_properties(t)
: it->second.p_;
auto p =
(t.is_platform_ || t.is_parking_ || t.indoor_ == indoor::kCorridor ||
t.is_stairs_room_ || !t.highway_.empty())
? get_way_properties(t)
: it->second.p_;
if (!p.is_accessible()) {
return;
}
Expand Down
Loading