osrm-backend/src/extractor/extractor_callbacks.cpp

292 lines
12 KiB
C++
Raw Normal View History

2016-01-02 11:13:44 -05:00
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_way.hpp"
2016-01-02 11:13:44 -05:00
#include "extractor/external_memory_node.hpp"
#include "extractor/restriction.hpp"
#include "util/for_each_pair.hpp"
2016-05-04 11:20:07 -04:00
#include "util/simple_logger.hpp"
#include "extractor/extractor_callbacks.hpp"
2016-05-27 15:05:04 -04:00
#include <boost/optional/optional.hpp>
#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-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
{
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
: external_memory(extraction_containers)
2014-05-09 10:17:31 -04:00
{
// we reserved 0, 1, 2 for the empty case
2016-05-26 18:47:46 -04:00
string_map[MapKey("", "")] = 0;
2014-05-09 10:17:31 -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!
*/
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
{
2015-01-22 06:19:11 -05:00
external_memory.all_nodes_list.push_back(
{util::toFixed(util::FloatLongitude(input_node.location().lon())),
util::toFixed(util::FloatLatitude(input_node.location().lat())),
2016-05-27 15:05:04 -04:00
OSMNodeID(input_node.id()),
result_node.barrier,
result_node.traffic_lights});
}
2014-08-27 10:24:40 -04:00
void ExtractorCallbacks::ProcessRestriction(
const boost::optional<InputRestrictionContainer> &restriction)
2014-05-09 10:17:31 -04:00
{
if (restriction)
2014-08-26 11:50:34 -04:00
{
external_memory.restrictions_list.push_back(restriction.get());
2016-01-05 10:51:13 -05:00
// util::SimpleLogger().Write() << "from: " << restriction.get().restriction.from.node <<
2014-11-18 10:54:48 -05:00
// ",via: " << restriction.get().restriction.via.node <<
// ", to: " << restriction.get().restriction.to.node <<
2015-01-22 06:19:11 -05:00
// ", only: " << (restriction.get().restriction.flags.is_only ?
// "y" : "n");
2014-08-26 11:50:34 -04:00
}
}
2015-04-08 12:53:10 -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
*
* 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!
*/
void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
2014-05-09 10:17:31 -04:00
{
if (((0 >= parsed_way.forward_speed) ||
2014-08-27 10:24:40 -04:00
(TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
2014-08-20 11:05:39 -04:00
((0 >= parsed_way.backward_speed) ||
2014-08-27 10:24:40 -04:00
(TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
2014-08-20 11:05:39 -04:00
(0 >= parsed_way.duration))
2014-05-09 10:17:31 -04:00
{ // Only true if the way is specified by the speed profile
2014-05-18 16:44:19 -04:00
return;
}
if (input_way.nodes().size() <= 1)
2014-06-02 13:23:50 -04:00
{ // safe-guard against broken data
return;
}
if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id())
2014-05-18 16:44:19 -04:00
{
2016-01-05 10:51:13 -05:00
util::SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << input_way.id()
2016-01-07 19:31:57 -05:00
<< " of size " << input_way.nodes().size();
2014-05-18 16:44:19 -04:00
return;
}
InternalExtractorEdge::WeightData forward_weight_data;
InternalExtractorEdge::WeightData backward_weight_data;
2014-05-18 16:44:19 -04:00
if (0 < parsed_way.duration)
{
const unsigned num_edges = (input_way.nodes().size() - 1);
// FIXME We devide by the numer of nodes here, but should rather consider
// the length of each segment. We would eigther 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.
forward_weight_data.duration = parsed_way.duration / num_edges;
forward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
backward_weight_data.duration = parsed_way.duration / num_edges;
backward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
}
else
{
if (parsed_way.forward_speed > 0 &&
parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
{
forward_weight_data.speed = parsed_way.forward_speed;
forward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
}
if (parsed_way.backward_speed > 0 &&
parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
{
backward_weight_data.speed = parsed_way.backward_speed;
backward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
}
2014-05-18 16:44:19 -04:00
}
if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID &&
backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID)
2014-05-18 16:44:19 -04:00
{
2016-03-03 08:26:13 -05:00
util::SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: "
<< input_way.id();
2014-05-18 16:44:19 -04:00
return;
}
2016-03-01 16:30:31 -05:00
// FIXME this need to be moved into the profiles
const char *data = input_way.get_value_by_key("highway");
guidance::RoadClassificationData road_classification;
if (data)
{
road_classification.road_class = guidance::functionalRoadClassFromTag(data);
}
2016-05-04 11:20:07 -04:00
// 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 constexpr auto MAX_STRING_LENGTH = 255u;
2014-05-18 16:44:19 -04:00
// Get the unique identifier for the street name
2016-05-26 18:47:46 -04:00
// Get the unique identifier for the street name and destination
const auto name_iterator = string_map.find(MapKey(parsed_way.name, parsed_way.destinations));
unsigned name_id = external_memory.name_lengths.size();
if (string_map.end() == name_iterator)
2014-05-18 16:44:19 -04:00
{
2016-05-04 11:20:07 -04:00
auto name_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.name.size());
2016-06-02 07:14:33 -04:00
auto destinations_length =
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.destinations.size());
auto pronunciation_length =
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.pronunciation.size());
2016-05-26 18:47:46 -04:00
2016-06-02 07:14:33 -04:00
external_memory.name_char_data.reserve(name_id + name_length + destinations_length +
pronunciation_length);
2016-05-04 11:20:07 -04:00
2016-05-27 15:05:04 -04:00
std::copy(parsed_way.name.c_str(),
parsed_way.name.c_str() + name_length,
2016-01-05 06:04:04 -05:00
std::back_inserter(external_memory.name_char_data));
2016-05-04 11:20:07 -04:00
2016-05-26 18:47:46 -04:00
std::copy(parsed_way.destinations.c_str(),
parsed_way.destinations.c_str() + destinations_length,
std::back_inserter(external_memory.name_char_data));
2016-05-26 18:47:46 -04:00
std::copy(parsed_way.pronunciation.c_str(),
parsed_way.pronunciation.c_str() + pronunciation_length,
std::back_inserter(external_memory.name_char_data));
2016-05-26 18:47:46 -04:00
external_memory.name_lengths.push_back(name_length);
external_memory.name_lengths.push_back(destinations_length);
external_memory.name_lengths.push_back(pronunciation_length);
2016-05-26 18:47:46 -04:00
auto k = MapKey{parsed_way.name, parsed_way.destinations};
auto v = MapVal{name_id};
string_map.emplace(std::move(k), std::move(v));
2014-05-18 16:44:19 -04:00
}
else
{
name_id = name_iterator->second;
2014-05-18 16:44:19 -04:00
}
2014-08-27 10:24:40 -04:00
const bool split_edge = (parsed_way.forward_speed > 0) &&
(TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
(parsed_way.backward_speed > 0) &&
(TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
((parsed_way.forward_speed != parsed_way.backward_speed) ||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
2014-08-12 08:18:02 -04:00
external_memory.used_node_id_list.reserve(external_memory.used_node_id_list.size() +
input_way.nodes().size());
2016-05-27 15:05:04 -04:00
std::transform(input_way.nodes().begin(),
input_way.nodes().end(),
std::back_inserter(external_memory.used_node_id_list),
2016-05-04 11:20:07 -04:00
[](const osmium::NodeRef &ref) { return OSMNodeID(ref.ref()); });
2014-08-26 11:50:34 -04:00
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
// traverse way in reverse in this case
2014-08-26 11:50:34 -04:00
if (is_opposite_way)
{
BOOST_ASSERT(split_edge == false);
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
2016-05-04 11:20:07 -04:00
util::for_each_pair(
2016-05-27 15:05:04 -04:00
input_way.nodes().crbegin(),
input_way.nodes().crend(),
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(
InternalExtractorEdge(OSMNodeID(first_node.ref()),
OSMNodeID(last_node.ref()),
name_id,
backward_weight_data,
true,
false,
parsed_way.roundabout,
parsed_way.is_access_restricted,
parsed_way.is_startpoint,
parsed_way.backward_travel_mode,
false,
road_classification));
2016-05-04 11:20:07 -04:00
});
external_memory.way_start_end_id_list.push_back(
2016-05-27 15:05:04 -04:00
{OSMWayID(input_way.id()),
OSMNodeID(input_way.nodes().back().ref()),
OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()),
2016-05-27 15:05:04 -04:00
OSMNodeID(input_way.nodes()[1].ref()),
OSMNodeID(input_way.nodes()[0].ref())});
2014-08-26 11:50:34 -04:00
}
else
{
const bool forward_only =
split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode;
2016-05-04 11:20:07 -04:00
util::for_each_pair(
2016-05-27 15:05:04 -04:00
input_way.nodes().cbegin(),
input_way.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(
InternalExtractorEdge(OSMNodeID(first_node.ref()),
OSMNodeID(last_node.ref()),
name_id,
forward_weight_data,
true,
!forward_only,
parsed_way.roundabout,
parsed_way.is_access_restricted,
parsed_way.is_startpoint,
parsed_way.forward_travel_mode,
split_edge,
road_classification));
2016-05-04 11:20:07 -04:00
});
if (split_edge)
2014-08-26 11:50:34 -04:00
{
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
2016-01-05 10:51:13 -05:00
util::for_each_pair(
2016-05-27 15:05:04 -04:00
input_way.nodes().cbegin(),
input_way.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(
InternalExtractorEdge(OSMNodeID(first_node.ref()),
OSMNodeID(last_node.ref()),
name_id,
backward_weight_data,
false,
true,
parsed_way.roundabout,
parsed_way.is_access_restricted,
parsed_way.is_startpoint,
parsed_way.backward_travel_mode,
true,
road_classification));
});
}
2014-08-26 11:50:34 -04:00
2014-05-09 10:17:31 -04:00
external_memory.way_start_end_id_list.push_back(
2016-05-27 15:05:04 -04:00
{OSMWayID(input_way.id()),
OSMNodeID(input_way.nodes().back().ref()),
OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()),
2016-05-27 15:05:04 -04:00
OSMNodeID(input_way.nodes()[1].ref()),
OSMNodeID(input_way.nodes()[0].ref())});
}
}
2016-01-05 10:51:13 -05:00
}
}