Implement Turn Lane Api
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -63,7 +64,7 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
|
||||
|
||||
inline bool hasValidLanes(const guidance::StepManeuver maneuver)
|
||||
{
|
||||
return maneuver.instruction.lane_tupel.lanes_in_turn > 0;
|
||||
return maneuver.lanes.lanes_in_turn > 0;
|
||||
}
|
||||
|
||||
std::string instructionTypeToString(const TurnType::Enum type)
|
||||
@@ -71,12 +72,31 @@ std::string instructionTypeToString(const TurnType::Enum type)
|
||||
return turn_type_names[static_cast<std::size_t>(type)];
|
||||
}
|
||||
|
||||
util::json::Array laneArrayFromLaneTupe(const util::guidance::LaneTupel lane_tupel)
|
||||
util::json::Array lanesFromManeuver(const guidance::StepManeuver &maneuver)
|
||||
{
|
||||
BOOST_ASSERT(lane_tupel.lanes_in_turn >= 1);
|
||||
BOOST_ASSERT(maneuver.lanes.lanes_in_turn >= 1);
|
||||
util::json::Array result;
|
||||
for (LaneID i = 0; i < lane_tupel.lanes_in_turn; ++i)
|
||||
result.values.push_back(lane_tupel.first_lane_from_the_right + i);
|
||||
LaneID lane_id = 0;
|
||||
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
|
||||
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
|
||||
tokenizer tokens(maneuver.turn_lane_string, sep);
|
||||
|
||||
lane_id = std::distance(tokens.begin(), tokens.end());
|
||||
|
||||
for (auto iter = tokens.begin(); iter != tokens.end(); ++iter)
|
||||
{
|
||||
--lane_id;
|
||||
util::json::Object lane;
|
||||
lane.values["marked"] = (iter->empty() ? "none" : *iter);
|
||||
if (lane_id >= maneuver.lanes.first_lane_from_the_right &&
|
||||
lane_id < maneuver.lanes.first_lane_from_the_right + maneuver.lanes.lanes_in_turn)
|
||||
lane.values["take"] = util::json::True();
|
||||
else
|
||||
lane.values["take"] = util::json::False();
|
||||
|
||||
result.values.push_back(lane);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -162,8 +182,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
|
||||
detail::instructionModifierToString(maneuver.instruction.direction_modifier);
|
||||
|
||||
if (detail::hasValidLanes(maneuver))
|
||||
step_maneuver.values["lanes"] =
|
||||
detail::laneArrayFromLaneTupe(maneuver.instruction.lane_tupel);
|
||||
step_maneuver.values["lanes"] = detail::lanesFromManeuver(maneuver);
|
||||
|
||||
step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location);
|
||||
step_maneuver.values["bearing_before"] = std::round(maneuver.bearing_before);
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "util/for_each_pair.hpp"
|
||||
#include "util/group_by.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
|
||||
namespace TurnType = osrm::extractor::guidance::TurnType;
|
||||
namespace DirectionModifier = osrm::extractor::guidance::DirectionModifier;
|
||||
|
||||
using osrm::util::guidance::isLeftTurn;
|
||||
using osrm::util::guidance::isRightTurn;
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps)
|
||||
{
|
||||
const constexpr auto MIN_DURATION_NEEDED_FOR_LANE_CHANGE = 15.;
|
||||
|
||||
// Postprocessing does not strictly guarantee for only turns
|
||||
const auto is_turn = [](const RouteStep &step) {
|
||||
return step.maneuver.instruction.type != TurnType::NewName &&
|
||||
step.maneuver.instruction.type != TurnType::Notification;
|
||||
};
|
||||
|
||||
const auto is_quick = [MIN_DURATION_NEEDED_FOR_LANE_CHANGE](const RouteStep &step) {
|
||||
return step.duration < MIN_DURATION_NEEDED_FOR_LANE_CHANGE;
|
||||
};
|
||||
|
||||
const auto is_quick_turn = [&](const RouteStep &step) {
|
||||
return is_turn(step) && is_quick(step);
|
||||
};
|
||||
|
||||
// Determine range of subsequent quick turns, candidates for possible lane anticipation
|
||||
using StepIter = decltype(steps)::iterator;
|
||||
using StepIterRange = std::pair<StepIter, StepIter>;
|
||||
|
||||
std::vector<StepIterRange> subsequent_quick_turns;
|
||||
|
||||
const auto keep_turn_range = [&](StepIterRange range) {
|
||||
if (std::distance(range.first, range.second) > 1)
|
||||
subsequent_quick_turns.push_back(std::move(range));
|
||||
};
|
||||
|
||||
util::group_by(begin(steps), end(steps), is_quick_turn, keep_turn_range);
|
||||
|
||||
// Walk backwards over all turns, constraining possible turn lanes.
|
||||
// Later turn lanes constrain earlier ones: we have to anticipate lane changes.
|
||||
const auto constrain_lanes = [](const StepIterRange &turns) {
|
||||
const std::reverse_iterator<StepIter> rev_first{turns.second};
|
||||
const std::reverse_iterator<StepIter> rev_last{turns.first};
|
||||
|
||||
// We're walking backwards over all adjacent turns:
|
||||
// the current turn lanes constrain the lanes we have to take in the previous turn.
|
||||
util::for_each_pair(rev_first, rev_last, [](RouteStep ¤t, RouteStep &previous) {
|
||||
const auto current_inst = current.maneuver.instruction;
|
||||
const auto current_lanes = current.maneuver.lanes;
|
||||
|
||||
// Constrain the previous turn's lanes
|
||||
auto &previous_inst = previous.maneuver.instruction;
|
||||
auto &previous_lanes = previous.maneuver.lanes;
|
||||
// Lane mapping (N:M) from previous lanes (N) to current lanes (M), with:
|
||||
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
|
||||
// otherwise nothing to constrain
|
||||
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
|
||||
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
|
||||
|
||||
if (!lanes_to_constrain || !lanes_fan_in)
|
||||
return;
|
||||
|
||||
// In case there is no lane information we work with one artificial lane
|
||||
const auto current_adjusted_lanes = std::max(current_lanes.lanes_in_turn, LaneID{1});
|
||||
|
||||
const auto num_shared_lanes = std::min(current_adjusted_lanes, //
|
||||
previous_lanes.lanes_in_turn);
|
||||
|
||||
if (isRightTurn(current_inst))
|
||||
{
|
||||
// Current turn is right turn, already keep right during the previous turn.
|
||||
// This implies constraining the leftmost lanes in the previous turn step.
|
||||
previous_lanes = {num_shared_lanes, previous_lanes.first_lane_from_the_right};
|
||||
}
|
||||
else if (isLeftTurn(current_inst))
|
||||
{
|
||||
// Current turn is left turn, already keep left during previous turn.
|
||||
// This implies constraining the rightmost lanes in the previous turn step.
|
||||
const LaneID shared_lane_delta = previous_lanes.lanes_in_turn - num_shared_lanes;
|
||||
const LaneID previous_adjusted_lanes =
|
||||
std::min(current_adjusted_lanes, shared_lane_delta);
|
||||
const LaneID constraint_first_lane_from_the_right =
|
||||
previous_lanes.first_lane_from_the_right + previous_adjusted_lanes;
|
||||
|
||||
previous_lanes = {num_shared_lanes, constraint_first_lane_from_the_right};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
std::for_each(begin(subsequent_quick_turns), end(subsequent_quick_turns), constrain_lanes);
|
||||
return steps;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
@@ -4,9 +4,8 @@
|
||||
#include "engine/guidance/assemble_steps.hpp"
|
||||
#include "engine/guidance/toolkit.hpp"
|
||||
|
||||
#include "util/for_each_pair.hpp"
|
||||
#include "util/group_by.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
#include "util/guidance/turn_lanes.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/range/algorithm_ext/erase.hpp>
|
||||
@@ -15,7 +14,6 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
@@ -24,8 +22,6 @@ namespace TurnType = osrm::extractor::guidance::TurnType;
|
||||
namespace DirectionModifier = osrm::extractor::guidance::DirectionModifier;
|
||||
using osrm::util::guidance::angularDeviation;
|
||||
using osrm::util::guidance::getTurnDirection;
|
||||
using osrm::util::guidance::isLeftTurn;
|
||||
using osrm::util::guidance::isRightTurn;
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -867,6 +863,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||
designated_depart.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||
// we need to make this conform with the intersection format for the first intersection
|
||||
auto &first_intersection = designated_depart.intersections.front();
|
||||
designated_depart.maneuver.lanes = util::guidance::LaneTupel();
|
||||
designated_depart.maneuver.turn_lane_string = "";
|
||||
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
|
||||
first_intersection.entry = {true};
|
||||
first_intersection.in = Intersection::NO_INDEX;
|
||||
@@ -933,6 +931,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||
next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive;
|
||||
next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||
next_to_last_step.maneuver.bearing_after = 0;
|
||||
next_to_last_step.maneuver.lanes = util::guidance::LaneTupel();
|
||||
next_to_last_step.maneuver.turn_lane_string = "";
|
||||
BOOST_ASSERT(next_to_last_step.intersections.size() == 1);
|
||||
auto &last_intersection = next_to_last_step.intersections.back();
|
||||
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};
|
||||
@@ -1038,94 +1038,6 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
|
||||
return steps;
|
||||
}
|
||||
|
||||
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps)
|
||||
{
|
||||
const constexpr auto MIN_DURATION_NEEDED_FOR_LANE_CHANGE = 15.;
|
||||
|
||||
// Postprocessing does not strictly guarantee for only turns
|
||||
const auto is_turn = [](const RouteStep &step) {
|
||||
return step.maneuver.instruction.type != TurnType::NewName &&
|
||||
step.maneuver.instruction.type != TurnType::Notification;
|
||||
};
|
||||
|
||||
const auto is_quick = [](const RouteStep &step) {
|
||||
return step.duration < MIN_DURATION_NEEDED_FOR_LANE_CHANGE;
|
||||
};
|
||||
|
||||
const auto is_quick_turn = [&](const RouteStep &step) {
|
||||
return is_turn(step) && is_quick(step);
|
||||
};
|
||||
|
||||
// Determine range of subsequent quick turns, candidates for possible lane anticipation
|
||||
using StepIter = decltype(steps)::iterator;
|
||||
using StepIterRange = std::pair<StepIter, StepIter>;
|
||||
|
||||
std::vector<StepIterRange> subsequent_quick_turns;
|
||||
|
||||
const auto keep_turn_range = [&](StepIterRange range) {
|
||||
if (std::distance(range.first, range.second) > 1)
|
||||
subsequent_quick_turns.push_back(std::move(range));
|
||||
};
|
||||
|
||||
util::group_by(begin(steps), end(steps), is_quick_turn, keep_turn_range);
|
||||
|
||||
// Walk backwards over all turns, constraining possible turn lanes.
|
||||
// Later turn lanes constrain earlier ones: we have to anticipate lane changes.
|
||||
const auto constrain_lanes = [](const StepIterRange &turns) {
|
||||
const std::reverse_iterator<StepIter> rev_first{turns.second};
|
||||
const std::reverse_iterator<StepIter> rev_last{turns.first};
|
||||
|
||||
// We're walking backwards over all adjacent turns:
|
||||
// the current turn lanes constrain the lanes we have to take in the previous turn.
|
||||
util::for_each_pair(rev_first, rev_last, [](RouteStep ¤t, RouteStep &previous) {
|
||||
const auto current_inst = current.maneuver.instruction;
|
||||
const auto current_lanes = current_inst.lane_tupel;
|
||||
|
||||
// Constrain the previous turn's lanes
|
||||
auto &previous_inst = previous.maneuver.instruction;
|
||||
auto &previous_lanes = previous_inst.lane_tupel;
|
||||
|
||||
// Lane mapping (N:M) from previous lanes (N) to current lanes (M), with:
|
||||
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
|
||||
// otherwise nothing to constrain
|
||||
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
|
||||
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
|
||||
|
||||
if (!lanes_to_constrain || !lanes_fan_in)
|
||||
return;
|
||||
|
||||
// In case there is no lane information we work with one artificial lane
|
||||
const auto current_adjusted_lanes = std::max(current_lanes.lanes_in_turn, LaneID{1});
|
||||
|
||||
const auto num_shared_lanes = std::min(current_adjusted_lanes, //
|
||||
previous_lanes.lanes_in_turn);
|
||||
|
||||
if (isRightTurn(current_inst))
|
||||
{
|
||||
// Current turn is right turn, already keep right during the previous turn.
|
||||
// This implies constraining the leftmost lanes in the previous turn step.
|
||||
previous_lanes = {num_shared_lanes, previous_lanes.first_lane_from_the_right};
|
||||
}
|
||||
else if (isLeftTurn(current_inst))
|
||||
{
|
||||
// Current turn is left turn, already keep left during previous turn.
|
||||
// This implies constraining the rightmost lanes in the previous turn step.
|
||||
const LaneID shared_lane_delta = previous_lanes.lanes_in_turn - num_shared_lanes;
|
||||
const LaneID previous_adjusted_lanes =
|
||||
std::min(current_adjusted_lanes, shared_lane_delta);
|
||||
const LaneID constraint_first_lane_from_the_right =
|
||||
previous_lanes.first_lane_from_the_right + previous_adjusted_lanes;
|
||||
|
||||
previous_lanes = {num_shared_lanes, constraint_first_lane_from_the_right};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
std::for_each(begin(subsequent_quick_turns), end(subsequent_quick_turns), constrain_lanes);
|
||||
|
||||
return steps;
|
||||
}
|
||||
|
||||
LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps)
|
||||
{
|
||||
// The geometry uses an adjacency array-like structure for representation.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/edge_based_graph_factory.hpp"
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/exception.hpp"
|
||||
@@ -182,6 +182,7 @@ void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
|
||||
const std::string &turn_lane_data_filename,
|
||||
lua_State *lua_state,
|
||||
const std::string &edge_segment_lookup_filename,
|
||||
const std::string &edge_penalty_filename,
|
||||
@@ -198,6 +199,7 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
|
||||
|
||||
TIMER_START(generate_edges);
|
||||
GenerateEdgeExpandedEdges(original_edge_data_filename,
|
||||
turn_lane_data_filename,
|
||||
lua_state,
|
||||
edge_segment_lookup_filename,
|
||||
edge_penalty_filename,
|
||||
@@ -296,6 +298,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||
/// Actually it also generates OriginalEdgeData and serializes them...
|
||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const std::string &original_edge_data_filename,
|
||||
const std::string &turn_lane_data_filename,
|
||||
lua_State *lua_state,
|
||||
const std::string &edge_segment_lookup_filename,
|
||||
const std::string &edge_fixed_penalties_filename,
|
||||
@@ -348,6 +351,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
|
||||
std::numeric_limits<std::uint32_t>::max());
|
||||
|
||||
guidance::LaneDataIdMap lane_data_map;
|
||||
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
progress.PrintStatus(node_u);
|
||||
@@ -364,8 +368,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
intersection =
|
||||
turn_analysis.assignTurnTypes(node_u, edge_from_u, std::move(intersection));
|
||||
|
||||
intersection =
|
||||
turn_lane_handler.assignTurnLanes(node_u, edge_from_u, std::move(intersection));
|
||||
intersection = turn_lane_handler.assignTurnLanes(
|
||||
node_u, edge_from_u, std::move(intersection), lane_data_map);
|
||||
const auto possible_turns = turn_analysis.transformIntersectionIntoTurns(intersection);
|
||||
|
||||
// the entry class depends on the turn, so we have to classify the interesction for
|
||||
@@ -437,6 +441,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
original_edge_data_vector.emplace_back(
|
||||
m_compressed_edge_container.GetPositionForID(edge_from_u),
|
||||
edge_data1.name_id,
|
||||
turn.lane_data_id,
|
||||
turn_instruction,
|
||||
entry_class_id,
|
||||
edge_data1.travel_mode);
|
||||
@@ -541,6 +546,22 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
util::SimpleLogger().Write() << "Created " << entry_class_hash.size() << " entry classes and "
|
||||
<< bearing_class_hash.size() << " Bearing Classes";
|
||||
|
||||
util::SimpleLogger().Write() << "Writing Turn Lane Data to File...";
|
||||
std::ofstream turn_lane_data_file(turn_lane_data_filename.c_str(), std::ios::binary);
|
||||
std::vector<util::guidance::LaneTupelIdPair> lane_data(lane_data_map.size());
|
||||
// extract lane data sorted by ID
|
||||
for (auto itr : lane_data_map)
|
||||
lane_data[itr.second] = itr.first;
|
||||
|
||||
std::uint64_t size = lane_data.size();
|
||||
turn_lane_data_file.write(reinterpret_cast<const char *>(&size), sizeof(size));
|
||||
|
||||
if (!lane_data.empty())
|
||||
turn_lane_data_file.write(reinterpret_cast<const char *>(&lane_data[0]),
|
||||
sizeof(util::guidance::LaneTupelIdPair) * lane_data.size());
|
||||
|
||||
util::SimpleLogger().Write() << "done.";
|
||||
|
||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||
|
||||
// Finally jump back to the empty space at the beginning and write length prefix
|
||||
|
||||
@@ -51,8 +51,6 @@ ExtractionContainers::ExtractionContainers()
|
||||
name_lengths.push_back(0);
|
||||
name_lengths.push_back(0);
|
||||
name_lengths.push_back(0);
|
||||
name_lengths.push_back(0);
|
||||
name_lengths.push_back(0);
|
||||
turn_lane_lengths.push_back(0);
|
||||
}
|
||||
|
||||
@@ -87,8 +85,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
PrepareRestrictions();
|
||||
WriteRestrictions(restrictions_file_name);
|
||||
|
||||
WriteCharData(name_file_name,name_lengths,name_char_data);
|
||||
WriteCharData(turn_lane_file_name,turn_lane_lengths,turn_lane_char_data);
|
||||
WriteCharData(name_file_name, name_lengths, name_char_data);
|
||||
WriteCharData(turn_lane_file_name, turn_lane_lengths, turn_lane_char_data);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
|
||||
@@ -239,7 +239,7 @@ int Extractor::run()
|
||||
extraction_containers.PrepareData(config.output_file_name,
|
||||
config.restriction_file_name,
|
||||
config.names_file_name,
|
||||
config.turn_lane_file_name,
|
||||
config.turn_lane_strings_file_name,
|
||||
main_context.state);
|
||||
|
||||
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
|
||||
@@ -504,7 +504,7 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
|
||||
|
||||
util::NameTable name_table(config.names_file_name);
|
||||
util::NameTable turn_lanes(config.turn_lane_file_name);
|
||||
util::NameTable turn_lanes(config.turn_lane_strings_file_name);
|
||||
|
||||
EdgeBasedGraphFactory edge_based_graph_factory(
|
||||
node_based_graph,
|
||||
@@ -518,6 +518,7 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
turn_lanes);
|
||||
|
||||
edge_based_graph_factory.Run(config.edge_output_path,
|
||||
config.turn_lane_data_file_name,
|
||||
lua_state,
|
||||
config.edge_segment_lookup_path,
|
||||
config.edge_penalty_path,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "extractor/extractor_callbacks.hpp"
|
||||
#include "extractor/extraction_containers.hpp"
|
||||
#include "extractor/extraction_node.hpp"
|
||||
#include "extractor/extraction_way.hpp"
|
||||
#include "extractor/extractor_callbacks.hpp"
|
||||
|
||||
#include "extractor/external_memory_node.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
@@ -149,9 +149,17 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
// Otherwise fetches the id based on the name and returns it without insertion.
|
||||
|
||||
const constexpr auto MAX_STRING_LENGTH = 255u;
|
||||
const auto requestId = [this,MAX_STRING_LENGTH](const std::string turn_lane_string) {
|
||||
if( turn_lane_string == "" )
|
||||
const auto requestId = [this, MAX_STRING_LENGTH](const std::string &turn_lane_string_) {
|
||||
if (turn_lane_string_ == "")
|
||||
return INVALID_LANE_STRINGID;
|
||||
|
||||
// requires https://github.com/cucumber/cucumber-js/issues/417
|
||||
// remove this handling when the issue is contained
|
||||
std::string turn_lane_string = turn_lane_string_;
|
||||
for (auto &val : turn_lane_string)
|
||||
if (val == '&')
|
||||
val = '|';
|
||||
|
||||
const auto &lane_map_iterator = lane_map.find(turn_lane_string);
|
||||
if (lane_map.end() == lane_map_iterator)
|
||||
{
|
||||
|
||||
@@ -113,7 +113,7 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
// traffic signals in the `traffic_lights` list, which EdgeData
|
||||
// doesn't have access to.
|
||||
const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end();
|
||||
if( has_node_penalty )
|
||||
if (has_node_penalty)
|
||||
continue;
|
||||
|
||||
// Get distances before graph is modified
|
||||
@@ -168,10 +168,10 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
return front;
|
||||
return back;
|
||||
};
|
||||
graph.GetEdgeData(forward_e1).lane_string_id =
|
||||
selectLaneID(graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
|
||||
graph.GetEdgeData(reverse_e1).lane_string_id =
|
||||
selectLaneID(graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
|
||||
graph.GetEdgeData(forward_e1).lane_string_id = selectLaneID(
|
||||
graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
|
||||
graph.GetEdgeData(reverse_e1).lane_string_id = selectLaneID(
|
||||
graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
|
||||
|
||||
// remove e2's (if bidir, otherwise only one)
|
||||
graph.DeleteEdge(node_v, forward_e2);
|
||||
|
||||
@@ -22,12 +22,9 @@ std::string toString(const ConnectedRoad &road)
|
||||
result += " angle: ";
|
||||
result += std::to_string(road.turn.angle);
|
||||
result += " instruction: ";
|
||||
result +=
|
||||
std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.turn.instruction.lane_tupel.lanes_in_turn)) +
|
||||
" " + std::to_string(static_cast<std::int32_t>(
|
||||
road.turn.instruction.lane_tupel.first_lane_from_the_right));
|
||||
result += std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) +
|
||||
" " + std::to_string(static_cast<std::int32_t>(road.turn.lane_data_id));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -114,9 +114,12 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
|
||||
has_uturn_edge = true;
|
||||
}
|
||||
|
||||
intersection.push_back(ConnectedRoad(
|
||||
TurnOperation{onto_edge, angle, {TurnType::Invalid, DirectionModifier::UTurn}},
|
||||
turn_is_valid));
|
||||
intersection.push_back(
|
||||
ConnectedRoad(TurnOperation{onto_edge,
|
||||
angle,
|
||||
{TurnType::Invalid, DirectionModifier::UTurn},
|
||||
INVALID_LANE_DATAID},
|
||||
turn_is_valid));
|
||||
}
|
||||
|
||||
// We hit the case of a street leading into nothing-ness. Since the code here assumes that this
|
||||
@@ -124,7 +127,9 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
|
||||
if (!has_uturn_edge)
|
||||
{
|
||||
intersection.push_back(
|
||||
{TurnOperation{via_eid, 0., {TurnType::Invalid, DirectionModifier::UTurn}}, false});
|
||||
{TurnOperation{
|
||||
via_eid, 0., {TurnType::Invalid, DirectionModifier::UTurn}, INVALID_LANE_DATAID},
|
||||
false});
|
||||
}
|
||||
|
||||
const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) {
|
||||
|
||||
@@ -373,11 +373,12 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
|
||||
if (1 == node_based_graph.GetDirectedOutDegree(node_v))
|
||||
{
|
||||
// No turn possible.
|
||||
if( intersection.size() == 2 )
|
||||
if (intersection.size() == 2)
|
||||
turn.instruction = TurnInstruction::NO_TURN();
|
||||
else
|
||||
{
|
||||
turn.instruction.type = TurnType::Suppressed; //make sure to report intersection
|
||||
turn.instruction.type =
|
||||
TurnType::Suppressed; // make sure to report intersection
|
||||
turn.instruction.direction_modifier = getTurnDirection(turn.angle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/turn_discovery.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -171,7 +171,6 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
|
||||
has_left |= modifier == DirectionModifier::SharpLeft;
|
||||
}
|
||||
|
||||
|
||||
// find missing tag and augment neighboring, if possible
|
||||
if (none_index == 0)
|
||||
{
|
||||
|
||||
@@ -52,8 +52,7 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
|
||||
// count the number of lanes
|
||||
const auto num_lanes = [](const std::string &turn_lane_string) {
|
||||
return boost::numeric_cast<LaneID>(
|
||||
std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1 +
|
||||
std::count(turn_lane_string.begin(), turn_lane_string.end(), '&'));
|
||||
std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1);
|
||||
}(turn_lane_string);
|
||||
|
||||
const auto getNextTag = [](std::string &string, const char *separators) {
|
||||
@@ -103,7 +102,7 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
|
||||
// FIXME this is a cucumber workaround, since escaping does not work properly in
|
||||
// cucumber.js (see https://github.com/cucumber/cucumber-js/issues/417). Needs to be
|
||||
// changed to "|" only, when the bug is fixed
|
||||
auto lane = getNextTag(turn_lane_string, "|&");
|
||||
auto lane = getNextTag(turn_lane_string, "|");
|
||||
setLaneData(lane_map, lane, lane_nr);
|
||||
++lane_nr;
|
||||
} while (lane_nr < num_lanes);
|
||||
@@ -135,8 +134,9 @@ LaneDataVector::const_iterator findTag(const std::string &tag, const LaneDataVec
|
||||
});
|
||||
}
|
||||
|
||||
bool hasTag(const std::string &tag, const LaneDataVector &data){
|
||||
return findTag(tag,data) != data.cend();
|
||||
bool hasTag(const std::string &tag, const LaneDataVector &data)
|
||||
{
|
||||
return findTag(tag, data) != data.cend();
|
||||
}
|
||||
|
||||
} // namespace lanes
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "extractor/guidance/turn_lane_handler.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/turn_discovery.hpp"
|
||||
#include "extractor/guidance/turn_lane_handler.hpp"
|
||||
#include "extractor/guidance/turn_lane_matcher.hpp"
|
||||
#include "extractor/guidance/turn_lane_augmentation.hpp"
|
||||
#include "extractor/guidance/turn_lane_matcher.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -40,7 +40,7 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
|
||||
}
|
||||
|
||||
/*
|
||||
Turn lanes are given in the form of strings that closely correspond to the direction modifiers
|
||||
Turn lanes are given in the form of strings that closely correspond to the direction modifiers
|
||||
we use for our turn types. However, we still cannot simply perform a 1:1 assignment.
|
||||
|
||||
This function parses the turn_lane_strings of a format that describes an intersection as:
|
||||
@@ -58,11 +58,9 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
|
||||
*/
|
||||
Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
const EdgeID via_edge,
|
||||
Intersection intersection) const
|
||||
Intersection intersection,
|
||||
LaneDataIdMap &id_map) const
|
||||
{
|
||||
// initialize to invalid
|
||||
for (auto &road : intersection)
|
||||
road.turn.instruction.lane_tupel = {0, INVALID_LANEID};
|
||||
const auto &data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto turn_lane_string = data.lane_string_id != INVALID_LANE_STRINGID
|
||||
? turn_lane_strings.GetNameForID(data.lane_string_id)
|
||||
@@ -89,17 +87,15 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
const std::size_t possible_entries = getNumberOfTurns(intersection);
|
||||
|
||||
// merge does not justify an instruction
|
||||
const bool has_merge_lane = (hasTag("merge_to_left", lane_data) ||
|
||||
hasTag("merge_to_right", lane_data));
|
||||
const bool has_merge_lane =
|
||||
(hasTag("merge_to_left", lane_data) || hasTag("merge_to_right", lane_data));
|
||||
|
||||
// Dead end streets that don't have any left-tag. This can happen due to the fallbacks for
|
||||
// broken data/barriers.
|
||||
const bool has_non_usable_u_turn =
|
||||
(intersection[0].entry_allowed && !hasTag("none", lane_data) &&
|
||||
!hasTag("left", lane_data) &&
|
||||
!hasTag("sharp_left", lane_data) &&
|
||||
!hasTag("reverse", lane_data) &&
|
||||
lane_data.size() + 1 == possible_entries);
|
||||
!hasTag("left", lane_data) && !hasTag("sharp_left", lane_data) &&
|
||||
!hasTag("reverse", lane_data) && lane_data.size() + 1 == possible_entries);
|
||||
|
||||
if (has_merge_lane || has_non_usable_u_turn)
|
||||
return std::move(intersection);
|
||||
@@ -118,7 +114,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
if (is_simple)
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, data.lane_string_id, id_map);
|
||||
}
|
||||
// if the intersection is not simple but we have lane data, we check for intersections with
|
||||
// middle islands. We have two cases. The first one is providing lane data on the current
|
||||
@@ -138,7 +135,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
isSimpleIntersection(lane_data, intersection))
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, data.lane_string_id, id_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,7 +146,7 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
{
|
||||
// acquire the lane data of a previous segment and, if possible, use it for the current
|
||||
// intersection.
|
||||
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection));
|
||||
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection), id_map);
|
||||
}
|
||||
|
||||
return std::move(intersection);
|
||||
@@ -158,7 +156,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
// actually take the turn, we need to look back to the edge we drove onto the intersection with.
|
||||
Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
const EdgeID via_edge,
|
||||
Intersection intersection) const
|
||||
Intersection intersection,
|
||||
LaneDataIdMap &id_map) const
|
||||
{
|
||||
NodeID previous_node = SPECIAL_NODEID;
|
||||
Intersection previous_intersection;
|
||||
@@ -176,6 +175,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
previous_id,
|
||||
previous_intersection))
|
||||
return "";
|
||||
BOOST_ASSERT(previous_id != SPECIAL_EDGEID);
|
||||
|
||||
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
|
||||
auto previous_string = previous_data.lane_string_id != INVALID_LANE_STRINGID
|
||||
@@ -204,11 +204,13 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
if (lane_data.empty())
|
||||
return std::move(intersection);
|
||||
|
||||
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
|
||||
const auto is_simple = isSimpleIntersection(lane_data, intersection);
|
||||
if (is_simple)
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -227,14 +229,14 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
isSimpleIntersection(lane_data, intersection))
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::move(intersection);
|
||||
}
|
||||
|
||||
|
||||
/* A simple intersection does not depend on the next intersection coming up. This is important
|
||||
* for turn lanes, since traffic signals and/or segregated a intersection can influence the
|
||||
* interpretation of turn-lanes at a given turn.
|
||||
@@ -296,7 +298,7 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
||||
}
|
||||
|
||||
if (num_turns > lane_data.size() && intersection[0].entry_allowed &&
|
||||
!( hasTag("reverse", lane_data) ||
|
||||
!(hasTag("reverse", lane_data) ||
|
||||
(lane_data.back().tag != "left" && lane_data.back().tag != "sharp_left")))
|
||||
{
|
||||
return false;
|
||||
@@ -417,7 +419,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
return {turn_lane_data, {}};
|
||||
}
|
||||
|
||||
std::size_t none_index = std::distance(turn_lane_data.begin(),findTag("none", turn_lane_data));
|
||||
std::size_t none_index = std::distance(turn_lane_data.begin(), findTag("none", turn_lane_data));
|
||||
|
||||
// if the turn lanes are pull forward, we might have to add an additional straight tag
|
||||
// did we find something that matches against the straightmost road?
|
||||
@@ -486,7 +488,9 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
}
|
||||
|
||||
Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection,
|
||||
const LaneDataVector &lane_data) const
|
||||
const LaneDataVector &lane_data,
|
||||
const LaneStringID lane_string_id,
|
||||
LaneDataIdMap &id_map) const
|
||||
{
|
||||
if (lane_data.empty() || !canMatchTrivially(intersection, lane_data))
|
||||
return std::move(intersection);
|
||||
@@ -496,7 +500,8 @@ Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection
|
||||
return boost::starts_with(data.tag, "merge");
|
||||
}) == 0);
|
||||
|
||||
return triviallyMatchLanesToTurns(std::move(intersection), lane_data, node_based_graph);
|
||||
return triviallyMatchLanesToTurns(
|
||||
std::move(intersection), lane_data, node_based_graph, lane_string_id, id_map);
|
||||
}
|
||||
|
||||
} // namespace lanes
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "extractor/guidance/turn_lane_matcher.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -169,9 +172,27 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
|
||||
|
||||
Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
const LaneDataVector &lane_data,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph)
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const LaneStringID lane_string_id,
|
||||
LaneDataIdMap &lane_data_to_id)
|
||||
{
|
||||
std::size_t road_index = 1, lane = 0;
|
||||
|
||||
const auto matchRoad = [&](ConnectedRoad &road, const TurnLaneData &data) {
|
||||
LaneTupelIdPair key{{LaneID(data.to - data.from + 1), data.from}, lane_string_id};
|
||||
|
||||
auto lane_data_id = boost::numeric_cast<LaneDataID>(lane_data_to_id.size());
|
||||
const auto it = lane_data_to_id.find(key);
|
||||
|
||||
if (it == lane_data_to_id.end())
|
||||
lane_data_to_id.insert({key, lane_data_id});
|
||||
else
|
||||
lane_data_id = it->second;
|
||||
|
||||
// set lane id instead after the switch:
|
||||
road.turn.lane_data_id = lane_data_id;
|
||||
};
|
||||
|
||||
for (; road_index < intersection.size() && lane < lane_data.size(); ++road_index)
|
||||
{
|
||||
if (intersection[road_index].entry_allowed)
|
||||
@@ -185,8 +206,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
if (TurnType::Suppressed == intersection[road_index].turn.instruction.type)
|
||||
intersection[road_index].turn.instruction.type = TurnType::UseLane;
|
||||
|
||||
intersection[road_index].turn.instruction.lane_tupel = {
|
||||
LaneID(lane_data[lane].to - lane_data[lane].from + 1), lane_data[lane].from};
|
||||
matchRoad(intersection[road_index], lane_data[lane]);
|
||||
++lane;
|
||||
}
|
||||
}
|
||||
@@ -209,8 +229,8 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
intersection[u_turn].entry_allowed = true;
|
||||
intersection[u_turn].turn.instruction.type = TurnType::Turn;
|
||||
intersection[u_turn].turn.instruction.direction_modifier = DirectionModifier::UTurn;
|
||||
intersection[u_turn].turn.instruction.lane_tupel = {
|
||||
LaneID(lane_data.back().to - lane_data.back().from + 1), lane_data.back().from};
|
||||
|
||||
matchRoad(intersection[u_turn], lane_data.back());
|
||||
}
|
||||
return std::move(intersection);
|
||||
}
|
||||
|
||||
+83
-3
@@ -147,6 +147,26 @@ int Storage::Run()
|
||||
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
|
||||
|
||||
boost::filesystem::ifstream turn_string_stream(config.turn_lane_string_path, std::ios::binary);
|
||||
if (!turn_string_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + config.turn_lane_string_path.string() +
|
||||
" for reading.");
|
||||
}
|
||||
|
||||
unsigned turn_string_blocks = 0;
|
||||
turn_string_stream.read((char *)&turn_string_blocks, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::TURN_STRING_OFFSETS,
|
||||
turn_string_blocks);
|
||||
shared_layout_ptr->SetBlockSize<typename util::RangeTable<16, true>::BlockT>(
|
||||
SharedDataLayout::TURN_STRING_BLOCKS, turn_string_blocks);
|
||||
BOOST_ASSERT_MSG(0 != turn_string_blocks, "turn string file broken");
|
||||
|
||||
unsigned number_of_turn_string_chars = 0;
|
||||
turn_string_stream.read((char *)&number_of_turn_string_chars, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TURN_STRING_CHAR_LIST,
|
||||
number_of_turn_string_chars);
|
||||
|
||||
// Loading information for original edges
|
||||
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
|
||||
if (!edges_input_stream)
|
||||
@@ -166,6 +186,8 @@ int Storage::Run()
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
|
||||
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<LaneDataID>(SharedDataLayout::LANE_DATA_ID,
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<EntryClassID>(SharedDataLayout::ENTRY_CLASSID,
|
||||
number_of_original_edges);
|
||||
|
||||
@@ -368,6 +390,14 @@ int Storage::Run()
|
||||
sizeof(bearing_class_table[0]) * num_bearings);
|
||||
shared_layout_ptr->SetBlockSize<DiscreteBearing>(SharedDataLayout::BEARING_VALUES,
|
||||
num_bearings);
|
||||
|
||||
// Loading turn lane data
|
||||
boost::filesystem::ifstream lane_data_stream(config.turn_lane_data_path, std::ios::binary);
|
||||
std::uint64_t lane_tupel_count = 0;
|
||||
lane_data_stream.read(reinterpret_cast<char *>(&lane_tupel_count), sizeof(lane_tupel_count));
|
||||
shared_layout_ptr->SetBlockSize<util::guidance::LaneTupelIdPair>(
|
||||
SharedDataLayout::TURN_LANE_DATA, lane_tupel_count);
|
||||
|
||||
if (!static_cast<bool>(intersection_stream))
|
||||
throw util::exception("Failed to read bearing values from " +
|
||||
config.intersection_class_path.string());
|
||||
@@ -436,9 +466,54 @@ int Storage::Run()
|
||||
name_stream.read(name_char_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST));
|
||||
}
|
||||
|
||||
name_stream.close();
|
||||
|
||||
// Loading turn lane strings
|
||||
unsigned *turn_string_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_STRING_OFFSETS);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_OFFSETS) > 0)
|
||||
{
|
||||
turn_string_stream.read(
|
||||
(char *)turn_string_offsets_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_OFFSETS));
|
||||
}
|
||||
|
||||
// make sure do write canary...
|
||||
auto *turn_lane_data_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<util::guidance::LaneTupelIdPair, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_LANE_DATA);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_LANE_DATA) > 0)
|
||||
{
|
||||
lane_data_stream.read(reinterpret_cast<char *>(turn_lane_data_ptr),
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_LANE_DATA));
|
||||
}
|
||||
lane_data_stream.close();
|
||||
|
||||
unsigned *turn_string_blocks_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_STRING_BLOCKS);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_BLOCKS) > 0)
|
||||
{
|
||||
turn_string_stream.read(
|
||||
(char *)turn_string_blocks_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_BLOCKS));
|
||||
}
|
||||
|
||||
char *turn_string_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_STRING_CHAR_LIST);
|
||||
turn_string_stream.read((char *)&temp_length, sizeof(unsigned));
|
||||
|
||||
BOOST_ASSERT_MSG(temp_length ==
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST),
|
||||
"turn string file corrupted!");
|
||||
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST) > 0)
|
||||
{
|
||||
turn_string_stream.read(
|
||||
turn_string_char_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST));
|
||||
}
|
||||
turn_string_stream.close();
|
||||
|
||||
// load original edge information
|
||||
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
|
||||
shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST);
|
||||
@@ -450,6 +525,9 @@ int Storage::Run()
|
||||
shared_layout_ptr->GetBlockPtr<extractor::TravelMode, true>(shared_memory_ptr,
|
||||
SharedDataLayout::TRAVEL_MODE);
|
||||
|
||||
LaneDataID *lane_data_id_ptr = shared_layout_ptr->GetBlockPtr<LaneDataID, true>(
|
||||
shared_memory_ptr, SharedDataLayout::LANE_DATA_ID);
|
||||
|
||||
extractor::guidance::TurnInstruction *turn_instructions_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<extractor::guidance::TurnInstruction, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
|
||||
@@ -464,6 +542,7 @@ int Storage::Run()
|
||||
via_node_ptr[i] = current_edge_data.via_node;
|
||||
name_id_ptr[i] = current_edge_data.name_id;
|
||||
travel_mode_ptr[i] = current_edge_data.travel_mode;
|
||||
lane_data_id_ptr[i] = current_edge_data.lane_data_id;
|
||||
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
||||
entry_class_id_ptr[i] = current_edge_data.entry_classid;
|
||||
}
|
||||
@@ -514,8 +593,9 @@ int Storage::Run()
|
||||
shared_memory_ptr, SharedDataLayout::DATASOURCE_NAME_DATA);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::DATASOURCE_NAME_DATA) > 0)
|
||||
{
|
||||
std::cout << "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
|
||||
<< " chars into name data ptr\n";
|
||||
util::SimpleLogger().Write()
|
||||
<< "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
|
||||
<< " chars into name data ptr\n";
|
||||
std::copy(
|
||||
m_datasource_name_data.begin(), m_datasource_name_data.end(), datasource_name_data_ptr);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ StorageConfig::StorageConfig(const boost::filesystem::path &base)
|
||||
datasource_names_path{base.string() + ".datasource_names"},
|
||||
datasource_indexes_path{base.string() + ".datasource_indexes"},
|
||||
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"},
|
||||
intersection_class_path{base.string() + ".icd"}
|
||||
intersection_class_path{base.string() + ".icd"}, turn_lane_data_path{base.string() + ".tld"},
|
||||
turn_lane_string_path{base.string() + ".tls"}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@ namespace util
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
LaneTupel::LaneTupel()
|
||||
: lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID)
|
||||
LaneTupel::LaneTupel() : lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID)
|
||||
{
|
||||
// basic constructor, set everything to zero
|
||||
}
|
||||
|
||||
@@ -36,11 +36,13 @@ NameTable::NameTable(const std::string &filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
util::SimpleLogger().Write(logINFO) << "list of street names is empty in construction of name table from: \"" << filename << "\"";
|
||||
util::SimpleLogger().Write(logINFO)
|
||||
<< "list of street names is empty in construction of name table from: \"" << filename
|
||||
<< "\"";
|
||||
}
|
||||
if (!name_stream)
|
||||
throw exception("Failed to read " + std::to_string(number_of_chars) +
|
||||
" characters from " + filename);
|
||||
throw exception("Failed to read " + std::to_string(number_of_chars) + " characters from " +
|
||||
filename);
|
||||
}
|
||||
|
||||
std::string NameTable::GetNameForID(const unsigned name_id) const
|
||||
|
||||
Reference in New Issue
Block a user