Deduplicate foward/reverse geometries
Changes the internal representation of compressed geometries to be a single array shared between forward and reverse geometries that can be read in either direction. Includes a change on extractor::OriginalEdgeData to store via_geometry ids that indicate which direction to read the geometry for that edge based edge. Closes #2592
This commit is contained in:
committed by
Jake Pruitt
parent
73179641b1
commit
a75e16e26b
@@ -23,7 +23,7 @@ CompressedEdgeContainer::CompressedEdgeContainer()
|
||||
|
||||
void CompressedEdgeContainer::IncreaseFreeList()
|
||||
{
|
||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
||||
m_compressed_oneway_geometries.resize(m_compressed_oneway_geometries.size() + 100);
|
||||
for (unsigned i = 100; i > 0; --i)
|
||||
{
|
||||
m_free_list.emplace_back(free_list_maximum);
|
||||
@@ -37,17 +37,44 @@ bool CompressedEdgeContainer::HasEntryForID(const EdgeID edge_id) const
|
||||
return iter != m_edge_id_to_list_index_map.end();
|
||||
}
|
||||
|
||||
bool CompressedEdgeContainer::HasZippedEntryForForwardID(const EdgeID edge_id) const
|
||||
{
|
||||
auto iter = m_forward_edge_id_to_zipped_index_map.find(edge_id);
|
||||
return iter != m_forward_edge_id_to_zipped_index_map.end();
|
||||
}
|
||||
|
||||
bool CompressedEdgeContainer::HasZippedEntryForReverseID(const EdgeID edge_id) const
|
||||
{
|
||||
auto iter = m_reverse_edge_id_to_zipped_index_map.find(edge_id);
|
||||
return iter != m_reverse_edge_id_to_zipped_index_map.end();
|
||||
}
|
||||
|
||||
unsigned CompressedEdgeContainer::GetPositionForID(const EdgeID edge_id) const
|
||||
{
|
||||
auto map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
||||
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
||||
BOOST_ASSERT(map_iterator->second < m_compressed_oneway_geometries.size());
|
||||
return map_iterator->second;
|
||||
}
|
||||
|
||||
unsigned CompressedEdgeContainer::GetZippedPositionForForwardID(const EdgeID edge_id) const
|
||||
{
|
||||
auto map_iterator = m_forward_edge_id_to_zipped_index_map.find(edge_id);
|
||||
BOOST_ASSERT(map_iterator != m_forward_edge_id_to_zipped_index_map.end());
|
||||
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
|
||||
return map_iterator->second;
|
||||
}
|
||||
|
||||
unsigned CompressedEdgeContainer::GetZippedPositionForReverseID(const EdgeID edge_id) const
|
||||
{
|
||||
auto map_iterator = m_reverse_edge_id_to_zipped_index_map.find(edge_id);
|
||||
BOOST_ASSERT(map_iterator != m_reverse_edge_id_to_zipped_index_map.end());
|
||||
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
|
||||
return map_iterator->second;
|
||||
}
|
||||
|
||||
void CompressedEdgeContainer::SerializeInternalVector(const std::string &path) const
|
||||
{
|
||||
|
||||
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
||||
const unsigned compressed_geometries = m_compressed_geometries.size() + 1;
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
|
||||
@@ -135,15 +162,15 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
||||
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
||||
const unsigned edge_bucket_id1 = iter->second;
|
||||
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
||||
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
||||
BOOST_ASSERT(edge_bucket_id1 < m_compressed_oneway_geometries.size());
|
||||
|
||||
std::vector<CompressedEdge> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
||||
std::vector<OnewayCompressedEdge> &edge_bucket_list1 = m_compressed_oneway_geometries[edge_bucket_id1];
|
||||
|
||||
// note we don't save the start coordinate: it is implicitly given by edge 1
|
||||
// weight1 is the distance to the (currently) last coordinate in the bucket
|
||||
if (edge_bucket_list1.empty())
|
||||
{
|
||||
edge_bucket_list1.emplace_back(CompressedEdge{via_node_id, weight1});
|
||||
edge_bucket_list1.emplace_back(OnewayCompressedEdge{via_node_id, weight1});
|
||||
}
|
||||
|
||||
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
||||
@@ -153,10 +180,10 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
||||
{
|
||||
// second edge is not atomic anymore
|
||||
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
|
||||
BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
|
||||
BOOST_ASSERT(list_to_remove_index < m_compressed_oneway_geometries.size());
|
||||
|
||||
std::vector<CompressedEdge> &edge_bucket_list2 =
|
||||
m_compressed_geometries[list_to_remove_index];
|
||||
std::vector<OnewayCompressedEdge> &edge_bucket_list2 =
|
||||
m_compressed_oneway_geometries[list_to_remove_index];
|
||||
|
||||
// found an existing list, append it to the list of edge_id_1
|
||||
edge_bucket_list1.insert(
|
||||
@@ -174,7 +201,7 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
||||
else
|
||||
{
|
||||
// we are certain that the second edge is atomic.
|
||||
edge_bucket_list1.emplace_back(CompressedEdge{target_node_id, weight2});
|
||||
edge_bucket_list1.emplace_back(OnewayCompressedEdge{target_node_id, weight2});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,28 +233,65 @@ void CompressedEdgeContainer::AddUncompressedEdge(const EdgeID edge_id,
|
||||
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
||||
const unsigned edge_bucket_id = iter->second;
|
||||
BOOST_ASSERT(edge_bucket_id == GetPositionForID(edge_id));
|
||||
BOOST_ASSERT(edge_bucket_id < m_compressed_geometries.size());
|
||||
BOOST_ASSERT(edge_bucket_id < m_compressed_oneway_geometries.size());
|
||||
|
||||
std::vector<CompressedEdge> &edge_bucket_list = m_compressed_geometries[edge_bucket_id];
|
||||
std::vector<OnewayCompressedEdge> &edge_bucket_list = m_compressed_oneway_geometries[edge_bucket_id];
|
||||
|
||||
// note we don't save the start coordinate: it is implicitly given by edge_id
|
||||
// weight is the distance to the (currently) last coordinate in the bucket
|
||||
// Don't re-add this if it's already in there.
|
||||
if (edge_bucket_list.empty())
|
||||
{
|
||||
edge_bucket_list.emplace_back(CompressedEdge{target_node_id, weight});
|
||||
edge_bucket_list.emplace_back(OnewayCompressedEdge{target_node_id, weight});
|
||||
}
|
||||
}
|
||||
|
||||
void CompressedEdgeContainer::InitializeBothwayVector()
|
||||
{
|
||||
m_compressed_geometries.reserve(m_compressed_oneway_geometries.size() / 2);
|
||||
}
|
||||
|
||||
unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID r_edge_id)
|
||||
{
|
||||
const auto &forward_bucket = GetBucketReference(f_edge_id);
|
||||
const auto &reverse_bucket = GetBucketReference(r_edge_id);
|
||||
|
||||
BOOST_ASSERT(forward_bucket.size() == reverse_bucket.size());
|
||||
|
||||
const unsigned zipped_geometry_id = m_compressed_geometries.size();
|
||||
m_forward_edge_id_to_zipped_index_map[f_edge_id] = zipped_geometry_id;
|
||||
m_reverse_edge_id_to_zipped_index_map[r_edge_id] = zipped_geometry_id;
|
||||
|
||||
std::vector<CompressedEdge> zipped_edge_bucket;
|
||||
const auto &first_node = reverse_bucket.back();
|
||||
zipped_edge_bucket.emplace_back(CompressedEdge{first_node.node_id, INVALID_EDGE_WEIGHT, first_node.weight});
|
||||
|
||||
for (std::size_t i = 0; i < forward_bucket.size() - 1; ++i)
|
||||
{
|
||||
const auto &fwd_node = forward_bucket.at(i);
|
||||
const auto &rev_node = reverse_bucket.at(reverse_bucket.size() - 2 - i);
|
||||
|
||||
BOOST_ASSERT(fwd_node.node_id == rev_node.node_id);
|
||||
|
||||
zipped_edge_bucket.emplace_back(CompressedEdge{fwd_node.node_id, fwd_node.weight, rev_node.weight});
|
||||
}
|
||||
|
||||
const auto &last_node = forward_bucket.back();
|
||||
zipped_edge_bucket.emplace_back(CompressedEdge{last_node.node_id, last_node.weight, INVALID_EDGE_WEIGHT});
|
||||
m_compressed_geometries.emplace_back(std::move(zipped_edge_bucket));
|
||||
|
||||
return zipped_geometry_id;
|
||||
}
|
||||
|
||||
void CompressedEdgeContainer::PrintStatistics() const
|
||||
{
|
||||
const uint64_t compressed_edges = m_compressed_geometries.size();
|
||||
const uint64_t compressed_edges = m_compressed_oneway_geometries.size();
|
||||
BOOST_ASSERT(0 == compressed_edges % 2);
|
||||
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
||||
BOOST_ASSERT(m_compressed_oneway_geometries.size() + m_free_list.size() > 0);
|
||||
|
||||
uint64_t compressed_geometries = 0;
|
||||
uint64_t longest_chain_length = 0;
|
||||
for (const std::vector<CompressedEdge> ¤t_vector : m_compressed_geometries)
|
||||
for (const std::vector<OnewayCompressedEdge> ¤t_vector : m_compressed_oneway_geometries)
|
||||
{
|
||||
compressed_geometries += current_vector.size();
|
||||
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
||||
@@ -243,11 +307,11 @@ void CompressedEdgeContainer::PrintStatistics() const
|
||||
<< (float)compressed_geometries / std::max((uint64_t)1, compressed_edges);
|
||||
}
|
||||
|
||||
const CompressedEdgeContainer::EdgeBucket &
|
||||
const CompressedEdgeContainer::OnewayEdgeBucket &
|
||||
CompressedEdgeContainer::GetBucketReference(const EdgeID edge_id) const
|
||||
{
|
||||
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
||||
return m_compressed_geometries.at(index);
|
||||
return m_compressed_oneway_geometries.at(index);
|
||||
}
|
||||
|
||||
// Since all edges are technically in the compressed geometry container,
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace extractor
|
||||
|
||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
CompressedEdgeContainer &compressed_edge_container,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||
@@ -124,10 +124,12 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
|
||||
const auto &forward_geometry = m_compressed_edge_container.GetBucketReference(edge_id_1);
|
||||
BOOST_ASSERT(forward_geometry.size() ==
|
||||
m_compressed_edge_container.GetBucketReference(edge_id_2).size());
|
||||
const auto geometry_size = forward_geometry.size();
|
||||
const auto segment_count = forward_geometry.size();
|
||||
|
||||
// There should always be some geometry
|
||||
BOOST_ASSERT(0 != geometry_size);
|
||||
BOOST_ASSERT(0 != segment_count);
|
||||
|
||||
const unsigned packed_geometry_id = m_compressed_edge_container.ZipEdges(edge_id_1, edge_id_2);
|
||||
|
||||
NodeID current_edge_source_coordinate_id = node_u;
|
||||
|
||||
@@ -140,12 +142,12 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
|
||||
return SegmentID{edge_based_node_id, true};
|
||||
};
|
||||
|
||||
// traverse arrays from start and end respectively
|
||||
for (const auto i : util::irange(std::size_t{0}, geometry_size))
|
||||
// traverse arrays
|
||||
for (const auto i : util::irange(std::size_t{0}, segment_count))
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
current_edge_source_coordinate_id ==
|
||||
m_compressed_edge_container.GetBucketReference(edge_id_2)[geometry_size - 1 - i]
|
||||
m_compressed_edge_container.GetBucketReference(edge_id_2)[segment_count - 1 - i]
|
||||
.node_id);
|
||||
const NodeID current_edge_target_coordinate_id = forward_geometry[i].node_id;
|
||||
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
||||
@@ -156,8 +158,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
|
||||
current_edge_source_coordinate_id,
|
||||
current_edge_target_coordinate_id,
|
||||
forward_data.name_id,
|
||||
m_compressed_edge_container.GetPositionForID(edge_id_1),
|
||||
m_compressed_edge_container.GetPositionForID(edge_id_2),
|
||||
packed_geometry_id,
|
||||
false,
|
||||
INVALID_COMPONENTID,
|
||||
i,
|
||||
@@ -257,6 +258,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||
{
|
||||
util::Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||
|
||||
m_compressed_edge_container.InitializeBothwayVector();
|
||||
|
||||
// loop over all edges and generate new set of nodes
|
||||
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
@@ -442,14 +445,26 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
|
||||
distance += turn_penalty;
|
||||
|
||||
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_from_u));
|
||||
original_edge_data_vector.emplace_back(
|
||||
m_compressed_edge_container.GetPositionForID(edge_from_u),
|
||||
edge_data1.name_id,
|
||||
turn.lane_data_id,
|
||||
turn_instruction,
|
||||
entry_class_id,
|
||||
edge_data1.travel_mode);
|
||||
const bool is_encoded_forwards = m_compressed_edge_container.HasZippedEntryForForwardID(edge_from_u);
|
||||
const bool is_encoded_backwards = m_compressed_edge_container.HasZippedEntryForReverseID(edge_from_u);
|
||||
BOOST_ASSERT(is_encoded_forwards || is_encoded_backwards);
|
||||
if (is_encoded_forwards) {
|
||||
original_edge_data_vector.emplace_back(
|
||||
GeometryID{m_compressed_edge_container.GetZippedPositionForForwardID(edge_from_u), true},
|
||||
edge_data1.name_id,
|
||||
turn.lane_data_id,
|
||||
turn_instruction,
|
||||
entry_class_id,
|
||||
edge_data1.travel_mode);
|
||||
} else if (is_encoded_backwards) {
|
||||
original_edge_data_vector.emplace_back(
|
||||
GeometryID{m_compressed_edge_container.GetZippedPositionForReverseID(edge_from_u), false},
|
||||
edge_data1.name_id,
|
||||
turn.lane_data_id,
|
||||
turn_instruction,
|
||||
entry_class_id,
|
||||
edge_data1.travel_mode);
|
||||
}
|
||||
|
||||
++original_edges_counter;
|
||||
|
||||
|
||||
@@ -474,8 +474,6 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
*node_based_graph,
|
||||
compressed_edge_container);
|
||||
|
||||
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
|
||||
|
||||
util::NameTable name_table(config.names_file_name);
|
||||
|
||||
// could use some additional capacity? To avoid a copy during processing, though small data so
|
||||
@@ -505,6 +503,7 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
config.generate_edge_lookup);
|
||||
|
||||
WriteTurnLaneData(config.turn_lane_descriptions_file_name);
|
||||
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
|
||||
|
||||
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
||||
edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
|
||||
|
||||
Reference in New Issue
Block a user