Direct edges in contractor correctly and add better graph validation.
This commit is contained in:
@@ -184,6 +184,7 @@ void ExtractionContainers::PrepareEdges()
|
||||
{
|
||||
if (edge_iterator->result.source < node_iterator->node_id)
|
||||
{
|
||||
edge_iterator->result.source = SPECIAL_NODEID;
|
||||
++edge_iterator;
|
||||
continue;
|
||||
}
|
||||
@@ -193,6 +194,15 @@ void ExtractionContainers::PrepareEdges()
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove loops
|
||||
if (edge_iterator->result.source == edge_iterator->result.target)
|
||||
{
|
||||
edge_iterator->result.source = SPECIAL_NODEID;
|
||||
edge_iterator->result.target = SPECIAL_NODEID;
|
||||
++edge_iterator;
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(edge_iterator->result.source == node_iterator->node_id);
|
||||
|
||||
// assign new node id
|
||||
@@ -222,13 +232,16 @@ void ExtractionContainers::PrepareEdges()
|
||||
edge_iterator = all_edges_list.begin();
|
||||
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
||||
{
|
||||
// skip all invalid edges
|
||||
if (edge_iterator->result.source == SPECIAL_NODEID)
|
||||
{
|
||||
++edge_iterator;
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -237,58 +250,50 @@ void ExtractionContainers::PrepareEdges()
|
||||
++node_iterator;
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(edge_iterator->result.target == node_iterator->node_id);
|
||||
if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
|
||||
edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
|
||||
{
|
||||
BOOST_ASSERT(edge_iterator->weight_data.speed != -1);
|
||||
BOOST_ASSERT(edge_iterator->weight_data.speed >= 0);
|
||||
BOOST_ASSERT(edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min());
|
||||
|
||||
const double distance = coordinate_calculation::euclidean_distance(
|
||||
edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon,
|
||||
node_iterator->lat, node_iterator->lon);
|
||||
const double distance = coordinate_calculation::euclidean_distance(
|
||||
edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon,
|
||||
node_iterator->lat, node_iterator->lon);
|
||||
|
||||
const double weight = [distance](const InternalExtractorEdge::WeightData& data) {
|
||||
switch (data.type)
|
||||
{
|
||||
case InternalExtractorEdge::WeightType::EDGE_DURATION:
|
||||
case InternalExtractorEdge::WeightType::WAY_DURATION:
|
||||
return data.duration * 10.;
|
||||
break;
|
||||
case InternalExtractorEdge::WeightType::SPEED:
|
||||
return (distance * 10.) / (data.speed / 3.6);
|
||||
break;
|
||||
default:
|
||||
osrm::exception("invalid weight type");
|
||||
}
|
||||
return -1.0;
|
||||
}(edge_iterator->weight_data);
|
||||
|
||||
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)
|
||||
const double weight = [distance](const InternalExtractorEdge::WeightData& data) {
|
||||
switch (data.type)
|
||||
{
|
||||
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;
|
||||
case InternalExtractorEdge::WeightType::EDGE_DURATION:
|
||||
case InternalExtractorEdge::WeightType::WAY_DURATION:
|
||||
return data.duration * 10.;
|
||||
break;
|
||||
case InternalExtractorEdge::WeightType::SPEED:
|
||||
return (distance * 10.) / (data.speed / 3.6);
|
||||
break;
|
||||
case InternalExtractorEdge::WeightType::INVALID:
|
||||
osrm::exception("invalid weight type");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// mark edge as invalid
|
||||
edge_iterator->result.source = SPECIAL_NODEID;
|
||||
edge_iterator->result.target = SPECIAL_NODEID;
|
||||
return -1.0;
|
||||
}(edge_iterator->weight_data);
|
||||
|
||||
// FIXME we should print a warning here.
|
||||
auto& edge = edge_iterator->result;
|
||||
edge.weight = std::max(1, static_cast<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;
|
||||
|
||||
// orient edges consistently: source id < target id
|
||||
// important for multi-edge removal
|
||||
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_iterator;
|
||||
}
|
||||
@@ -303,13 +308,18 @@ void ExtractionContainers::PrepareEdges()
|
||||
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();)
|
||||
for (unsigned i = 0; i < all_edges_list.size();)
|
||||
{
|
||||
// only invalid edges left
|
||||
if (all_edges_list[i].result.source == SPECIAL_NODEID)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// skip invalid edges
|
||||
if (all_edges_list[i].result.target == SPECIAL_NODEID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned start_idx = i;
|
||||
NodeID source = all_edges_list[i].result.source;
|
||||
@@ -320,6 +330,7 @@ void ExtractionContainers::PrepareEdges()
|
||||
unsigned min_forward_idx = std::numeric_limits<unsigned>::max();
|
||||
unsigned min_backward_idx = std::numeric_limits<unsigned>::max();
|
||||
|
||||
// find minimal edge in both directions
|
||||
while (all_edges_list[i].result.source == source &&
|
||||
all_edges_list[i].result.target == target)
|
||||
{
|
||||
@@ -338,26 +349,34 @@ void ExtractionContainers::PrepareEdges()
|
||||
|
||||
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);
|
||||
BOOST_ASSERT(min_backward_idx != std::numeric_limits<unsigned>::max() ||
|
||||
min_forward_idx != std::numeric_limits<unsigned>::max());
|
||||
|
||||
// reset direction for both edges
|
||||
if (min_forward_idx != std::numeric_limits<unsigned>::max())
|
||||
if (min_backward_idx == min_forward_idx)
|
||||
{
|
||||
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.is_split = false;
|
||||
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;
|
||||
all_edges_list[min_forward_idx].result.backward = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool has_forward = min_forward_idx != std::numeric_limits<unsigned>::max();
|
||||
bool has_backward = min_backward_idx != std::numeric_limits<unsigned>::max();
|
||||
if (has_forward)
|
||||
{
|
||||
all_edges_list[min_forward_idx].result.forward = true;
|
||||
all_edges_list[min_forward_idx].result.backward = false;
|
||||
all_edges_list[min_forward_idx].result.is_split = has_backward;
|
||||
}
|
||||
if (has_backward)
|
||||
{
|
||||
std::swap(all_edges_list[min_backward_idx].result.source,
|
||||
all_edges_list[min_backward_idx].result.target);
|
||||
all_edges_list[min_backward_idx].result.forward = true;
|
||||
all_edges_list[min_backward_idx].result.backward = false;
|
||||
all_edges_list[min_backward_idx].result.is_split = has_forward;
|
||||
}
|
||||
}
|
||||
|
||||
// invalidate all unused edges
|
||||
for (unsigned j = start_idx; j < i; j++)
|
||||
|
||||
Reference in New Issue
Block a user