19 const std::map<std::string, ClassDefaults> &ClassTable() {
20 static const std::map<std::string, ClassDefaults> table = {
21 {
"motorway", ClassDefaults{3.5, 2, std::nullopt, 2.5, 1.0}},
22 {
"motorway_link", ClassDefaults{3.5, 1, std::nullopt, 1.5, 0.75}},
23 {
"trunk", ClassDefaults{3.5, 2, std::nullopt, 1.5, std::nullopt}},
24 {
"trunk_link", ClassDefaults{3.5, 1, std::nullopt, 1.0, std::nullopt}},
25 {
"primary", ClassDefaults{3.6, 2, 2.0, std::nullopt, std::nullopt}},
26 {
"primary_link", ClassDefaults{3.6, 1, 2.0, std::nullopt, std::nullopt}},
27 {
"secondary", ClassDefaults{3.5, 2, 2.0, std::nullopt, std::nullopt}},
28 {
"secondary_link", ClassDefaults{3.5, 1, 2.0, std::nullopt, std::nullopt}},
29 {
"tertiary", ClassDefaults{3.5, 2, 2.0, std::nullopt, std::nullopt}},
30 {
"tertiary_link", ClassDefaults{3.5, 1, 2.0, std::nullopt, std::nullopt}},
31 {
"unclassified", ClassDefaults{3.5, 2, 2.0, std::nullopt, std::nullopt}},
32 {
"residential", ClassDefaults{3.5, 2, 2.0, std::nullopt, std::nullopt}},
33 {
"living_street", ClassDefaults{3.5, 2, 2.0, std::nullopt, std::nullopt}},
34 {
"pedestrian", ClassDefaults{3.5, 1, 2.0, std::nullopt, std::nullopt}},
35 {
"service", ClassDefaults{3.5, 2, std::nullopt, std::nullopt, std::nullopt}},
40 bool ParseInt(
const std::string &text,
int &out) {
42 std::size_t used = 0u;
43 const int value = std::stoi(text, &used);
54 bool ParseDouble(
const std::string &text,
double &out) {
56 std::size_t used = 0u;
57 const double value = std::stod(text, &used);
71 static const std::set<std::string> drivable = {
72 "motorway",
"motorway_link",
"trunk",
"trunk_link",
"primary",
"primary_link",
73 "secondary",
"secondary_link",
"tertiary",
"tertiary_link",
"unclassified",
74 "residential",
"living_street",
"service"};
75 return drivable.count(
highway) != 0u;
79 const auto &table = ClassTable();
80 const auto it = table.find(
highway);
81 return (it == table.end()) ? nullptr : &it->second;
85 if (value.empty() || value ==
"none" || value ==
"signals") {
89 if (!ParseDouble(value, number) || number <= 0.0) {
92 const bool mph = value.find(
"mph") != std::string::npos;
93 return mph ? number * 0.44704 : number / 3.6;
100 const ClassDefaults &base = (defaults !=
nullptr) ? *defaults : fallback;
107 const std::string *oneway =
FindTag(
tags,
"oneway");
108 profile.
oneway = (oneway !=
nullptr) && (*oneway ==
"yes" || *oneway ==
"1" || *oneway ==
"-1");
113 int total = base.
lanes;
114 const std::string *lanes_tag =
FindTag(
tags,
"lanes");
115 if (lanes_tag !=
nullptr) {
117 if (ParseInt(*lanes_tag, parsed) && parsed > 0) {
130 const std::string *forward_tag =
FindTag(
tags,
"lanes:forward");
131 const std::string *backward_tag =
FindTag(
tags,
"lanes:backward");
133 if (forward_tag !=
nullptr && ParseInt(*forward_tag, parsed) && parsed >= 0) {
136 if (backward_tag !=
nullptr && ParseInt(*backward_tag, parsed) && parsed >= 0) {
140 const std::string *width_tag =
FindTag(
tags,
"width");
141 if (width_tag !=
nullptr) {
144 if (ParseDouble(*width_tag, width) && width > 0.0) {
145 profile.
lane_width = std::max(2.5, width / count);
149 const std::string *maxspeed =
FindTag(
tags,
"maxspeed");
150 if (maxspeed !=
nullptr) {
154 const std::string *sidewalk =
FindTag(
tags,
"sidewalk");
155 if (sidewalk !=
nullptr && (*sidewalk ==
"no" || *sidewalk ==
"none")) {
std::optional< double > ParseMaxSpeed(const std::string &value)
Parse an OSM maxspeed value into m/s; "50", "50 km/h" and "30 mph".
LaneProfile ResolveProfile(const std::string &highway, const Tags &tags)
Resolve the lane layout from the way's tags, falling back to the class defaults.
const std::string * FindTag(const Tags &tags, const std::string &key)
bool IsDrivable(const std::string &highway)
True when the way carries motor traffic and should become a Road.
std::map< std::string, std::string > Tags
const ClassDefaults * FindClassDefaults(const std::string &highway)
Per highway class defaults, ported from profiles.py's _EU_CLASSES.
std::optional< double > shoulder
std::optional< double > sidewalk_width
std::optional< double > shoulder_inner
The lane layout an OSM way resolves to, before it is cut at junctions.
std::optional< double > speed_limit
std::optional< double > shoulder_inner
std::optional< double > sidewalk_width
std::optional< double > shoulder