fix same segment routes
This commit is contained in:
		
							parent
							
								
									cd9addf0e2
								
							
						
					
					
						commit
						f9350a276c
					
				| @ -118,7 +118,7 @@ RouteLeg assembleLeg(const DataFacadeT &facade, | ||||
| 
 | ||||
|     //                 s
 | ||||
|     //                 |
 | ||||
|     // Given a route a---b---c  where there is a right turn at b.
 | ||||
|     // Given a route a---b---c  where there is a right turn at c.
 | ||||
|     //                       |
 | ||||
|     //                       d
 | ||||
|     //                       |--t
 | ||||
|  | ||||
| @ -89,11 +89,10 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
|             const std::int32_t new_distance = reverse_heap.GetKey(node) + distance; | ||||
|             if (new_distance < upper_bound) | ||||
|             { | ||||
|                 // if loops are forced, they are so at the source
 | ||||
|                 if (new_distance >= 0 && | ||||
|                     (!force_loop_forward || | ||||
|                      forward_heap.GetData(node).parent != | ||||
|                          node) // if loops are forced, they are so at the source
 | ||||
|                     && (!force_loop_reverse || reverse_heap.GetData(node).parent != node)) | ||||
|                     (!force_loop_forward || forward_heap.GetData(node).parent != node) && | ||||
|                     (!force_loop_reverse || reverse_heap.GetData(node).parent != node)) | ||||
|                 { | ||||
|                     middle_node_id = node; | ||||
|                     upper_bound = new_distance; | ||||
| @ -320,8 +319,11 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
|                 for (std::size_t i = start_index; i < end_index; ++i) | ||||
|                 { | ||||
|                     unpacked_path.push_back( | ||||
|                         PathData{id_vector[i], name_index, weight_vector[i], | ||||
|                                  extractor::guidance::TurnInstruction::NO_TURN(), travel_mode}); | ||||
|                         PathData{id_vector[i], | ||||
|                                  name_index, | ||||
|                                  weight_vector[i], | ||||
|                                  extractor::guidance::TurnInstruction::NO_TURN(), | ||||
|                                  travel_mode}); | ||||
|                 } | ||||
|                 BOOST_ASSERT(unpacked_path.size() > 0); | ||||
|                 unpacked_path.back().turn_instruction = turn_instruction; | ||||
| @ -339,6 +341,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
|                     // However the first segment duration needs to be adjusted to the fact that the
 | ||||
|                     // source phantom is in the middle of the segment.
 | ||||
|                     // We do this by subtracting v--s from the duration.
 | ||||
| 
 | ||||
|                     BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight); | ||||
|                     unpacked_path.front().duration_until_turn -= source_weight; | ||||
|                 } | ||||
| @ -369,8 +372,10 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
|         } | ||||
| 
 | ||||
