Move renumbering and edge deduplication in extractor

This commit is contained in:
Patrick Niklaus 2015-05-13 01:26:54 +02:00
parent a57fb4f1ab
commit 3065de63dd
11 changed files with 235 additions and 194 deletions

View File

@ -343,8 +343,14 @@ void EdgeBasedGraphFactory::CompressGeometry()
continue;
}
if ( // TODO: rename to IsCompatibleTo
fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2))
// this case can happen if two ways with different names overlap
if (fwd_edge_data1.nameID != rev_edge_data1.nameID ||
fwd_edge_data2.nameID != rev_edge_data2.nameID)
{
continue;
}
if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2))
{
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
m_node_based_graph->GetEdgeData(reverse_e1).nameID);

View File

@ -303,44 +303,38 @@ void Prepare::SetupScriptingEnvironment(
/**
\brief Build load restrictions from .restriction file
*/
void Prepare::LoadRestrictionMap(const std::unordered_map<NodeID, NodeID> &external_to_internal_node_map,
RestrictionMap &restriction_map)
std::shared_ptr<RestrictionMap> Prepare::LoadRestrictionMap()
{
boost::filesystem::ifstream input_stream(config.restrictions_path, std::ios::in | std::ios::binary);
std::vector<TurnRestriction> restriction_list;
loadRestrictionsFromFile(input_stream, external_to_internal_node_map, restriction_list);
loadRestrictionsFromFile(input_stream, restriction_list);
SimpleLogger().Write() << " - " << restriction_list.size() << " restrictions.";
restriction_map = RestrictionMap(restriction_list);
return std::make_shared<RestrictionMap>(restriction_list);
}
/**
\brief Build load node based graph from .osrm file and restrictions from .restrictions file
\brief Load node based graph from .osrm file
*/
std::shared_ptr<NodeBasedDynamicGraph>
Prepare::LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_list,
RestrictionMap &restriction_map,
std::vector<QueryNode>& internal_to_external_node_map)
{
std::vector<NodeBasedEdge> edge_list;
std::unordered_map<NodeID, NodeID> external_to_internal_node_map;
boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary);
NodeID number_of_node_based_nodes = loadNodesFromFile(input_stream,
barrier_node_list, traffic_light_list,
internal_to_external_node_map,
external_to_internal_node_map);
internal_to_external_node_map);
SimpleLogger().Write() << " - " << barrier_node_list.size() << " bollard nodes, "
<< traffic_light_list.size() << " traffic lights";
loadEdgesFromFile(input_stream, external_to_internal_node_map, edge_list);
LoadRestrictionMap(external_to_internal_node_map, restriction_map);
loadEdgesFromFile(input_stream, edge_list);
if (edge_list.empty())
{
@ -369,9 +363,9 @@ Prepare::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_nod
auto barrier_node_list = osrm::make_unique<std::vector<NodeID>>();
auto traffic_light_list = osrm::make_unique<std::vector<NodeID>>();
auto restriction_map = std::make_shared<RestrictionMap>();
auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, *restriction_map, internal_to_external_node_map);
auto restriction_map = LoadRestrictionMap();
auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, internal_to_external_node_map);
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();

View File

@ -61,8 +61,7 @@ class Prepare
protected:
void SetupScriptingEnvironment(lua_State *myLuaState,
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
void LoadRestrictionMap(const std::unordered_map<NodeID, NodeID> &external_to_internal_node_map,
RestrictionMap &restriction_map);
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
unsigned CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list);
void ContractGraph(const std::size_t number_of_edge_based_nodes,
DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list,
@ -72,7 +71,6 @@ class Prepare
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list);
std::shared_ptr<NodeBasedDynamicGraph> LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_list,
RestrictionMap &restriction_map,
std::vector<QueryNode>& internal_to_external_node_map);
std::pair<std::size_t, std::size_t>
BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,

View File

@ -47,6 +47,13 @@ bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
return source < other.source;
}
NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
backward(false), roundabout(false), in_tiny_cc(false),
access_restricted(false), is_split(false), travel_mode(false)
{
}
NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,

View File

