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);
}
Example #2
0
    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);
    }