enable suppression name suffix changes
This commit is contained in:
parent
fddb035539
commit
a154d71841
@ -2,6 +2,11 @@
|
|||||||
- API:
|
- API:
|
||||||
- added roundabout-turn instruction. The instruction indicates a small roundabout that is treated as an intersection
|
- added roundabout-turn instruction. The instruction indicates a small roundabout that is treated as an intersection
|
||||||
(turn right at the roundabout for first exit, go straight at the roundabout...)
|
(turn right at the roundabout for first exit, go straight at the roundabout...)
|
||||||
|
- reduced new name instructions for trivial changes
|
||||||
|
- combined multiple turns into a single instruction at segregated roads`
|
||||||
|
|
||||||
|
- Profile Changes:
|
||||||
|
- introduced a suffix_list / get_name_suffix_list to specify name suffices to be suppressed in name change announcements
|
||||||
|
|
||||||
- Infrastructure
|
- Infrastructure
|
||||||
- BREAKING: reordered internal instruction types. This breaks the data format
|
- BREAKING: reordered internal instruction types. This breaks the data format
|
||||||
|
62
features/guidance/suffix-changes.feature
Normal file
62
features/guidance/suffix-changes.feature
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
@routing @guidance
|
||||||
|
Feature: Suppress New Names on dedicated Suffices
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
|
||||||
|
Scenario: Suffix To Suffix
|
||||||
|
Given the node map
|
||||||
|
| a | | b | | c |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name |
|
||||||
|
| ab | 42 N |
|
||||||
|
| bc | 42 S |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,c | 42 N,42 S | depart,arrive |
|
||||||
|
|
||||||
|
Scenario: Suffix To Suffix - Turn
|
||||||
|
Given the node map
|
||||||
|
| a | | b | | c |
|
||||||
|
| | | d | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name |
|
||||||
|
| ab | 42 N |
|
||||||
|
| bc | 42 S |
|
||||||
|
| bd | 42 E |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,c | 42 N,42 S | depart,arrive |
|
||||||
|
| a,d | 42 N,42 E,42 E | depart,turn right,arrive |
|
||||||
|
|
||||||
|
Scenario: Suffix To No Suffix
|
||||||
|
Given the node map
|
||||||
|
| a | | b | | c |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name |
|
||||||
|
| ab | 42 N |
|
||||||
|
| bc | 42 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,c | 42 N,42 | depart,arrive |
|
||||||
|
|
||||||
|
Scenario: No Suffix To Suffix
|
||||||
|
Given the node map
|
||||||
|
| a | | b | | c |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name |
|
||||||
|
| ab | 42 |
|
||||||
|
| bc | 42 S |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,c | 42,42 S | depart,arrive |
|
||||||
|
|
@ -79,7 +79,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
|
|
||||||
// some name changes are not announced in our processing. For these, we have to keep the
|
// some name changes are not announced in our processing. For these, we have to keep the
|
||||||
// first name on the segment
|
// first name on the segment
|
||||||
unsigned step_name_id = source_node.name_id;
|
auto step_name_id = source_node.name_id;
|
||||||
for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index)
|
for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index)
|
||||||
{
|
{
|
||||||
const auto &path_point = leg_data[leg_data_index];
|
const auto &path_point = leg_data[leg_data_index];
|
||||||
|
@ -65,8 +65,8 @@ inline extractor::guidance::DirectionModifier angleToDirectionModifier(const dou
|
|||||||
|
|
||||||
inline double angularDeviation(const double angle, const double from)
|
inline double angularDeviation(const double angle, const double from)
|
||||||
{
|
{
|
||||||
const double deviation = std::abs(angle - from);
|
const double deviation = std::abs(angle - from);
|
||||||
return std::min(360 - deviation, deviation);
|
return std::min(360 - deviation, deviation);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "extractor/guidance/intersection.hpp"
|
#include "extractor/guidance/intersection.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
|
#include "extractor/suffix_table.hpp"
|
||||||
|
|
||||||
#include "util/name_table.hpp"
|
#include "util/name_table.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
@ -26,7 +27,8 @@ class IntersectionHandler
|
|||||||
public:
|
public:
|
||||||
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table);
|
const util::NameTable &name_table,
|
||||||
|
const SuffixTable &street_name_suffix_table);
|
||||||
virtual ~IntersectionHandler();
|
virtual ~IntersectionHandler();
|
||||||
|
|
||||||
// check whether the handler can actually handle the intersection
|
// check whether the handler can actually handle the intersection
|
||||||
@ -41,6 +43,7 @@ class IntersectionHandler
|
|||||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||||
const std::vector<QueryNode> &node_info_list;
|
const std::vector<QueryNode> &node_info_list;
|
||||||
const util::NameTable &name_table;
|
const util::NameTable &name_table;
|
||||||
|
const SuffixTable &street_name_suffix_table;
|
||||||
|
|
||||||
// counts the number on allowed entry roads
|
// counts the number on allowed entry roads
|
||||||
std::size_t countValid(const Intersection &intersection) const;
|
std::size_t countValid(const Intersection &intersection) const;
|
||||||
|
@ -24,7 +24,8 @@ class MotorwayHandler : public IntersectionHandler
|
|||||||
public:
|
public:
|
||||||
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table);
|
const util::NameTable &name_table,
|
||||||
|
const SuffixTable &street_name_suffix_table);
|
||||||
~MotorwayHandler() override final;
|
~MotorwayHandler() override final;
|
||||||
|
|
||||||
// check whether the handler can actually handle the intersection
|
// check whether the handler can actually handle the intersection
|
||||||
|
@ -40,8 +40,9 @@ class RoundaboutHandler : public IntersectionHandler
|
|||||||
public:
|
public:
|
||||||
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
const util::NameTable &name_table,
|
const util::NameTable &name_table,
|
||||||
const CompressedEdgeContainer &compressed_edge_container);
|
const SuffixTable &street_name_suffix_table);
|
||||||
|
|
||||||
~RoundaboutHandler() override final;
|
~RoundaboutHandler() override final;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "extractor/compressed_edge_container.hpp"
|
#include "extractor/compressed_edge_container.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
|
#include "extractor/suffix_table.hpp"
|
||||||
|
|
||||||
#include "extractor/guidance/classification_data.hpp"
|
#include "extractor/guidance/classification_data.hpp"
|
||||||
#include "extractor/guidance/discrete_angle.hpp"
|
#include "extractor/guidance/discrete_angle.hpp"
|
||||||
@ -20,6 +21,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -305,7 +307,9 @@ inline bool isDistinct(const DirectionModifier first, const DirectionModifier se
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool requiresNameAnnounced(const std::string &from, const std::string &to)
|
inline bool requiresNameAnnounced(const std::string &from,
|
||||||
|
const std::string &to,
|
||||||
|
const SuffixTable &suffix_table)
|
||||||
{
|
{
|
||||||
// FIXME, handle in profile to begin with?
|
// FIXME, handle in profile to begin with?
|
||||||
// this uses the encoding of references in the profile, which is very BAD
|
// this uses the encoding of references in the profile, which is very BAD
|
||||||
@ -332,12 +336,19 @@ inline bool requiresNameAnnounced(const std::string &from, const std::string &to
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const auto getCommonLength = [](const std::string &first, const std::string &second) {
|
||||||
|
BOOST_ASSERT(first.size() <= second.size());
|
||||||
|
const auto mismatch_result = std::mismatch(first.begin(), first.end(), second.begin());
|
||||||
|
return std::distance(first.begin(), mismatch_result.first);
|
||||||
|
};
|
||||||
|
|
||||||
split(from, from_name, from_ref);
|
split(from, from_name, from_ref);
|
||||||
split(to, to_name, to_ref);
|
split(to, to_name, to_ref);
|
||||||
|
|
||||||
// check similarity of names
|
// check similarity of names
|
||||||
const auto names_are_empty = from_name.empty() && to_name.empty();
|
const auto names_are_empty = from_name.empty() && to_name.empty();
|
||||||
const auto name_is_contained = boost::starts_with(from_name,to_name) || boost::starts_with(to_name,from_name);
|
const auto name_is_contained =
|
||||||
|
boost::starts_with(from_name, to_name) || boost::starts_with(to_name, from_name);
|
||||||
const auto names_are_equal = from_name == to_name || name_is_contained;
|
const auto names_are_equal = from_name == to_name || name_is_contained;
|
||||||
const auto name_is_removed = !from_name.empty() && to_name.empty();
|
const auto name_is_removed = !from_name.empty() && to_name.empty();
|
||||||
// references are contained in one another
|
// references are contained in one another
|
||||||
@ -347,9 +358,41 @@ inline bool requiresNameAnnounced(const std::string &from, const std::string &to
|
|||||||
(from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos);
|
(from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos);
|
||||||
const auto ref_is_removed = !from_ref.empty() && to_ref.empty();
|
const auto ref_is_removed = !from_ref.empty() && to_ref.empty();
|
||||||
|
|
||||||
const auto obvious_change =
|
const auto checkForSuffixChange = [](const std::size_t common_length, const std::string &first,
|
||||||
(names_are_empty && refs_are_empty) || (names_are_equal && ref_is_contained) ||
|
const std::string &second,
|
||||||
(names_are_equal && refs_are_empty) || name_is_removed || ref_is_removed;
|
const SuffixTable &suffix_table) {
|
||||||
|
if (0 == common_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto endsOnSuffix = [](const std::size_t trim_length,
|
||||||
|
const std::string &string_with_possible_suffix,
|
||||||
|
const SuffixTable &suffix_table) {
|
||||||
|
auto suffix =
|
||||||
|
string_with_possible_suffix.size() > trim_length
|
||||||
|
? string_with_possible_suffix.substr(
|
||||||
|
trim_length + (string_with_possible_suffix[trim_length] == ' ' ? 1 : 0))
|
||||||
|
: " ";
|
||||||
|
boost::algorithm::to_lower(suffix);
|
||||||
|
return suffix.empty() || suffix_table.isSuffix(suffix);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto first_delta_is_suffix = endsOnSuffix(common_length, first, suffix_table);
|
||||||
|
const auto second_delta_is_suffix = endsOnSuffix(common_length, second, suffix_table);
|
||||||
|
|
||||||
|
return first_delta_is_suffix && second_delta_is_suffix;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto common_length = from_name.size() < to_name.size()
|
||||||
|
? getCommonLength(from_name, to_name)
|
||||||
|
: getCommonLength(to_name, from_name);
|
||||||
|
|
||||||
|
const auto is_suffix_change =
|
||||||
|
checkForSuffixChange(common_length, from_name, to_name, suffix_table);
|
||||||
|
|
||||||
|
const auto obvious_change = (names_are_empty && refs_are_empty) ||
|
||||||
|
(names_are_equal && ref_is_contained) ||
|
||||||
|
(names_are_equal && refs_are_empty) || name_is_removed ||
|
||||||
|
ref_is_removed || is_suffix_change;
|
||||||
|
|
||||||
return !obvious_change;
|
return !obvious_change;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "extractor/guidance/turn_handler.hpp"
|
#include "extractor/guidance/turn_handler.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
#include "extractor/restriction_map.hpp"
|
#include "extractor/restriction_map.hpp"
|
||||||
|
#include "extractor/suffix_table.hpp"
|
||||||
|
|
||||||
#include "util/name_table.hpp"
|
#include "util/name_table.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
@ -39,7 +40,8 @@ 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);
|
const util::NameTable &name_table,
|
||||||
|
const SuffixTable &street_name_suffix_table);
|
||||||
|
|
||||||
// the entry into the turn analysis
|
// the entry into the turn analysis
|
||||||
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
|
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
|
||||||
|
@ -26,7 +26,8 @@ class TurnHandler : public IntersectionHandler
|
|||||||
public:
|
public:
|
||||||
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table);
|
const util::NameTable &name_table,
|
||||||
|
const SuffixTable &street_name_suffix_table);
|
||||||
~TurnHandler() override final;
|
~TurnHandler() override final;
|
||||||
|
|
||||||
// check whether the handler can actually handle the intersection
|
// check whether the handler can actually handle the intersection
|
||||||
|
30
include/extractor/suffix_table.hpp
Normal file
30
include/extractor/suffix_table.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef OSRM_EXTRACTOR_SUFFIX_LIST_HPP_
|
||||||
|
#define OSRM_EXTRACTOR_SUFFIX_LIST_HPP_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
struct lua_State;
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
// A table containing suffixes.
|
||||||
|
// At the moment, it is only a front for an unordered set. At some point we might want to make it
|
||||||
|
// country dependent and have it behave accordingly
|
||||||
|
class SuffixTable final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SuffixTable(lua_State *lua_state);
|
||||||
|
|
||||||
|
// check whether a string is part of the know suffix list
|
||||||
|
bool isSuffix(const std::string &possible_suffix) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_set<std::string> suffix_set;
|
||||||
|
};
|
||||||
|
} /* namespace extractor */
|
||||||
|
} /* namespace osrm */
|
||||||
|
|
||||||
|
#endif /* OSRM_EXTRACTOR_SUFFIX_LIST_HPP_ */
|
@ -11,6 +11,9 @@ access_tags_hierarchy = { "motorcar", "motor_vehicle", "vehicle", "access" }
|
|||||||
service_tag_restricted = { ["parking_aisle"] = true }
|
service_tag_restricted = { ["parking_aisle"] = true }
|
||||||
restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
||||||
|
|
||||||
|
-- A list of suffixes to suppress in name change instructions
|
||||||
|
suffix_list = { "N", "NE", "E", "SE", "S", "SW", "W", "NW" }
|
||||||
|
|
||||||
speed_profile = {
|
speed_profile = {
|
||||||
["motorway"] = 90,
|
["motorway"] = 90,
|
||||||
["motorway_link"] = 45,
|
["motorway_link"] = 45,
|
||||||
@ -150,6 +153,12 @@ local max = math.max
|
|||||||
|
|
||||||
local speed_reduction = 0.8
|
local speed_reduction = 0.8
|
||||||
|
|
||||||
|
function get_name_suffix_list(vector)
|
||||||
|
for index,suffix in ipairs(suffix_list) do
|
||||||
|
vector:Add(suffix)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function get_exceptions(vector)
|
function get_exceptions(vector)
|
||||||
for i,v in ipairs(restriction_exception_tags) do
|
for i,v in ipairs(restriction_exception_tags) do
|
||||||
vector:Add(v)
|
vector:Add(v)
|
||||||
|
@ -28,6 +28,9 @@ with open(profile_path) as f:
|
|||||||
|
|
||||||
n_errors = 0
|
n_errors = 0
|
||||||
for n, line in enumerate(profile):
|
for n, line in enumerate(profile):
|
||||||
|
# allow arbitrary suffix lists
|
||||||
|
if line.strip().startswith("suffix_list"):
|
||||||
|
continue
|
||||||
# ignore comments
|
# ignore comments
|
||||||
if line.strip().startswith("--"):
|
if line.strip().startswith("--"):
|
||||||
continue
|
continue
|
||||||
|
@ -29,14 +29,26 @@ namespace engine
|
|||||||
namespace guidance
|
namespace guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
// invalidate a step and set its content to nothing
|
||||||
|
void invalidateStep(RouteStep &step)
|
||||||
|
{
|
||||||
|
step = {};
|
||||||
|
step.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||||
|
};
|
||||||
|
|
||||||
void print(const std::vector<RouteStep> &steps)
|
void print(const std::vector<RouteStep> &steps)
|
||||||
{
|
{
|
||||||
std::cout << "Path\n";
|
std::cout << "Path\n";
|
||||||
int segment = 0;
|
int segment = 0;
|
||||||
for (const auto &step : steps)
|
for (const auto &step : steps)
|
||||||
{
|
{
|
||||||
const auto type = static_cast<int>(step.maneuver.instruction.type);
|
const auto type =
|
||||||
const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier);
|
static_cast<std::underlying_type<TurnType>::type>(step.maneuver.instruction.type);
|
||||||
|
const auto modifier = static_cast<std::underlying_type<DirectionModifier>::type>(
|
||||||
|
step.maneuver.instruction.direction_modifier);
|
||||||
|
|
||||||
std::cout << "\t[" << ++segment << "]: " << type << " " << modifier
|
std::cout << "\t[" << ++segment << "]: " << type << " " << modifier
|
||||||
<< " Duration: " << step.duration << " Distance: " << step.distance
|
<< " Duration: " << step.duration << " Distance: " << step.distance
|
||||||
@ -53,37 +65,6 @@ void print(const std::vector<RouteStep> &steps)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
void print(const std::vector<RouteStep> &steps)
|
|
||||||
{
|
|
||||||
std::cout << "Path\n";
|
|
||||||
int segment = 0;
|
|
||||||
for (const auto &step : steps)
|
|
||||||
{
|
|
||||||
const auto type = static_cast<int>(step.maneuver.instruction.type);
|
|
||||||
const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier);
|
|
||||||
|
|
||||||
std::cout << "\t[" << ++segment << "]: " << type << " " << modifier
|
|
||||||
<< " Duration: " << step.duration << " Distance: " << step.distance
|
|
||||||
<< " Geometry: " << step.geometry_begin << " " << step.geometry_end
|
|
||||||
<< " exit: " << step.maneuver.exit
|
|
||||||
<< " Intersections: " << step.maneuver.intersections.size() << " [";
|
|
||||||
|
|
||||||
for (auto intersection : step.maneuver.intersections)
|
|
||||||
std::cout << "(" << intersection.duration << " " << intersection.distance << ")";
|
|
||||||
|
|
||||||
std::cout << "] name[" << step.name_id << "]: " << step.name << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool canMergeTrivially(const RouteStep &destination, const RouteStep &source)
|
|
||||||
{
|
|
||||||
return destination.maneuver.exit == 0 && destination.name_id == source.name_id &&
|
|
||||||
isSilent(source.maneuver.instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
|
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
|
||||||
{
|
{
|
||||||
// Merge a turn into a silent turn
|
// Merge a turn into a silent turn
|
||||||
@ -95,13 +76,6 @@ RouteStep forwardInto(RouteStep destination, const RouteStep &source)
|
|||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
// invalidate a step and set its content to nothing
|
|
||||||
inline void invalidateStep(RouteStep &step)
|
|
||||||
{
|
|
||||||
step = {};
|
|
||||||
step.maneuver.instruction = TurnInstruction::NO_TURN();
|
|
||||||
};
|
|
||||||
|
|
||||||
void fixFinalRoundabout(std::vector<RouteStep> &steps)
|
void fixFinalRoundabout(std::vector<RouteStep> &steps)
|
||||||
{
|
{
|
||||||
for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0;
|
for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0;
|
||||||
@ -194,7 +168,7 @@ void closeOffRoundabout(const bool on_roundabout,
|
|||||||
BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) ||
|
BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) ||
|
||||||
steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout);
|
steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout);
|
||||||
steps[0].geometry_end = 1;
|
steps[0].geometry_end = 1;
|
||||||
steps[1] = detail::forwardInto(steps[1], steps[0]);
|
steps[1] = forwardInto(steps[1], steps[0]);
|
||||||
steps[0].duration = 0;
|
steps[0].duration = 0;
|
||||||
steps[0].distance = 0;
|
steps[0].distance = 0;
|
||||||
const auto exitToEnter = [](const TurnType type) {
|
const auto exitToEnter = [](const TurnType type) {
|
||||||
@ -223,7 +197,7 @@ void closeOffRoundabout(const bool on_roundabout,
|
|||||||
--propagation_index)
|
--propagation_index)
|
||||||
{
|
{
|
||||||
auto &propagation_step = steps[propagation_index];
|
auto &propagation_step = steps[propagation_index];
|
||||||
propagation_step = detail::forwardInto(propagation_step, steps[propagation_index + 1]);
|
propagation_step = forwardInto(propagation_step, steps[propagation_index + 1]);
|
||||||
if (entersRoundabout(propagation_step.maneuver.instruction))
|
if (entersRoundabout(propagation_step.maneuver.instruction))
|
||||||
{
|
{
|
||||||
propagation_step.maneuver.exit = step.maneuver.exit;
|
propagation_step.maneuver.exit = step.maneuver.exit;
|
||||||
@ -334,7 +308,7 @@ RouteStep elongate(RouteStep step, const RouteStep &by_step)
|
|||||||
// A check whether two instructions can be treated as one. This is only the case for very short
|
// A check whether two instructions can be treated as one. This is only the case for very short
|
||||||
// maneuvers that can, in some form, be seen as one. The additional in_step is to find out about
|
// maneuvers that can, in some form, be seen as one. The additional in_step is to find out about
|
||||||
// a possible u-turn.
|
// a possible u-turn.
|
||||||
inline bool collapsable(const RouteStep &step)
|
bool collapsable(const RouteStep &step)
|
||||||
{
|
{
|
||||||
const constexpr double MAX_COLLAPSE_DISTANCE = 25;
|
const constexpr double MAX_COLLAPSE_DISTANCE = 25;
|
||||||
return step.distance < MAX_COLLAPSE_DISTANCE;
|
return step.distance < MAX_COLLAPSE_DISTANCE;
|
||||||
@ -345,6 +319,8 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
const std::size_t one_back_index,
|
const std::size_t one_back_index,
|
||||||
const std::size_t step_index)
|
const std::size_t step_index)
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(step_index < steps.size());
|
||||||
|
BOOST_ASSERT(one_back_index < steps.size());
|
||||||
const auto ¤t_step = steps[step_index];
|
const auto ¤t_step = steps[step_index];
|
||||||
|
|
||||||
const auto &one_back_step = steps[one_back_index];
|
const auto &one_back_step = steps[one_back_index];
|
||||||
@ -357,6 +333,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
// Very Short New Name
|
// Very Short New Name
|
||||||
if (TurnType::NewName == one_back_step.maneuver.instruction.type)
|
if (TurnType::NewName == one_back_step.maneuver.instruction.type)
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
if (one_back_step.mode == steps[two_back_index].mode)
|
if (one_back_step.mode == steps[two_back_index].mode)
|
||||||
{
|
{
|
||||||
steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step);
|
steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step);
|
||||||
@ -387,6 +364,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
current_step.maneuver.bearing_after))
|
current_step.maneuver.bearing_after))
|
||||||
|
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
// the simple case is a u-turn that changes directly into the in-name again
|
// the simple case is a u-turn that changes directly into the in-name again
|
||||||
const bool direct_u_turn = steps[two_back_index].name == current_step.name;
|
const bool direct_u_turn = steps[two_back_index].name == current_step.name;
|
||||||
|
|
||||||
@ -420,7 +398,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace
|
||||||
|
|
||||||
// Post processing can invalidate some instructions. For example StayOnRoundabout
|
// Post processing can invalidate some instructions. For example StayOnRoundabout
|
||||||
// is turned into exit counts. These instructions are removed by the following function
|
// is turned into exit counts. These instructions are removed by the following function
|
||||||
@ -469,7 +447,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
|||||||
into.maneuver.intersections.push_back(
|
into.maneuver.intersections.push_back(
|
||||||
{last_step.duration, last_step.distance, intersection.maneuver.location});
|
{last_step.duration, last_step.distance, intersection.maneuver.location});
|
||||||
|
|
||||||
return detail::forwardInto(std::move(into), intersection);
|
return forwardInto(std::move(into), intersection);
|
||||||
};
|
};
|
||||||
|
|
||||||
// count the exits forward. if enter/exit roundabout happen both, no further treatment is
|
// count the exits forward. if enter/exit roundabout happen both, no further treatment is
|
||||||
@ -484,7 +462,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
|||||||
if (entersRoundabout(instruction))
|
if (entersRoundabout(instruction))
|
||||||
{
|
{
|
||||||
last_valid_instruction = step_index;
|
last_valid_instruction = step_index;
|
||||||
has_entered_roundabout = detail::setUpRoundabout(step);
|
has_entered_roundabout = setUpRoundabout(step);
|
||||||
|
|
||||||
if (has_entered_roundabout && step_index + 1 < steps.size())
|
if (has_entered_roundabout && step_index + 1 < steps.size())
|
||||||
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
|
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
|
||||||
@ -506,7 +484,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
|||||||
// the first valid instruction
|
// the first valid instruction
|
||||||
last_valid_instruction = 1;
|
last_valid_instruction = 1;
|
||||||
}
|
}
|
||||||
detail::closeOffRoundabout(has_entered_roundabout, steps, step_index);
|
closeOffRoundabout(has_entered_roundabout, steps, step_index);
|
||||||
has_entered_roundabout = false;
|
has_entered_roundabout = false;
|
||||||
on_roundabout = false;
|
on_roundabout = false;
|
||||||
}
|
}
|
||||||
@ -529,7 +507,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
|||||||
// A roundabout without exit translates to enter-roundabout.
|
// A roundabout without exit translates to enter-roundabout.
|
||||||
if (has_entered_roundabout || on_roundabout)
|
if (has_entered_roundabout || on_roundabout)
|
||||||
{
|
{
|
||||||
detail::fixFinalRoundabout(steps);
|
fixFinalRoundabout(steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
return removeNoTurnInstructions(std::move(steps));
|
return removeNoTurnInstructions(std::move(steps));
|
||||||
@ -541,6 +519,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
// Get the previous non-invalid instruction
|
// Get the previous non-invalid instruction
|
||||||
const auto getPreviousIndex = [&steps](std::size_t index) {
|
const auto getPreviousIndex = [&steps](std::size_t index) {
|
||||||
BOOST_ASSERT(index > 0);
|
BOOST_ASSERT(index > 0);
|
||||||
|
BOOST_ASSERT(index < steps.size());
|
||||||
--index;
|
--index;
|
||||||
while (index > 0 && steps[index].maneuver.instruction == TurnInstruction::NO_TURN())
|
while (index > 0 && steps[index].maneuver.instruction == TurnInstruction::NO_TURN())
|
||||||
--index;
|
--index;
|
||||||
@ -553,6 +532,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
{
|
{
|
||||||
const auto ¤t_step = steps[step_index];
|
const auto ¤t_step = steps[step_index];
|
||||||
const auto one_back_index = getPreviousIndex(step_index);
|
const auto one_back_index = getPreviousIndex(step_index);
|
||||||
|
BOOST_ASSERT(one_back_index < steps.size());
|
||||||
|
|
||||||
// cannot collapse the depart instruction
|
// cannot collapse the depart instruction
|
||||||
if (one_back_index == 0 || current_step.maneuver.instruction == TurnInstruction::NO_TURN())
|
if (one_back_index == 0 || current_step.maneuver.instruction == TurnInstruction::NO_TURN())
|
||||||
@ -560,6 +540,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
|
|
||||||
const auto &one_back_step = steps[one_back_index];
|
const auto &one_back_step = steps[one_back_index];
|
||||||
const auto two_back_index = getPreviousIndex(one_back_index);
|
const auto two_back_index = getPreviousIndex(one_back_index);
|
||||||
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
|
|
||||||
// If we look at two consecutive name changes, we can check for a name oszillation.
|
// If we look at two consecutive name changes, we can check for a name oszillation.
|
||||||
// A name oszillation changes from name A shortly to name B and back to A.
|
// A name oszillation changes from name A shortly to name B and back to A.
|
||||||
@ -574,20 +555,20 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
if (current_step.mode == one_back_step.mode &&
|
if (current_step.mode == one_back_step.mode &&
|
||||||
one_back_step.mode == steps[two_back_index].mode)
|
one_back_step.mode == steps[two_back_index].mode)
|
||||||
{
|
{
|
||||||
steps[two_back_index] = detail::elongate(
|
steps[two_back_index] =
|
||||||
detail::elongate(std::move(steps[two_back_index]), steps[one_back_index]),
|
elongate(elongate(std::move(steps[two_back_index]), steps[one_back_index]),
|
||||||
steps[step_index]);
|
steps[step_index]);
|
||||||
detail::invalidateStep(steps[one_back_index]);
|
invalidateStep(steps[one_back_index]);
|
||||||
detail::invalidateStep(steps[step_index]);
|
invalidateStep(steps[step_index]);
|
||||||
}
|
}
|
||||||
// TODO discuss: we could think about changing the new-name to a pure notification
|
// TODO discuss: we could think about changing the new-name to a pure notification
|
||||||
// about mode changes
|
// about mode changes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (detail::collapsable(one_back_step))
|
else if (collapsable(one_back_step))
|
||||||
{
|
{
|
||||||
// check for one of the multiple collapse scenarios and, if possible, collapse the turn
|
// check for one of the multiple collapse scenarios and, if possible, collapse the turn
|
||||||
detail::collapseTurnAt(steps, two_back_index, one_back_index, step_index);
|
collapseTurnAt(steps, two_back_index, one_back_index, step_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return removeNoTurnInstructions(std::move(steps));
|
return removeNoTurnInstructions(std::move(steps));
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "util/simple_logger.hpp"
|
#include "util/simple_logger.hpp"
|
||||||
#include "util/timing_util.hpp"
|
#include "util/timing_util.hpp"
|
||||||
|
|
||||||
|
#include "extractor/suffix_table.hpp"
|
||||||
#include "extractor/guidance/toolkit.hpp"
|
#include "extractor/guidance/toolkit.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@ -320,8 +321,10 @@ 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());
|
||||||
|
SuffixTable street_name_suffix_table(lua_state);
|
||||||
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
|
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
|
||||||
m_barrier_nodes, m_compressed_edge_container, name_table);
|
m_barrier_nodes, m_compressed_edge_container, name_table,
|
||||||
|
street_name_suffix_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);
|
||||||
|
@ -27,8 +27,10 @@ inline bool requiresAnnouncement(const EdgeData &from, const EdgeData &to)
|
|||||||
|
|
||||||
IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table)
|
const util::NameTable &name_table,
|
||||||
: node_based_graph(node_based_graph), node_info_list(node_info_list), name_table(name_table)
|
const SuffixTable &street_name_suffix_table)
|
||||||
|
: node_based_graph(node_based_graph), node_info_list(node_info_list), name_table(name_table),
|
||||||
|
street_name_suffix_table(street_name_suffix_table)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +88,8 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
|||||||
const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid);
|
const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||||
if (in_data.name_id != out_data.name_id &&
|
if (in_data.name_id != out_data.name_id &&
|
||||||
requiresNameAnnounced(name_table.GetNameForID(in_data.name_id),
|
requiresNameAnnounced(name_table.GetNameForID(in_data.name_id),
|
||||||
name_table.GetNameForID(out_data.name_id)))
|
name_table.GetNameForID(out_data.name_id),
|
||||||
|
street_name_suffix_table))
|
||||||
{
|
{
|
||||||
// obvious turn onto a through street is a merge
|
// obvious turn onto a through street is a merge
|
||||||
if (through_street)
|
if (through_street)
|
||||||
|
@ -44,8 +44,9 @@ inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_base
|
|||||||
|
|
||||||
MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table)
|
const util::NameTable &name_table,
|
||||||
: IntersectionHandler(node_based_graph, node_info_list, name_table)
|
const SuffixTable &street_name_suffix_table)
|
||||||
|
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,10 @@ namespace guidance
|
|||||||
|
|
||||||
RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
const util::NameTable &name_table,
|
const util::NameTable &name_table,
|
||||||
const CompressedEdgeContainer &compressed_edge_container)
|
const SuffixTable &street_name_suffix_table)
|
||||||
: IntersectionHandler(node_based_graph, node_info_list, name_table),
|
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
|
||||||
compressed_edge_container(compressed_edge_container)
|
compressed_edge_container(compressed_edge_container)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -142,9 +143,11 @@ bool RoundaboutHandler::qualifiesAsRoundaboutIntersection(
|
|||||||
if (!has_limited_size)
|
if (!has_limited_size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const bool simple_exits = !std::find_if( roundabout_nodes.begin(), roundabout_nodes.end(), [this]( const NodeID node ){
|
const bool simple_exits =
|
||||||
return (node_based_graph.GetOutDegree(node) > 3);
|
roundabout_nodes.end() ==
|
||||||
});
|
std::find_if(roundabout_nodes.begin(), roundabout_nodes.end(), [this](const NodeID node) {
|
||||||
|
return (node_based_graph.GetOutDegree(node) > 3);
|
||||||
|
});
|
||||||
|
|
||||||
if (!simple_exits)
|
if (!simple_exits)
|
||||||
return false;
|
return false;
|
||||||
@ -219,7 +222,8 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
|||||||
// roundabout does not keep its name
|
// roundabout does not keep its name
|
||||||
if (roundabout_name_id != 0 && roundabout_name_id != edge_data.name_id &&
|
if (roundabout_name_id != 0 && roundabout_name_id != edge_data.name_id &&
|
||||||
requiresNameAnnounced(name_table.GetNameForID(roundabout_name_id),
|
requiresNameAnnounced(name_table.GetNameForID(roundabout_name_id),
|
||||||
name_table.GetNameForID(edge_data.name_id)))
|
name_table.GetNameForID(edge_data.name_id),
|
||||||
|
street_name_suffix_table))
|
||||||
{
|
{
|
||||||
return SPECIAL_EDGEID;
|
return SPECIAL_EDGEID;
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,16 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
|||||||
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)
|
const util::NameTable &name_table,
|
||||||
|
const SuffixTable &street_name_suffix_table)
|
||||||
: node_based_graph(node_based_graph), intersection_generator(node_based_graph,
|
: node_based_graph(node_based_graph), intersection_generator(node_based_graph,
|
||||||
restriction_map,
|
restriction_map,
|
||||||
barrier_nodes,
|
barrier_nodes,
|
||||||
node_info_list,
|
node_info_list,
|
||||||
compressed_edge_container),
|
compressed_edge_container),
|
||||||
roundabout_handler(node_based_graph, node_info_list, name_table, compressed_edge_container),
|
roundabout_handler(node_based_graph, node_info_list, compressed_edge_container, name_table, street_name_suffix_table),
|
||||||
motorway_handler(node_based_graph, node_info_list, name_table),
|
motorway_handler(node_based_graph, node_info_list, name_table,street_name_suffix_table),
|
||||||
turn_handler(node_based_graph, node_info_list, name_table)
|
turn_handler(node_based_graph, node_info_list, name_table,street_name_suffix_table)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,9 @@ namespace guidance
|
|||||||
|
|
||||||
TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table)
|
const util::NameTable &name_table,
|
||||||
: IntersectionHandler(node_based_graph, node_info_list, name_table)
|
const SuffixTable &street_name_suffix_table)
|
||||||
|
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,22 +407,23 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge,
|
|||||||
Intersection intersection,
|
Intersection intersection,
|
||||||
const std::size_t starting_at) const
|
const std::size_t starting_at) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!intersection.empty());
|
|
||||||
BOOST_ASSERT(starting_at <= intersection.size());
|
BOOST_ASSERT(starting_at <= intersection.size());
|
||||||
for (auto &road : intersection)
|
const auto switch_left_and_right = []( Intersection &intersection )
|
||||||
road = mirror(road);
|
{
|
||||||
|
BOOST_ASSERT(!intersection.empty());
|
||||||
|
|
||||||
std::reverse(intersection.begin() + 1, intersection.end());
|
for (auto &road : intersection)
|
||||||
|
road = mirror(std::move(road));
|
||||||
|
|
||||||
|
std::reverse(intersection.begin() + 1, intersection.end());
|
||||||
|
};
|
||||||
|
|
||||||
|
switch_left_and_right(intersection);
|
||||||
// account for the u-turn in the beginning
|
// account for the u-turn in the beginning
|
||||||
const auto count = intersection.size() - starting_at + 1;
|
const auto count = intersection.size() - starting_at + 1;
|
||||||
|
|
||||||
intersection = assignRightTurns(via_edge, std::move(intersection), count);
|
intersection = assignRightTurns(via_edge, std::move(intersection), count);
|
||||||
|
switch_left_and_right(intersection);
|
||||||
|
|
||||||
std::reverse(intersection.begin() + 1, intersection.end());
|
|
||||||
|
|
||||||
for (auto &road : intersection)
|
|
||||||
road = mirror(road);
|
|
||||||
|
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
48
src/extractor/suffix_table.cpp
Normal file
48
src/extractor/suffix_table.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "extractor/suffix_table.hpp"
|
||||||
|
|
||||||
|
#include "util/lua_util.hpp"
|
||||||
|
#include "util/simple_logger.hpp"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/range/adaptor/transformed.hpp>
|
||||||
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
SuffixTable::SuffixTable(lua_State *lua_state)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(lua_state != nullptr);
|
||||||
|
if (!util::luaFunctionExists(lua_state, "get_name_suffix_list"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<std::string> suffixes_vector;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// call lua profile to compute turn penalty
|
||||||
|
luabind::call_function<void>(lua_state, "get_name_suffix_list",
|
||||||
|
boost::ref(suffixes_vector));
|
||||||
|
}
|
||||||
|
catch (const luabind::error &er)
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write(logWARNING) << er.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &suffix : suffixes_vector)
|
||||||
|
boost::algorithm::to_lower(suffix);
|
||||||
|
suffix_set.insert(std::begin(suffixes_vector), std::end(suffixes_vector));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SuffixTable::isSuffix(const std::string &possible_suffix) const
|
||||||
|
{
|
||||||
|
return suffix_set.count(possible_suffix) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace extractor */
|
||||||
|
} /* namespace osrm */
|
Loading…
Reference in New Issue
Block a user