@ -35,6 +35,7 @@ struct NodeBasedEdge
{
bool operator<(const NodeBasedEdge &e) const;
NodeBasedEdge();
explicit NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
@ -58,8 +59,6 @@ struct NodeBasedEdge
bool access_restricted : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
NodeBasedEdge() = delete;
};
struct EdgeBasedEdge

View File

@ -64,7 +64,7 @@ struct NodeBasedEdgeData
backward = temp_flag;
}
bool IsEqualTo(const NodeBasedEdgeData &other) const
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
{
return (forward == other.forward) && (backward == other.backward) &&
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
@ -85,6 +85,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<NodeBasedE
NodeBasedDynamicGraph::InputEdge edge;
for (const NodeBasedEdge &import_edge : input_edge_list)
{
BOOST_ASSERT(import_edge.forward || import_edge.backward);
if (import_edge.forward)
{
edge.source = import_edge.source;

View File

@ -79,10 +79,6 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
{
try
{
PrepareRestrictions();
WriteRestrictions(restrictions_file_name);
std::ofstream file_out_stream;
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
@ -94,6 +90,9 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
file_out_stream.close();
PrepareRestrictions();
WriteRestrictions(restrictions_file_name);
WriteNames(name_file_name);
}
catch (const std::exception &e)
@ -151,6 +150,14 @@ void ExtractionContainers::PrepareNodes()
TIMER_STOP(erasing_dups);
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
std::cout << "[extractor] Building node id map ... " << std::flush;
TIMER_START(id_map);
external_to_internal_node_id_map.reserve(used_node_id_list.size());
for (NodeID i = 0u; i < used_node_id_list.size(); ++i)
external_to_internal_node_id_map[used_node_id_list[i]] = i;
TIMER_STOP(id_map);
std::cout << "ok, after " << TIMER_SEC(id_map) << "s" << std::endl;
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
TIMER_START(sorting_nodes);
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), ExternalMemoryNodeSTXXLCompare(),
@ -187,6 +194,12 @@ void ExtractionContainers::PrepareEdges()
}
BOOST_ASSERT(edge_iterator->result.source == node_iterator->node_id);
// assign new node id
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
edge_iterator->result.source = id_iter->second;
edge_iterator->source_coordinate.lat = node_iterator->lat;
edge_iterator->source_coordinate.lon = node_iterator->lon;
++edge_iterator;
@ -211,6 +224,10 @@ void ExtractionContainers::PrepareEdges()
{
if (edge_iterator->result.target < node_iterator->node_id)
{
// mark edge as invalid
edge_iterator->result.source = SPECIAL_NODEID;
edge_iterator->result.target = SPECIAL_NODEID;
// FIXME we are skipping edges here: That means the data is broken!
++edge_iterator;
continue;
@ -246,12 +263,113 @@ void ExtractionContainers::PrepareEdges()
return -1.0;
}(edge_iterator->weight_data);
edge_iterator->result.weight = std::max(1, (int)std::floor(weight + .5));
auto& edge = edge_iterator->result;
edge.weight = std::max(1, (int)std::floor(weight + .5));
// assign new node id
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
edge.target = id_iter->second;
// if source id > target id -> swap
if (edge.source > edge.target)
{
std::swap(edge.source, edge.target);
// std::swap does not work with bit-fields
bool temp = edge.forward;
edge.forward = edge.backward;
edge.backward = temp;
}
}
else
{
// mark edge as invalid
edge_iterator->result.source = SPECIAL_NODEID;
edge_iterator->result.target = SPECIAL_NODEID;
// FIXME we should print a warning here.
}
++edge_iterator;
}
TIMER_STOP(compute_weights);
std::cout << "ok, after " << TIMER_SEC(compute_weights) << "s" << std::endl;
// Sort edges by start.
std::cout << "[extractor] Sorting edges by renumbered start ... " << std::flush;
TIMER_START(sort_edges_by_renumbered_start);
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartThenTargetID(), stxxl_memory);
TIMER_STOP(sort_edges_by_renumbered_start);
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s" << std::endl;
BOOST_ASSERT(all_edges_list.size() > 0);
for (unsigned i = 1; i < all_edges_list.size();)
{
// only invalid edges left
if (all_edges_list[i].result.source == SPECIAL_NODEID)
{
break;
}
unsigned start_idx = i;
NodeID source = all_edges_list[i].result.source;
NodeID target = all_edges_list[i].result.target;
int min_forward_weight = std::numeric_limits<int>::max();
int min_backward_weight = std::numeric_limits<int>::max();
unsigned min_forward_idx = std::numeric_limits<unsigned>::max();
unsigned min_backward_idx = std::numeric_limits<unsigned>::max();
while (all_edges_list[i].result.source == source &&
all_edges_list[i].result.target == target)
{
if (all_edges_list[i].result.forward && all_edges_list[i].result.weight < min_forward_weight)
{
min_forward_idx = i;
}
if (all_edges_list[i].result.backward && all_edges_list[i].result.weight < min_backward_weight)
{
min_backward_idx = i;
}
// this also increments the outer loop counter!
i++;
}
BOOST_ASSERT(min_forward_idx == std::numeric_limits<unsigned>::max() || min_forward_idx < i);
BOOST_ASSERT(min_backward_idx == std::numeric_limits<unsigned>::max() || min_backward_idx < i);
// reset direction for both edges
if (min_forward_idx != std::numeric_limits<unsigned>::max())
{
all_edges_list[min_forward_idx].result.forward = false;
all_edges_list[min_forward_idx].result.backward = false;
}
if (min_backward_idx != std::numeric_limits<unsigned>::max())
{
all_edges_list[min_backward_idx].result.forward = false;
all_edges_list[min_backward_idx].result.backward = false;
}
// set directions that were chosen as min
// note that this needs to come after the ifs above, since
// the minimal forward and backward edge can be the same
if (min_forward_idx != std::numeric_limits<unsigned>::max())
all_edges_list[min_forward_idx].result.forward = true;
if (min_backward_idx != std::numeric_limits<unsigned>::max())
all_edges_list[min_backward_idx].result.backward = true;
// invalidate all unused edges
for (unsigned j = start_idx; j < i; j++)
{
if (j == min_forward_idx || j == min_backward_idx)
{
continue;
}
all_edges_list[j].result.source = SPECIAL_NODEID;
all_edges_list[j].result.target = SPECIAL_NODEID;
}
}
}
void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const
@ -266,11 +384,13 @@ void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const
for (const auto& edge : all_edges_list)
{
if (edge.result.weight > 0)
if (edge.result.source == SPECIAL_NODEID || edge.result.target == SPECIAL_NODEID)
{
file_out_stream.write((char*) &edge.result, sizeof(NodeBasedEdge));
number_of_used_edges++;
continue;
}
file_out_stream.write((char*) &edge.result, sizeof(NodeBasedEdge));
number_of_used_edges++;
}
TIMER_STOP(write_edges);
std::cout << "ok, after " << TIMER_SEC(write_edges) << "s" << std::endl;
@ -339,6 +459,7 @@ void ExtractionContainers::WriteRestrictions(const std::string& path) const
for (const auto &restriction_container : restrictions_list)
{
if (SPECIAL_NODEID != restriction_container.restriction.from.node &&
SPECIAL_NODEID != restriction_container.restriction.via.node &&
SPECIAL_NODEID != restriction_container.restriction.to.node)
{
restrictions_out_stream.write((char *)&(restriction_container.restriction),
@ -362,7 +483,7 @@ void ExtractionContainers::PrepareRestrictions()
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
std::cout << "[extractor] Sorting " << restrictions_list.size()
<< " restrictions. by from... " << std::flush;
<< " restriction. by from... " << std::flush;
TIMER_START(sort_restrictions);
stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
CmpRestrictionContainerByFrom(), stxxl_memory);
@ -385,23 +506,42 @@ void ExtractionContainers::PrepareRestrictions()
if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way)
{
SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.from.way;
restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
++restrictions_iterator;
continue;
}
BOOST_ASSERT(way_start_and_end_iterator->way_id ==
restrictions_iterator->restriction.from.way);
// we do not remap the via id yet, since we will need it for the to node as well
const NodeID via_node_id = restrictions_iterator->restriction.via.node;
// check if via is actually valid, if not invalidate
auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
if(via_id_iter == external_to_internal_node_id_map.end())
{
SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid node: " << restrictions_iterator->restriction.via.node;
restrictions_iterator->restriction.via.node = SPECIAL_NODEID;
++restrictions_iterator;
continue;
}
if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
{
restrictions_iterator->restriction.from.node =
way_start_and_end_iterator->first_segment_target_id;
// assign new from node id
auto id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->first_segment_target_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.from.node = id_iter->second;
}
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
{
restrictions_iterator->restriction.from.node =
way_start_and_end_iterator->last_segment_source_id;
// assign new from node id
auto id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->last_segment_source_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.from.node = id_iter->second;
}
++restrictions_iterator;
}
@ -428,8 +568,16 @@ void ExtractionContainers::PrepareRestrictions()
++way_start_and_end_iterator;
continue;
}
if (restrictions_iterator->restriction.from.node == SPECIAL_NODEID ||
restrictions_iterator->restriction.via.node == SPECIAL_NODEID)
{
++restrictions_iterator;
continue;
}
if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
{
SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.to.way;
restrictions_iterator->restriction.to.way = SPECIAL_NODEID;
++restrictions_iterator;
continue;
}
@ -437,15 +585,24 @@ void ExtractionContainers::PrepareRestrictions()
restrictions_iterator->restriction.to.way);
const NodeID via_node_id = restrictions_iterator->restriction.via.node;
// assign new via node id
auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
BOOST_ASSERT(via_id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.via.node = via_id_iter->second;
if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
{
restrictions_iterator->restriction.to.node =
way_start_and_end_iterator->first_segment_target_id;
auto to_id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->first_segment_target_id);
BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.to.node = to_id_iter->second;
}
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
{
restrictions_iterator->restriction.to.node =
way_start_and_end_iterator->last_segment_source_id;
auto to_id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->last_segment_source_id);
BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.to.node = to_id_iter->second;
}
++restrictions_iterator;
}

