void ApiResponseGenerator<DataFacadeT>::DescribeRoute(const RouteParameters &config, const InternalRouteResult &raw_route, util::json::Object &json_result) { if (!raw_route.is_valid()) { return; } const constexpr bool ALLOW_SIMPLIFICATION = true; const constexpr bool EXTRACT_ROUTE = false; const constexpr bool EXTRACT_ALTERNATIVE = true; Segments segment_list(raw_route, EXTRACT_ROUTE, config.zoom_level, ALLOW_SIMPLIFICATION, facade); json_result.values["route_summary"] = SummarizeRoute(raw_route, segment_list); json_result.values["via_points"] = ListViaPoints(raw_route); json_result.values["via_indices"] = ListViaIndices(segment_list); if (config.geometry) { json_result.values["route_geometry"] = GetGeometry(config.compression, segment_list); } if (config.print_instructions) { json_result.values["route_instructions"] = guidance::AnnotateRoute(segment_list.Get(), facade); } RouteNames route_names; if (raw_route.has_alternative()) { Segments alternate_segment_list(raw_route, EXTRACT_ALTERNATIVE, config.zoom_level, ALLOW_SIMPLIFICATION, facade); // Alternative Route Summaries are stored in an array to (down the line) allow multiple // alternatives util::json::Array json_alternate_route_summary_array; json_alternate_route_summary_array.values.emplace_back( SummarizeRoute(raw_route, alternate_segment_list)); json_result.values["alternative_summaries"] = json_alternate_route_summary_array; json_result.values["alternative_indices"] = ListViaIndices(alternate_segment_list); if (config.geometry) { auto alternate_geometry_string = GetGeometry(config.compression, alternate_segment_list); util::json::Array json_alternate_geometries_array; json_alternate_geometries_array.values.emplace_back( std::move(alternate_geometry_string)); json_result.values["alternative_geometries"] = json_alternate_geometries_array; } if (config.print_instructions) { util::json::Array json_alternate_annotations_array; json_alternate_annotations_array.values.emplace_back( guidance::AnnotateRoute(alternate_segment_list.Get(), facade)); json_result.values["alternative_instructions"] = json_alternate_annotations_array; } // generate names for both the main path and the alternative route auto path_segments = BuildRouteSegments(segment_list); auto alternate_segments = BuildRouteSegments(alternate_segment_list); route_names = extractRouteNames(path_segments, alternate_segments, facade); util::json::Array json_alternate_names_array; util::json::Array json_alternate_names; json_alternate_names.values.push_back(route_names.alternative_path_name_1); json_alternate_names.values.push_back(route_names.alternative_path_name_2); json_alternate_names_array.values.emplace_back(std::move(json_alternate_names)); json_result.values["alternative_names"] = json_alternate_names_array; json_result.values["found_alternative"] = util::json::True(); } else { json_result.values["found_alternative"] = util::json::False(); // generate names for the main route on its own auto path_segments = BuildRouteSegments(segment_list); std::vector<detail::Segment> alternate_segments; route_names = extractRouteNames(path_segments, alternate_segments, facade); } util::json::Array json_route_names; json_route_names.values.push_back(route_names.shortest_path_name_1); json_route_names.values.push_back(route_names.shortest_path_name_2); json_result.values["route_name"] = json_route_names; json_result.values["hint_data"] = BuildHintData(raw_route); }
SegmentList<DataFacadeT>::SegmentList(const InternalRouteResult &raw_route, const bool extract_alternative, const unsigned zoom_level, const bool allow_simplification, const DataFacade *facade) : total_distance(0), total_duration(0) { if (!raw_route.is_valid()) { return; } if (extract_alternative) { BOOST_ASSERT(raw_route.has_alternative()); InitRoute(raw_route.segment_end_coordinates.front().source_phantom, raw_route.alt_source_traversed_in_reverse.front()); AddLeg(raw_route.unpacked_alternative, raw_route.segment_end_coordinates.back().target_phantom, raw_route.alt_source_traversed_in_reverse.back(), false, facade); } else { InitRoute(raw_route.segment_end_coordinates.front().source_phantom, raw_route.source_traversed_in_reverse.front()); for (std::size_t raw_index = 0; raw_index < raw_route.segment_end_coordinates.size(); ++raw_index) { AddLeg(raw_route.unpacked_path_segments[raw_index], raw_route.segment_end_coordinates[raw_index].target_phantom, raw_route.target_traversed_in_reverse[raw_index], raw_route.is_via_leg(raw_index), facade); if (raw_route.is_via_leg(raw_index)) { const auto &source_phantom = raw_route.segment_end_coordinates[raw_index].target_phantom; if (raw_route.target_traversed_in_reverse[raw_index] != raw_route.source_traversed_in_reverse[raw_index + 1]) { bool traversed_in_reverse = raw_route.target_traversed_in_reverse[raw_index]; const extractor::TravelMode travel_mode = (traversed_in_reverse ? source_phantom.backward_travel_mode : source_phantom.forward_travel_mode); const bool constexpr IS_NECESSARY = true; const bool constexpr IS_VIA_LOCATION = true; segments.emplace_back(source_phantom.location, source_phantom.name_id, 0, 0.f, extractor::TurnInstruction::UTurn, IS_NECESSARY, IS_VIA_LOCATION, travel_mode); } } } } if (!allow_simplification) { // to prevent any simplifications, we mark all segments as necessary for (auto &segment : segments) { segment.necessary = true; } } Finalize(extract_alternative, raw_route, zoom_level, allow_simplification); }