Make intersection backwards compatible
For `depart` and `arrive` `step.intersections[0].{bearings|entry}` will have
only one entry.
			
			
This commit is contained in:
		
							parent
							
								
									3b37769624
								
							
						
					
					
						commit
						95af72c70c
					
				
							
								
								
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @ -4,12 +4,10 @@ | |||||||
|    - API: |    - API: | ||||||
|      - new parameter `annotate` for `route` and `match` requests.  Returns additional data about each |      - new parameter `annotate` for `route` and `match` requests.  Returns additional data about each | ||||||
|        coordinate along the selected/matched route line. |        coordinate along the selected/matched route line. | ||||||
|      - Introducing Intersections for Route Steps. This breaks the API format in multiple ways. |      - Introducing Intersections for Route Steps. This changes the API format in multiple ways. | ||||||
|          - `bearing_before`/`bearing_after` are no longer supplied with a StepManeuver |          - `bearing_before`/`bearing_after` of `StepManeuver` are now deprecated and will be removed in the next major release | ||||||
|          - `exit` is no longer supplied for turns other than roundabouts |          - `location` of `StepManeuvers` is now deprecated and will be removed in the next major release | ||||||
|          - `location` is no longer supplied for StepManeuvers |          - every `RouteStep` now has property `intersections` containing a list of `Intersection` objects. | ||||||
|          - every RouteStep is supplied with a list of at least one `Intersection`. |  | ||||||
|          - Intersections offer the removed values from StepManeuver |  | ||||||
| 
 | 
 | ||||||
|    - Profile changes: |    - Profile changes: | ||||||
|      - duration parser now accepts P[n]DT[n]H[n]M[n]S, P[n]W, PTHHMMSS and PTHH:MM:SS ISO8601 formats. |      - duration parser now accepts P[n]DT[n]H[n]M[n]S, P[n]W, PTHHMMSS and PTHH:MM:SS ISO8601 formats. | ||||||
|  | |||||||
| @ -377,7 +377,7 @@ Represents a route between two waypoints. | |||||||
| - `duration`: The estimated travel time, in `float` number of seconds. | - `duration`: The estimated travel time, in `float` number of seconds. | ||||||
| - `summary`: Summary of the route taken as `string`. Depends on the `steps` parameter: | - `summary`: Summary of the route taken as `string`. Depends on the `steps` parameter: | ||||||
|     |     | ||||||
|    | summary      |                                                                       | |    | steps        |                                                                       | | ||||||
|    |--------------|-----------------------------------------------------------------------| |    |--------------|-----------------------------------------------------------------------| | ||||||
|    | true         | Names of the two major roads used. Can be empty if route is too short.| |    | true         | Names of the two major roads used. Can be empty if route is too short.| | ||||||
|    | false        | empty `string`                                                        | |    | false        | empty `string`                                                        | | ||||||
| @ -464,6 +464,12 @@ step. | |||||||
| ### StepManeuver | ### StepManeuver | ||||||
| 
 | 
 | ||||||
| #### Properties | #### Properties | ||||||
|  | 
 | ||||||
|  | - `location`: A `[longitude, latitude]` pair describing the location of the turn. | ||||||
|  | - `bearing_before`: The clockwise angle from true north to the | ||||||
|  |   direction of travel immediately before the maneuver. | ||||||
|  | - `bearing_after`: The clockwise angle from true north to the | ||||||
|  |   direction of travel immediately after the maneuver. | ||||||
| - `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change** | - `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change** | ||||||
|    Types  unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed. |    Types  unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed. | ||||||
|    |    | ||||||
| @ -517,6 +523,7 @@ step. | |||||||
|   | `type`                 | Description                                                                                                               | |   | `type`                 | Description                                                                                                               | | ||||||
|   |------------------------|---------------------------------------------------------------------------------------------------------------------------| |   |------------------------|---------------------------------------------------------------------------------------------------------------------------| | ||||||
|   | `roundabout`           | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout.                       | |   | `roundabout`           | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout.                       | | ||||||
|  |   | else                   | Indicates the number of intersections passed until the turn. Example instruction: `at the fourth intersection, turn left` | | ||||||
|    |    | ||||||
| 
 | 
 | ||||||
| New properties (potentially depending on `type`) may be introduced in the future without an API version change. | New properties (potentially depending on `type`) may be introduced in the future without an API version change. | ||||||
|  | |||||||
| @ -28,12 +28,10 @@ namespace guidance | |||||||
| { | { | ||||||
| namespace detail | namespace detail | ||||||
| { | { | ||||||
| 
 | std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry); | ||||||
| Intersection intersectionFromGeometry(const WaypointType waypoint_type, | std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry); | ||||||
|                                       const double segment_duration, | std::pair<short, short> getIntermediateBearings(const LegGeometry &leg_geometry, | ||||||
|                                       const LegGeometry &leg_geometry, |  | ||||||
|                                                 const std::size_t segment_index); |                                                 const std::size_t segment_index); | ||||||
| 
 |  | ||||||
| } // ns detail
 | } // ns detail
 | ||||||
| 
 | 
 | ||||||
| template <typename DataFacadeT> | template <typename DataFacadeT> | ||||||
| @ -65,16 +63,19 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade, | |||||||
|     std::size_t segment_index = 0; |     std::size_t segment_index = 0; | ||||||
|     BOOST_ASSERT(leg_geometry.locations.size() >= 2); |     BOOST_ASSERT(leg_geometry.locations.size() >= 2); | ||||||
| 
 | 
 | ||||||
|  |     auto bearings = detail::getDepartBearings(leg_geometry); | ||||||
|  |     std::cout << "depart bearings: " << bearings.first << "->" << bearings.second << std::endl; | ||||||
|  | 
 | ||||||
|  |     StepManeuver maneuver{source_node.location, bearings.first, | ||||||
|  |                           bearings.second,      extractor::guidance::TurnInstruction::NO_TURN(), | ||||||
|  |                           WaypointType::Depart, 0}; | ||||||
|  |     Intersection intersection{ | ||||||
|  |         source_node.location, | ||||||
|  |         std::vector<short>({bearings.second}), | ||||||
|  |         std::vector<bool>({true}), Intersection::NO_INDEX, 0}; | ||||||
|  | 
 | ||||||