View File

@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../util/fingerprint.hpp"
#include <stxxl/vector>
#include <unordered_map>
/**
* Uses external memory containers from stxxl to store all the data that
@ -73,6 +74,7 @@ class ExtractionContainers
STXXLStringVector name_list;
STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
std::unordered_map<NodeID, NodeID> external_to_internal_node_id_map;
const FingerPrint fingerprint;
ExtractionContainers();

View File

@ -105,6 +105,20 @@ struct InternalExtractorEdge
}
};
struct CmpEdgeByStartThenTargetID
{
using value_type = InternalExtractorEdge;
bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
{
return (lhs.result.source < rhs.result.source) ||
((lhs.result.source == rhs.result.source) &&
(lhs.result.target < rhs.result.target));
}
value_type max_value() { return InternalExtractorEdge::max_value(); }
value_type min_value() { return InternalExtractorEdge::min_value(); }
};
struct CmpEdgeByStartID
{
using value_type = InternalExtractorEdge;

View File

@ -76,22 +76,19 @@ void DeleteFileIfExists(const std::string &file_name)
}
}
void LoadRestrictions(const char* path,
std::unique_ptr<std::unordered_map<NodeID, NodeID>> ext_to_int_id_map,
std::vector<TurnRestriction>& restriction_list)
void LoadRestrictions(const char* path, std::vector<TurnRestriction>& restriction_list)
{
std::ifstream input_stream(path, std::ios::binary);
if (!input_stream.is_open())
{
throw osrm::exception("Cannot open restriction file");
}
loadRestrictionsFromFile(input_stream, *ext_to_int_id_map, restriction_list);
loadRestrictionsFromFile(input_stream, restriction_list);
}
std::size_t LoadGraph(const char* path,
std::vector<QueryNode>& coordinate_list,
std::vector<NodeID>& barrier_node_list,
std::unordered_map<NodeID, NodeID>& ext_to_int_id_map,
std::vector<TarjanEdge>& graph_edge_list)
{
std::ifstream input_stream(path, std::ifstream::in | std::ifstream::binary);
@ -106,10 +103,9 @@ std::size_t LoadGraph(const char* path,
auto number_of_nodes = loadNodesFromFile(input_stream, barrier_node_list,
traffic_light_node_list,
coordinate_list,
ext_to_int_id_map);
coordinate_list);
loadEdgesFromFile(input_stream, ext_to_int_id_map, edge_list);
loadEdgesFromFile(input_stream, edge_list);
traffic_light_node_list.clear();
traffic_light_node_list.shrink_to_fit();
@ -142,7 +138,6 @@ int main(int argc, char *argv[])
std::vector<QueryNode> coordinate_list;
std::vector<TurnRestriction> restriction_list;
std::vector<NodeID> barrier_node_list;
auto ext_to_int_id_map = osrm::make_unique<std::unordered_map<NodeID, NodeID>>();
LogPolicy::GetInstance().Unmute();
try
@ -158,8 +153,8 @@ int main(int argc, char *argv[])
SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
std::vector<TarjanEdge> graph_edge_list;
auto number_of_nodes = LoadGraph(argv[1], coordinate_list, barrier_node_list, *ext_to_int_id_map, graph_edge_list);
LoadRestrictions(argv[2], std::move(ext_to_int_id_map), restriction_list);
auto number_of_nodes = LoadGraph(argv[1], coordinate_list, barrier_node_list, graph_edge_list);
LoadRestrictions(argv[2], restriction_list);
tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end());
const auto graph = std::make_shared<TarjanGraph>(number_of_nodes, graph_edge_list);

View File

@ -58,7 +58,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* we need to renumber it to the new internal id.
*/
unsigned loadRestrictionsFromFile(std::istream& input_stream,
const std::unordered_map<NodeID, NodeID>& ext_to_int_id_map,
std::vector<TurnRestriction>& restriction_list)
{
const FingerPrint fingerprint_orig;
@ -79,38 +78,6 @@ unsigned loadRestrictionsFromFile(std::istream& input_stream,
number_of_usable_restrictions * sizeof(TurnRestriction));
}
// renumber ids referenced in restrictions
for (TurnRestriction &current_restriction : restriction_list)
{
auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node);
if (internal_id_iter == ext_to_int_id_map.end())
{
SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node
<< " of restriction";
continue;
}
current_restriction.from.node = internal_id_iter->second;
internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node);
if (internal_id_iter == ext_to_int_id_map.end())
{
SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node
<< " of restriction";
continue;
}
current_restriction.via.node = internal_id_iter->second;
internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node);
if (internal_id_iter == ext_to_int_id_map.end())
{
SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node
<< " of restriction";
continue;
}
current_restriction.to.node = internal_id_iter->second;
}
return number_of_usable_restrictions;
}
@ -119,14 +86,12 @@ unsigned loadRestrictionsFromFile(std::istream& input_stream,
* Reads the beginning of an .osrm file and produces:
* - list of barrier nodes
* - list of traffic lights
* - index to original node id map
* - original node id to index map
* - nodes indexed by their internal (non-osm) id
*/
NodeID loadNodesFromFile(std::istream &input_stream,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
std::vector<QueryNode> &int_to_ext_node_id_map,
std::unordered_map<NodeID, NodeID> &ext_to_int_id_map)
std::vector<QueryNode> &node_array)
{
const FingerPrint fingerprint_orig;
FingerPrint fingerprint_loaded;
@ -146,9 +111,7 @@ NodeID loadNodesFromFile(std::istream &input_stream,
for (NodeID i = 0; i < n; ++i)
{
input_stream.read(reinterpret_cast<char *>(&current_node), sizeof(ExternalMemoryNode));
int_to_ext_node_id_map.emplace_back(current_node.lat, current_node.lon,
current_node.node_id);
ext_to_int_id_map.emplace(current_node.node_id, i);
node_array.emplace_back(current_node.lat, current_node.lon, current_node.node_id);
if (current_node.barrier)
{
barrier_node_list.emplace_back(i);
@ -167,122 +130,27 @@ NodeID loadNodesFromFile(std::istream &input_stream,
}
/**
* Reads a .osrm file and produces the edges. Edges reference nodes in the old
* OSM based format, we need to renumber it here.
* Reads a .osrm file and produces the edges.
*/
NodeID loadEdgesFromFile(std::istream &input_stream,
const std::unordered_map<NodeID, NodeID> &ext_to_int_id_map,
std::vector<NodeBasedEdge> &edge_list)
{
EdgeID m;
input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned));
edge_list.reserve(m);
edge_list.resize(m);
SimpleLogger().Write() << " and " << m << " edges ";
NodeBasedEdge edge(0, 0, 0, 0, false, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false);
for (EdgeID i = 0; i < m; ++i)
input_stream.read((char *) edge_list.data(), m * sizeof(NodeBasedEdge));
#ifndef NDEBUG
for (const auto& edge : edge_list)
{
input_stream.read(reinterpret_cast<char *>(&edge), sizeof(NodeBasedEdge));
BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight");
BOOST_ASSERT_MSG(edge.forward || edge.backward, "loaded null weight");
BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded null weight");
// translate the external NodeIDs to internal IDs
auto internal_id_iter = ext_to_int_id_map.find(edge.source);
if (ext_to_int_id_map.find(edge.source) == ext_to_int_id_map.end())
{
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << edge.source;
#endif
continue;
}
edge.source = internal_id_iter->second;
internal_id_iter = ext_to_int_id_map.find(edge.target);
if (ext_to_int_id_map.find(edge.target) == ext_to_int_id_map.end())
{
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << edge.target;
#endif
continue;
}
edge.target = internal_id_iter->second;
BOOST_ASSERT_MSG(edge.source != SPECIAL_NODEID && edge.target != SPECIAL_NODEID,
"nonexisting source or target");
if (edge.source > edge.target)
{
std::swap(edge.source, edge.target);
// std::swap does not work with bit-fields
bool temp = edge.forward;
edge.forward = edge.backward;
edge.backward = temp;
}
edge_list.push_back(edge);
BOOST_ASSERT_MSG(edge.forward || edge.backward, "loaded invalid direction");
BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded non-accessible");
}
#endif
tbb::parallel_sort(edge_list.begin(), edge_list.end());
// Removes multi-edges between nodes
for (unsigned i = 1; i < edge_list.size(); ++i)
{
if ((edge_list[i - 1].target == edge_list[i].target) &&
(edge_list[i - 1].source == edge_list[i].source))
{
const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) &&
(edge_list[i - 1].backward == edge_list[i].backward);
const bool edge_flags_are_superset1 =
(edge_list[i - 1].forward && edge_list[i - 1].backward) &&
(edge_list[i].forward != edge_list[i].backward);
const bool edge_flags_are_superset_2 =
(edge_list[i].forward && edge_list[i].backward) &&
(edge_list[i - 1].forward != edge_list[i - 1].backward);
if (edge_flags_equivalent)
{
edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight);
edge_list[i - 1].source = SPECIAL_NODEID;
}
else if (edge_flags_are_superset1)
{
if (edge_list[i - 1].weight <= edge_list[i].weight)
{
// edge i-1 is smaller and goes in both directions. Throw away the other edge
edge_list[i].source = SPECIAL_NODEID;
}
else
{
// edge i-1 is open in both directions, but edge i is smaller in one direction.
// Close edge i-1 in this direction
edge_list[i - 1].forward = !edge_list[i].forward;
edge_list[i - 1].backward = !edge_list[i].backward;
}
}
else if (edge_flags_are_superset_2)
{
if (edge_list[i - 1].weight <= edge_list[i].weight)
{
// edge i-1 is smaller for one direction. edge i is open in both. close edge i
// in the other direction
edge_list[i].forward = !edge_list[i - 1].forward;
edge_list[i].backward = !edge_list[i - 1].backward;
}
else
{
// edge i is smaller and goes in both direction. Throw away edge i-1
edge_list[i - 1].source = SPECIAL_NODEID;
}
}
}
}
const auto new_end_iter =
std::remove_if(edge_list.begin(), edge_list.end(), [](const NodeBasedEdge &edge)
{
return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID;
});
edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
edge_list.shrink_to_fit();
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
return m;