less new names, forks consider road classes, api clean-up

This commit is contained in:
Moritz Kobitzsch 2016-03-16 15:47:33 +01:00 committed by Patrick Niklaus
parent 831a536224
commit a3cf7f09e8
10 changed files with 392 additions and 44 deletions

View File

@ -0,0 +1,140 @@
@routing @guidance
Feature: Basic Roundabout
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Scenario: Enter and Exit
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | false |
| cd | false |
| ef | false |
| gh | false |
| bcegb | true |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart, roundabout-exit-1, arrive |
| a,f | ab,ef,ef | depart, roundabout-exit-2, arrive |
| a,h | ab,gh,gh | depart, roundabout-exit-3, arrive |
| d,f | cd,ef,ef | depart, roundabout-exit-1, arrive |
| d,h | cd,gh,gh | depart, roundabout-exit-2, arrive |
| d,a | cd,ab,ab | depart, roundabout-exit-3, arrive |
| f,h | ef,gh,gh | depart, roundabout-exit-1, arrive |
| f,a | ef,ab,ab | depart, roundabout-exit-2, arrive |
| f,d | ef,cd,cd | depart, roundabout-exit-3, arrive |
| h,a | gh,ab,ab | depart, roundabout-exit-1, arrive |
| h,d | gh,cd,cd | depart, roundabout-exit-2, arrive |
| h,f | gh,ef,ef | depart, roundabout-exit-3, arrive |
Scenario: Only Enter
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | false |
| cd | false |
| ef | false |
| gh | false |
| bcegb | true |
When I route I should get
| waypoints | route | turns |
| a,b | ab,ab | depart, arrive |
| a,c | ab,bcegb | depart, roundabout-enter, arrive |
| a,e | ab,bcegb | depart, roundabout-enter, arrive |
| a,g | ab,bcegb | depart, roundabout-enter, arrive |
| d,c | cd,cd | depart, arrive |
| d,e | cd,bcegb | depart, roundabout-enter, arrive |
| d,g | cd,bcegb | depart, roundabout-enter, arrive |
| d,b | cd,bcegb | depart, roundabout-enter, arrive |
| f,e | ef,ef | depart, arrive |
| f,g | ef,bcegb | depart, roundabout-enter, arrive |
| f,b | ef,bcegb | depart, roundabout-enter, arrive |
| f,c | ef,bcegb | depart, roundabout-enter, arrive |
| h,g | gh,gh | depart, arrive |
| h,b | gh,bcegb | depart, roundabout-enter, arrive |
| h,c | gh,bcegb | depart, roundabout-enter, arrive |
| h,e | gh,bcegb | depart, roundabout-enter, arrive |
Scenario: Only Exit
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | false |
| cd | false |
| ef | false |
| gh | false |
| bcegb | true |
When I route I should get
| waypoints | route | turns |
| b,a | ab,ab | depart, arrive |
| b,d | bcegb,cd,cd | depart, roundabout-exit-1, arrive |
| b,f | bcegb,ef,ef | depart, roundabout-exit-2, arrive |
| b,h | bcegb,gh,gh | depart, roundabout-exit-3, arrive |
| c,d | cd,cd | depart, arrive |
| c,f | bcegb,ef,ef | depart, roundabout-exit-1, arrive |
| c,h | bcegb,gh,gh | depart, roundabout-exit-2, arrive |
| c,a | bcegb,ab,ab | depart, roundabout-exit-3, arrive |
| e,f | ef,ef | depart, arrive |
| e,h | bcegb,gh,gh | depart, roundabout-exit-1, arrive |
| e,a | bcegb,ab,ab | depart, roundabout-exit-2, arrive |
| e,d | bcegb,cd,cd | depart, roundabout-exit-3, arrive |
| g,h | gh,gh | depart, arrive |
| g,a | bcegb,ab,ab | depart, roundabout-exit-1, arrive |
| g,d | bcegb,cd,cd | depart, roundabout-exit-2, arrive |
| g,f | bcegb,ef,ef | depart, roundabout-exit-3, arrive |
Scenario: Drive Around
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | false |
| cd | false |
| ef | false |
| gh | false |
| bcegb | true |
When I route I should get
| waypoints | route | turns |
| b,c | bcegb,bcegb | depart, arrive |
| b,e | bcegb,bcegb | depart, arrive |
| b,g | bcegb,bcegb | depart, arrive |
| c,e | bcegb,bcegb | depart, arrive |
| c,g | bcegb,bcegb | depart, arrive |
| c,b | bcegb,bcegb | depart, arrive |
| e,g | bcegb,bcegb | depart, arrive |
| e,b | bcegb,bcegb | depart, arrive |
| e,c | bcegb,bcegb | depart, arrive |
| g,b | bcegb,bcegb | depart, arrive |
| g,c | bcegb,bcegb | depart, arrive |
| g,e | bcegb,bcegb | depart, arrive |
Scenario: Mixed Entry and Exit