|     if (leg_data.size() > 0) |     if (leg_data.size() > 0) | ||||||
|     { |     { | ||||||
|         StepManeuver maneuver = {extractor::guidance::TurnInstruction::NO_TURN(), |  | ||||||
|                                  WaypointType::Depart, 0}; |  | ||||||
| 
 |  | ||||||
|         auto intersection = |  | ||||||
|             detail::intersectionFromGeometry(WaypointType::Depart, 0, leg_geometry, 0); |  | ||||||
|         intersection = util::guidance::setIntersectionClasses(std::move(intersection), source_node); |  | ||||||
|         // maneuver.location = source_node.location;
 |  | ||||||
| 
 |  | ||||||
|         // PathData saves the information we need of the segment _before_ the turn,
 |         // PathData saves the information we need of the segment _before_ the turn,
 | ||||||
|         // but a RouteStep is with regard to the segment after the turn.
 |         // but a RouteStep is with regard to the segment after the turn.
 | ||||||
|         // We need to skip the first segment because it is already covered by the
 |         // We need to skip the first segment because it is already covered by the
 | ||||||
| @ -95,16 +96,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade, | |||||||
|                 BOOST_ASSERT(segment_duration >= 0); |                 BOOST_ASSERT(segment_duration >= 0); | ||||||
|                 const auto name = facade.GetNameForID(step_name_id); |                 const auto name = facade.GetNameForID(step_name_id); | ||||||
|                 const auto distance = leg_geometry.segment_distances[segment_index]; |                 const auto distance = leg_geometry.segment_distances[segment_index]; | ||||||
|                 std::vector<Intersection> intersections(1, intersection); | 
 | ||||||
|                 intersection = detail::intersectionFromGeometry( |  | ||||||
|                     WaypointType::None, segment_duration / 10., leg_geometry, segment_index); |  | ||||||
|                 intersection.entry_class = facade.GetEntryClass(path_point.entry_classid); |  | ||||||
|                 intersection.bearing_class = |  | ||||||
|                     facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node)); |  | ||||||
|                 steps.push_back(RouteStep{ |  | ||||||
|                     step_name_id, name, NO_ROTARY_NAME, segment_duration / 10.0, distance, |  | ||||||
|                     path_point.travel_mode, maneuver, leg_geometry.FrontIndex(segment_index), |  | ||||||
|                     leg_geometry.BackIndex(segment_index) + 1, std::move(intersections)}); |  | ||||||
|                 if (leg_data_index + 1 < leg_data.size()) |                 if (leg_data_index + 1 < leg_data.size()) | ||||||
|                 { |                 { | ||||||
|                     step_name_id = leg_data[leg_data_index + 1].name_id; |                     step_name_id = leg_data[leg_data_index + 1].name_id; | ||||||
| @ -113,7 +105,26 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade, | |||||||
|                 { |                 { | ||||||
|                     step_name_id = target_node.name_id; |                     step_name_id = target_node.name_id; | ||||||
|                 } |                 } | ||||||
|                 maneuver = {path_point.turn_instruction, WaypointType::None, 0}; |                 steps.push_back(RouteStep{ | ||||||
|  |                     step_name_id, name, NO_ROTARY_NAME, segment_duration / 10.0, distance, | ||||||
|  |                     path_point.travel_mode, maneuver, leg_geometry.FrontIndex(segment_index), | ||||||
|  |                     leg_geometry.BackIndex(segment_index) + 1, {intersection}}); | ||||||
|  | 
 | ||||||
|  |                 bearings = detail::getIntermediateBearings(leg_geometry, segment_index); | ||||||
|  |                 const auto entry_class = facade.GetEntryClass(path_point.entry_classid); | ||||||
|  |                 const auto bearing_class = facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node)); | ||||||
|  |                 intersection.in = bearing_class.findMatchingBearing(util::bearing::reverseBearing(bearings.first)); | ||||||
|  |                 intersection.out = bearing_class.findMatchingBearing(bearings.second); | ||||||
|  |                 intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node); | ||||||
|  |                 intersection.bearings.clear(); | ||||||
|  |                 std::copy(bearing_class.getAvailableBearings().begin(), bearing_class.getAvailableBearings().end(), | ||||||
|  |                           std::back_inserter(intersection.bearings)); | ||||||
|  |                 intersection.entry.clear(); | ||||||
|  |                 for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size())) | ||||||
|  |                 { | ||||||
|  |                     intersection.entry.push_back(entry_class.allowsEntry(idx)); | ||||||
|  |                 } | ||||||
|  |                 maneuver = {intersection.location, bearings.first, bearings.second, path_point.turn_instruction, WaypointType::None, 0}; | ||||||
|                 segment_index++; |                 segment_index++; | ||||||
|                 segment_duration = 0; |                 segment_duration = 0; | ||||||
|             } |             } | ||||||
| @ -124,7 +135,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade, | |||||||
|         steps.push_back(RouteStep{ |         steps.push_back(RouteStep{ | ||||||
|             step_name_id, facade.GetNameForID(step_name_id), NO_ROTARY_NAME, duration / 10., |             step_name_id, facade.GetNameForID(step_name_id), NO_ROTARY_NAME, duration / 10., | ||||||
|             distance, target_mode, maneuver, leg_geometry.FrontIndex(segment_index), |             distance, target_mode, maneuver, leg_geometry.FrontIndex(segment_index), | ||||||
|             leg_geometry.BackIndex(segment_index) + 1, std::vector<Intersection>(1, intersection)}); |             leg_geometry.BackIndex(segment_index) + 1, {intersection}}); | ||||||
|     } |     } | ||||||
|     // In this case the source + target are on the same edge segment
 |     // In this case the source + target are on the same edge segment
 | ||||||
|     else |     else | ||||||
| @ -135,38 +146,42 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade, | |||||||
|         // |---| source_duration
 |         // |---| source_duration
 | ||||||
|         // |---------| target_duration
 |         // |---------| target_duration
 | ||||||
| 
 | 
 | ||||||
|         StepManeuver maneuver = {extractor::guidance::TurnInstruction::NO_TURN(), |  | ||||||
|                                  WaypointType::Depart, 0}; |  | ||||||
|         int duration = target_duration - source_duration; |         int duration = target_duration - source_duration; | ||||||
|         BOOST_ASSERT(duration >= 0); |         BOOST_ASSERT(duration >= 0); | ||||||
| 
 | 
 | ||||||
