From 3230690d1537b6df0e5bcf9f8683fa262bfa39f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20G=C3=BCndling?= Date: Sat, 12 Apr 2025 10:50:58 +0200 Subject: [PATCH 1/2] walkable corridor edges, use room=stairs edges like highway=steps --- include/osr/extract/tags.h | 38 +++++++++++++++++++++++++++++++++++++- src/extract.cc | 18 +++++++++++------- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/include/osr/extract/tags.h b/include/osr/extract/tags.h index dd1a8f0a..7cd56f17 100644 --- a/include/osr/extract/tags.h +++ b/include/osr/extract/tags.h @@ -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 }; @@ -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; @@ -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}; @@ -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; } diff --git a/src/extract.cc b/src/extract.cc index 4cbabd93..1dd93289 100644 --- a/src/extract.cc +++ b/src/extract.cc @@ -112,7 +112,7 @@ 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); @@ -198,15 +198,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; } From 795cc9285be20081eee9e74fa7cba85ccd261012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20G=C3=BCndling?= Date: Mon, 14 Apr 2025 11:11:11 +0200 Subject: [PATCH 2/2] wip.. try to improve situation --- include/osr/geojson.h | 8 +++- include/osr/routing/profiles/bike_sharing.h | 8 +++- include/osr/routing/profiles/car_parking.h | 2 +- include/osr/routing/profiles/foot.h | 43 +++++++++++++++------ include/osr/ways.h | 2 + src/extract.cc | 2 + 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/include/osr/geojson.h b/include/osr/geojson.h index e51df84b..7f61a348 100644 --- a/include/osr/geojson.h +++ b/include/osr/geojson.h @@ -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{ w_.get_node_pos(from), w_.get_node_pos(to)})}}); } @@ -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)); diff --git a/include/osr/routing/profiles/bike_sharing.h b/include/osr/routing/profiles/bike_sharing.h index 9ec299bc..3c93636e 100644 --- a/include/osr/routing/profiles/bike_sharing.h +++ b/include/osr/routing/profiles/bike_sharing.h @@ -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, @@ -84,6 +86,7 @@ struct bike_sharing { node_idx_t n_{node_idx_t::invalid()}; level_t lvl_{}; + bool indoor_{}; }; using hash = footp::hash; @@ -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 { @@ -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::node to_bike(node const n) { diff --git a/include/osr/routing/profiles/car_parking.h b/include/osr/routing/profiles/car_parking.h index 6c2c6ef8..dbcbac90 100644 --- a/include/osr/routing/profiles/car_parking.h +++ b/include/osr/routing/profiles/car_parking.h @@ -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) { diff --git a/include/osr/routing/profiles/foot.h b/include/osr/routing/profiles/foot.h index bfce1b8c..d2464ac3 100644 --- a/include/osr/routing/profiles/foot.h +++ b/include/osr/routing/profiles/foot.h @@ -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_; } @@ -40,6 +41,7 @@ struct foot { node_idx_t n_; level_t lvl_; + bool indoor_; }; using key = node; @@ -47,7 +49,7 @@ struct foot { 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, @@ -60,6 +62,7 @@ struct foot { node_idx_t n_; cost_t cost_; level_t lvl_; + bool indoor_; [[no_unique_address]] Tracking tracking_; }; @@ -67,7 +70,7 @@ struct foot { constexpr std::optional 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, @@ -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_; }; @@ -99,7 +103,8 @@ struct foot { return wyhash::mix( wyhash::hash(static_cast( to_idx(n.lvl_ == kNoLevel ? level_t{0.F} : n.lvl_))), - wyhash::hash(static_cast(to_idx(n.n_)))); + wyhash::mix(wyhash::hash(static_cast(to_idx(n.n_))), + wyhash::hash(n.indoor_))); } }; @@ -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}); } } @@ -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_}); } } } @@ -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(cost), dist, way, from, to, elevation_storage::elevation{}); }); @@ -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(cost), - dist, way, from, to, elevation_storage::elevation{}); + fn(node{target_node, *target_lvl, target_way_prop.is_indoor_}, + static_cast(cost), dist, way, from, to, + elevation_storage::elevation{}); } }; diff --git a/include/osr/ways.h b/include/osr/ways.h index 2dad7cdd..e4fccf3a 100644 --- a/include/osr/ways.h +++ b/include/osr/ways.h @@ -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); diff --git a/src/extract.cc b/src/extract.cc index 1dd93289..7e2c935a 100644 --- a/src/extract.cc +++ b/src/extract.cc @@ -120,6 +120,8 @@ way_properties get_way_properties(tags const& t) { 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; }