View File

@ -17,6 +17,7 @@
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include "util/deallocating_vector.hpp" #include "util/deallocating_vector.hpp"
#include "util/name_table.hpp"
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
@ -51,7 +52,8 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &traffic_lights, const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map, std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list, const std::vector<QueryNode> &node_info_list,
SpeedProfileProperties speed_profile); SpeedProfileProperties speed_profile,
const util::NameTable &name_table);
void Run(const std::string &original_edge_data_filename, void Run(const std::string &original_edge_data_filename,
lua_State *lua_state, lua_State *lua_state,
@ -106,6 +108,8 @@ class EdgeBasedGraphFactory
SpeedProfileProperties speed_profile; SpeedProfileProperties speed_profile;
const util::NameTable &name_table;
void CompressGeometry(); void CompressGeometry();
unsigned RenumberEdges(); unsigned RenumberEdges();
void GenerateEdgeExpandedNodes(); void GenerateEdgeExpandedNodes();

View File

@ -12,9 +12,12 @@
#include "extractor/guidance/classification_data.hpp" #include "extractor/guidance/classification_data.hpp"
#include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_instruction.hpp"
#include <algorithm>
#include <map> #include <map>
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <string>
#include <iostream>
namespace osrm namespace osrm
{ {
@ -331,6 +334,73 @@ inline bool isDistinct(const DirectionModifier first, const DirectionModifier se
return true; return true;
} }
inline bool requiresNameAnnounced(const std::string &from, const std::string &to)
{
// FIXME, handle in profile to begin with?
// this uses the encoding of references in the profile, which is very BAD
// Input for this function should be a struct separating streetname, suffix (e.g. road,
// boulevard, North, West ...), and a list of references
std::string from_name = "", from_ref = "", to_name = "", to_ref = "";
auto split = [](const std::string &name, std::string &out_name, std::string &out_ref)
{
const auto ref_begin = name.find_first_of('(');
if (ref_begin != std::string::npos)
{
out_name = name.substr(0, ref_begin);
out_ref = name.substr(ref_begin + 1, name.find_first_of(')') - 1);
}
else
{
out_name = name;
out_ref = "";
}
};
split(from, from_name, from_ref);
split(to, to_name, to_ref);
// check similarity of names
if (from_name != "" && to_name != "")
{
if ((from_name.back() >= '0' && from_name.back() <= '9') ||
(to_name.back() >= '0' && to_name.back() <= '9'))
return from_name != to_name;
if (from.find("Weg ") == 0 && to_name.find("Weg ") == 0)
return from_name != to_name;
auto from_itr = from_name.begin();
auto to_itr = to_name.begin();
for (; from_itr != from_name.end() && to_itr != to_name.end() && *from_itr == *to_itr;
++to_itr, ++from_itr)
{
/* do nothing */
}
const auto common_length = std::distance(from_name.begin(), from_itr);
return (100 * common_length / std::min(to_name.length(), from_name.length())) < 80;
}
else if (from_ref != "" && to_ref != "")
{
// references are contained in one another
if (from_ref.find(to_ref) != std::string::npos ||
to_ref.find(from_ref) != std::string::npos)
return false;
}
return true;
}
inline int getPriority( const FunctionalRoadClass road_class )
{
const constexpr int road_priority[] = {10, 0, 10, 2, 10, 4, 10, 6, 10, 8, 10, 11, 10, 12, 10, 14};
return road_priority[static_cast<int>(road_class)];
}
inline bool canBeSeenAsFork(const FunctionalRoadClass first, const FunctionalRoadClass second)
{
// forks require similar road categories
return std::abs(getPriority(first) - getPriority(second)) <= 1;
}
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor
} // namespace osrm } // namespace osrm

View File

@ -6,6 +6,8 @@
#include "extractor/restriction_map.hpp" #include "extractor/restriction_map.hpp"
#include "extractor/compressed_edge_container.hpp" #include "extractor/compressed_edge_container.hpp"
#include "util/name_table.hpp"
#include <cstdint> #include <cstdint>
#include <string> #include <string>
@ -53,7 +55,8 @@ class TurnAnalysis
const std::vector<QueryNode> &node_info_list, const std::vector<QueryNode> &node_info_list,
const RestrictionMap &restriction_map, const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const CompressedEdgeContainer &compressed_edge_container); const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table);
// the entry into the turn analysis // the entry into the turn analysis
std::vector<TurnCandidate> getTurns(const NodeID from_node, const EdgeID via_eid) const; std::vector<TurnCandidate> getTurns(const NodeID from_node, const EdgeID via_eid) const;
@ -64,6 +67,7 @@ class TurnAnalysis
const RestrictionMap &restriction_map; const RestrictionMap &restriction_map;
const std::unordered_set<NodeID> &barrier_nodes; const std::unordered_set<NodeID> &barrier_nodes;
const CompressedEdgeContainer &compressed_edge_container; const CompressedEdgeContainer &compressed_edge_container;
const util::NameTable &name_table;
// Check for restrictions/barriers and generate a list of valid and invalid turns present at the // Check for restrictions/barriers and generate a list of valid and invalid turns present at the
// node reached // node reached