|         auto intersection = detail::intersectionFromGeometry(WaypointType::Depart, duration / 10., |  | ||||||
|                                                              leg_geometry, segment_index); |  | ||||||
|         intersection = util::guidance::setIntersectionClasses(std::move(intersection), source_node); |  | ||||||
| 
 |  | ||||||
|         steps.push_back(RouteStep{ |         steps.push_back(RouteStep{ | ||||||
|             source_node.name_id, facade.GetNameForID(source_node.name_id), NO_ROTARY_NAME, |             source_node.name_id, facade.GetNameForID(source_node.name_id), NO_ROTARY_NAME, | ||||||
|             duration / 10., leg_geometry.segment_distances[segment_index], source_mode, |             duration / 10., leg_geometry.segment_distances[segment_index], source_mode, | ||||||
|             std::move(maneuver), leg_geometry.FrontIndex(segment_index), |             std::move(maneuver), leg_geometry.FrontIndex(segment_index), | ||||||
|             leg_geometry.BackIndex(segment_index) + 1, std::vector<Intersection>(1, intersection)}); |             leg_geometry.BackIndex(segment_index) + 1, {intersection}}); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     BOOST_ASSERT(segment_index == number_of_segments - 1); |     BOOST_ASSERT(segment_index == number_of_segments - 1); | ||||||
|  |     bearings = detail::getArriveBearings(leg_geometry); | ||||||
|     // This step has length zero, the only reason we need it is the target location
 |     // This step has length zero, the only reason we need it is the target location
 | ||||||
|     StepManeuver final_maneuver = {extractor::guidance::TurnInstruction::NO_TURN(), |     maneuver = {intersection.location, bearings.first, bearings.second, extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, 0}; | ||||||
|                                    WaypointType::Arrive, 0}; |     intersection = { | ||||||
| 
 |         target_node.location, | ||||||
|     auto intersection = |         std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}), | ||||||
|         detail::intersectionFromGeometry(WaypointType::Arrive, 0, leg_geometry, segment_index); |         std::vector<bool>({true}), 0, Intersection::NO_INDEX}; | ||||||
|     intersection = util::guidance::setIntersectionClasses(std::move(intersection), target_node); |  | ||||||
| 
 | 
 | ||||||
|     BOOST_ASSERT(!leg_geometry.locations.empty()); |     BOOST_ASSERT(!leg_geometry.locations.empty()); | ||||||
|     steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id), |     steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id), | ||||||
|                               NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, target_mode, |                               NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, target_mode, | ||||||
|                               std::move(final_maneuver), leg_geometry.locations.size() - 1, |                               std::move(maneuver), leg_geometry.locations.size() - 1, | ||||||
|                               leg_geometry.locations.size(), |                               leg_geometry.locations.size(), | ||||||
|                               std::vector<Intersection>(1, intersection)}); |                               {intersection}}); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart); | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive); | ||||||
|     return steps; |     return steps; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -28,24 +28,21 @@ namespace guidance | |||||||
| // A represenetation of intermediate intersections
 | // A represenetation of intermediate intersections
 | ||||||
| struct Intersection | struct Intersection | ||||||
| { | { | ||||||
|     double duration; |     static const constexpr std::size_t NO_INDEX = std::numeric_limits<std::size_t>::max(); | ||||||
|     double distance; |  | ||||||
|     util::Coordinate location; |     util::Coordinate location; | ||||||
|     double bearing_before; |     std::vector<short> bearings; | ||||||
|     double bearing_after; |     std::vector<bool> entry; | ||||||
|     util::guidance::EntryClass entry_class; |     std::size_t in; | ||||||
|     util::guidance::BearingClass bearing_class; |     std::size_t out; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| inline Intersection getInvalidIntersection() | inline Intersection getInvalidIntersection() | ||||||
| { | { | ||||||
|     return {0, |     return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}}, | ||||||
|             0, |         {}, | ||||||
|             util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}}, |         {}, | ||||||
|             0, |         Intersection::NO_INDEX, | ||||||
|             0, |         Intersection::NO_INDEX}; | ||||||
|             util::guidance::EntryClass(), |  | ||||||
|             util::guidance::BearingClass()}; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct RouteStep | struct RouteStep | ||||||
| @ -74,7 +71,7 @@ inline RouteStep getInvalidRouteStep() | |||||||
|             getInvalidStepManeuver(), |             getInvalidStepManeuver(), | ||||||
|             0, |             0, | ||||||
|             0, |             0, | ||||||
|             std::vector<Intersection>(1, getInvalidIntersection())}; |             {getInvalidIntersection()}}; | ||||||
| } | } | ||||||
| } | } | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,6 +23,9 @@ enum class WaypointType : std::uint8_t | |||||||
| 
 | 
 | ||||||
| struct StepManeuver | struct StepManeuver | ||||||
| { | { | ||||||
|  |     util::Coordinate location; | ||||||
|  |     short bearing_before; | ||||||
|  |     short bearing_after; | ||||||
|     extractor::guidance::TurnInstruction instruction; |     extractor::guidance::TurnInstruction instruction; | ||||||
|     WaypointType waypoint_type; |     WaypointType waypoint_type; | ||||||
|     unsigned exit; |     unsigned exit; | ||||||
| @ -30,7 +33,12 @@ struct StepManeuver | |||||||
| 
 | 
 | ||||||
| inline StepManeuver getInvalidStepManeuver() | inline StepManeuver getInvalidStepManeuver() | ||||||
| { | { | ||||||
|     return {extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::None, 0}; |     return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}}, | ||||||
|  |             0, | ||||||
|  |             0, | ||||||
|  |             extractor::guidance::TurnInstruction::NO_TURN(), | ||||||
|  |             WaypointType::None, | ||||||
|  |             0}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace guidance
 | } // namespace guidance
 | ||||||