|         std::size_t end_index = phantom_node_pair.target_phantom.fwd_segment_position; | ||||
|         const std::size_t delta = target_traversed_in_reverse ? 1 : 0; | ||||
|         if (target_traversed_in_reverse) | ||||
|         { | ||||
|             start_index += 1; | ||||
|             std::reverse(id_vector.begin(), id_vector.end()); | ||||
|             std::reverse(weight_vector.begin(), weight_vector.end()); | ||||
|             end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position; | ||||
| @ -392,8 +397,10 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
|         { | ||||
|             BOOST_ASSERT(i < id_vector.size()); | ||||
|             BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0); | ||||
|             unpacked_path.emplace_back( | ||||
|                 PathData{id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i], | ||||
|             unpacked_path.push_back( | ||||
|                 PathData{id_vector[i], | ||||
|                          phantom_node_pair.target_phantom.name_id, | ||||
|                          weight_vector[i - delta], | ||||
|                          extractor::guidance::TurnInstruction::NO_TURN(), | ||||
|                          target_traversed_in_reverse | ||||
|                              ? phantom_node_pair.target_phantom.backward_travel_mode | ||||
| @ -402,9 +409,9 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
| 
 | ||||
|         if (is_local_path && unpacked_path.size() > 0) | ||||
|         { | ||||
|             auto source_weight = start_traversed_in_reverse | ||||
|                                      ? phantom_node_pair.source_phantom.reverse_weight | ||||
|                                      : phantom_node_pair.source_phantom.forward_weight; | ||||
|             const auto source_weight = start_traversed_in_reverse | ||||
|                                            ? phantom_node_pair.source_phantom.reverse_weight | ||||
|                                            : phantom_node_pair.source_phantom.forward_weight; | ||||
|             // The above code will create segments for (v, w), (w,x), (x, y) and (y, Z).
 | ||||
|             // However the first segment duration needs to be adjusted to the fact that the source
 | ||||
|             // phantom is in the middle of the segment. We do this by subtracting v--s from the
 | ||||
| @ -423,9 +430,6 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
|             const std::size_t last_index = unpacked_path.size() - 1; | ||||
|             const std::size_t second_to_last_index = last_index - 1; | ||||
| 
 | ||||
|             // looks like a trivially true check but tests for underflow
 | ||||
|             BOOST_ASSERT(last_index > second_to_last_index); | ||||
| 
 | ||||
|             if (unpacked_path[last_index].turn_via_node == | ||||
|                 unpacked_path[second_to_last_index].turn_via_node) | ||||
|             { | ||||
| @ -651,8 +655,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface | ||||
|         } | ||||
|         // TODO check if unordered_set might be faster
 | ||||
|         // sort by id and increasing by distance
 | ||||
|         auto entry_point_comparator = [](const std::pair<NodeID, EdgeWeight> &lhs, | ||||
|                                          const std::pair<NodeID, EdgeWeight> &rhs) | ||||
|         auto entry_point_comparator = | ||||
|             [](const std::pair<NodeID, EdgeWeight> &lhs, const std::pair<NodeID, EdgeWeight> &rhs) | ||||
|         { | ||||
|             return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second); | ||||
|         }; | ||||
|  | ||||
| @ -293,10 +293,6 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | ||||
| 
 | ||||
| void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | ||||
| { | ||||
| #if OSRM_POST_PROCESSING_PRINT_DEBUG | ||||
|     std::cout << "[Pre-Trimming]" << std::endl; | ||||
|     print(steps); | ||||
| #endif | ||||
|     // Doing this step in post-processing provides a few challenges we cannot overcome.
 | ||||
|     // The removal of an initial step imposes some copy overhead in the steps, moving all later
 | ||||
|     // steps to the front.
 | ||||
| @ -305,7 +301,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | ||||
|     // few seconds of inaccuracy at both ends. This is acceptable, however, since the turn should
 | ||||
|     // usually not be as relevant.
 | ||||
| 
 | ||||
|     if (steps.size() <= 2) | ||||
|     if (steps.size() < 2) | ||||
|         return; | ||||
| 
 | ||||
|     // if phantom node is located at the connection of two segments, either one can be selected as
 | ||||
| @ -321,37 +317,59 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | ||||
|     // We have to be careful though, since routing that starts in a roundabout has a valid.
 | ||||
|     // To catch these cases correctly, we have to perform trimming prior to the post-processing
 | ||||
| 
 | ||||
|     if (steps.front().distance <= std::numeric_limits<double>::epsilon()) | ||||
|     BOOST_ASSERT(geometry.locations.size() >= steps.size()); | ||||
|     const bool zero_length_step = steps.front().distance <= std::numeric_limits<double>::epsilon(); | ||||
|     const bool duplicated_coordinate = geometry.locations[0] == geometry.locations[1]; | ||||
|     if (zero_length_step || duplicated_coordinate) | ||||
|     { | ||||
|         // We have to adjust the first step both for its name and the bearings
 | ||||
|         const auto ¤t_depart = steps.front(); | ||||
|         auto &designated_depart = *(steps.begin() + 1); | ||||
| 
 | ||||
|         // FIXME this is required to be consistent with the route durations. The initial turn is not
 | ||||
|         // actually part of the route, though
 | ||||
|         designated_depart.duration += current_depart.duration; | ||||
| 
 | ||||
|         // fixup the coordinate
 | ||||
|         geometry.locations.erase(geometry.locations.begin()); | ||||
| 
 | ||||
|         BOOST_ASSERT(geometry.segment_offsets[1] == 1); | ||||
|         // geometry offsets have to be adjusted. Move all offsets to the front and reduce by one.
 | ||||
|         std::transform(geometry.segment_offsets.begin() + 1, geometry.segment_offsets.end(), | ||||
|                        geometry.segment_offsets.begin(), [](const std::size_t val) | ||||
|                        { | ||||
|                            return val - 1; | ||||
|                        }); | ||||
|         geometry.segment_offsets.pop_back(); | ||||
| 
 | ||||
|         // remove the initial distance value
 | ||||
|         geometry.segment_distances.erase(geometry.segment_distances.begin()); | ||||
| 
 | ||||
|         // update initial turn direction/bearings. Due to the duplicated first coordinate, the
 | ||||
|         // initial bearing is invalid
 | ||||
|         designated_depart.maneuver = detail::stepManeuverFromGeometry( | ||||
|             TurnInstruction::NO_TURN(), WaypointType::Depart, geometry); | ||||
|         // We have to adjust the first step both for its name and the bearings
 | ||||
|         if (zero_length_step) | ||||
|         { | ||||
|             // move offsets to front
 | ||||
|             BOOST_ASSERT(geometry.segment_offsets[1] == 1); | ||||
|             // geometry offsets have to be adjusted. Move all offsets to the front and reduce by
 | ||||
|             // one. (This is an inplace forward one and reduce by one)
 | ||||
|             std::transform(geometry.segment_offsets.begin() + 1, geometry.segment_offsets.end(), | ||||
|                            geometry.segment_offsets.begin(), [](const std::size_t val) | ||||
|                            { | ||||
|                                return val - 1; | ||||
|                            }); | ||||
| 
 | ||||
|         // finally remove the initial (now duplicated move)
 | ||||
|         steps.erase(steps.begin()); | ||||
|             geometry.segment_offsets.pop_back(); | ||||
|             const auto ¤t_depart = steps.front(); | ||||
|             auto &designated_depart = *(steps.begin() + 1); | ||||
| 
 | ||||
|             // FIXME this is required to be consistent with the route durations. The initial turn is
 | ||||
|             // not actually part of the route, though
 | ||||
|             designated_depart.duration += current_depart.duration; | ||||
| 
 | ||||
|             // update initial turn direction/bearings. Due to the duplicated first coordinate, the
 | ||||
|             // initial bearing is invalid
 | ||||
|             designated_depart.maneuver = detail::stepManeuverFromGeometry( | ||||
|                 TurnInstruction::NO_TURN(), WaypointType::Depart, geometry); | ||||
| 
 | ||||
|             // finally remove the initial (now duplicated move)
 | ||||
|             steps.erase(steps.begin()); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             steps.front().geometry_begin = 1; | ||||
|             // reduce all offsets by one (inplace)
 | ||||
|             std::transform(geometry.segment_offsets.begin(), geometry.segment_offsets.end(), | ||||
|                            geometry.segment_offsets.begin(), [](const std::size_t val) | ||||
|                            { | ||||
|                                return val - 1; | ||||
|                            }); | ||||
| 
 | ||||
|             steps.front().maneuver = detail::stepManeuverFromGeometry( | ||||
|                 TurnInstruction::NO_TURN(), WaypointType::Depart, geometry); | ||||
|         } | ||||
| 
 | ||||
|         // and update the leg geometry indices for the removed entry
 | ||||
|         std::for_each(steps.begin(), steps.end(), [](RouteStep &step) | ||||
| @ -362,9 +380,10 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | ||||
|     } | ||||
| 
 | ||||
|     // make sure we still have enough segments
 | ||||
|     if (steps.size() <= 2) | ||||
|     if (steps.size() < 2) | ||||
|         return; | ||||
| 
 | ||||
|     BOOST_ASSERT(geometry.locations.size() >= steps.size()); | ||||
|     auto &next_to_last_step = *(steps.end() - 2); | ||||
|     // in the end, the situation with the roundabout cannot occur. As a result, we can remove all
 | ||||
|     // zero-length instructions
 | ||||
| @ -380,6 +399,21 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | ||||
|         steps.pop_back(); | ||||
|         // the geometry indices of the last step are already correct;
 | ||||
|     } | ||||
|     else if (geometry.locations[geometry.locations.size() - 2] == | ||||
|              geometry.locations[geometry.locations.size() - 1]) | ||||
|     { | ||||
|         // correct steps but duplicated coordinate in the end.
 | ||||
|         // This can happen if the last coordinate snaps to a node in the unpacked geometry
 | ||||
|         geometry.locations.pop_back(); | ||||
|         geometry.segment_offsets.back()--; | ||||
|         BOOST_ASSERT(next_to_last_step.geometry_end == steps.back().geometry_begin); | ||||
|         BOOST_ASSERT(next_to_last_step.geometry_begin < next_to_last_step.geometry_end); | ||||
|         next_to_last_step.geometry_end--; | ||||
|         steps.back().geometry_begin--; | ||||
|         steps.back().geometry_end--; | ||||
|         steps.back().maneuver = detail::stepManeuverFromGeometry(TurnInstruction::NO_TURN(), | ||||
|                                                                  WaypointType::Arrive, geometry); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // assign relative locations to depart/arrive instructions
 | ||||
| @ -399,8 +433,7 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps, | ||||
|         distance_to_start >= MINIMAL_RELATIVE_DISTANCE && | ||||
|                 distance_to_start <= MAXIMAL_RELATIVE_DISTANCE | ||||
|             ? angleToDirectionModifier(util::coordinate_calculation::computeAngle( | ||||
|                   source_node.input_location, leg_geometry.locations.at(0), | ||||
|                   leg_geometry.locations.at(1))) | ||||
|                   source_node.input_location, leg_geometry.locations[0], leg_geometry.locations[1])) | ||||
|             : extractor::guidance::DirectionModifier::UTurn; | ||||
| 
 | ||||
|     steps.front().maneuver.instruction.direction_modifier = initial_modifier; | ||||
| @ -411,8 +444,8 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps, | ||||
|         distance_from_end >= MINIMAL_RELATIVE_DISTANCE && | ||||
|                 distance_from_end <= MAXIMAL_RELATIVE_DISTANCE | ||||
|             ? angleToDirectionModifier(util::coordinate_calculation::computeAngle( | ||||
|                   leg_geometry.locations.at(leg_geometry.locations.size() - 2), | ||||
|                   leg_geometry.locations.at(leg_geometry.locations.size() - 1), | ||||
|                   leg_geometry.locations[leg_geometry.locations.size() - 2], | ||||
|                   leg_geometry.locations[leg_geometry.locations.size() - 1], | ||||
|                   target_node.input_location)) | ||||
|             : extractor::guidance::DirectionModifier::UTurn; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user