Move renumbering and edge deduplication in extractor
This commit is contained in:
parent
a57fb4f1ab
commit
3065de63dd
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 ¤t_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 *>(¤t_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;
|
||||
|
Loading…
Reference in New Issue
Block a user