2016-01-02 11:13:44 -05:00
|
|
|
#include "extractor/extraction_containers.hpp"
|
|
|
|
#include "extractor/extraction_node.hpp"
|
|
|
|
#include "extractor/extraction_way.hpp"
|
2012-08-29 12:33:18 -04:00
|
|
|
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "extractor/external_memory_node.hpp"
|
|
|
|
#include "extractor/restriction.hpp"
|
|
|
|
#include "util/simple_logger.hpp"
|
2016-01-11 12:05:24 -05:00
|
|
|
#include "util/for_each_pair.hpp"
|
2014-01-09 10:13:35 -05:00
|
|
|
|
2015-09-18 08:26:32 -04:00
|
|
|
#include <boost/optional/optional.hpp>
|
2016-05-19 19:06:35 -04:00
|
|
|
#include "extractor/extractor_callbacks.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-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
|
|
|
|
{
|
|
|
|
|
2015-04-10 06:40:30 -04:00
|
|
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
|
|
|
|
: external_memory(extraction_containers)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2015-04-10 06:40:30 -04:00
|
|
|
string_map[""] = 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
|
|
|
{
|
2015-01-22 06:19:11 -05:00
|
|
|
external_memory.all_nodes_list.push_back(
|
2016-02-23 15:23:13 -05:00
|
|
|
{util::toFixed(util::FloatLongitude(input_node.location().lon())),
|
|
|
|
util::toFixed(util::FloatLatitude(input_node.location().lat())),
|
2016-03-03 08:26:13 -05:00
|
|
|
OSMNodeID(input_node.id()), result_node.barrier, result_node.traffic_lights});
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
|
|
|
|
2014-08-27 10:24:40 -04:00
|
|
|
void ExtractorCallbacks::ProcessRestriction(
|
2015-09-18 08:26:32 -04:00
|
|
|
const boost::optional<InputRestrictionContainer> &restriction)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2014-08-29 05:27:51 -04:00
|
|
|
if (restriction)
|
2014-08-26 11:50:34 -04:00
|
|
|
{
|
2014-08-29 05:27:51 -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
|
|
|
}
|
2012-08-29 12:33:18 -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
|
|
|
{
|
2014-09-29 05:37:36 -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;
|
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
|
2014-10-13 07:53:06 -04:00
|
|
|
if (input_way.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-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;
|
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
|
|
|
|
InternalExtractorEdge::WeightData forward_weight_data;
|
|
|
|
InternalExtractorEdge::WeightData backward_weight_data;
|
|
|
|
|
2014-05-18 16:44:19 -04:00
|
|
|
if (0 < parsed_way.duration)
|
|
|
|
{
|
2015-05-09 11:21:36 -04:00
|
|
|
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
|
|
|
}
|
2013-02-27 11:36:44 -05:00
|
|
|
|
2015-09-18 08:26:32 -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;
|
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-05-18 16:44:19 -04:00
|
|
|
// Get the unique identifier for the street name
|
|
|
|
const auto &string_map_iterator = string_map.find(parsed_way.name);
|
2015-12-13 14:02:55 -05:00
|
|
|
unsigned name_id = external_memory.name_lengths.size();
|
2014-05-18 16:44:19 -04:00
|
|
|
if (string_map.end() == string_map_iterator)
|
|
|
|
{
|
2015-12-13 14:27:54 -05:00
|
|
|
auto name_length = std::min<unsigned>(255u, parsed_way.name.size());
|
2016-01-05 06:04:04 -05:00
|
|
|
std::copy(parsed_way.name.c_str(), parsed_way.name.c_str() + name_length,
|
|
|
|
std::back_inserter(external_memory.name_char_data));
|
2015-12-13 14:02:55 -05:00
|
|
|
external_memory.name_lengths.push_back(name_length);
|
2014-08-26 11:50:34 -04:00
|
|
|
string_map.insert(std::make_pair(parsed_way.name, name_id));
|
2014-05-18 16:44:19 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-08-26 11:50:34 -04:00
|
|
|
name_id = string_map_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
|
|
|
|
2015-06-27 09:27:08 -04:00
|
|
|
std::transform(input_way.nodes().begin(), input_way.nodes().end(),
|
|
|
|
std::back_inserter(external_memory.used_node_id_list),
|
2015-09-18 08:26:32 -04:00
|
|
|
[](const osmium::NodeRef &ref)
|
|
|
|
{
|
2015-11-24 19:33:19 -05:00
|
|
|
return OSMNodeID(ref.ref());
|
2015-09-18 08:26:32 -04:00
|
|
|
});
|
2014-08-26 11:50:34 -04:00
|
|
|
|
|
|
|
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
|
2015-06-27 09:27:08 -04:00
|
|
|
|
2015-05-09 11:21:36 -04:00
|
|
|
// traverse way in reverse in this case
|
2014-08-26 11:50:34 -04:00
|
|
|
if (is_opposite_way)
|
|
|
|
{
|
2015-06-27 09:27:08 -04:00
|
|
|
BOOST_ASSERT(split_edge == false);
|
|
|
|
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
2016-01-05 10:51:13 -05:00
|
|
|
util::for_each_pair(input_way.nodes().crbegin(), input_way.nodes().crend(),
|
2015-06-27 09:27:08 -04:00
|
|
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
|
|
|
|
{
|
|
|
|
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
2016-01-05 06:04:04 -05:00
|
|
|
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,
|
2016-03-01 16:30:31 -05:00
|
|
|
false, road_classification));
|
2015-06-27 09:27:08 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
external_memory.way_start_end_id_list.push_back(
|
2016-03-03 08:26:13 -05:00
|
|
|
{OSMWayID(input_way.id()), OSMNodeID(input_way.nodes().back().ref()),
|
2015-11-24 19:33:19 -05:00
|
|
|
OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()),
|
2016-03-03 08:26:13 -05:00
|
|
|
OSMNodeID(input_way.nodes()[1].ref()), OSMNodeID(input_way.nodes()[0].ref())});
|
2014-08-26 11:50:34 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-09-18 08:26:32 -04:00
|
|
|
const bool forward_only =
|
|
|
|
split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode;
|
2016-01-05 10:51:13 -05:00
|
|
|
util::for_each_pair(input_way.nodes().cbegin(), input_way.nodes().cend(),
|
2015-06-27 09:27:08 -04:00
|
|
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
|
|
|
|
{
|
|
|
|
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
2016-01-05 06:04:04 -05:00
|
|
|
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,
|
2016-03-01 16:30:31 -05:00
|
|
|
split_edge, road_classification));
|
2015-06-27 09:27:08 -04:00
|
|
|
});
|
|
|
|
if (split_edge)
|
2014-08-26 11:50:34 -04:00
|
|
|
{
|
2015-06-27 09:27:08 -04:00
|
|
|
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
2016-01-05 10:51:13 -05:00
|
|
|
util::for_each_pair(
|
2015-09-18 08:26:32 -04:00
|
|
|
input_way.nodes().cbegin(), input_way.nodes().cend(),
|
|
|
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
|
|
|
|
{
|
|
|
|
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
2016-01-05 06:04:04 -05:00
|
|
|
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,
|
2016-03-01 16:30:31 -05:00
|
|
|
parsed_way.backward_travel_mode, true, road_classification));
|
2015-09-18 08:26:32 -04:00
|
|
|
});
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
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-03-03 08:26:13 -05:00
|
|
|
{OSMWayID(input_way.id()), OSMNodeID(input_way.nodes().back().ref()),
|
2015-11-24 19:33:19 -05:00
|
|
|
OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()),
|
2016-03-03 08:26:13 -05:00
|
|
|
OSMNodeID(input_way.nodes()[1].ref()), OSMNodeID(input_way.nodes()[0].ref())});
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
|
|
|
}
|
2016-01-05 10:51:13 -05:00
|
|
|
}
|
|
|
|
}
|