Ejemplo n.º 1
0
    Status HandleRequest(const RouteParameters &route_parameters,
                      osrm::json::Object &json_result) override final
    {
        if (max_locations_trip > 0 &&
            (static_cast<int>(route_parameters.coordinates.size()) > max_locations_trip))
        {
            json_result.values["status_message"] =
                "Number of entries " + std::to_string(route_parameters.coordinates.size()) +
                " is higher than current maximum (" + std::to_string(max_locations_trip) + ")";
            return Status::Error;
        }

        // check if all inputs are coordinates
        if (!check_all_coordinates(route_parameters.coordinates))
        {
            json_result.values["status_message"] = "Invalid coordinates";
            return Status::Error;
        }

        const auto &input_bearings = route_parameters.bearings;
        if (input_bearings.size() > 0 &&
            route_parameters.coordinates.size() != input_bearings.size())
        {
            json_result.values["status_message"] =
                "Number of bearings does not match number of coordinates";
            return Status::Error;
        }

        // get phantom nodes
        auto phantom_node_list = GetPhantomNodes(route_parameters);
        if (phantom_node_list.size() != route_parameters.coordinates.size())
        {
            BOOST_ASSERT(phantom_node_list.size() < route_parameters.coordinates.size());
            json_result.values["status_message"] =
                std::string("Could not find a matching segment for coordinate ") +
                std::to_string(phantom_node_list.size());
            return Status::NoSegment;
        }

        const auto number_of_locations = phantom_node_list.size();

        // compute the distance table of all phantom nodes
        const auto result_table = DistTableWrapper<EdgeWeight>(
            *search_engine_ptr->distance_table(phantom_node_list, phantom_node_list),
            number_of_locations);

        if (result_table.size() == 0)
        {
            return Status::Error;
        }

        const constexpr std::size_t BF_MAX_FEASABLE = 10;
        BOOST_ASSERT_MSG(result_table.size() == number_of_locations * number_of_locations,
                         "Distance Table has wrong size");

        // get scc components
        SCC_Component scc = SplitUnaccessibleLocations(number_of_locations, result_table);

        using NodeIDIterator = typename std::vector<NodeID>::const_iterator;

        std::vector<std::vector<NodeID>> route_result;
        route_result.reserve(scc.GetNumberOfComponents());
        TIMER_START(TRIP_TIMER);
        // run Trip computation for every SCC
        for (std::size_t k = 0; k < scc.GetNumberOfComponents(); ++k)
        {
            const auto component_size = scc.range[k + 1] - scc.range[k];

            BOOST_ASSERT_MSG(component_size > 0, "invalid component size");

            std::vector<NodeID> scc_route;
            NodeIDIterator start = std::begin(scc.component) + scc.range[k];
            NodeIDIterator end = std::begin(scc.component) + scc.range[k + 1];

            if (component_size > 1)
            {

                if (component_size < BF_MAX_FEASABLE)
                {
                    scc_route =
                        osrm::trip::BruteForceTrip(start, end, number_of_locations, result_table);
                }
                else
                {
                    scc_route = osrm::trip::FarthestInsertionTrip(start, end, number_of_locations,
                                                                  result_table);
                }

                // use this output if debugging of route is needed:
                // SimpleLogger().Write() << "Route #" << k << ": " << [&scc_route]()
                // {
                //     std::string s = "";
                //     for (auto x : scc_route)
                //     {
                //         s += std::to_string(x) + " ";
                //     }
                //     return s;
                // }();

            }
            else
            {
                scc_route = std::vector<NodeID>(start, end);
            }

            route_result.push_back(std::move(scc_route));
        }

        // compute all round trip routes
        std::vector<InternalRouteResult> comp_route;
        comp_route.reserve(route_result.size());
        for (auto &elem : route_result)
        {
            comp_route.push_back(ComputeRoute(phantom_node_list, route_parameters, elem));
        }

        TIMER_STOP(TRIP_TIMER);

        // prepare JSON output
        // create a json object for every trip
        osrm::json::Array trip;
        for (std::size_t i = 0; i < route_result.size(); ++i)
        {
            std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor =
                osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
            descriptor->SetConfig(route_parameters);

            osrm::json::Object scc_trip;

            // set permutation output
            SetLocPermutationOutput(route_result[i], scc_trip);
            // set viaroute output
            descriptor->Run(comp_route[i], scc_trip);

            trip.values.push_back(std::move(scc_trip));
        }


        if (trip.values.empty())
        {
            json_result.values["status_message"] = "Cannot find trips";
            return Status::EmptyResult;
        }

        json_result.values["trips"] = std::move(trip);
        json_result.values["status_message"] = "Found trips";
        return Status::Ok;
    }