|  | |||||||
| @ -89,6 +89,14 @@ inline bool CheckInBounds(const int A, const int B, const int range) | |||||||
|         return normalized_B - range <= normalized_A && normalized_A <= normalized_B + range; |         return normalized_B - range <= normalized_A && normalized_A <= normalized_B + range; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | inline double reverseBearing(const double bearing) | ||||||
|  | { | ||||||
|  |     if (bearing >= 180) | ||||||
|  |         return bearing - 180.; | ||||||
|  |     return bearing + 180; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| } | } | ||||||
| } | } | ||||||
|  | |||||||
| @ -49,36 +49,6 @@ inline extractor::guidance::DirectionModifier getTurnDirection(const double angl | |||||||
|     return extractor::guidance::DirectionModifier::UTurn; |     return extractor::guidance::DirectionModifier::UTurn; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline engine::guidance::Intersection |  | ||||||
| setIntersectionClasses(engine::guidance::Intersection intersection, |  | ||||||
|                        const engine::PhantomNode &phantom) |  | ||||||
| { |  | ||||||
|     BOOST_ASSERT(intersection.bearing_before == 0 || intersection.bearing_after == 0); |  | ||||||
|     const double bearing = std::max(intersection.bearing_before, intersection.bearing_after); |  | ||||||
| 
 |  | ||||||
|     intersection.bearing_class = {}; |  | ||||||
|     intersection.entry_class = {}; |  | ||||||
|     if (bearing >= 180.) |  | ||||||
|     { |  | ||||||
|         intersection.bearing_class.add(std::round(bearing - 180.)); |  | ||||||
|         if (phantom.forward_segment_id.id != SPECIAL_SEGMENTID && |  | ||||||
|             phantom.reverse_segment_id.id != SPECIAL_SEGMENTID) |  | ||||||
|             intersection.entry_class.activate(0); |  | ||||||
|         intersection.bearing_class.add(std::round(bearing)); |  | ||||||
|         intersection.entry_class.activate(1); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         intersection.bearing_class.add(std::round(bearing)); |  | ||||||
|         intersection.entry_class.activate(0); |  | ||||||
|         intersection.bearing_class.add(std::round(bearing + 180.)); |  | ||||||
|         if (phantom.forward_segment_id.id != SPECIAL_SEGMENTID && |  | ||||||
|             phantom.reverse_segment_id.id != SPECIAL_SEGMENTID) |  | ||||||
|             intersection.entry_class.activate(1); |  | ||||||
|     } |  | ||||||
|     return intersection; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace guidance
 | } // namespace guidance
 | ||||||
| } // namespace util
 | } // namespace util
 | ||||||
| } // namespace osrm
 | } // namespace osrm
 | ||||||
