expose lanes as enums, adjusted for comments
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -76,23 +75,18 @@ util::json::Array lanesFromManeuver(const guidance::StepManeuver &maneuver)
|
||||
{
|
||||
BOOST_ASSERT(maneuver.lanes.lanes_in_turn >= 1);
|
||||
util::json::Array result;
|
||||
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);
|
||||
LaneID lane_id = maneuver.lane_description.size();
|
||||
|
||||
lane_id = std::distance(tokens.begin(), tokens.end());
|
||||
|
||||
for (auto iter = tokens.begin(); iter != tokens.end(); ++iter)
|
||||
for (const auto &lane_desc : maneuver.lane_description)
|
||||
{
|
||||
--lane_id;
|
||||
util::json::Object lane;
|
||||
lane.values["marked"] = (iter->empty() ? "none" : *iter);
|
||||
lane.values["indications"] = extractor::guidance::TurnLaneType::toJsonArray(lane_desc);
|
||||
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();
|
||||
lane.values["valid"] = util::json::True();
|
||||
else
|
||||
lane.values["take"] = util::json::False();
|
||||
lane.values["valid"] = util::json::False();
|
||||
|
||||
result.values.push_back(lane);
|
||||
}
|
||||
|
||||
@@ -140,8 +140,6 @@ RouteStep forwardInto(RouteStep destination, const RouteStep &source)
|
||||
|
||||
destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin);
|
||||
destination.geometry_end = std::max(destination.geometry_end, source.geometry_end);
|
||||
destination.maneuver.exit = source.maneuver.exit;
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
@@ -224,6 +222,7 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
const std::size_t step_index)
|
||||
{
|
||||
auto &step = steps[step_index];
|
||||
step.maneuver.exit += 1;
|
||||
if (!on_roundabout)
|
||||
{
|
||||
// We reached a special case that requires the addition of a special route step in the
|
||||
@@ -257,7 +256,6 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
if (steps[1].maneuver.instruction.type == TurnType::EnterRotary)
|
||||
steps[1].rotary_name = steps[0].name;
|
||||
}
|
||||
step.maneuver.exit += 1;
|
||||
|
||||
// Normal exit from the roundabout, or exit from a previously fixed roundabout. Propagate the
|
||||
// index back to the entering location and prepare the current silent set of instructions for
|
||||
@@ -280,7 +278,6 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
propagation_step = forwardInto(propagation_step, steps[propagation_index + 1]);
|
||||
if (entersRoundabout(propagation_step.maneuver.instruction))
|
||||
{
|
||||
propagation_step.maneuver.exit = step.maneuver.exit;
|
||||
const auto entry_intersection = propagation_step.intersections.front();
|
||||
|
||||
// remember rotary name
|
||||
@@ -412,7 +409,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
||||
else if (one_back_step.distance <= MAX_COLLAPSE_DISTANCE &&
|
||||
isCollapsableInstruction(current_step.maneuver.instruction))
|
||||
{
|
||||
// TODO check for lanes
|
||||
// TODO check for lanes (https://github.com/Project-OSRM/osrm-backend/issues/2553)
|
||||
if (compatible(one_back_step, current_step))
|
||||
{
|
||||
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
||||
@@ -583,8 +580,6 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
||||
has_entered_roundabout = false;
|
||||
on_roundabout = false;
|
||||
}
|
||||
else if (has_entered_roundabout)
|
||||
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
|
||||
}
|
||||
|
||||
// unterminated roundabout
|
||||
@@ -864,7 +859,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||
// 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 = "";
|
||||
designated_depart.maneuver.lane_description.clear();
|
||||
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
|
||||
first_intersection.entry = {true};
|
||||
first_intersection.in = Intersection::NO_INDEX;
|
||||
@@ -932,7 +927,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||
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 = "";
|
||||
next_to_last_step.maneuver.lane_description.clear();
|
||||
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]};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "extractor/edge_based_graph_factory.hpp"
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/edge_based_graph_factory.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/exception.hpp"
|
||||
@@ -41,13 +41,14 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
ProfileProperties profile_properties,
|
||||
const util::NameTable &name_table,
|
||||
const util::NameTable &turn_lanes)
|
||||
const std::vector<std::uint32_t> &turn_lane_offsets,
|
||||
const std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks)
|
||||
: m_max_edge_id(0), m_node_info_list(node_info_list),
|
||||
m_node_based_graph(std::move(node_based_graph)),
|
||||
m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes),
|
||||
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
|
||||
profile_properties(std::move(profile_properties)), name_table(name_table),
|
||||
turn_lanes(turn_lanes)
|
||||
turn_lane_offsets(turn_lane_offsets), turn_lane_masks(turn_lane_masks)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -346,7 +347,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
name_table,
|
||||
street_name_suffix_table);
|
||||
guidance::lanes::TurnLaneHandler turn_lane_handler(
|
||||
*m_node_based_graph, turn_lanes, m_node_info_list, turn_analysis);
|
||||
*m_node_based_graph, turn_lane_offsets, turn_lane_masks, m_node_info_list, turn_analysis);
|
||||
|
||||
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
|
||||
std::numeric_limits<std::uint32_t>::max());
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "util/exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/io.hpp"
|
||||
#include "util/lua_util.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/timing_util.hpp"
|
||||
@@ -51,7 +52,11 @@ ExtractionContainers::ExtractionContainers()
|
||||
name_lengths.push_back(0);
|
||||
name_lengths.push_back(0);
|
||||
name_lengths.push_back(0);
|
||||
turn_lane_lengths.push_back(0);
|
||||
|
||||
// the offsets have to be initialized with two values, since we have the empty turn string for
|
||||
// the first id
|
||||
turn_lane_offsets.push_back(0);
|
||||
turn_lane_offsets.push_back(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +91,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
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);
|
||||
WriteTurnLaneMasks(turn_lane_file_name, turn_lane_offsets, turn_lane_masks);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -94,6 +99,32 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractionContainers::WriteTurnLaneMasks(
|
||||
const std::string &file_name,
|
||||
const stxxl::vector<std::uint32_t> &offsets,
|
||||
const stxxl::vector<guidance::TurnLaneType::Mask> &masks) const
|
||||
{
|
||||
util::SimpleLogger().Write() << "Writing turn lane masks...";
|
||||
TIMER_START(turn_lane_timer);
|
||||
|
||||
std::ofstream ofs(file_name, std::ios::binary);
|
||||
|
||||
if (!util::serializeVector(ofs, offsets))
|
||||
{
|
||||
util::SimpleLogger().Write(logWARNING) << "Error while writing.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!util::serializeVector(ofs, masks))
|
||||
{
|
||||
util::SimpleLogger().Write(logWARNING) << "Error while writing.";
|
||||
return;
|
||||
}
|
||||
|
||||
TIMER_STOP(turn_lane_timer);
|
||||
util::SimpleLogger().Write() << "done (" << TIMER_SEC(turn_lane_timer) << ")";
|
||||
}
|
||||
|
||||
void ExtractionContainers::WriteCharData(const std::string &file_name,
|
||||
const stxxl::vector<unsigned> &offsets,
|
||||
const stxxl::vector<char> &char_data) const
|
||||
|
||||
@@ -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_strings_file_name,
|
||||
config.turn_lane_descriptions_file_name,
|
||||
main_context.state);
|
||||
|
||||
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
|
||||
@@ -504,7 +504,14 @@ 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_strings_file_name);
|
||||
|
||||
std::vector<std::uint32_t> turn_lane_offsets;
|
||||
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
|
||||
if( !util::deserializeAdjacencyArray(
|
||||
config.turn_lane_descriptions_file_name, turn_lane_offsets, turn_lane_masks) )
|
||||
{
|
||||
util::SimpleLogger().Write(logWARNING) << "Reading Turn Lane Masks failed.";
|
||||
}
|
||||
|
||||
EdgeBasedGraphFactory edge_based_graph_factory(
|
||||
node_based_graph,
|
||||
@@ -515,7 +522,8 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
internal_to_external_node_map,
|
||||
profile_properties,
|
||||
name_table,
|
||||
turn_lanes);
|
||||
turn_lane_offsets,
|
||||
turn_lane_masks);
|
||||
|
||||
edge_based_graph_factory.Run(config.edge_output_path,
|
||||
config.turn_lane_data_file_name,
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#include "extractor/extractor_callbacks.hpp"
|
||||
#include "extractor/external_memory_node.hpp"
|
||||
#include "extractor/extraction_containers.hpp"
|
||||
#include "extractor/extraction_node.hpp"
|
||||
#include "extractor/extraction_way.hpp"
|
||||
|
||||
#include "extractor/external_memory_node.hpp"
|
||||
#include "extractor/extractor_callbacks.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
|
||||
#include "util/for_each_pair.hpp"
|
||||
#include "util/guidance/turn_lanes.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
#include "extractor/extractor_callbacks.hpp"
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include <osmium/osm.hpp>
|
||||
|
||||
@@ -27,12 +27,15 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
using TurnLaneDescription = guidance::TurnLaneDescription;
|
||||
namespace TurnLaneType = guidance::TurnLaneType;
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
|
||||
: external_memory(extraction_containers)
|
||||
{
|
||||
// we reserved 0, 1, 2 for the empty case
|
||||
string_map[MapKey("", "")] = 0;
|
||||
lane_map[""] = 0;
|
||||
lane_description_map[TurnLaneDescription()] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,44 +147,109 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
road_classification.road_class = guidance::functionalRoadClassFromTag(data);
|
||||
}
|
||||
|
||||
// Deduplicates street names and street destination names based on the street_map map.
|
||||
// In case we do not already store the name, inserts (name, id) tuple and return id.
|
||||
// Otherwise fetches the id based on the name and returns it without insertion.
|
||||
const auto laneStringToDescription = [](std::string lane_string) -> TurnLaneDescription {
|
||||
if (lane_string.empty())
|
||||
return {};
|
||||
|
||||
const constexpr auto MAX_STRING_LENGTH = 255u;
|
||||
const auto requestId = [this, MAX_STRING_LENGTH](const std::string &turn_lane_string_) {
|
||||
if (turn_lane_string_ == "")
|
||||
return INVALID_LANE_STRINGID;
|
||||
TurnLaneDescription lane_description;
|
||||
|
||||
// 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 = '|';
|
||||
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
|
||||
boost::char_separator<char> sep("|&", "", boost::keep_empty_tokens);
|
||||
boost::char_separator<char> inner_sep(";", "");
|
||||
tokenizer tokens(lane_string, sep);
|
||||
|
||||
const auto &lane_map_iterator = lane_map.find(turn_lane_string);
|
||||
if (lane_map.end() == lane_map_iterator)
|
||||
const constexpr std::size_t num_osm_tags = 11;
|
||||
const constexpr char *osm_lane_strings[num_osm_tags] = {"none",
|
||||
"through",
|
||||
"sharp_left",
|
||||
"left",
|
||||
"slight_left",
|
||||
"slight_right",
|
||||
"right",
|
||||
"sharp_right",
|
||||
"reverse",
|
||||
"merge_to_left",
|
||||
"merge_to_right"};
|
||||
const constexpr TurnLaneType::Mask masks_by_osm_string[num_osm_tags + 1] = {
|
||||
TurnLaneType::none,
|
||||
TurnLaneType::straight,
|
||||
TurnLaneType::sharp_left,
|
||||
TurnLaneType::left,
|
||||
TurnLaneType::slight_left,
|
||||
TurnLaneType::slight_right,
|
||||
TurnLaneType::right,
|
||||
TurnLaneType::sharp_right,
|
||||
TurnLaneType::uturn,
|
||||
TurnLaneType::merge_to_left,
|
||||
TurnLaneType::merge_to_right,
|
||||
TurnLaneType::empty}; // fallback, if string not found
|
||||
|
||||
for (auto iter = tokens.begin(); iter != tokens.end(); ++iter)
|
||||
{
|
||||
LaneStringID turn_lane_id =
|
||||
boost::numeric_cast<LaneStringID>(external_memory.turn_lane_lengths.size());
|
||||
auto turn_lane_length = std::min<unsigned>(MAX_STRING_LENGTH, turn_lane_string.size());
|
||||
std::copy(turn_lane_string.c_str(),
|
||||
turn_lane_string.c_str() + turn_lane_length,
|
||||
std::back_inserter(external_memory.turn_lane_char_data));
|
||||
external_memory.turn_lane_lengths.push_back(turn_lane_length);
|
||||
lane_map.insert(std::make_pair(turn_lane_string, turn_lane_id));
|
||||
return turn_lane_id;
|
||||
tokenizer inner_tokens(*iter, inner_sep);
|
||||
guidance::TurnLaneType::Mask lane_mask = inner_tokens.begin() == inner_tokens.end()
|
||||
? TurnLaneType::none
|
||||
: TurnLaneType::empty;
|
||||
for (auto token_itr = inner_tokens.begin(); token_itr != inner_tokens.end();
|
||||
++token_itr)
|
||||
{
|
||||
auto position = std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr);
|
||||
const auto translated_mask =
|
||||
masks_by_osm_string[std::distance(osm_lane_strings, position)];
|
||||
if (translated_mask == TurnLaneType::empty)
|
||||
{
|
||||
// if we have unsupported tags, don't handle them
|
||||
util::SimpleLogger().Write(logDEBUG) << "Unsupported lane tag found: \""
|
||||
<< *token_itr << "\"";
|
||||
return {};
|
||||
}
|
||||
BOOST_ASSERT((lane_mask & translated_mask) == 0); // make sure the mask is valid
|
||||
lane_mask |= translated_mask;
|
||||
}
|
||||
// add the lane to the description
|
||||
lane_description.push_back(lane_mask);
|
||||
}
|
||||
return lane_description;
|
||||
};
|
||||
|
||||
// convert the lane description into an ID and, if necessary, remembr the description in the
|
||||
// description_map
|
||||
const auto requestId = [&](std::string lane_string) {
|
||||
if( lane_string.empty() )
|
||||
return INVALID_LANE_DESCRIPTIONID;
|
||||
TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string));
|
||||
|
||||
const auto lane_description_itr = lane_description_map.find(lane_description);
|
||||
if (lane_description_itr == lane_description_map.end())
|
||||
{
|
||||
const LaneDescriptionID new_id =
|
||||
boost::numeric_cast<LaneDescriptionID>(lane_description_map.size());
|
||||
lane_description_map[lane_description] = new_id;
|
||||
|
||||
// since we are getting a new ID, we can augment the current offsets
|
||||
|
||||
// and store the turn lane masks, sadly stxxl does not support insert
|
||||
for (const auto mask : lane_description)
|
||||
external_memory.turn_lane_masks.push_back(mask);
|
||||
|
||||
external_memory.turn_lane_offsets.push_back(external_memory.turn_lane_offsets.back() +
|
||||
lane_description.size());
|
||||
|
||||
return new_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lane_map_iterator->second;
|
||||
return lane_description_itr->second;
|
||||
}
|
||||
};
|
||||
|
||||
// Deduplicates street names and street destination names based on the street_map map.
|
||||
// In case we do not already store the name, inserts (name, id) tuple and return id.
|
||||
// Otherwise fetches the id based on the name and returns it without insertion.
|
||||
const auto turn_lane_id_forward = requestId(parsed_way.turn_lanes_forward);
|
||||
const auto turn_lane_id_backward = requestId(parsed_way.turn_lanes_backward);
|
||||
|
||||
const constexpr auto MAX_STRING_LENGTH = 255u;
|
||||
// Get the unique identifier for the street name
|
||||
// Get the unique identifier for the street name and destination
|
||||
const auto name_iterator = string_map.find(MapKey(parsed_way.name, parsed_way.destinations));
|
||||
|
||||
@@ -160,18 +160,18 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
* turn-lanes. Without this,we would have to treat any turn-lane beginning/ending just
|
||||
* like a barrier.
|
||||
*/
|
||||
const auto selectLaneID = [](const LaneStringID front, const LaneStringID back) {
|
||||
const auto selectLaneID = [](const LaneDescriptionID front, const LaneDescriptionID back) {
|
||||
// A lane has tags: u - (front) - v - (back) - w
|
||||
// During contraction, we keep only one of the tags. Usually the one closer to the
|
||||
// intersection is preferred. If its empty, however, we keep the non-empty one
|
||||
if (back == INVALID_LANE_STRINGID)
|
||||
if (back == INVALID_LANE_DESCRIPTIONID)
|
||||
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_description_id = selectLaneID(
|
||||
graph.GetEdgeData(forward_e1).lane_description_id, fwd_edge_data2.lane_description_id);
|
||||
graph.GetEdgeData(reverse_e1).lane_description_id = selectLaneID(
|
||||
graph.GetEdgeData(reverse_e1).lane_description_id, rev_edge_data2.lane_description_id);
|
||||
|
||||
// remove e2's (if bidir, otherwise only one)
|
||||
graph.DeleteEdge(node_v, forward_e2);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "extractor/guidance/turn_lane_augmentation.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -18,14 +19,14 @@ namespace lanes
|
||||
namespace
|
||||
{
|
||||
|
||||
const constexpr char *tag_by_modifier[] = {"reverse",
|
||||
"sharp_right",
|
||||
"right",
|
||||
"slight_right",
|
||||
"through",
|
||||
"slight_left",
|
||||
"left",
|
||||
"sharp_left"};
|
||||
const constexpr TurnLaneType::Mask tag_by_modifier[] = {TurnLaneType::uturn,
|
||||
TurnLaneType::sharp_right,
|
||||
TurnLaneType::right,
|
||||
TurnLaneType::slight_right,
|
||||
TurnLaneType::straight,
|
||||
TurnLaneType::slight_left,
|
||||
TurnLaneType::left,
|
||||
TurnLaneType::sharp_left};
|
||||
|
||||
std::size_t getNumberOfTurns(const Intersection &intersection)
|
||||
{
|
||||
@@ -126,7 +127,6 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
|
||||
// This handles situations like "left | | | right".
|
||||
LaneDataVector mergeNoneTag(const std::size_t none_index, LaneDataVector lane_data)
|
||||
{
|
||||
|
||||
if (none_index == 0 || none_index + 1 == lane_data.size())
|
||||
{
|
||||
if (none_index == 0)
|
||||
@@ -175,11 +175,11 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
|
||||
if (none_index == 0)
|
||||
{
|
||||
if (has_right &&
|
||||
(lane_data.size() == 1 || (lane_data[none_index + 1].tag != "sharp_right" &&
|
||||
lane_data[none_index + 1].tag != "right")))
|
||||
(lane_data.size() == 1 || (lane_data[none_index + 1].tag != TurnLaneType::sharp_right &&
|
||||
lane_data[none_index + 1].tag != TurnLaneType::right)))
|
||||
{
|
||||
lane_data[none_index].tag = "right";
|
||||
if (lane_data.size() > 1 && lane_data[none_index + 1].tag == "through")
|
||||
lane_data[none_index].tag = TurnLaneType::right;
|
||||
if (lane_data.size() > 1 && lane_data[none_index + 1].tag == TurnLaneType::straight)
|
||||
{
|
||||
lane_data[none_index + 1].from = lane_data[none_index].from;
|
||||
// turning right through a possible through lane is not possible
|
||||
@@ -187,39 +187,39 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
|
||||
}
|
||||
}
|
||||
else if (has_through &&
|
||||
(lane_data.size() == 1 || lane_data[none_index + 1].tag != "through"))
|
||||
(lane_data.size() == 1 || lane_data[none_index + 1].tag != TurnLaneType::straight))
|
||||
{
|
||||
lane_data[none_index].tag = "through";
|
||||
lane_data[none_index].tag = TurnLaneType::straight;
|
||||
}
|
||||
}
|
||||
else if (none_index + 1 == lane_data.size())
|
||||
{
|
||||
if (has_left && ((lane_data[none_index - 1].tag != "sharp_left" &&
|
||||
lane_data[none_index - 1].tag != "left")))
|
||||
if (has_left && ((lane_data[none_index - 1].tag != TurnLaneType::sharp_left &&
|
||||
lane_data[none_index - 1].tag != TurnLaneType::left)))
|
||||
{
|
||||
lane_data[none_index].tag = "left";
|
||||
if (lane_data[none_index - 1].tag == "through")
|
||||
lane_data[none_index].tag = TurnLaneType::left;
|
||||
if (lane_data[none_index - 1].tag == TurnLaneType::straight)
|
||||
{
|
||||
lane_data[none_index - 1].to = lane_data[none_index].to;
|
||||
// turning left through a possible through lane is not possible
|
||||
lane_data[none_index].from = lane_data[none_index].to;
|
||||
}
|
||||
}
|
||||
else if (has_through && lane_data[none_index - 1].tag != "through")
|
||||
else if (has_through && lane_data[none_index - 1].tag != TurnLaneType::straight)
|
||||
{
|
||||
lane_data[none_index].tag = "through";
|
||||
lane_data[none_index].tag = TurnLaneType::straight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((lane_data[none_index + 1].tag == "left" ||
|
||||
lane_data[none_index + 1].tag == "slight_left" ||
|
||||
lane_data[none_index + 1].tag == "sharp_left") &&
|
||||
(lane_data[none_index - 1].tag == "right" ||
|
||||
lane_data[none_index - 1].tag == "slight_right" ||
|
||||
lane_data[none_index - 1].tag == "sharp_right"))
|
||||
if ((lane_data[none_index + 1].tag == TurnLaneType::left ||
|
||||
lane_data[none_index + 1].tag == TurnLaneType::slight_left ||
|
||||
lane_data[none_index + 1].tag == TurnLaneType::sharp_left) &&
|
||||
(lane_data[none_index - 1].tag == TurnLaneType::right ||
|
||||
lane_data[none_index - 1].tag == TurnLaneType::slight_right ||
|
||||
lane_data[none_index - 1].tag == TurnLaneType::sharp_right))
|
||||
{
|
||||
lane_data[none_index].tag = "through";
|
||||
lane_data[none_index].tag = TurnLaneType::straight;
|
||||
}
|
||||
}
|
||||
return std::move(lane_data);
|
||||
@@ -236,7 +236,7 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
|
||||
const Intersection &intersection)
|
||||
{
|
||||
const bool needs_no_processing =
|
||||
(intersection.empty() || lane_data.empty() || !hasTag("none", lane_data));
|
||||
(intersection.empty() || lane_data.empty() || !hasTag(TurnLaneType::none, lane_data));
|
||||
|
||||
if (needs_no_processing)
|
||||
return std::move(lane_data);
|
||||
@@ -265,10 +265,10 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
|
||||
|
||||
const std::size_t connection_count =
|
||||
getNumberOfTurns(intersection) -
|
||||
((intersection[0].entry_allowed && lane_data.back().tag != "reverse") ? 1 : 0);
|
||||
((intersection[0].entry_allowed && lane_data.back().tag != TurnLaneType::uturn) ? 1 : 0);
|
||||
|
||||
// TODO check for impossible turns to see whether the turn lane is at the correct place
|
||||
const std::size_t none_index = std::distance(lane_data.begin(), findTag("none", lane_data));
|
||||
const std::size_t none_index = std::distance(lane_data.begin(), findTag(TurnLaneType::none, lane_data));
|
||||
BOOST_ASSERT(none_index != lane_data.size());
|
||||
// we have to create multiple turns
|
||||
if (connection_count > lane_data.size())
|
||||
@@ -279,7 +279,7 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
|
||||
// we have to reduce it, assigning it to neighboring turns
|
||||
else if (connection_count < lane_data.size())
|
||||
{
|
||||
// a prerequisite is simple turns. Larger differences should not end up here
|
||||
// a pgerequisite is simple turns. Larger differences should not end up here
|
||||
// an additional line at the side is only reasonable if it is targeting public
|
||||
// service vehicles. Otherwise, we should not have it
|
||||
BOOST_ASSERT(connection_count + 1 == lane_data.size());
|
||||
|
||||
@@ -30,55 +30,69 @@ bool TurnLaneData::operator<(const TurnLaneData &other) const
|
||||
if (to > other.to)
|
||||
return false;
|
||||
|
||||
const constexpr char *tag_by_modifier[] = {"sharp_right",
|
||||
"right",
|
||||
"slight_right",
|
||||
"through",
|
||||
"slight_left",
|
||||
"left",
|
||||
"sharp_left",
|
||||
"reverse"};
|
||||
const constexpr TurnLaneType::Mask tag_by_modifier[] = {TurnLaneType::sharp_right,
|
||||
TurnLaneType::right,
|
||||
TurnLaneType::slight_right,
|
||||
TurnLaneType::straight,
|
||||
TurnLaneType::slight_left,
|
||||
TurnLaneType::left,
|
||||
TurnLaneType::sharp_left,
|
||||
TurnLaneType::uturn};
|
||||
return std::find(tag_by_modifier, tag_by_modifier + 8, this->tag) <
|
||||
std::find(tag_by_modifier, tag_by_modifier + 8, other.tag);
|
||||
}
|
||||
|
||||
LaneDataVector laneDataFromString(std::string turn_lane_string)
|
||||
LaneDataVector laneDataFromDescription(const TurnLaneDescription &turn_lane_description)
|
||||
{
|
||||
typedef std::unordered_map<std::string, std::pair<LaneID, LaneID>> LaneMap;
|
||||
typedef std::unordered_map<TurnLaneType::Mask, std::pair<LaneID, LaneID>> LaneMap;
|
||||
|
||||
// FIXME this is a workaround due to https://github.com/cucumber/cucumber-js/issues/417,
|
||||
// need to switch statements when fixed
|
||||
// const auto num_lanes = std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1;
|
||||
// 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);
|
||||
}(turn_lane_string);
|
||||
const auto num_lanes = boost::numeric_cast<LaneID>(turn_lane_description.size());
|
||||
const auto setLaneData = [&](
|
||||
LaneMap &map, TurnLaneType::Mask full_mask, const LaneID current_lane) {
|
||||
const auto isSet = [&](const TurnLaneType::Mask test_mask) -> bool {
|
||||
return (test_mask & full_mask) == test_mask;
|
||||
};
|
||||
|
||||
const auto getNextTag = [](std::string &string, const char *separators) {
|
||||
auto pos = string.find_last_of(separators);
|
||||
auto result = pos != std::string::npos ? string.substr(pos + 1) : string;
|
||||
|
||||
string.resize(pos == std::string::npos ? 0 : pos);
|
||||
return result;
|
||||
};
|
||||
|
||||
const auto setLaneData = [&](LaneMap &map, std::string lane, const LaneID current_lane) {
|
||||
do
|
||||
for (std::size_t shift = 0; shift < TurnLaneType::detail::num_supported_lane_types; ++shift)
|
||||
{
|
||||
auto identifier = getNextTag(lane, ";");
|
||||
if (identifier.empty())
|
||||
identifier = "none";
|
||||
auto map_iterator = map.find(identifier);
|
||||
if (map_iterator == map.end())
|
||||
map[identifier] = std::make_pair(current_lane, current_lane);
|
||||
else
|
||||
TurnLaneType::Mask mask = 1 << shift;
|
||||
if (isSet(mask))
|
||||
{
|
||||
map_iterator->second.second = current_lane;
|
||||
auto map_iterator = map.find(mask);
|
||||
if (map_iterator == map.end())
|
||||
map[mask] = std::make_pair(current_lane, current_lane);
|
||||
else
|
||||
{
|
||||
map_iterator->second.first = current_lane;
|
||||
}
|
||||
}
|
||||
} while (!lane.empty());
|
||||
}
|
||||
};
|
||||
|
||||
LaneMap lane_map;
|
||||
LaneID lane_nr = num_lanes - 1;
|
||||
if (turn_lane_description.empty())
|
||||
return {};
|
||||
|
||||
for (auto full_mask : turn_lane_description)
|
||||
{
|
||||
setLaneData(lane_map, full_mask, lane_nr);
|
||||
--lane_nr;
|
||||
}
|
||||
|
||||
// transform the map into the lane data vector
|
||||
LaneDataVector lane_data;
|
||||
for (const auto tag : lane_map)
|
||||
{
|
||||
lane_data.push_back({tag.first, tag.second.first, tag.second.second});
|
||||
}
|
||||
|
||||
std::sort(lane_data.begin(), lane_data.end());
|
||||
|
||||
// check whether a given turn lane string resulted in valid lane data
|
||||
const auto hasValidOverlaps = [](const LaneDataVector &lane_data) {
|
||||
// Allow an overlap of at most one. Larger overlaps would result in crossing another turn,
|
||||
@@ -91,50 +105,26 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
|
||||
return true;
|
||||
};
|
||||
|
||||
LaneMap lane_map;
|
||||
LaneID lane_nr = 0;
|
||||
LaneDataVector lane_data;
|
||||
if (turn_lane_string.empty())
|
||||
return lane_data;
|
||||
|
||||
do
|
||||
{
|
||||
// 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, "|");
|
||||
setLaneData(lane_map, lane, lane_nr);
|
||||
++lane_nr;
|
||||
} while (lane_nr < num_lanes);
|
||||
|
||||
for (const auto tag : lane_map)
|
||||
{
|
||||
lane_data.push_back({tag.first, tag.second.first, tag.second.second});
|
||||
}
|
||||
|
||||
std::sort(lane_data.begin(), lane_data.end());
|
||||
if (!hasValidOverlaps(lane_data))
|
||||
{
|
||||
lane_data.clear();
|
||||
}
|
||||
|
||||
return lane_data;
|
||||
}
|
||||
|
||||
LaneDataVector::iterator findTag(const std::string &tag, LaneDataVector &data)
|
||||
LaneDataVector::iterator findTag(const TurnLaneType::Mask tag, LaneDataVector &data)
|
||||
{
|
||||
return std::find_if(data.begin(), data.end(), [&](const TurnLaneData &lane_data) {
|
||||
return tag == lane_data.tag;
|
||||
return (tag & lane_data.tag) != TurnLaneType::empty;
|
||||
});
|
||||
}
|
||||
LaneDataVector::const_iterator findTag(const std::string &tag, const LaneDataVector &data)
|
||||
LaneDataVector::const_iterator findTag(const TurnLaneType::Mask tag, const LaneDataVector &data)
|
||||
{
|
||||
return std::find_if(data.cbegin(), data.cend(), [&](const TurnLaneData &lane_data) {
|
||||
return tag == lane_data.tag;
|
||||
return (tag & lane_data.tag) != TurnLaneType::empty;
|
||||
});
|
||||
}
|
||||
|
||||
bool hasTag(const std::string &tag, const LaneDataVector &data)
|
||||
bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data)
|
||||
{
|
||||
return findTag(tag, data) != data.cend();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "extractor/guidance/turn_lane_handler.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/turn_discovery.hpp"
|
||||
#include "extractor/guidance/turn_lane_augmentation.hpp"
|
||||
#include "extractor/guidance/turn_lane_handler.hpp"
|
||||
#include "extractor/guidance/turn_lane_matcher.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
@@ -31,11 +31,12 @@ std::size_t getNumberOfTurns(const Intersection &intersection)
|
||||
} // namespace
|
||||
|
||||
TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const util::NameTable &turn_lane_strings,
|
||||
const std::vector<std::uint32_t> &turn_lane_offsets,
|
||||
const std::vector<TurnLaneType::Mask> &turn_lane_masks,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const TurnAnalysis &turn_analysis)
|
||||
: node_based_graph(node_based_graph), turn_lane_strings(turn_lane_strings),
|
||||
node_info_list(node_info_list), turn_analysis(turn_analysis)
|
||||
: node_based_graph(node_based_graph), turn_lane_offsets(turn_lane_offsets),
|
||||
turn_lane_masks(turn_lane_masks), node_info_list(node_info_list), turn_analysis(turn_analysis)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,7 +44,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
|
||||
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:
|
||||
This function parses the turn_lane_descriptions of a format that describes an intersection as:
|
||||
|
||||
----------
|
||||
A -^
|
||||
@@ -53,49 +54,64 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
|
||||
C -v
|
||||
----------
|
||||
|
||||
with a string like |left|through;right|right| and performs an assignment onto the turns:
|
||||
for example: (130, turn slight right), (180, ramp straight), (320, turn sharp left)
|
||||
witch is the result of a string like looking |left|through;right|right| and performs an
|
||||
assignment onto the turns.
|
||||
For example: (130, turn slight right), (180, ramp straight), (320, turn sharp left).
|
||||
*/
|
||||
Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
const EdgeID via_edge,
|
||||
Intersection intersection,
|
||||
LaneDataIdMap &id_map) const
|
||||
{
|
||||
//if only a uturn exists, there is nothing we can do
|
||||
if( intersection.size() == 1 )
|
||||
return std::move(intersection);
|
||||
|
||||
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)
|
||||
: "";
|
||||
// Extract a lane description for the ID
|
||||
|
||||
const auto turn_lane_description =
|
||||
data.lane_description_id != INVALID_LANE_DESCRIPTIONID
|
||||
? TurnLaneDescription(
|
||||
turn_lane_masks.begin() + turn_lane_offsets[data.lane_description_id],
|
||||
turn_lane_masks.begin() + turn_lane_offsets[data.lane_description_id + 1])
|
||||
: TurnLaneDescription();
|
||||
|
||||
BOOST_ASSERT( turn_lane_description.empty() || turn_lane_description.size() == (turn_lane_offsets[data.lane_description_id+1] - turn_lane_offsets[data.lane_description_id]));
|
||||
|
||||
// going straight, due to traffic signals, we can have uncompressed geometry
|
||||
if (intersection.size() == 2 &&
|
||||
((data.lane_string_id != INVALID_LANE_STRINGID &&
|
||||
data.lane_string_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].turn.eid).lane_string_id) ||
|
||||
((data.lane_description_id != INVALID_LANE_DESCRIPTIONID &&
|
||||
data.lane_description_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].turn.eid).lane_description_id) ||
|
||||
angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE))
|
||||
return std::move(intersection);
|
||||
|
||||
auto lane_data = laneDataFromString(turn_lane_string);
|
||||
auto lane_data = laneDataFromDescription(turn_lane_description);
|
||||
|
||||
// if we see an invalid conversion, we stop immediately
|
||||
if (!turn_lane_string.empty() && lane_data.empty())
|
||||
if (!turn_lane_description.empty() && lane_data.empty())
|
||||
return std::move(intersection);
|
||||
|
||||
// might be reasonable to handle multiple turns, if we know of a sequence of lanes
|
||||
// e.g. one direction per lane, if three lanes and right, through, left available
|
||||
if (!turn_lane_string.empty() && lane_data.size() == 1 && lane_data[0].tag == "none")
|
||||
if (!turn_lane_description.empty() && lane_data.size() == 1 &&
|
||||
lane_data[0].tag == TurnLaneType::none)
|
||||
return std::move(intersection);
|
||||
|
||||
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));
|
||||
hasTag(TurnLaneType::merge_to_left | TurnLaneType::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);
|
||||
const bool has_non_usable_u_turn = (intersection[0].entry_allowed &&
|
||||
!hasTag(TurnLaneType::none | TurnLaneType::left |
|
||||
TurnLaneType::sharp_left | TurnLaneType::uturn,
|
||||
lane_data) &&
|
||||
lane_data.size() + 1 == possible_entries);
|
||||
|
||||
if (has_merge_lane || has_non_usable_u_turn)
|
||||
return std::move(intersection);
|
||||
@@ -103,19 +119,19 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
if (!lane_data.empty() && canMatchTrivially(intersection, lane_data) &&
|
||||
lane_data.size() !=
|
||||
static_cast<std::size_t>(
|
||||
lane_data.back().tag != "reverse" && intersection[0].entry_allowed ? 1 : 0) +
|
||||
lane_data.back().tag != TurnLaneType::uturn && intersection[0].entry_allowed ? 1
|
||||
: 0) +
|
||||
possible_entries &&
|
||||
intersection[0].entry_allowed && !hasTag("none", lane_data))
|
||||
lane_data.push_back({"reverse", lane_data.back().to, lane_data.back().to});
|
||||
intersection[0].entry_allowed && !hasTag(TurnLaneType::none, lane_data))
|
||||
lane_data.push_back({TurnLaneType::uturn, lane_data.back().to, lane_data.back().to});
|
||||
|
||||
bool is_simple = isSimpleIntersection(lane_data, intersection);
|
||||
|
||||
// simple intersections can be assigned directly
|
||||
if (is_simple)
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, data.lane_string_id, id_map);
|
||||
std::move(intersection), lane_data, data.lane_description_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
|
||||
@@ -136,13 +152,13 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, data.lane_string_id, id_map);
|
||||
std::move(intersection), lane_data, data.lane_description_id, id_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
// The second part does not provide lane data on the current segment, but on the segment prior
|
||||
// to the turn. We try to partition the data and only consider the second part.
|
||||
else if (turn_lane_string.empty())
|
||||
else if (turn_lane_description.empty())
|
||||
{
|
||||
// acquire the lane data of a previous segment and, if possible, use it for the current
|
||||
// intersection.
|
||||
@@ -162,10 +178,11 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
NodeID previous_node = SPECIAL_NODEID;
|
||||
Intersection previous_intersection;
|
||||
EdgeID previous_id = SPECIAL_EDGEID;
|
||||
LaneDataVector lane_data;
|
||||
|
||||
// Get the previous lane string. We only accept strings that stem from a not-simple intersection
|
||||
// and are not empty.
|
||||
const auto previous_lane_string = [&]() -> std::string {
|
||||
const auto previous_lane_description = [&]() -> TurnLaneDescription {
|
||||
if (!findPreviousIntersection(at,
|
||||
via_edge,
|
||||
intersection,
|
||||
@@ -174,32 +191,38 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
previous_node,
|
||||
previous_id,
|
||||
previous_intersection))
|
||||
return "";
|
||||
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
|
||||
? turn_lane_strings.GetNameForID(previous_data.lane_string_id)
|
||||
: "";
|
||||
if (previous_string.empty())
|
||||
return "";
|
||||
const auto &previous_edge_data = node_based_graph.GetEdgeData(previous_id);
|
||||
// TODO access correct data
|
||||
const auto previous_description =
|
||||
previous_edge_data.lane_description_id != INVALID_LANE_DESCRIPTIONID
|
||||
? TurnLaneDescription(
|
||||
turn_lane_masks.begin() +
|
||||
turn_lane_offsets[previous_edge_data.lane_description_id],
|
||||
turn_lane_masks.begin() +
|
||||
turn_lane_offsets[previous_edge_data.lane_description_id + 1])
|
||||
: TurnLaneDescription();
|
||||
if (previous_description.empty())
|
||||
return previous_description;
|
||||
|
||||
previous_intersection = turn_analysis.assignTurnTypes(
|
||||
previous_node, previous_id, std::move(previous_intersection));
|
||||
|
||||
auto previous_lane_data = laneDataFromString(previous_string);
|
||||
lane_data = laneDataFromDescription(previous_description);
|
||||
|
||||
if (isSimpleIntersection(previous_lane_data, previous_intersection))
|
||||
return "";
|
||||
return previous_string;
|
||||
if (isSimpleIntersection(lane_data, previous_intersection))
|
||||
return {};
|
||||
else
|
||||
return previous_description;
|
||||
}();
|
||||
|
||||
// no lane string, no problems
|
||||
if (previous_lane_string.empty())
|
||||
if (previous_lane_description.empty())
|
||||
return std::move(intersection);
|
||||
|
||||
auto lane_data = laneDataFromString(previous_lane_string);
|
||||
|
||||
// stop on invalid lane data conversion
|
||||
if (lane_data.empty())
|
||||
return std::move(intersection);
|
||||
@@ -210,7 +233,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
|
||||
std::move(intersection), lane_data, previous_data.lane_description_id, id_map);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -230,7 +253,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
|
||||
{
|
||||
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
|
||||
return simpleMatchTuplesToTurns(
|
||||
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
|
||||
std::move(intersection), lane_data, previous_data.lane_description_id, id_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,7 +280,10 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
||||
return std::count_if(
|
||||
lane_data.begin(),
|
||||
lane_data.end(),
|
||||
[](const TurnLaneData &data) { return boost::starts_with(data.tag, "merge"); }) +
|
||||
[](const TurnLaneData &data) {
|
||||
return ((data.tag & TurnLaneType::merge_to_left) != TurnLaneType::empty) ||
|
||||
((data.tag & TurnLaneType::merge_to_right) != TurnLaneType::empty);
|
||||
}) +
|
||||
std::size_t{1} >=
|
||||
lane_data.size();
|
||||
}
|
||||
@@ -268,7 +294,7 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
||||
const auto num_turns = [&]() {
|
||||
auto count = getNumberOfTurns(intersection);
|
||||
if (count < lane_data.size() && !intersection[0].entry_allowed &&
|
||||
lane_data.back().tag == "reverse")
|
||||
lane_data.back().tag == TurnLaneType::uturn)
|
||||
return count + 1;
|
||||
return count;
|
||||
}();
|
||||
@@ -281,8 +307,8 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
||||
|
||||
// single additional lane data entry is alright, if it is none at the side. This usually
|
||||
// refers to a bus-lane
|
||||
if (num_turns + std::size_t{1} == lane_data.size() && lane_data.front().tag != "none" &&
|
||||
lane_data.back().tag != "none")
|
||||
if (num_turns + std::size_t{1} == lane_data.size() &&
|
||||
lane_data.front().tag != TurnLaneType::none && lane_data.back().tag != TurnLaneType::none)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -291,15 +317,16 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
||||
if (num_turns > lane_data.size() &&
|
||||
lane_data.end() ==
|
||||
std::find_if(lane_data.begin(), lane_data.end(), [](const TurnLaneData &data) {
|
||||
return data.tag == "none";
|
||||
return data.tag == TurnLaneType::none;
|
||||
}))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_turns > lane_data.size() && intersection[0].entry_allowed &&
|
||||
!(hasTag("reverse", lane_data) ||
|
||||
(lane_data.back().tag != "left" && lane_data.back().tag != "sharp_left")))
|
||||
!(hasTag(TurnLaneType::uturn, lane_data) ||
|
||||
(lane_data.back().tag != TurnLaneType::left &&
|
||||
lane_data.back().tag != TurnLaneType::sharp_left)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -310,21 +337,21 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
||||
std::unordered_set<std::size_t> matched_indices;
|
||||
for (const auto &data : lane_data)
|
||||
{
|
||||
if (data.tag == "none")
|
||||
if (data.tag == TurnLaneType::none)
|
||||
{
|
||||
has_none = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto best_match = [&]() {
|
||||
if (data.tag != "reverse" || lane_data.size() == 1)
|
||||
if (data.tag != TurnLaneType::uturn || lane_data.size() == 1)
|
||||
return findBestMatch(data.tag, intersection);
|
||||
|
||||
// lane_data.size() > 1
|
||||
if (lane_data.back().tag == "reverse")
|
||||
if (lane_data.back().tag == TurnLaneType::uturn)
|
||||
return findBestMatchForReverse(lane_data[lane_data.size() - 2].tag, intersection);
|
||||
|
||||
BOOST_ASSERT(lane_data.front().tag == "reverse");
|
||||
BOOST_ASSERT(lane_data.front().tag == TurnLaneType::uturn);
|
||||
return findBestMatchForReverse(lane_data[1].tag, intersection);
|
||||
}();
|
||||
std::size_t match_index = std::distance(intersection.begin(), best_match);
|
||||
@@ -396,7 +423,8 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
std::size_t straightmost_tag_index = turn_lane_data.size();
|
||||
for (std::size_t lane = 0; lane < turn_lane_data.size(); ++lane)
|
||||
{
|
||||
if (turn_lane_data[lane].tag == "none" || turn_lane_data[lane].tag == "reverse")
|
||||
if ((turn_lane_data[lane].tag & (TurnLaneType::none | TurnLaneType::uturn)) !=
|
||||
TurnLaneType::empty)
|
||||
continue;
|
||||
|
||||
const auto best_match = findBestMatch(turn_lane_data[lane].tag, intersection);
|
||||
@@ -419,7 +447,8 @@ 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(TurnLaneType::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?
|
||||
@@ -477,7 +506,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
std::count(matched_at_second.begin(), matched_at_second.end(), true)) ==
|
||||
getNumberOfTurns(next_intersection))
|
||||
{
|
||||
TurnLaneData data = {"through", 255, 0};
|
||||
TurnLaneData data = {TurnLaneType::straight, 255, 0};
|
||||
augmentEntry(data);
|
||||
first.push_back(data);
|
||||
std::sort(first.begin(), first.end());
|
||||
@@ -489,19 +518,18 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
|
||||
Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection,
|
||||
const LaneDataVector &lane_data,
|
||||
const LaneStringID lane_string_id,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
LaneDataIdMap &id_map) const
|
||||
{
|
||||
if (lane_data.empty() || !canMatchTrivially(intersection, lane_data))
|
||||
return std::move(intersection);
|
||||
|
||||
BOOST_ASSERT(!hasTag("none", lane_data));
|
||||
BOOST_ASSERT(std::count_if(lane_data.begin(), lane_data.end(), [](const TurnLaneData &data) {
|
||||
return boost::starts_with(data.tag, "merge");
|
||||
}) == 0);
|
||||
BOOST_ASSERT(
|
||||
!hasTag(TurnLaneType::none | TurnLaneType::merge_to_left | TurnLaneType::merge_to_right,
|
||||
lane_data));
|
||||
|
||||
return triviallyMatchLanesToTurns(
|
||||
std::move(intersection), lane_data, node_based_graph, lane_string_id, id_map);
|
||||
std::move(intersection), lane_data, node_based_graph, lane_description_id, id_map);
|
||||
}
|
||||
|
||||
} // namespace lanes
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "extractor/guidance/turn_lane_matcher.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "extractor/guidance/turn_lane_matcher.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -17,18 +17,18 @@ namespace lanes
|
||||
{
|
||||
|
||||
// Translate Turn Tags into a Matching Direction Modifier
|
||||
DirectionModifier::Enum getMatchingModifier(const std::string &tag)
|
||||
DirectionModifier::Enum getMatchingModifier(const TurnLaneType::Mask &tag)
|
||||
{
|
||||
const constexpr char *tag_by_modifier[] = {"reverse",
|
||||
"sharp_right",
|
||||
"right",
|
||||
"slight_right",
|
||||
"through",
|
||||
"slight_left",
|
||||
"left",
|
||||
"sharp_left",
|
||||
"merge_to_left",
|
||||
"merge_to_right"};
|
||||
const constexpr TurnLaneType::Mask tag_by_modifier[] = {TurnLaneType::uturn,
|
||||
TurnLaneType::sharp_right,
|
||||
TurnLaneType::right,
|
||||
TurnLaneType::slight_right,
|
||||
TurnLaneType::straight,
|
||||
TurnLaneType::slight_left,
|
||||
TurnLaneType::left,
|
||||
TurnLaneType::sharp_left,
|
||||
TurnLaneType::merge_to_left,
|
||||
TurnLaneType::merge_to_right};
|
||||
const auto index =
|
||||
std::distance(tag_by_modifier, std::find(tag_by_modifier, tag_by_modifier + 10, tag));
|
||||
|
||||
@@ -51,7 +51,7 @@ DirectionModifier::Enum getMatchingModifier(const std::string &tag)
|
||||
}
|
||||
|
||||
// check whether a match of a given tag and a turn instruction can be seen as valid
|
||||
bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
|
||||
bool isValidMatch(const TurnLaneType::Mask &tag, const TurnInstruction instruction)
|
||||
{
|
||||
using util::guidance::hasLeftModifier;
|
||||
using util::guidance::hasRightModifier;
|
||||
@@ -59,12 +59,13 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
|
||||
return instruction.type == TurnType::Merge;
|
||||
};
|
||||
|
||||
if (tag == "reverse")
|
||||
if (tag == TurnLaneType::uturn)
|
||||
{
|
||||
return hasLeftModifier(instruction) ||
|
||||
instruction.direction_modifier == DirectionModifier::UTurn;
|
||||
}
|
||||
else if (tag == "sharp_right" || tag == "right" || tag == "slight_right")
|
||||
else if (tag == TurnLaneType::sharp_right || tag == TurnLaneType::right ||
|
||||
tag == TurnLaneType::slight_right)
|
||||
{
|
||||
if (isMirroredModifier(instruction))
|
||||
return hasLeftModifier(instruction);
|
||||
@@ -72,7 +73,7 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
|
||||
// needs to be adjusted for left side driving
|
||||
return leavesRoundabout(instruction) || hasRightModifier(instruction);
|
||||
}
|
||||
else if (tag == "through")
|
||||
else if (tag == TurnLaneType::straight)
|
||||
{
|
||||
return instruction.direction_modifier == DirectionModifier::Straight ||
|
||||
instruction.type == TurnType::Suppressed || instruction.type == TurnType::NewName ||
|
||||
@@ -87,7 +88,8 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
|
||||
instruction.direction_modifier == DirectionModifier::SlightRight)) ||
|
||||
instruction.type == TurnType::UseLane;
|
||||
}
|
||||
else if (tag == "slight_left" || tag == "left" || tag == "sharp_left")
|
||||
else if (tag == TurnLaneType::slight_left || tag == TurnLaneType::left ||
|
||||
tag == TurnLaneType::sharp_left)
|
||||
{
|
||||
if (isMirroredModifier(instruction))
|
||||
return hasRightModifier(instruction);
|
||||
@@ -100,7 +102,11 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
|
||||
return false;
|
||||
}
|
||||
|
||||
typename Intersection::const_iterator findBestMatch(const std::string &tag,
|
||||
// Every tag is somewhat idealized in form of the expected angle. A through lane should go straight
|
||||
// (or follow a 180 degree turn angle between in/out segments.) The following function tries to find
|
||||
// the best possible match for every tag in a given intersection, considering a few corner cases
|
||||
// introduced to OSRM handling u-turns
|
||||
typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask &tag,
|
||||
const Intersection &intersection)
|
||||
{
|
||||
const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315};
|
||||
@@ -122,15 +128,20 @@ typename Intersection::const_iterator findBestMatch(const std::string &tag,
|
||||
});
|
||||
}
|
||||
|
||||
typename Intersection::const_iterator findBestMatchForReverse(const std::string &leftmost_tag,
|
||||
const Intersection &intersection)
|
||||
// Reverse is a special case, because it requires access to the leftmost tag. It has its own
|
||||
// matching function as a result of that. The leftmost tag is required, since u-turns are disabled
|
||||
// by default in OSRM. Therefor we cannot check whether a turn is allowed, since it could be
|
||||
// possible that it is forbidden. In addition, the best u-turn angle does not necessarily represent
|
||||
// the u-turn, since it could be a sharp-left turn instead on a road with a middle island.
|
||||
typename Intersection::const_iterator
|
||||
findBestMatchForReverse(const TurnLaneType::Mask &leftmost_tag, const Intersection &intersection)
|
||||
{
|
||||
const auto leftmost_itr = findBestMatch(leftmost_tag, intersection);
|
||||
if (leftmost_itr + 1 == intersection.cend())
|
||||
return intersection.begin();
|
||||
|
||||
const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315};
|
||||
const std::string tag = "reverse";
|
||||
const TurnLaneType::Mask tag = TurnLaneType::uturn;
|
||||
const auto idealized_angle = idealized_turn_angles[getMatchingModifier(tag)];
|
||||
return std::min_element(
|
||||
intersection.begin() + std::distance(intersection.begin(), leftmost_itr),
|
||||
@@ -149,6 +160,8 @@ typename Intersection::const_iterator findBestMatchForReverse(const std::string
|
||||
});
|
||||
}
|
||||
|
||||
// a match is trivial if all turns can be associated with their best match in a valid way and the
|
||||
// matches occur in order
|
||||
bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &lane_data)
|
||||
{
|
||||
std::size_t road_index = 1, lane = 0;
|
||||
@@ -163,17 +176,18 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
|
||||
if (findBestMatch(lane_data[lane].tag, intersection) !=
|
||||
intersection.begin() + road_index)
|
||||
return false;
|
||||
|
||||
++lane;
|
||||
}
|
||||
}
|
||||
return lane == lane_data.size() ||
|
||||
(lane + 1 == lane_data.size() && lane_data.back().tag == "reverse");
|
||||
(lane + 1 == lane_data.size() && lane_data.back().tag == TurnLaneType::uturn);
|
||||
}
|
||||
|
||||
Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
const LaneDataVector &lane_data,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const LaneStringID lane_string_id,
|
||||
const LaneDescriptionID lane_string_id,
|
||||
LaneDataIdMap &lane_data_to_id)
|
||||
{
|
||||
std::size_t road_index = 1, lane = 0;
|
||||
@@ -212,7 +226,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
}
|
||||
|
||||
// handle reverse tag, if present
|
||||
if (lane + 1 == lane_data.size() && lane_data.back().tag == "reverse")
|
||||
if (lane + 1 == lane_data.size() && lane_data.back().tag == TurnLaneType::uturn)
|
||||
{
|
||||
std::size_t u_turn = 0;
|
||||
if (node_based_graph.GetEdgeData(intersection[0].turn.eid).reversed)
|
||||
|
||||
+32
-51
@@ -1,4 +1,3 @@
|
||||
#include "storage/storage.hpp"
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
@@ -9,6 +8,7 @@
|
||||
#include "storage/shared_barriers.hpp"
|
||||
#include "storage/shared_datatype.hpp"
|
||||
#include "storage/shared_memory.hpp"
|
||||
#include "storage/storage.hpp"
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/exception.hpp"
|
||||
@@ -147,25 +147,17 @@ 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);
|
||||
std::vector<std::uint32_t> lane_description_offsets;
|
||||
std::vector<extractor::guidance::TurnLaneType::Mask> lane_description_masks;
|
||||
if (!util::deserializeAdjacencyArray(config.turn_lane_description_path.string(),
|
||||
lane_description_offsets,
|
||||
lane_description_masks))
|
||||
throw util::exception("Could not open read lane descriptions from: " +
|
||||
config.turn_lane_description_path.string());
|
||||
shared_layout_ptr->SetBlockSize<std::uint32_t>(SharedDataLayout::LANE_DESCRIPTION_OFFSETS,
|
||||
lane_description_offsets.size());
|
||||
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnLaneType::Mask>(
|
||||
SharedDataLayout::LANE_DESCRIPTION_MASKS, lane_description_masks.size());
|
||||
|
||||
// Loading information for original edges
|
||||
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
|
||||
@@ -454,7 +446,7 @@ int Storage::Run()
|
||||
|
||||
char *name_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_CHAR_LIST);
|
||||
unsigned temp_length;
|
||||
unsigned temp_length = 0;
|
||||
name_stream.read((char *)&temp_length, sizeof(unsigned));
|
||||
|
||||
BOOST_ASSERT_MSG(shared_layout_ptr->AlignBlockSize(temp_length) ==
|
||||
@@ -468,16 +460,6 @@ int Storage::Run()
|
||||
}
|
||||
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>(
|
||||
@@ -489,30 +471,29 @@ int Storage::Run()
|
||||
}
|
||||
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)
|
||||
auto *turn_lane_offset_ptr = shared_layout_ptr->GetBlockPtr<std::uint32_t, true>(
|
||||
shared_memory_ptr, SharedDataLayout::LANE_DESCRIPTION_OFFSETS);
|
||||
if (!lane_description_offsets.empty())
|
||||
{
|
||||
turn_string_stream.read(
|
||||
(char *)turn_string_blocks_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_BLOCKS));
|
||||
BOOST_ASSERT(shared_layout_ptr->GetBlockSize(SharedDataLayout::LANE_DESCRIPTION_OFFSETS) >=
|
||||
sizeof(lane_description_offsets[0]) * lane_description_offsets.size());
|
||||
std::copy(
|
||||
lane_description_offsets.begin(), lane_description_offsets.end(), turn_lane_offset_ptr);
|
||||
std::vector<std::uint32_t> tmp;
|
||||
lane_description_offsets.swap(tmp);
|
||||
}
|
||||
|
||||
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)
|
||||
auto *turn_lane_mask_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<extractor::guidance::TurnLaneType::Mask, true>(
|
||||
shared_memory_ptr, SharedDataLayout::LANE_DESCRIPTION_MASKS);
|
||||
if (!lane_description_masks.empty())
|
||||
{
|
||||
turn_string_stream.read(
|
||||
turn_string_char_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST));
|
||||
BOOST_ASSERT(shared_layout_ptr->GetBlockSize(SharedDataLayout::LANE_DESCRIPTION_MASKS) >=
|
||||
sizeof(lane_description_masks[0]) * lane_description_masks.size());
|
||||
std::copy(lane_description_masks.begin(), lane_description_masks.end(), turn_lane_mask_ptr);
|
||||
std::vector<extractor::guidance::TurnLaneType::Mask> tmp;
|
||||
lane_description_masks.swap(tmp);
|
||||
}
|
||||
turn_string_stream.close();
|
||||
|
||||
// load original edge information
|
||||
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
|
||||
@@ -595,7 +576,7 @@ int Storage::Run()
|
||||
{
|
||||
util::SimpleLogger().Write()
|
||||
<< "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
|
||||
<< " chars into name data ptr\n";
|
||||
<< " chars into name data ptr";
|
||||
std::copy(
|
||||
m_datasource_name_data.begin(), m_datasource_name_data.end(), datasource_name_data_ptr);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ StorageConfig::StorageConfig(const boost::filesystem::path &base)
|
||||
datasource_indexes_path{base.string() + ".datasource_indexes"},
|
||||
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"},
|
||||
intersection_class_path{base.string() + ".icd"}, turn_lane_data_path{base.string() + ".tld"},
|
||||
turn_lane_string_path{base.string() + ".tls"}
|
||||
turn_lane_description_path{base.string() + ".tls"}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user