Handle case of dead-end edges by inserting an invalid turn
This commit is contained in:
		
							parent
							
								
									21a1a2da93
								
							
						
					
					
						commit
						811372fca8
					
				| @ -817,18 +817,22 @@ std::vector<TurnCandidate> TurnAnalysis::handleOneWayTurn( | |||||||
| { | { | ||||||
|     BOOST_ASSERT(turn_candidates[0].angle < 0.001); |     BOOST_ASSERT(turn_candidates[0].angle < 0.001); | ||||||
|     (void)from, (void)via_edge; |     (void)from, (void)via_edge; | ||||||
|     if (!turn_candidates[0].valid) |  | ||||||
|     { |  | ||||||
|         util::SimpleLogger().Write(logWARNING) |  | ||||||
|             << "Graph Broken. Dead end without exit found or missing reverse edge."; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
| #if PRINT_DEBUG_CANDIDATES | #if PRINT_DEBUG_CANDIDATES | ||||||
|     std::cout << "Basic (one) Turn Candidates:\n"; |     std::cout << "Basic (one) Turn Candidates:\n"; | ||||||
|     for (auto tc : turn_candidates) |     for (auto tc : turn_candidates) | ||||||
|         std::cout << "\t" << tc.toString() << " " |     { | ||||||
|                   << (int)node_based_graph.GetEdgeData(tc.eid).road_classification.road_class |         std::cout << "\t" << tc.toString() << " "; | ||||||
|                   << " name: " << node_based_graph.GetEdgeData(tc.eid).name_id << std::endl; |         if (tc.eid != SPECIAL_EDGEID) | ||||||
|  |         { | ||||||
|  |             std::cout << (int)node_based_graph.GetEdgeData(tc.eid).road_classification.road_class << | ||||||
|  |                 "name: " << node_based_graph.GetEdgeData(tc.eid).name_id << std::endl; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             std::cout << " dead end" << std::endl; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| #endif | #endif | ||||||
|     return turn_candidates; |     return turn_candidates; | ||||||
| } | } | ||||||
| @ -1659,87 +1663,84 @@ std::vector<TurnCandidate> TurnAnalysis::getTurnCandidates(const NodeID from_nod | |||||||
|     const NodeID only_restriction_to_node = |     const NodeID only_restriction_to_node = | ||||||
|         restriction_map.CheckForEmanatingIsOnlyTurn(from_node, turn_node); |         restriction_map.CheckForEmanatingIsOnlyTurn(from_node, turn_node); | ||||||
|     const bool is_barrier_node = barrier_nodes.find(turn_node) != barrier_nodes.end(); |     const bool is_barrier_node = barrier_nodes.find(turn_node) != barrier_nodes.end(); | ||||||
|  |     bool has_uturn_edge = false; | ||||||
| 
 | 
 | ||||||
|     for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node)) |     for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node)) | ||||||
|     { |     { | ||||||
|         bool turn_is_valid = true; |         // reverse edges are never valid turns because the resulting turn would look like this:
 | ||||||
|  |         // from_node --via_edge--> turn_node <--onto_edge-- to_node
 | ||||||
|         if (node_based_graph.GetEdgeData(onto_edge).reversed) |         if (node_based_graph.GetEdgeData(onto_edge).reversed) | ||||||
|         { |         { | ||||||
|             turn_is_valid = false; |             continue; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         const NodeID to_node = node_based_graph.GetTarget(onto_edge); |         const NodeID to_node = node_based_graph.GetTarget(onto_edge); | ||||||
| 
 | 
 | ||||||
|         if (turn_is_valid && (only_restriction_to_node != SPECIAL_NODEID) && |         bool turn_is_valid = | ||||||
|             (to_node != only_restriction_to_node)) |             // we are not turning over a barrier
 | ||||||
|         { |             (!is_barrier_node || from_node == to_node) && | ||||||
|             // We are at an only_-restriction but not at the right turn.
 |             // We are at an only_-restriction but not at the right turn.
 | ||||||
|             //            ++restricted_turns_counter;
 |             (only_restriction_to_node == SPECIAL_NODEID || to_node == only_restriction_to_node) && | ||||||
|             turn_is_valid = false; |             // the turn is not restricted
 | ||||||
|         } |             !restriction_map.CheckIfTurnIsRestricted(from_node, turn_node, to_node); | ||||||
| 
 | 
 | ||||||
|         if (turn_is_valid) |         auto angle = 0.; | ||||||
|  |         if (from_node == to_node) | ||||||
|         { |         { | ||||||
|             if (is_barrier_node) |             has_uturn_edge = true; | ||||||
|  |             if (turn_is_valid && !is_barrier_node) | ||||||
|             { |             { | ||||||
|                 if (from_node != to_node) |                 // we only add u-turns for dead-end streets.
 | ||||||
|                 { |                 if (node_based_graph.GetOutDegree(turn_node) > 1) | ||||||
|                     //                    ++skipped_barrier_turns_counter;
 |  | ||||||
|                     turn_is_valid = false; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 if (from_node == to_node && node_based_graph.GetOutDegree(turn_node) > 1) |  | ||||||
|                 { |                 { | ||||||
|                     auto number_of_emmiting_bidirectional_edges = 0; |                     auto number_of_emmiting_bidirectional_edges = 0; | ||||||
|                     for (auto edge : node_based_graph.GetAdjacentEdgeRange(turn_node)) |                     for (auto edge : node_based_graph.GetAdjacentEdgeRange(turn_node)) | ||||||
|                     { |                     { | ||||||
|                         auto target = node_based_graph.GetTarget(edge); |                         auto target = node_based_graph.GetTarget(edge); | ||||||
|                         auto reverse_edge = node_based_graph.FindEdge(target, turn_node); |                         auto reverse_edge = node_based_graph.FindEdge(target, turn_node); | ||||||
|  |                         BOOST_ASSERT(reverse_edge != SPECIAL_EDGEID); | ||||||
|                         if (!node_based_graph.GetEdgeData(reverse_edge).reversed) |                         if (!node_based_graph.GetEdgeData(reverse_edge).reversed) | ||||||
|                         { |                         { | ||||||
|                             ++number_of_emmiting_bidirectional_edges; |                             ++number_of_emmiting_bidirectional_edges; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     if (number_of_emmiting_bidirectional_edges > 1) |                     // is a dead-end
 | ||||||
|                     { |                     turn_is_valid = number_of_emmiting_bidirectional_edges <= 1; | ||||||
|                         //                        ++skipped_uturns_counter;
 |  | ||||||
|                         turn_is_valid = false; |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             BOOST_ASSERT(angle >= 0. && angle < std::numeric_limits<double>::epsilon()); | ||||||
|         } |         } | ||||||
| 
 |         else | ||||||
|         // only add an edge if turn is not a U-turn except when it is
 |  | ||||||
|         // at the end of a dead-end street
 |  | ||||||
|         if (restriction_map.CheckIfTurnIsRestricted(from_node, turn_node, to_node) && |  | ||||||
|             (only_restriction_to_node == SPECIAL_NODEID) && (to_node != only_restriction_to_node)) |  | ||||||
|         { |         { | ||||||
|             // We are at an only_-restriction but not at the right turn.
 |             // unpack first node of second segment if packed
 | ||||||
|             //            ++restricted_turns_counter;
 |             const auto first_coordinate = getRepresentativeCoordinate( | ||||||
|             turn_is_valid = false; |                 from_node, turn_node, via_eid, INVERT, compressed_edge_container, node_info_list); | ||||||
|  |             const auto third_coordinate = getRepresentativeCoordinate( | ||||||
|  |                 turn_node, to_node, onto_edge, !INVERT, compressed_edge_container, node_info_list); | ||||||
|  |             angle = util::coordinate_calculation::computeAngle( | ||||||
|  |                 first_coordinate, node_info_list[turn_node], third_coordinate); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // unpack first node of second segment if packed
 |  | ||||||
| 
 |  | ||||||
|         const auto first_coordinate = getRepresentativeCoordinate( |  | ||||||
|             from_node, turn_node, via_eid, INVERT, compressed_edge_container, node_info_list); |  | ||||||
|         const auto third_coordinate = getRepresentativeCoordinate( |  | ||||||
|             turn_node, to_node, onto_edge, !INVERT, compressed_edge_container, node_info_list); |  | ||||||
| 
 |  | ||||||
|         const auto angle = util::coordinate_calculation::computeAngle( |  | ||||||
|             first_coordinate, node_info_list[turn_node], third_coordinate); |  | ||||||
| 
 |  | ||||||
|         turn_candidates.push_back( |         turn_candidates.push_back( | ||||||
|             {onto_edge, turn_is_valid, angle, {TurnType::Invalid, DirectionModifier::UTurn}, 0}); |             {onto_edge, turn_is_valid, angle, {TurnType::Invalid, DirectionModifier::UTurn}, 0}); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // We hit the case of a street leading into nothing-ness. Since the code here assumes that this will
 | ||||||
|  |     // never happen we add an artificial invalid uturn in this case.
 | ||||||
|  |     if (!has_uturn_edge) | ||||||
|  |     { | ||||||
|  |         turn_candidates.push_back( | ||||||
|  |             {SPECIAL_EDGEID, false, 0., {TurnType::Invalid, DirectionModifier::UTurn}, 0}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const auto ByAngle = [](const TurnCandidate &first, const TurnCandidate second) |     const auto ByAngle = [](const TurnCandidate &first, const TurnCandidate second) | ||||||
|     { |     { | ||||||
|         return first.angle < second.angle; |         return first.angle < second.angle; | ||||||
|     }; |     }; | ||||||
|     std::sort(std::begin(turn_candidates), std::end(turn_candidates), ByAngle); |     std::sort(std::begin(turn_candidates), std::end(turn_candidates), ByAngle); | ||||||
| 
 | 
 | ||||||
|  |     BOOST_ASSERT(turn_candidates[0].angle >= 0. && turn_candidates[0].angle < std::numeric_limits<double>::epsilon()); | ||||||
|  | 
 | ||||||
|     return mergeSegregatedRoads(from_node, via_eid, std::move(turn_candidates)); |     return mergeSegregatedRoads(from_node, via_eid, std::move(turn_candidates)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user