|  | |||||||
| @ -78,63 +78,6 @@ util::json::Array coordinateToLonLat(const util::Coordinate coordinate) | |||||||
|     return array; |     return array; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| util::json::Object |  | ||||||
| getIntersection(const guidance::Intersection &intersection, bool locate_before, bool locate_after) |  | ||||||
| { |  | ||||||
|     util::json::Object result; |  | ||||||
|     util::json::Array bearings; |  | ||||||
|     util::json::Array entry; |  | ||||||
| 
 |  | ||||||
|     const auto &available_bearings = intersection.bearing_class.getAvailableBearings(); |  | ||||||
|     for (std::size_t i = 0; i < available_bearings.size(); ++i) |  | ||||||
|     { |  | ||||||
|         bearings.values.push_back(available_bearings[i]); |  | ||||||
|         entry.values.push_back(intersection.entry_class.allowsEntry(i) ? "true" : "false"); |  | ||||||
|     } |  | ||||||
|     result.values["location"] = detail::coordinateToLonLat(intersection.location); |  | ||||||
| 
 |  | ||||||
|     if (locate_before) |  | ||||||
|     { |  | ||||||
|         // bearings are oriented in the direction of driving. For the in-bearing, we actually need
 |  | ||||||
|         // to
 |  | ||||||
|         // find the bearing from the view of the intersection. This means we have to rotate the
 |  | ||||||
|         // bearing
 |  | ||||||
|         // by 180 degree.
 |  | ||||||
|         const auto rotated_bearing_before = (intersection.bearing_before >= 180.0) |  | ||||||
|                                                 ? (intersection.bearing_before - 180.0) |  | ||||||
|                                                 : (intersection.bearing_before + 180.0); |  | ||||||
|         result.values["in"] = |  | ||||||
|             intersection.bearing_class.findMatchingBearing(rotated_bearing_before); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (locate_after) |  | ||||||
|     { |  | ||||||
|         result.values["out"] = |  | ||||||
|             intersection.bearing_class.findMatchingBearing(intersection.bearing_after); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     result.values["bearings"] = bearings; |  | ||||||
|     result.values["entry"] = entry; |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| util::json::Array getIntersection(const guidance::RouteStep &step) |  | ||||||
| { |  | ||||||
|     util::json::Array result; |  | ||||||
|     bool first = true; |  | ||||||
|     for (const auto &intersection : step.intersections) |  | ||||||
|     { |  | ||||||
|         // on waypoints, the first/second bearing is invalid. In these cases, we cannot locate the
 |  | ||||||
|         // bearing as part of the available bearings at the intersection.
 |  | ||||||
|         result.values.push_back(getIntersection( |  | ||||||
|             intersection, !first || step.maneuver.waypoint_type != guidance::WaypointType::Depart, |  | ||||||
|             !first || step.maneuver.waypoint_type != guidance::WaypointType::Arrive)); |  | ||||||
|         first = false; |  | ||||||
|     } |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // FIXME this actually needs to be configurable from the profiles
 | // FIXME this actually needs to be configurable from the profiles
 | ||||||
| std::string modeToString(const extractor::TravelMode mode) | std::string modeToString(const extractor::TravelMode mode) | ||||||
| { | { | ||||||
| @ -198,12 +141,46 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver) | |||||||
|         step_maneuver.values["modifier"] = |         step_maneuver.values["modifier"] = | ||||||
|             detail::instructionModifierToString(maneuver.instruction.direction_modifier); |             detail::instructionModifierToString(maneuver.instruction.direction_modifier); | ||||||
| 
 | 
 | ||||||
|  |     step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location); | ||||||
|  |     step_maneuver.values["bearing_before"] = std::round(maneuver.bearing_before); | ||||||
|  |     step_maneuver.values["bearing_after"] = std::round(maneuver.bearing_after); | ||||||
|     if (maneuver.exit != 0) |     if (maneuver.exit != 0) | ||||||
|         step_maneuver.values["exit"] = maneuver.exit; |         step_maneuver.values["exit"] = maneuver.exit; | ||||||
| 
 | 
 | ||||||
|     return step_maneuver; |     return step_maneuver; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | util::json::Object | ||||||
|  | makeIntersection(const guidance::Intersection &intersection) | ||||||
|  | { | ||||||
|  |     util::json::Object result; | ||||||
|  |     util::json::Array bearings; | ||||||
|  |     util::json::Array entry; | ||||||
|  | 
 | ||||||
|  |     bearings.values.reserve(intersection.bearings.size()); | ||||||
|  |     std::copy(intersection.bearings.begin(), intersection.bearings.end(), std::back_inserter(bearings.values)); | ||||||
|  | 
 | ||||||
|  |     entry.values.reserve(intersection.entry.size()); | ||||||
|  |     std::transform(intersection.entry.begin(), intersection.entry.end(), | ||||||
|  |                    std::back_inserter(entry.values), [](const bool has_entry) -> util::json::Value | ||||||
|  |                    { | ||||||
|  |                        if (has_entry) | ||||||
|  |                            return util::json::True(); | ||||||
|  |                        else | ||||||
|  |                            return util::json::False(); | ||||||
|  |                    }); | ||||||
|  | 
 | ||||||
|  |     result.values["location"] = detail::coordinateToLonLat(intersection.location); | ||||||
|  |     result.values["bearings"] = bearings; | ||||||
|  |     result.values["entry"] = entry; | ||||||
|  |     if (intersection.in != guidance::Intersection::NO_INDEX) | ||||||
|  |         result.values["in"] = intersection.in; | ||||||
|  |     if (intersection.out != guidance::Intersection::NO_INDEX) | ||||||
|  |         result.values["out"] = intersection.out; | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geometry) | util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geometry) | ||||||
| { | { | ||||||
|     util::json::Object route_step; |     util::json::Object route_step; | ||||||
| @ -216,7 +193,13 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo | |||||||
|     route_step.values["mode"] = detail::modeToString(std::move(step.mode)); |     route_step.values["mode"] = detail::modeToString(std::move(step.mode)); | ||||||
|     route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver)); |     route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver)); | ||||||
|     route_step.values["geometry"] = std::move(geometry); |     route_step.values["geometry"] = std::move(geometry); | ||||||
|     route_step.values["intersections"] = detail::getIntersection(step); | 
 | ||||||
|  |     util::json::Array intersections; | ||||||
|  |     intersections.values.reserve(step.intersections.size()); | ||||||
|  |     std::transform(step.intersections.begin(), step.intersections.end(), | ||||||
|  |                    std::back_inserter(intersections.values), makeIntersection); | ||||||
|  |     route_step.values["intersections"] = std::move(intersections); | ||||||
|  | 
 | ||||||
|     return route_step; |     return route_step; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -13,10 +13,7 @@ namespace guidance | |||||||
| { | { | ||||||
| namespace detail | namespace detail | ||||||
| { | { | ||||||
| namespace | std::pair<short, short> getIntermediateBearings(const LegGeometry &leg_geometry, | ||||||
| { |  | ||||||
| void fillInIntermediate(Intersection &intersection, |  | ||||||
|                         const LegGeometry &leg_geometry, |  | ||||||
|                                                 const std::size_t segment_index) |                                                 const std::size_t segment_index) | ||||||
| { | { | ||||||
|     auto turn_index = leg_geometry.BackIndex(segment_index); |     auto turn_index = leg_geometry.BackIndex(segment_index); | ||||||
| @ -28,58 +25,27 @@ void fillInIntermediate(Intersection &intersection, | |||||||
|     const auto turn_coordinate = leg_geometry.locations[turn_index]; |     const auto turn_coordinate = leg_geometry.locations[turn_index]; | ||||||
|     const auto post_turn_coordinate = leg_geometry.locations[turn_index + 1]; |     const auto post_turn_coordinate = leg_geometry.locations[turn_index + 1]; | ||||||
| 
 | 
 | ||||||
|     intersection.bearing_before = |     return std::make_pair<short, short>( | ||||||
|         util::coordinate_calculation::bearing(pre_turn_coordinate, turn_coordinate); |         std::round(util::coordinate_calculation::bearing(pre_turn_coordinate, turn_coordinate)), | ||||||
|     intersection.bearing_after = |         std::round(util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate))); | ||||||
|         util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate); |  | ||||||
| 
 |  | ||||||
|     intersection.location = turn_coordinate; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void fillInDepart(Intersection &intersection, const LegGeometry &leg_geometry) | std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry) | ||||||
| { | { | ||||||
|     BOOST_ASSERT(leg_geometry.locations.size() >= 2); |     BOOST_ASSERT(leg_geometry.locations.size() >= 2); | ||||||
|     const auto turn_coordinate = leg_geometry.locations.front(); |     const auto turn_coordinate = leg_geometry.locations.front(); | ||||||
|     const auto post_turn_coordinate = *(leg_geometry.locations.begin() + 1); |     const auto post_turn_coordinate = *(leg_geometry.locations.begin() + 1); | ||||||
|     intersection.location = turn_coordinate; |     return std::make_pair<short, short>( | ||||||
|     intersection.bearing_before = 0; |         0, std::round(util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate))); | ||||||
|     intersection.bearing_after = |  | ||||||
|         util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void fillInArrive(Intersection &intersection, const LegGeometry &leg_geometry) | std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry) | ||||||
| { | { | ||||||
|     BOOST_ASSERT(leg_geometry.locations.size() >= 2); |     BOOST_ASSERT(leg_geometry.locations.size() >= 2); | ||||||
|     const auto turn_coordinate = leg_geometry.locations.back(); |     const auto turn_coordinate = leg_geometry.locations.back(); | ||||||
|     const auto pre_turn_coordinate = *(leg_geometry.locations.end() - 2); |     const auto pre_turn_coordinate = *(leg_geometry.locations.end() - 2); | ||||||
|     intersection.location = turn_coordinate; |     return std::make_pair<short, short>( | ||||||
|     intersection.bearing_before = |         std::round(util::coordinate_calculation::bearing(pre_turn_coordinate, turn_coordinate)), 0); | ||||||
|         util::coordinate_calculation::bearing(pre_turn_coordinate, turn_coordinate); |  | ||||||
|     intersection.bearing_after = 0; |  | ||||||
| } |  | ||||||
| } // namespace
 |  | ||||||
| 
 |  | ||||||
| Intersection intersectionFromGeometry(const WaypointType waypoint_type, |  | ||||||
|                                       const double segment_duration, |  | ||||||
|                                       const LegGeometry &leg_geometry, |  | ||||||
|                                       const std::size_t segment_index) |  | ||||||
| { |  | ||||||
|     Intersection intersection; |  | ||||||
|     intersection.duration = segment_duration; |  | ||||||
|     intersection.distance = leg_geometry.segment_distances[segment_index]; |  | ||||||
|     switch (waypoint_type) |  | ||||||
|     { |  | ||||||
|     case WaypointType::None: |  | ||||||
|         fillInIntermediate(intersection, leg_geometry, segment_index); |  | ||||||
|         break; |  | ||||||
|     case WaypointType::Depart: |  | ||||||
|         fillInDepart(intersection, leg_geometry); |  | ||||||
|         break; |  | ||||||
|     case WaypointType::Arrive: |  | ||||||
|         fillInArrive(intersection, leg_geometry); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     return intersection; |  | ||||||
| } | } | ||||||
| } // ns detail
 | } // ns detail
 | ||||||
| } // ns engine
 | } // ns engine
 | ||||||
|  | |||||||
| @ -54,11 +54,12 @@ void print(const std::vector<RouteStep> &steps) | |||||||
| 
 | 
 | ||||||
|         for (const auto &intersection : step.intersections) |         for (const auto &intersection : step.intersections) | ||||||
|         { |         { | ||||||
|             std::cout << "(" << intersection.duration << " " << intersection.distance << " " |             std::cout << "(bearings:"; | ||||||
|                       << " Bearings: " << intersection.bearing_before << " " |             for( auto bearing : intersection.bearings) | ||||||
|                       << intersection.bearing_after << " -- "; |  | ||||||
|             for( auto bearing : intersection.bearing_class.getAvailableBearings() ) |  | ||||||
|                 std:: cout << " " << bearing; |                 std:: cout << " " << bearing; | ||||||
|  |             std::cout << ", entry: "; | ||||||
|  |             for( auto entry : intersection.entry) | ||||||
|  |                 std:: cout << " " << entry; | ||||||
|             std::cout << ")"; |             std::cout << ")"; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -86,6 +87,7 @@ RouteStep forwardInto(RouteStep destination, const RouteStep &source) | |||||||
| 
 | 
 | ||||||
|     destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin); |     destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin); | ||||||
|     destination.geometry_end = std::max(destination.geometry_end, source.geometry_end); |     destination.geometry_end = std::max(destination.geometry_end, source.geometry_end); | ||||||
|  |     destination.maneuver.exit = destination.intersections.size() - 1; | ||||||
| 
 | 
 | ||||||
|     return destination; |     return destination; | ||||||
| } | } | ||||||
| @ -205,7 +207,8 @@ void closeOffRoundabout(const bool on_roundabout, | |||||||
|     // removal.
 |     // removal.
 | ||||||
|     std::vector<std::size_t> intermediate_steps; |     std::vector<std::size_t> intermediate_steps; | ||||||
|     BOOST_ASSERT(!steps[step_index].intersections.empty()); |     BOOST_ASSERT(!steps[step_index].intersections.empty()); | ||||||
|     const auto exit_bearing = steps[step_index].intersections.back().bearing_after; |     const auto exit_intersection = steps[step_index].intersections.back(); | ||||||
|  |     const auto exit_bearing = exit_intersection.bearings[exit_intersection.out]; | ||||||
|     if (step_index > 1) |     if (step_index > 1) | ||||||
|     { |     { | ||||||
|         // The very first route-step is head, so we cannot iterate past that one
 |         // The very first route-step is head, so we cannot iterate past that one
 | ||||||
| @ -218,6 +221,7 @@ void closeOffRoundabout(const bool on_roundabout, | |||||||
|             { |             { | ||||||
|                 propagation_step.maneuver.exit = step.maneuver.exit; |                 propagation_step.maneuver.exit = step.maneuver.exit; | ||||||
|                 propagation_step.geometry_end = step.geometry_end; |                 propagation_step.geometry_end = step.geometry_end; | ||||||
|  |                 const auto entry_intersection = propagation_step.intersections.front(); | ||||||
| 
 | 
 | ||||||
|                 // remember rotary name
 |                 // remember rotary name
 | ||||||
|                 if (propagation_step.maneuver.instruction.type == TurnType::EnterRotary || |                 if (propagation_step.maneuver.instruction.type == TurnType::EnterRotary || | ||||||
| @ -259,7 +263,7 @@ void closeOffRoundabout(const bool on_roundabout, | |||||||
| 
 | 
 | ||||||
|                         const auto angle = 540 - rotated_exit; |                         const auto angle = 540 - rotated_exit; | ||||||
|                         return angle > 360 ? angle - 360 : angle; |                         return angle > 360 ? angle - 360 : angle; | ||||||
|                     }(propagation_step.intersections.front().bearing_before, exit_bearing); |                     }(util::bearing::reverseBearing(entry_intersection.bearings[entry_intersection.in]), exit_bearing); | ||||||
| 
 | 
 | ||||||
|                     propagation_step.maneuver.instruction.direction_modifier = |                     propagation_step.maneuver.instruction.direction_modifier = | ||||||
|                         ::osrm::util::guidance::getTurnDirection(angle); |                         ::osrm::util::guidance::getTurnDirection(angle); | ||||||
| @ -376,8 +380,8 @@ void collapseTurnAt(std::vector<RouteStep> &steps, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     // Potential U-Turn
 |     // Potential U-Turn
 | ||||||
|     else if (bearingsAreReversed(one_back_step.intersections.front().bearing_before, |     else if (bearingsAreReversed(util::bearing::reverseBearing(one_back_step.intersections.front().bearings[one_back_step.intersections.front().in]), | ||||||
|                                  current_step.intersections.front().bearing_after)) |                                  current_step.intersections.front().bearings[current_step.intersections.front().out])) | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|         BOOST_ASSERT(two_back_index < steps.size()); |         BOOST_ASSERT(two_back_index < steps.size()); | ||||||
| @ -433,6 +437,17 @@ std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps) | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     boost::remove_erase_if(steps, not_is_valid); |     boost::remove_erase_if(steps, not_is_valid); | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.size() >= 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart); | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive); | ||||||
|  | 
 | ||||||
|     return steps; |     return steps; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -442,7 +457,6 @@ std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps) | |||||||
| // They are required for maintenance purposes. We can calculate the number
 | // They are required for maintenance purposes. We can calculate the number
 | ||||||
| // of exits to pass in a roundabout and the number of intersections
 | // of exits to pass in a roundabout and the number of intersections
 | ||||||
| // that we come across.
 | // that we come across.
 | ||||||
| 
 |  | ||||||
| std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | ||||||
| { | { | ||||||
|     // the steps should always include the first/last step in form of a location
 |     // the steps should always include the first/last step in form of a location
 | ||||||
| @ -507,6 +521,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | |||||||
|             last_valid_instruction = step_index; |             last_valid_instruction = step_index; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     // unterminated roundabout
 |     // unterminated roundabout
 | ||||||
|     // Move backwards through the instructions until the start and remove the exit number
 |     // Move backwards through the instructions until the start and remove the exit number
 | ||||||
|     // A roundabout without exit translates to enter-roundabout.
 |     // A roundabout without exit translates to enter-roundabout.
 | ||||||
| @ -515,6 +530,16 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | |||||||
|         fixFinalRoundabout(steps); |         fixFinalRoundabout(steps); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.size() >= 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart); | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive); | ||||||
|  | 
 | ||||||
|     return removeNoTurnInstructions(std::move(steps)); |     return removeNoTurnInstructions(std::move(steps)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -603,18 +628,29 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps) | |||||||
|             collapseTurnAt(steps, two_back_index, one_back_index, step_index); |             collapseTurnAt(steps, two_back_index, one_back_index, step_index); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.size() >= 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart); | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive); | ||||||
|  | 
 | ||||||
|     return removeNoTurnInstructions(std::move(steps)); |     return removeNoTurnInstructions(std::move(steps)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // 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. In addition, we cannot reduce the travel time that is accumulated at a
 | ||||||
|  | // different location.
 | ||||||
|  | // As a direct implication, we have to keep the time of the initial/final turns (which adds a
 | ||||||
|  | // few seconds of inaccuracy at both ends. This is acceptable, however, since the turn should
 | ||||||
|  | // usually not be as relevant.
 | ||||||
| void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | ||||||
| { | { | ||||||
|     // 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. In addition, we cannot reduce the travel time that is accumulated at a
 |  | ||||||
|     // different location.
 |  | ||||||
|     // As a direct implication, we have to keep the time of the initial/final turns (which adds a
 |  | ||||||
|     // few seconds of inaccuracy at both ends. This is acceptable, however, since the turn should
 |  | ||||||
|     // usually not be as relevant.
 |  | ||||||
| 
 | 
 | ||||||
|     if (steps.size() < 2 || geometry.locations.size() <= 2) |     if (steps.size() < 2 || geometry.locations.size() <= 2) | ||||||
|         return; |         return; | ||||||
| @ -669,20 +705,29 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | |||||||
| 
 | 
 | ||||||
|             // update initial turn direction/bearings. Due to the duplicated first coordinate,
 |             // update initial turn direction/bearings. Due to the duplicated first coordinate,
 | ||||||
|             // the initial bearing is invalid
 |             // the initial bearing is invalid
 | ||||||
|             designated_depart.maneuver = {TurnInstruction::NO_TURN(), WaypointType::Depart, 0}; |             designated_depart.maneuver.waypoint_type = WaypointType::Depart; | ||||||
|  |             designated_depart.maneuver.bearing_before = 0; | ||||||
|  |             designated_depart.maneuver.instruction = TurnInstruction::NO_TURN(); | ||||||
|  |             // we need to make this conform with the intersection format for the first intersection
 | ||||||
|  |             auto& first_intersection = designated_depart.intersections.front(); | ||||||
|  |             first_intersection.bearings = {first_intersection.bearings[first_intersection.out]}; | ||||||
|  |             first_intersection.entry = {true}; | ||||||
|  |             first_intersection.in = Intersection::NO_INDEX; | ||||||
|  |             first_intersection.out = 0; | ||||||
| 
 | 
 | ||||||
|             // finally remove the initial (now duplicated move)
 |             // finally remove the initial (now duplicated move)
 | ||||||
|             steps.erase(steps.begin()); |             steps.erase(steps.begin()); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|  |             // we need to make this at least 1 because we will substract 1
 | ||||||
|  |             // from all offsets at the end of the loop.
 | ||||||
|             steps.front().geometry_begin = 1; |             steps.front().geometry_begin = 1; | ||||||
|  | 
 | ||||||
|             // reduce all offsets by one (inplace)
 |             // reduce all offsets by one (inplace)
 | ||||||
|             std::transform(geometry.segment_offsets.begin(), geometry.segment_offsets.end(), |             std::transform(geometry.segment_offsets.begin(), geometry.segment_offsets.end(), | ||||||
|                            geometry.segment_offsets.begin(), |                            geometry.segment_offsets.begin(), | ||||||
|                            [](const std::size_t val) { return val - 1; }); |                            [](const std::size_t val) { return val - 1; }); | ||||||
| 
 |  | ||||||
|             steps.front().maneuver = {TurnInstruction::NO_TURN(), WaypointType::Depart, 0}; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // and update the leg geometry indices for the removed entry
 |         // and update the leg geometry indices for the removed entry
 | ||||||
| @ -690,12 +735,32 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | |||||||
|             --step.geometry_begin; |             --step.geometry_begin; | ||||||
|             --step.geometry_end; |             --step.geometry_end; | ||||||
|         }); |         }); | ||||||
|  | 
 | ||||||
|  |         auto& first_step = steps.front(); | ||||||
|  |         // we changed the geometry, we need to recalculate the bearing
 | ||||||
|  |         auto bearing = std::round(util::coordinate_calculation::bearing( | ||||||
|  |             geometry.locations[first_step.geometry_begin], | ||||||
|  |             geometry.locations[first_step.geometry_begin+1])); | ||||||
|  |         std::cout << geometry.locations[first_step.geometry_begin] << geometry.locations[first_step.geometry_begin+1] << std::endl; | ||||||
|  |         first_step.maneuver.bearing_after = bearing; | ||||||
|  |         first_step.intersections.front().bearings.front() = bearing; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.size() >= 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart); | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive); | ||||||
|  | 
 | ||||||
