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); }
virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) override final { if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) { // We do not need to do much, if there is no route ;-) return; } // check if first segment is non-zero BOOST_ASSERT(raw_route.unpacked_path_segments.size() == raw_route.segment_end_coordinates.size()); description_factory.SetStartSegment( raw_route.segment_end_coordinates.front().source_phantom, raw_route.source_traversed_in_reverse.front()); // for each unpacked segment add the leg to the description for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size())) { #ifndef NDEBUG const int added_segments = #endif DescribeLeg(raw_route.unpacked_path_segments[i], raw_route.segment_end_coordinates[i], raw_route.target_traversed_in_reverse[i], raw_route.is_via_leg(i)); BOOST_ASSERT(0 < added_segments); } description_factory.Run(config.zoom_level); if (config.geometry) { osrm::json::Value route_geometry = description_factory.AppendGeometryString(config.encode_geometry); json_result.values["route_geometry"] = route_geometry; } if (config.instructions) { osrm::json::Array json_route_instructions = BuildTextualDescription(description_factory, shortest_path_segments); json_result.values["route_instructions"] = json_route_instructions; } description_factory.BuildRouteSummary(description_factory.get_entire_length(), raw_route.shortest_path_length); osrm::json::Object json_route_summary; json_route_summary.values["total_distance"] = description_factory.summary.distance; json_route_summary.values["total_time"] = description_factory.summary.duration; json_route_summary.values["start_point"] = facade->get_name_for_id(description_factory.summary.source_name_id); json_route_summary.values["end_point"] = facade->get_name_for_id(description_factory.summary.target_name_id); json_result.values["route_summary"] = json_route_summary; BOOST_ASSERT(!raw_route.segment_end_coordinates.empty()); osrm::json::Array json_via_points_array; osrm::json::Array json_first_coordinate; json_first_coordinate.values.push_back( raw_route.segment_end_coordinates.front().source_phantom.location.lat / COORDINATE_PRECISION); json_first_coordinate.values.push_back( raw_route.segment_end_coordinates.front().source_phantom.location.lon / COORDINATE_PRECISION); json_via_points_array.values.push_back(json_first_coordinate); for (const PhantomNodes &nodes : raw_route.segment_end_coordinates) { std::string tmp; osrm::json::Array json_coordinate; json_coordinate.values.push_back(nodes.target_phantom.location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(nodes.target_phantom.location.lon / COORDINATE_PRECISION); json_via_points_array.values.push_back(json_coordinate); } json_result.values["via_points"] = json_via_points_array; osrm::json::Array json_via_indices_array; std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices(); json_via_indices_array.values.insert(json_via_indices_array.values.end(), shortest_leg_end_indices.begin(), shortest_leg_end_indices.end()); json_result.values["via_indices"] = json_via_indices_array; // only one alternative route is computed at this time, so this is hardcoded if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) { json_result.values["found_alternative"] = osrm::json::True(); BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty()); alternate_description_factory.SetStartSegment( raw_route.segment_end_coordinates.front().source_phantom, raw_route.alt_source_traversed_in_reverse.front()); // Get all the coordinates for the computed route for (const PathData &path_data : raw_route.unpacked_alternative) { current = facade->GetCoordinateOfNode(path_data.node); alternate_description_factory.AppendSegment(current, path_data); } alternate_description_factory.SetEndSegment( raw_route.segment_end_coordinates.back().target_phantom, raw_route.alt_source_traversed_in_reverse.back()); alternate_description_factory.Run(config.zoom_level); if (config.geometry) { osrm::json::Value alternate_geometry_string = alternate_description_factory.AppendGeometryString(config.encode_geometry); osrm::json::Array json_alternate_geometries_array; json_alternate_geometries_array.values.push_back(alternate_geometry_string); json_result.values["alternative_geometries"] = json_alternate_geometries_array; } // Generate instructions for each alternative (simulated here) osrm::json::Array json_alt_instructions; osrm::json::Array json_current_alt_instructions; if (config.instructions) { json_current_alt_instructions = BuildTextualDescription(alternate_description_factory, alternative_path_segments); json_alt_instructions.values.push_back(json_current_alt_instructions); json_result.values["alternative_instructions"] = json_alt_instructions; } alternate_description_factory.BuildRouteSummary( alternate_description_factory.get_entire_length(), raw_route.alternative_path_length); osrm::json::Object json_alternate_route_summary; osrm::json::Array json_alternate_route_summary_array; json_alternate_route_summary.values["total_distance"] = alternate_description_factory.summary.distance; json_alternate_route_summary.values["total_time"] = alternate_description_factory.summary.duration; json_alternate_route_summary.values["start_point"] = facade->get_name_for_id(alternate_description_factory.summary.source_name_id); json_alternate_route_summary.values["end_point"] = facade->get_name_for_id(alternate_description_factory.summary.target_name_id); json_alternate_route_summary_array.values.push_back(json_alternate_route_summary); json_result.values["alternative_summaries"] = json_alternate_route_summary_array; std::vector<unsigned> const &alternate_leg_end_indices = alternate_description_factory.GetViaIndices(); osrm::json::Array json_altenative_indices_array; json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(), alternate_leg_end_indices.begin(), alternate_leg_end_indices.end()); json_result.values["alternative_indices"] = json_altenative_indices_array; } else { json_result.values["found_alternative"] = osrm::json::False(); } // Get Names for both routes RouteNames route_names = GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade); osrm::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; if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) { osrm::json::Array json_alternate_names_array; osrm::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.push_back(json_alternate_names); json_result.values["alternative_names"] = json_alternate_names_array; } json_result.values["hint_data"] = BuildHintData(raw_route); }