View File

@ -0,0 +1,26 @@
#ifndef OSRM_UTIL_NAME_TABLE_HPP
#define OSRM_UTIL_NAME_TABLE_HPP
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/range_table.hpp"
#include <string>
namespace osrm
{
namespace util
{
class NameTable
{
private:
//FIXME should this use shared memory
RangeTable<16, false> m_name_table;
ShM<char, false>::vector m_names_char_list;
public:
NameTable( const std::string &filename );
std::string get_name_for_id(const unsigned name_id) const;
};
} // namespace util
} // namespace osrm
#endif // OSRM_UTIL_NAME_TABLE_HPP

View File

@ -28,17 +28,23 @@ namespace json
namespace detail namespace detail
{ {
const constexpr char *modifier_names[] = {"uturn", "sharp right", "right", "slight right", const constexpr char *modifier_names[] = {"uturn",
"straight", "slight left", "left", "sharp left"}; "sharp right",
"right",
"slight right",
"straight",
"slight left",
"left",
"sharp left"};
// translations of TurnTypes. Not all types are exposed to the outside world. // translations of TurnTypes. Not all types are exposed to the outside world.
// invalid types should never be returned as part of the API // invalid types should never be returned as part of the API
const constexpr char *turn_type_names[] = { const constexpr char *turn_type_names[] = {
"invalid", "no turn", "invalid", "new name", "continue", "turn", "invalid", "no turn", "invalid", "new name", "continue", "turn",
"turn", "turn", "turn", "merge", "ramp", "ramp", "turn", "turn", "turn", "turn", "merge", "ramp",
"ramp", "ramp", "fork", "end of road", "roundabout", "invalid", "ramp", "ramp", "ramp", "ramp", "fork", "end of road",
"roundabout", "invalid", "traffic circle", "invalid", "traffic circle", "invalid", "roundabout", "invalid", "roundabout", "invalid", "traffic circle", "invalid",
"invalid", "restriction", "notification"}; "traffic circle", "invalid", "invalid", "restriction", "notification"};
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"}; const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
// Check whether to include a modifier in the result of the API // Check whether to include a modifier in the result of the API
@ -50,23 +56,6 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
return true; return true;
} }
inline bool isMultiTurn(const TurnType type)
{
return (type == TurnType::FirstTurn || type == TurnType::SecondTurn ||
type == TurnType::ThirdTurn);
}
inline std::string getCount(const TurnType type)
{
if (type == TurnType::FirstTurn)
return "1";
if (type == TurnType::SecondTurn)
return "2";
if (type == TurnType::ThirdTurn)
return "3";
return "0";
}
std::string instructionTypeToString(const TurnType type) std::string instructionTypeToString(const TurnType type)
{ {
return turn_type_names[static_cast<std::size_t>(type)]; return turn_type_names[static_cast<std::size_t>(type)];
@ -152,8 +141,6 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
else else
step_maneuver.values["type"] = detail::waypointTypeToString(maneuver.waypoint_type); step_maneuver.values["type"] = detail::waypointTypeToString(maneuver.waypoint_type);
if (detail::isMultiTurn(maneuver.instruction.type))
step_maneuver.values["count"] = detail::getCount(maneuver.instruction.type);
if (detail::isValidModifier(maneuver)) if (detail::isValidModifier(maneuver))
step_maneuver.values["modifier"] = step_maneuver.values["modifier"] =
detail::instructionModifierToString(maneuver.instruction.direction_modifier); detail::instructionModifierToString(maneuver.instruction.direction_modifier);

View File

@ -35,12 +35,13 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const std::unordered_set<NodeID> &traffic_lights, const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map, std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list, const std::vector<QueryNode> &node_info_list,
SpeedProfileProperties speed_profile) SpeedProfileProperties speed_profile,
const util::NameTable &name_table)
: m_max_edge_id(0), m_node_info_list(node_info_list), : m_max_edge_id(0), m_node_info_list(node_info_list),
m_node_based_graph(std::move(node_based_graph)), m_node_based_graph(std::move(node_based_graph)),
m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes), m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes),
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container), m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
speed_profile(std::move(speed_profile)) speed_profile(std::move(speed_profile)), name_table(name_table)
{ {
} }
@ -124,10 +125,9 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
// traverse arrays from start and end respectively // traverse arrays from start and end respectively
for (const auto i : util::irange(0UL, geometry_size)) for (const auto i : util::irange(0UL, geometry_size))
{ {
BOOST_ASSERT( BOOST_ASSERT(current_edge_source_coordinate_id ==
current_edge_source_coordinate_id == m_compressed_edge_container.GetBucketReference(
m_compressed_edge_container.GetBucketReference(edge_id_2)[geometry_size - 1 - i] edge_id_2)[geometry_size - 1 - i].node_id);
.node_id);
const NodeID current_edge_target_coordinate_id = forward_geometry[i].node_id; const NodeID current_edge_target_coordinate_id = forward_geometry[i].node_id;
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id); BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
@ -305,8 +305,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// Three nested loop look super-linear, but we are dealing with a (kind of) // Three nested loop look super-linear, but we are dealing with a (kind of)
// linear number of turns only. // linear number of turns only.
util::Percent progress(m_node_based_graph->GetNumberOfNodes()); util::Percent progress(m_node_based_graph->GetNumberOfNodes());
guidance::TurnAnalysis turn_analysis( *m_node_based_graph, m_node_info_list, guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
*m_restriction_map, m_barrier_nodes, m_compressed_edge_container ); m_barrier_nodes, m_compressed_edge_container, name_table);
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes())) for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{ {
// progress.printStatus(node_u); // progress.printStatus(node_u);

View File

@ -15,6 +15,7 @@
#include "util/timing_util.hpp" #include "util/timing_util.hpp"
#include "util/lua_util.hpp" #include "util/lua_util.hpp"
#include "util/graph_loader.hpp" #include "util/graph_loader.hpp"
#include "util/name_table.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
@ -521,10 +522,12 @@ Extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_n
compressed_edge_container.SerializeInternalVector(config.geometry_output_path); compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
util::NameTable name_table(config.names_file_name);
EdgeBasedGraphFactory edge_based_graph_factory( EdgeBasedGraphFactory edge_based_graph_factory(
node_based_graph, compressed_edge_container, barrier_nodes, traffic_lights, node_based_graph, compressed_edge_container, barrier_nodes, traffic_lights,
std::const_pointer_cast<RestrictionMap const>(restriction_map), std::const_pointer_cast<RestrictionMap const>(restriction_map),
internal_to_external_node_map, speed_profile); internal_to_external_node_map, speed_profile, name_table);
edge_based_graph_factory.Run(config.edge_output_path, lua_state, edge_based_graph_factory.Run(config.edge_output_path, lua_state,
config.edge_segment_lookup_path, config.edge_penalty_path, config.edge_segment_lookup_path, config.edge_penalty_path,

View File

@ -55,10 +55,11 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list, const std::vector<QueryNode> &node_info_list,
const RestrictionMap &restriction_map, const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const CompressedEdgeContainer &compressed_edge_container) const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table)
: node_based_graph(node_based_graph), node_info_list(node_info_list), : node_based_graph(node_based_graph), node_info_list(node_info_list),
restriction_map(restriction_map), barrier_nodes(barrier_nodes), restriction_map(restriction_map), barrier_nodes(barrier_nodes),
compressed_edge_container(compressed_edge_container) compressed_edge_container(compressed_edge_container), name_table(name_table)
{ {
} }
@ -784,7 +785,9 @@ TurnInstruction TurnAnalysis::getInstructionForObvious(const std::size_t num_can
{ {
const auto &in_data = node_based_graph.GetEdgeData(via_edge); const auto &in_data = node_based_graph.GetEdgeData(via_edge);
const auto &out_data = node_based_graph.GetEdgeData(candidate.eid); const auto &out_data = node_based_graph.GetEdgeData(candidate.eid);
if (in_data.name_id != out_data.name_id) if (in_data.name_id != out_data.name_id &&
requiresNameAnnounced(name_table.get_name_for_id(in_data.name_id),
name_table.get_name_for_id(out_data.name_id)))
return {TurnType::NewName, getTurnDirection(candidate.angle)}; return {TurnType::NewName, getTurnDirection(candidate.angle)};
else else
return {TurnType::Suppressed, getTurnDirection(candidate.angle)}; return {TurnType::Suppressed, getTurnDirection(candidate.angle)};
@ -859,6 +862,7 @@ std::vector<TurnCandidate> TurnAnalysis::handleThreeWayTurn(
angularDeviation(turn.angle, STRAIGHT_ANGLE) > angularDeviation(turn.angle, STRAIGHT_ANGLE) >
1.4); 1.4);
}; };
/* Two nearly straight turns -> FORK /* Two nearly straight turns -> FORK
OOOOOOO OOOOOOO
/ /
@ -871,7 +875,26 @@ std::vector<TurnCandidate> TurnAnalysis::handleThreeWayTurn(
{ {
if (turn_candidates[1].valid && turn_candidates[2].valid) if (turn_candidates[1].valid && turn_candidates[2].valid)
{ {
assignFork(via_edge, turn_candidates[2], turn_candidates[1]); const auto left_class =
node_based_graph.GetEdgeData(turn_candidates[2].eid).road_classification.road_class;
const auto right_class =
node_based_graph.GetEdgeData(turn_candidates[1].eid).road_classification.road_class;
if (canBeSeenAsFork(left_class, right_class))
assignFork(via_edge, turn_candidates[2], turn_candidates[1]);
else if (getPriority(left_class) > getPriority(right_class))
{
turn_candidates[1].instruction =
getInstructionForObvious(turn_candidates.size(), via_edge, turn_candidates[1]);
turn_candidates[2].instruction = {findBasicTurnType(via_edge, turn_candidates[2]),
DirectionModifier::SlightLeft};
}
else
{
turn_candidates[2].instruction =
getInstructionForObvious(turn_candidates.size(), via_edge, turn_candidates[2]);
turn_candidates[1].instruction = {findBasicTurnType(via_edge, turn_candidates[1]),
DirectionModifier::SlightRight};
}
} }
else else
{ {
@ -1073,7 +1096,27 @@ void TurnAnalysis::handleDistinctConflict(const EdgeID via_edge,
if (getTurnDirection(left.angle) == DirectionModifier::Straight || if (getTurnDirection(left.angle) == DirectionModifier::Straight ||
getTurnDirection(left.angle) == DirectionModifier::SlightLeft || getTurnDirection(left.angle) == DirectionModifier::SlightLeft ||
getTurnDirection(right.angle) == DirectionModifier::SlightRight) getTurnDirection(right.angle) == DirectionModifier::SlightRight)
assignFork(via_edge, left, right); {
const auto left_class =
node_based_graph.GetEdgeData(left.eid).road_classification.road_class;
const auto right_class =
node_based_graph.GetEdgeData(right.eid).road_classification.road_class;
if (canBeSeenAsFork(left_class, right_class))
assignFork(via_edge, left, right);
else if (getPriority(left_class) > getPriority(right_class))
{
// FIXME this should possibly know about the actual candidates?
right.instruction = getInstructionForObvious(4, via_edge, right);
left.instruction = {findBasicTurnType(via_edge, left), DirectionModifier::SlightLeft};
}
else
{
// FIXME this should possibly know about the actual candidates?
left.instruction = getInstructionForObvious(4, via_edge, left);
right.instruction = {findBasicTurnType(via_edge, right),
DirectionModifier::SlightRight};
}
}
const auto left_type = findBasicTurnType(via_edge, left); const auto left_type = findBasicTurnType(via_edge, left);
const auto right_type = findBasicTurnType(via_edge, right); const auto right_type = findBasicTurnType(via_edge, right);
@ -1196,8 +1239,27 @@ std::vector<TurnCandidate> TurnAnalysis::handleComplexTurn(
{ {
if (fork_range.second - fork_range.first == 1) if (fork_range.second - fork_range.first == 1)
{ {
assignFork(via_edge, turn_candidates[fork_range.second], auto &left = turn_candidates[fork_range.second];
turn_candidates[fork_range.first]); auto &right = turn_candidates[fork_range.first];
const auto left_class =
node_based_graph.GetEdgeData(left.eid).road_classification.road_class;
const auto right_class =
node_based_graph.GetEdgeData(right.eid).road_classification.road_class;
if (canBeSeenAsFork(left_class, right_class))
assignFork(via_edge, left, right);
else if (getPriority(left_class) > getPriority(right_class))
{
right.instruction =
getInstructionForObvious(turn_candidates.size(), via_edge, right);
left.instruction = {findBasicTurnType(via_edge, left),
DirectionModifier::SlightLeft};
}
else
{
left.instruction = getInstructionForObvious(turn_candidates.size(), via_edge, left);
right.instruction = {findBasicTurnType(via_edge, right),
DirectionModifier::SlightRight};
}
} }
else if (fork_range.second - fork_range.second == 2) else if (fork_range.second - fork_range.second == 2)
{ {

52
src/util/name_table.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "util/name_table.hpp"
#include "util/simple_logger.hpp"
#include <algorithm>
#include <limits>
#include <fstream>
#include <boost/filesystem/fstream.hpp>
namespace osrm
{
namespace util
{
NameTable::NameTable(const std::string &filename)
{
boost::filesystem::ifstream name_stream(filename, std::ios::binary);
name_stream >> m_name_table;
unsigned number_of_chars = 0;
name_stream.read(reinterpret_cast<char *>(&number_of_chars), sizeof(number_of_chars));
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
name_stream.read(reinterpret_cast<char *>(&m_names_char_list[0]),
number_of_chars * sizeof(m_names_char_list[0]));
if (0 == m_names_char_list.size())
{
util::SimpleLogger().Write(logWARNING) << "list of street names is empty";
}
}
std::string NameTable::get_name_for_id(const unsigned name_id) const
{
if (std::numeric_limits<unsigned>::max() == name_id)
{
return "";
}
auto range = m_name_table.GetRange(name_id);
std::string result;
result.reserve(range.size());
if (range.begin() != range.end())
{
result.resize(range.back() - range.front() + 1);
std::copy(m_names_char_list.begin() + range.front(),
m_names_char_list.begin() + range.back() + 1, result.begin());
}
return result;
}
} // namespace util
} // namespace osrm