2016-09-09 12:28:44 -04:00
|
|
|
#include "extractor/extractor_callbacks.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "extractor/extraction_containers.hpp"
|
|
|
|
#include "extractor/extraction_node.hpp"
|
|
|
|
#include "extractor/extraction_way.hpp"
|
2016-06-24 10:06:45 -04:00
|
|
|
#include "extractor/guidance/road_classification.hpp"
|
2016-05-12 12:50:10 -04:00
|
|
|
#include "extractor/profile_properties.hpp"
|
2017-07-06 20:16:40 -04:00
|
|
|
#include "extractor/query_node.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "extractor/restriction.hpp"
|
2016-06-21 04:41:08 -04:00
|
|
|
|
2016-01-11 12:05:24 -05:00
|
|
|
#include "util/for_each_pair.hpp"
|
2016-05-13 13:18:00 -04:00
|
|
|
#include "util/guidance/turn_lanes.hpp"
|
2016-12-06 15:30:46 -05:00
|
|
|
#include "util/log.hpp"
|
2014-01-09 10:13:35 -05:00
|
|
|
|
2016-05-13 13:18:00 -04:00
|
|
|
#include <boost/numeric/conversion/cast.hpp>
|
2016-05-27 15:05:04 -04:00
|
|
|
#include <boost/optional/optional.hpp>
|
2016-06-21 04:41:08 -04:00
|
|
|
#include <boost/tokenizer.hpp>
|
2015-09-18 08:26:32 -04:00
|
|
|
|
|
|
|
#include <osmium/osm.hpp>
|
|
|
|
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "osrm/coordinate.hpp"
|
2013-12-16 05:29:38 -05:00
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
#include <cstring>
|
2016-04-12 09:00:08 -04:00
|
|
|
#include <iterator>
|
2014-05-09 13:35:09 -04:00
|
|
|
#include <limits>
|
2013-12-16 05:29:38 -05:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace extractor
|
|
|
|
{
|
|
|
|
|
2016-06-21 04:41:08 -04:00
|
|
|
using TurnLaneDescription = guidance::TurnLaneDescription;
|
|
|
|
namespace TurnLaneType = guidance::TurnLaneType;
|
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_,
|
2017-06-27 18:01:05 -04:00
|
|
|
std::unordered_map<std::string, ClassData> &classes_map,
|
|
|
|
guidance::LaneDescriptionMap &lane_description_map,
|
2016-05-12 12:50:10 -04:00
|
|
|
const ProfileProperties &properties)
|
2017-06-27 18:01:05 -04:00
|
|
|
: external_memory(extraction_containers_), classes_map(classes_map),
|
|
|
|
lane_description_map(lane_description_map),
|
2017-03-29 17:48:57 -04:00
|
|
|
fallback_to_duration(properties.fallback_to_duration),
|
|
|
|
force_split_edges(properties.force_split_edges)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2017-06-29 16:12:25 -04:00
|
|
|
// we reserved 0, 1, 2, 3, 4 for the empty case
|
|
|
|
string_map[MapKey("", "", "", "", "")] = 0;
|
2017-06-07 00:31:07 -04:00
|
|
|
lane_description_map.data[TurnLaneDescription()] = 0;
|
2014-05-09 10:17:31 -04:00
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
|
2015-04-10 06:35:24 -04:00
|
|
|
/**
|
|
|
|
* Takes the node position from osmium and the filtered properties from the lua
|
|
|
|
* profile and saves them to external memory.
|
|
|
|
*
|
|
|
|
* warning: caller needs to take care of synchronization!
|
|
|
|
*/
|
2014-10-13 07:53:06 -04:00
|
|
|
void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
|
2014-08-27 10:24:40 -04:00
|
|
|
const ExtractionNode &result_node)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2017-07-06 20:16:40 -04:00
|
|
|
const auto id = OSMNodeID{static_cast<std::uint64_t>(input_node.id())};
|
|
|
|
|
2015-01-22 06:19:11 -05:00
|
|
|
external_memory.all_nodes_list.push_back(
|
2017-07-06 20:16:40 -04:00
|
|
|
QueryNode{util::toFixed(util::UnsafeFloatLongitude{input_node.location().lon()}),
|
|
|
|
util::toFixed(util::UnsafeFloatLatitude{input_node.location().lat()}),
|
|
|
|
id});
|
|
|
|
|
|
|
|
if (result_node.barrier)
|
|
|
|
{
|
|
|
|
external_memory.barrier_nodes.push_back(id);
|
|
|
|
}
|
|
|
|
if (result_node.traffic_lights)
|
|
|
|
{
|
2017-07-20 08:03:39 -04:00
|
|
|
external_memory.traffic_signals.push_back(id);
|
2017-07-06 20:16:40 -04:00
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
void ExtractorCallbacks::ProcessRestriction(const InputConditionalTurnRestriction &restriction)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
external_memory.restrictions_list.push_back(restriction);
|
|
|
|
// util::Log() << restriction.toString();
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
2017-07-06 11:09:24 -04:00
|
|
|
|
2015-04-08 12:53:10 -04:00
|
|
|
/**
|
2015-04-10 06:35:24 -04:00
|
|
|
* Takes the geometry contained in the ```input_way``` and the tags computed
|
|
|
|
* by the lua profile inside ```parsed_way``` and computes all edge segments.
|
2015-04-08 12:53:10 -04:00
|
|
|
*
|
2015-04-10 06:35:24 -04:00
|
|
|
* Depending on the forward/backwards weights the edges are split into forward
|
|
|
|
* and backward edges.
|
2015-04-08 12:53:10 -04:00
|
|
|
*
|
|
|
|
* warning: caller needs to take care of synchronization!
|
|
|
|
*/
|
2014-10-13 07:53:06 -04:00
|
|
|
void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2017-01-31 06:36:38 -05:00
|
|
|
if ((parsed_way.forward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
|
|
|
|
parsed_way.forward_speed <= 0) &&
|
|
|
|
(parsed_way.backward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
|
|
|
|
parsed_way.backward_speed <= 0) &&
|
|
|
|
parsed_way.duration <= 0)
|
|
|
|
{ // Only true if the way is assigned a valid speed/duration
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fallback_to_duration && (parsed_way.forward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
|
|
|
|
parsed_way.forward_rate <= 0) &&
|
|
|
|
(parsed_way.backward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
|
|
|
|
parsed_way.backward_rate <= 0) &&
|
|
|
|
parsed_way.weight <= 0)
|
|
|
|
{ // Only true if the way is assigned a valid rate/weight and there is no duration fallback
|
2014-05-18 16:44:19 -04:00
|
|
|
return;
|
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
const auto &nodes = input_way.nodes();
|
|
|
|
if (nodes.size() <= 1)
|
2014-06-02 13:23:50 -04:00
|
|
|
{ // safe-guard against broken data
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-13 09:51:40 -04:00
|
|
|
if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id())
|
2014-05-18 16:44:19 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
util::Log(logDEBUG) << "found bogus way with id: " << input_way.id() << " of size "
|
2016-05-12 12:50:10 -04:00
|
|
|
<< nodes.size();
|
2014-05-18 16:44:19 -04:00
|
|
|
return;
|
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
InternalExtractorEdge::DurationData forward_duration_data;
|
|
|
|
InternalExtractorEdge::DurationData backward_duration_data;
|
2015-05-09 11:21:36 -04:00
|
|
|
InternalExtractorEdge::WeightData forward_weight_data;
|
|
|
|
InternalExtractorEdge::WeightData backward_weight_data;
|
|
|
|
|
2017-02-02 11:05:08 -05:00
|
|
|
const auto toValueByEdgeOrByMeter = [&nodes](const double by_way, const double by_meter) {
|
|
|
|
using Value = detail::ByEdgeOrByMeterValue;
|
2017-02-14 06:59:16 -05:00
|
|
|
// get value by weight per edge
|
2017-02-02 11:05:08 -05:00
|
|
|
if (by_way >= 0)
|
2016-05-12 12:50:10 -04:00
|
|
|
{
|
|
|
|
// FIXME We divide by the number of edges here, but should rather consider
|
|
|
|
// the length of each segment. We would either have to compute the length
|
|
|
|
// of the whole way here (we can't: no node coordinates) or push that back
|
|
|
|
// to the container and keep a reference to the way.
|
2017-02-02 11:05:08 -05:00
|
|
|
const std::size_t num_edges = (nodes.size() - 1);
|
|
|
|
return Value(Value::by_edge, by_way / num_edges);
|
2016-05-12 12:50:10 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-14 06:59:16 -05:00
|
|
|
// get value by deriving weight from speed per edge
|
2017-02-02 11:05:08 -05:00
|
|
|
return Value(Value::by_meter, by_meter);
|
2016-05-12 12:50:10 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2016-05-12 12:50:10 -04:00
|
|
|
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.forward_speed > 0);
|
|
|
|
forward_duration_data =
|
|
|
|
toValueByEdgeOrByMeter(parsed_way.duration, parsed_way.forward_speed / 3.6);
|
|
|
|
// fallback to duration as weight
|
2017-02-02 04:56:52 -05:00
|
|
|
if (fallback_to_duration)
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2017-02-02 04:56:52 -05:00
|
|
|
forward_weight_data = forward_duration_data;
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2017-02-02 04:56:52 -05:00
|
|
|
else
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2017-02-02 04:56:52 -05:00
|
|
|
BOOST_ASSERT(parsed_way.weight > 0 || parsed_way.forward_rate > 0);
|
|
|
|
forward_weight_data =
|
|
|
|
toValueByEdgeOrByMeter(parsed_way.weight, parsed_way.forward_rate);
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2014-05-18 16:44:19 -04:00
|
|
|
}
|
2016-05-12 12:50:10 -04:00
|
|
|
if (parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
2014-05-18 16:44:19 -04:00
|
|
|
{
|
2016-05-12 12:50:10 -04:00
|
|
|
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.backward_speed > 0);
|
|
|
|
backward_duration_data =
|
|
|
|
toValueByEdgeOrByMeter(parsed_way.duration, parsed_way.backward_speed / 3.6);
|
|
|
|
// fallback to duration as weight
|
2017-02-02 04:56:52 -05:00
|
|
|
if (fallback_to_duration)
|
2016-05-12 12:50:10 -04:00
|
|
|
{
|
2017-02-02 04:56:52 -05:00
|
|
|
backward_weight_data = backward_duration_data;
|
2016-05-12 12:50:10 -04:00
|
|
|
}
|
2017-02-02 04:56:52 -05:00
|
|
|
else
|
2016-05-12 12:50:10 -04:00
|
|
|
{
|
2017-02-02 04:56:52 -05:00
|
|
|
BOOST_ASSERT(parsed_way.weight > 0 || parsed_way.backward_rate > 0);
|
|
|
|
backward_weight_data =
|
|
|
|
toValueByEdgeOrByMeter(parsed_way.weight, parsed_way.backward_rate);
|
2016-05-12 12:50:10 -04:00
|
|
|
}
|
2014-05-18 16:44:19 -04:00
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
|
2017-06-27 18:01:05 -04:00
|
|
|
const auto classStringToMask = [this](const std::string &class_name) {
|
|
|
|
auto iter = classes_map.find(class_name);
|
|
|
|
if (iter == classes_map.end())
|
|
|
|
{
|
|
|
|
if (classes_map.size() > MAX_CLASS_INDEX)
|
|
|
|
{
|
|
|
|
throw util::exception("Maximum number of classes if " +
|
|
|
|
std::to_string(MAX_CLASS_INDEX + 1));
|
|
|
|
}
|
|
|
|
ClassData class_mask = 1u << classes_map.size();
|
|
|
|
classes_map[class_name] = class_mask;
|
|
|
|
return class_mask;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return iter->second;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const auto classesToMask = [&](const auto &classes) {
|
|
|
|
ClassData mask = 0;
|
|
|
|
for (const auto &name_and_flag : classes)
|
|
|
|
{
|
|
|
|
if (name_and_flag.second)
|
|
|
|
{
|
|
|
|
mask |= classStringToMask(name_and_flag.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return mask;
|
|
|
|
};
|
|
|
|
const ClassData forward_classes = classesToMask(parsed_way.forward_classes);
|
|
|
|
const ClassData backward_classes = classesToMask(parsed_way.backward_classes);
|
|
|
|
|
2016-09-14 14:27:17 -04:00
|
|
|
const auto laneStringToDescription = [](const std::string &lane_string) -> TurnLaneDescription {
|
2016-06-21 04:41:08 -04:00
|
|
|
if (lane_string.empty())
|
|
|
|
return {};
|
2016-05-04 11:20:07 -04:00
|
|
|
|
2016-06-21 04:41:08 -04:00
|
|
|
TurnLaneDescription lane_description;
|
|
|
|
|
|
|
|
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
|
2016-07-07 09:31:20 -04:00
|
|
|
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
|
2016-06-21 04:41:08 -04:00
|
|
|
boost::char_separator<char> inner_sep(";", "");
|
|
|
|
tokenizer tokens(lane_string, sep);
|
|
|
|
|
|
|
|
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"};
|
2016-06-30 03:31:08 -04:00
|
|
|
|
2016-06-21 04:41:08 -04:00
|
|
|
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)
|
2016-05-13 13:18:00 -04:00
|
|
|
{
|
2016-06-21 04:41:08 -04:00
|
|
|
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)
|
|
|
|
{
|
2016-07-25 05:43:35 -04:00
|
|
|
auto position =
|
|
|
|
std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr);
|
2016-06-21 04:41:08 -04:00
|
|
|
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
|
2016-12-06 15:30:46 -05:00
|
|
|
util::Log(logDEBUG) << "Unsupported lane tag found: \"" << *token_itr << "\"";
|
2016-06-21 04:41:08 -04:00
|
|
|
return {};
|
|
|
|
}
|
2016-07-25 05:43:35 -04:00
|
|
|
|
|
|
|
// In case of multiple times the same lane indicators withn a lane, as in
|
|
|
|
// "left;left|.." or-ing the masks generates a single "left" enum.
|
|
|
|
// Which is fine since this is data issue and we can't represent it anyway.
|
2016-06-21 04:41:08 -04:00
|
|
|
lane_mask |= translated_mask;
|
|
|
|
}
|
|
|
|
// add the lane to the description
|
|
|
|
lane_description.push_back(lane_mask);
|
|
|
|
}
|
|
|
|
return lane_description;
|
|
|
|
};
|
|
|
|
|
2016-11-29 04:23:13 -05:00
|
|
|
// convert the lane description into an ID and, if necessary, remember the description in the
|
2016-06-21 04:41:08 -04:00
|
|
|
// description_map
|
2016-09-14 14:27:17 -04:00
|
|
|
const auto requestId = [&](const std::string &lane_string) {
|
2016-07-05 14:08:21 -04:00
|
|
|
if (lane_string.empty())
|
2016-06-21 04:41:08 -04:00
|
|
|
return INVALID_LANE_DESCRIPTIONID;
|
|
|
|
TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string));
|
|
|
|
|
2017-06-07 00:31:07 -04:00
|
|
|
return lane_description_map.ConcurrentFindOrAdd(lane_description);
|
2016-05-13 13:18:00 -04:00
|
|
|
};
|
|
|
|
|
2017-06-29 16:12:25 -04:00
|
|
|
// Deduplicates street names, refs, destinations, pronunciation, exits.
|
2016-09-09 12:28:44 -04:00
|
|
|
// In case we do not already store the key, inserts (key, id) tuple and return id.
|
2016-06-21 04:41:08 -04:00
|
|
|
// Otherwise fetches the id based on the name and returns it without insertion.
|
2016-05-13 13:18:00 -04:00
|
|
|
const auto turn_lane_id_forward = requestId(parsed_way.turn_lanes_forward);
|
|
|
|
const auto turn_lane_id_backward = requestId(parsed_way.turn_lanes_backward);
|
2016-05-04 11:20:07 -04:00
|
|
|
|
2016-12-06 07:22:51 -05:00
|
|
|
const auto road_classification = parsed_way.road_classification;
|
|
|
|
|
2016-09-05 09:01:51 -04:00
|
|
|
// Get the unique identifier for the street name, destination, and ref
|
2017-06-29 16:12:25 -04:00
|
|
|
const auto name_iterator = string_map.find(MapKey(parsed_way.name,
|
|
|
|
parsed_way.destinations,
|
|
|
|
parsed_way.ref,
|
|
|
|
parsed_way.pronunciation,
|
|
|
|
parsed_way.exits));
|
2017-01-19 09:14:30 -05:00
|
|
|
NameID name_id = EMPTY_NAMEID;
|
2016-05-25 21:35:38 -04:00
|
|
|
if (string_map.end() == name_iterator)
|
2014-05-18 16:44:19 -04:00
|
|
|
{
|
2017-01-19 09:14:30 -05:00
|
|
|
// name_offsets has a sentinel element with the total name data size
|
|
|
|
// take the sentinels index as the name id of the new name data pack
|
2017-06-29 16:12:25 -04:00
|
|
|
// (name [name_id], destination [+1], pronunciation [+2], ref [+3], exits [+4])
|
2016-07-05 14:08:21 -04:00
|
|
|
name_id = external_memory.name_offsets.size() - 1;
|
|
|
|
|
2017-01-19 09:14:30 -05:00
|
|
|
std::copy(parsed_way.name.begin(),
|
|
|
|
parsed_way.name.end(),
|
2016-01-05 06:04:04 -05:00
|
|
|
std::back_inserter(external_memory.name_char_data));
|
2016-07-05 14:08:21 -04:00
|
|
|
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
2016-05-04 11:20:07 -04:00
|
|
|
|
2017-01-19 09:14:30 -05:00
|
|
|
std::copy(parsed_way.destinations.begin(),
|
|
|
|
parsed_way.destinations.end(),
|
2016-05-26 18:47:46 -04:00
|
|
|
std::back_inserter(external_memory.name_char_data));
|
2016-07-05 14:08:21 -04:00
|
|
|
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
2016-05-25 21:35:38 -04:00
|
|
|
|
2017-01-19 09:14:30 -05:00
|
|
|
std::copy(parsed_way.pronunciation.begin(),
|
|
|
|
parsed_way.pronunciation.end(),
|
2016-05-25 21:35:38 -04:00
|
|
|
std::back_inserter(external_memory.name_char_data));
|
2016-07-05 14:08:21 -04:00
|
|
|
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
2016-05-25 21:35:38 -04:00
|
|
|
|
2017-01-19 09:14:30 -05:00
|
|
|
std::copy(parsed_way.ref.begin(),
|
|
|
|
parsed_way.ref.end(),
|
2016-09-05 09:01:51 -04:00
|
|
|
std::back_inserter(external_memory.name_char_data));
|
|
|
|
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
|
|
|
|
2017-06-29 16:12:25 -04:00
|
|
|
std::copy(parsed_way.exits.begin(),
|
|
|
|
parsed_way.exits.end(),
|
|
|
|
std::back_inserter(external_memory.name_char_data));
|
|
|
|
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
|
|
|
|
|
|
|
auto k = MapKey{parsed_way.name,
|
|
|
|
parsed_way.destinations,
|
|
|
|
parsed_way.ref,
|
|
|
|
parsed_way.pronunciation,
|
|
|
|
parsed_way.exits};
|
2016-05-26 18:47:46 -04:00
|
|
|
auto v = MapVal{name_id};
|
|
|
|
string_map.emplace(std::move(k), std::move(v));
|
2014-05-18 16:44:19 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-05-25 21:35:38 -04:00
|
|
|
name_id = name_iterator->second;
|
2014-05-18 16:44:19 -04:00
|
|
|
}
|
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
const bool in_forward_direction =
|
|
|
|
(parsed_way.forward_speed > 0 || parsed_way.forward_rate > 0 || parsed_way.duration > 0 ||
|
|
|
|
parsed_way.weight > 0) &&
|
|
|
|
(parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
2014-08-12 08:18:02 -04:00
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
const bool in_backward_direction =
|
|
|
|
(parsed_way.backward_speed > 0 || parsed_way.backward_rate > 0 || parsed_way.duration > 0 ||
|
|
|
|
parsed_way.weight > 0) &&
|
|
|
|
(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
2016-06-08 05:28:32 -04:00
|
|
|
|
2017-02-14 06:59:16 -05:00
|
|
|
// split an edge into two edges if forwards/backwards behavior differ
|
2017-03-29 06:36:54 -04:00
|
|
|
const bool split_edge =
|
|
|
|
in_forward_direction && in_backward_direction &&
|
2017-03-29 17:48:57 -04:00
|
|
|
(force_split_edges || (parsed_way.forward_rate != parsed_way.backward_rate) ||
|
2017-03-29 06:36:54 -04:00
|
|
|
(parsed_way.forward_speed != parsed_way.backward_speed) ||
|
|
|
|
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) ||
|
2017-06-27 18:01:05 -04:00
|
|
|
(turn_lane_id_forward != turn_lane_id_backward) || (forward_classes != backward_classes));
|
2015-06-27 09:27:08 -04:00
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
if (in_forward_direction)
|
2017-03-29 04:10:57 -04:00
|
|
|
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction
|
2016-05-04 11:20:07 -04:00
|
|
|
util::for_each_pair(
|
2016-05-12 12:50:10 -04:00
|
|
|
nodes.cbegin(),
|
|
|
|
nodes.cend(),
|
2016-05-04 11:20:07 -04:00
|
|
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
2016-05-27 15:05:04 -04:00
|
|
|
external_memory.all_edges_list.push_back(
|
2016-06-24 01:01:37 -04:00
|
|
|
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
|
|
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
2016-05-27 15:05:04 -04:00
|
|
|
name_id,
|
2016-05-12 12:50:10 -04:00
|
|
|
forward_weight_data,
|
|
|
|
forward_duration_data,
|
2016-05-27 15:05:04 -04:00
|
|
|
true,
|
2016-05-12 12:50:10 -04:00
|
|
|
in_backward_direction && !split_edge,
|
2016-05-27 15:05:04 -04:00
|
|
|
parsed_way.roundabout,
|
2016-11-24 07:29:17 -05:00
|
|
|
parsed_way.circular,
|
2016-05-27 15:05:04 -04:00
|
|
|
parsed_way.is_startpoint,
|
2017-02-14 06:59:16 -05:00
|
|
|
parsed_way.forward_restricted,
|
2016-05-12 12:50:10 -04:00
|
|
|
split_edge,
|
2017-02-14 06:59:16 -05:00
|
|
|
parsed_way.forward_travel_mode,
|
2017-06-27 18:01:05 -04:00
|
|
|
forward_classes,
|
2016-05-12 12:50:10 -04:00
|
|
|
turn_lane_id_forward,
|
|
|
|
road_classification,
|
|
|
|
{}));
|
2016-05-04 11:20:07 -04:00
|
|
|
});
|
2014-08-26 11:50:34 -04:00
|
|
|
}
|
2016-05-12 12:50:10 -04:00
|
|
|
|
2017-03-29 04:10:57 -04:00
|
|
|
if (in_backward_direction && (!in_forward_direction || split_edge))
|
|
|
|
{ // add (backward) segments for split edges or not in forward direction
|
2016-05-04 11:20:07 -04:00
|
|
|
util::for_each_pair(
|
2016-05-12 12:50:10 -04:00
|
|
|
nodes.cbegin(),
|
|
|
|
nodes.cend(),
|
2016-05-04 11:20:07 -04:00
|
|
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
2016-05-27 15:05:04 -04:00
|
|
|
external_memory.all_edges_list.push_back(
|
2016-06-24 01:01:37 -04:00
|
|
|
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
|
|
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
2016-05-27 15:05:04 -04:00
|
|
|
name_id,
|
2016-05-12 12:50:10 -04:00
|
|
|
backward_weight_data,
|
|
|
|
backward_duration_data,
|
|
|
|
false,
|
2016-05-27 15:05:04 -04:00
|
|
|
true,
|
|
|
|
parsed_way.roundabout,
|
2016-11-24 07:29:17 -05:00
|
|
|
parsed_way.circular,
|
2016-05-27 15:05:04 -04:00
|
|
|
parsed_way.is_startpoint,
|
2017-02-14 06:59:16 -05:00
|
|
|
parsed_way.backward_restricted,
|
2016-05-27 15:05:04 -04:00
|
|
|
split_edge,
|
2017-02-14 06:59:16 -05:00
|
|
|
parsed_way.backward_travel_mode,
|
2017-06-27 18:01:05 -04:00
|
|
|
backward_classes,
|
2016-05-12 12:50:10 -04:00
|
|
|
turn_lane_id_backward,
|
|
|
|
road_classification,
|
|
|
|
{}));
|
2016-05-04 11:20:07 -04:00
|
|
|
});
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
2016-05-12 12:50:10 -04:00
|
|
|
|
|
|
|
std::transform(nodes.begin(),
|
|
|
|
nodes.end(),
|
|
|
|
std::back_inserter(external_memory.used_node_id_list),
|
|
|
|
[](const osmium::NodeRef &ref) {
|
|
|
|
return OSMNodeID{static_cast<std::uint64_t>(ref.ref())};
|
|
|
|
});
|
|
|
|
|
|
|
|
external_memory.way_start_end_id_list.push_back(
|
|
|
|
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
|
|
|
OSMNodeID{static_cast<std::uint64_t>(nodes[0].ref())},
|
|
|
|
OSMNodeID{static_cast<std::uint64_t>(nodes[1].ref())},
|
|
|
|
OSMNodeID{static_cast<std::uint64_t>(nodes[nodes.size() - 2].ref())},
|
|
|
|
OSMNodeID{static_cast<std::uint64_t>(nodes.back().ref())}});
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
2016-07-22 03:08:40 -04:00
|
|
|
|
|
|
|
} // namespace extractor
|
|
|
|
} // namespace osrm
|