|     // make sure we still have enough segments
 |     // make sure we still have enough segments
 | ||||||
|     if (steps.size() < 2 || geometry.locations.size() == 2) |     if (steps.size() < 2 || geometry.locations.size() == 2) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     BOOST_ASSERT(geometry.locations.size() >= steps.size()); |     BOOST_ASSERT(geometry.locations.size() >= steps.size()); | ||||||
|     auto &next_to_last_step = *(steps.end() - 2); |     auto &next_to_last_step = *(steps.end() - 2); | ||||||
|     // in the end, the situation with the roundabout cannot occur. As a result, we can remove
 |     // in the end, the situation with the roundabout cannot occur. As a result, we can remove
 | ||||||
| @ -708,9 +773,15 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | |||||||
|         BOOST_ASSERT(geometry.segment_distances.back() < 1); |         BOOST_ASSERT(geometry.segment_distances.back() < 1); | ||||||
|         geometry.segment_distances.pop_back(); |         geometry.segment_distances.pop_back(); | ||||||
| 
 | 
 | ||||||
|         next_to_last_step.maneuver = {TurnInstruction::NO_TURN(), WaypointType::Arrive, 0}; |         next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive; | ||||||
|         BOOST_ASSERT(!next_to_last_step.intersections.empty()); |         next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN(); | ||||||
|         next_to_last_step.intersections.front().bearing_after = 0; |         next_to_last_step.maneuver.bearing_after = 0; | ||||||
|  |         BOOST_ASSERT(next_to_last_step.intersections.size() == 1); | ||||||
|  |         auto& last_intersection = next_to_last_step.intersections.back(); | ||||||
|  |         last_intersection.bearings = {last_intersection.bearings[last_intersection.in]}; | ||||||
|  |         last_intersection.entry = {true}; | ||||||
|  |         last_intersection.out = Intersection::NO_INDEX; | ||||||
|  |         last_intersection.in = 0; | ||||||
|         steps.pop_back(); |         steps.pop_back(); | ||||||
| 
 | 
 | ||||||