Ejemplo n.º 2
0
Status TripPlugin::HandleRequest(const api::TripParameters &parameters,
                                 util::json::Object &json_result)
{
    BOOST_ASSERT(parameters.IsValid());

    // enforce maximum number of locations for performance reasons
    if (max_locations_trip > 0 &&
        static_cast<int>(parameters.coordinates.size()) > max_locations_trip)
    {
        return Error("TooBig", "Too many trip coordinates", json_result);
    }

    if (!CheckAllCoordinates(parameters.coordinates))
    {
        return Error("InvalidValue", "Invalid coordinate value.", json_result);
    }

    auto phantom_node_pairs = GetPhantomNodes(parameters);
    if (phantom_node_pairs.size() != parameters.coordinates.size())
    {
        return Error("NoSegment",
                     std::string("Could not find a matching segment for coordinate ") +
                         std::to_string(phantom_node_pairs.size()),
                     json_result);
    }
    BOOST_ASSERT(phantom_node_pairs.size() == parameters.coordinates.size());

    auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);

    const auto number_of_locations = snapped_phantoms.size();

    // compute the duration table of all phantom nodes
    const auto result_table = util::DistTableWrapper<EdgeWeight>(
        duration_table(snapped_phantoms, {}, {}), number_of_locations);

    if (result_table.size() == 0)
    {
        return Status::Error;
    }

    const constexpr std::size_t BF_MAX_FEASABLE = 10;
    BOOST_ASSERT_MSG(result_table.size() == number_of_locations * number_of_locations,
                     "Distance Table has wrong size");

    // get scc components
    SCC_Component scc = SplitUnaccessibleLocations(number_of_locations, result_table);

    std::vector<std::vector<NodeID>> trips;
    trips.reserve(scc.GetNumberOfComponents());
    // run Trip computation for every SCC
    for (std::size_t k = 0; k < scc.GetNumberOfComponents(); ++k)
    {
        const auto component_size = scc.range[k + 1] - scc.range[k];

        BOOST_ASSERT_MSG(component_size > 0, "invalid component size");

        std::vector<NodeID> scc_route;
        auto route_begin = std::begin(scc.component) + scc.range[k];
        auto route_end = std::begin(scc.component) + scc.range[k + 1];

        if (component_size > 1)
        {

            if (component_size < BF_MAX_FEASABLE)
            {
                scc_route =
                    trip::BruteForceTrip(route_begin, route_end, number_of_locations, result_table);
            }
            else
            {
                scc_route = trip::FarthestInsertionTrip(route_begin, route_end, number_of_locations,
                                                        result_table);
            }
        }
        else
        {
            scc_route = std::vector<NodeID>(route_begin, route_end);
        }

        trips.push_back(std::move(scc_route));
    }
    if (trips.empty())
    {
        return Error("NoTrips", "Cannot find trips", json_result);
    }

    // compute all round trip routes
    std::vector<InternalRouteResult> routes;
    routes.reserve(trips.size());
    for (const auto &trip : trips)
    {
        routes.push_back(ComputeRoute(snapped_phantoms, parameters, trip));
    }

    api::TripAPI trip_api{BasePlugin::facade, parameters};
    trip_api.MakeResponse(trips, routes, snapped_phantoms, json_result);

    return Status::Ok;
}