|         // Because we eliminated a really short segment, it was probably
 |         // Because we eliminated a really short segment, it was probably
 | ||||||
| @ -738,10 +809,29 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry) | |||||||
|         BOOST_ASSERT(next_to_last_step.geometry_end == steps.back().geometry_begin + 1); |         BOOST_ASSERT(next_to_last_step.geometry_end == steps.back().geometry_begin + 1); | ||||||
|         BOOST_ASSERT(next_to_last_step.geometry_begin < next_to_last_step.geometry_end); |         BOOST_ASSERT(next_to_last_step.geometry_begin < next_to_last_step.geometry_end); | ||||||
|         next_to_last_step.geometry_end--; |         next_to_last_step.geometry_end--; | ||||||
|         steps.back().geometry_begin--; |         auto& last_step = steps.back(); | ||||||
|         steps.back().geometry_end--; |         last_step.geometry_begin--; | ||||||
|         steps.back().maneuver = {TurnInstruction::NO_TURN(), WaypointType::Arrive, 0}; |         last_step.geometry_end--; | ||||||
|  |         BOOST_ASSERT(next_to_last_step.geometry_end == last_step.geometry_begin + 1); | ||||||
|  |         BOOST_ASSERT(last_step.geometry_begin == last_step.geometry_end-1); | ||||||
|  |         BOOST_ASSERT(next_to_last_step.geometry_end >= 2); | ||||||
|  |         // we changed the geometry, we need to recalculate the bearing
 | ||||||
|  |         auto bearing = std::round(util::coordinate_calculation::bearing( | ||||||
|  |             geometry.locations[next_to_last_step.geometry_end - 2], | ||||||
|  |             geometry.locations[last_step.geometry_begin])); | ||||||
|  |         last_step.maneuver.bearing_before = bearing; | ||||||
|  |         last_step.intersections.front().bearings.front() = util::bearing::reverseBearing(bearing); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.size() >= 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart); | ||||||
|  | 
 | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // assign relative locations to depart/arrive instructions
 | // assign relative locations to depart/arrive instructions
 | ||||||
| @ -765,12 +855,6 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps, | |||||||
|             : extractor::guidance::DirectionModifier::UTurn; |             : extractor::guidance::DirectionModifier::UTurn; | ||||||
| 
 | 
 | ||||||
|     steps.front().maneuver.instruction.direction_modifier = initial_modifier; |     steps.front().maneuver.instruction.direction_modifier = initial_modifier; | ||||||
|     BOOST_ASSERT(!steps.front().intersections.empty()); |  | ||||||
|     steps.front().intersections.front().bearing_before = 0; |  | ||||||
|     steps.front().intersections.front().bearing_after = |  | ||||||
|         util::coordinate_calculation::bearing(leg_geometry.locations[0], leg_geometry.locations[1]); |  | ||||||
|     steps.front().intersections.front() = util::guidance::setIntersectionClasses( |  | ||||||
|         std::move(steps.front().intersections.front()), source_node); |  | ||||||
| 
 | 
 | ||||||
|     const auto distance_from_end = util::coordinate_calculation::haversineDistance( |     const auto distance_from_end = util::coordinate_calculation::haversineDistance( | ||||||
|         target_node.input_location, leg_geometry.locations.back()); |         target_node.input_location, leg_geometry.locations.back()); | ||||||
| @ -784,15 +868,16 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps, | |||||||
|             : extractor::guidance::DirectionModifier::UTurn; |             : extractor::guidance::DirectionModifier::UTurn; | ||||||
| 
 | 
 | ||||||
|     steps.back().maneuver.instruction.direction_modifier = final_modifier; |     steps.back().maneuver.instruction.direction_modifier = final_modifier; | ||||||
|     BOOST_ASSERT(steps.back().intersections.size() == 1); |  | ||||||
| 
 | 
 | ||||||
|     BOOST_ASSERT(!steps.back().intersections.empty()); |     BOOST_ASSERT(steps.front().intersections.size() >= 1); | ||||||
|     steps.back().intersections.front().bearing_before = util::coordinate_calculation::bearing( |     BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1); | ||||||
|         leg_geometry.locations[leg_geometry.locations.size() - 2], |     BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1); | ||||||
|         leg_geometry.locations[leg_geometry.locations.size() - 1]); |     BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart); | ||||||
|     steps.back().intersections.front().bearing_after = 0; | 
 | ||||||
|     steps.back().intersections.front() = util::guidance::setIntersectionClasses( |     BOOST_ASSERT(steps.back().intersections.size() == 1); | ||||||
|         std::move(steps.back().intersections.front()), target_node); |     BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1); | ||||||
|  |     BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive); | ||||||
|     return steps; |     return steps; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user