コード例 #1
0
ファイル: table.cpp プロジェクト: Project-OSRM/osrm-backend
Status TablePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacade> facade,
                                  const api::TableParameters &params,
                                  util::json::Object &result) const
{
    BOOST_ASSERT(params.IsValid());

    if (!CheckAllCoordinates(params.coordinates))
    {
        return Error("InvalidOptions", "Coordinates are invalid", result);
    }

    if (params.bearings.size() > 0 && params.coordinates.size() != params.bearings.size())
    {
        return Error(
                   "InvalidOptions", "Number of bearings does not match number of coordinates", result);
    }

    // Empty sources or destinations means the user wants all of them included, respectively
    // The ManyToMany routing algorithm we dispatch to below already handles this perfectly.
    const auto num_sources =
        params.sources.empty() ? params.coordinates.size() : params.sources.size();
    const auto num_destinations =
        params.destinations.empty() ? params.coordinates.size() : params.destinations.size();

    if (max_locations_distance_table > 0 &&
            ((num_sources * num_destinations) >
             static_cast<std::size_t>(max_locations_distance_table * max_locations_distance_table)))
    {
        return Error("TooBig", "Too many table coordinates", result);
    }

    auto snapped_phantoms = SnapPhantomNodes(GetPhantomNodes(*facade, params));
    auto result_table =
        distance_table(*facade, snapped_phantoms, params.sources, params.destinations);

    if (result_table.empty())
    {
        return Error("NoTable", "No table found", result);
    }

    api::TableAPI table_api{*facade, params};
    table_api.MakeResponse(result_table, snapped_phantoms, result);

    return Status::Ok;
}
コード例 #2
0
ファイル: viaroute.cpp プロジェクト: beemogmbh/osrm-backend
Status ViaRoutePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacade> facade,
                                     const api::RouteParameters &route_parameters,
                                     util::json::Object &json_result)
{
    BOOST_ASSERT(route_parameters.IsValid());

    if (max_locations_viaroute > 0 &&
        (static_cast<int>(route_parameters.coordinates.size()) > max_locations_viaroute))
    {
        return Error("TooBig",
                     "Number of entries " + std::to_string(route_parameters.coordinates.size()) +
                         " is higher than current maximum (" +
                         std::to_string(max_locations_viaroute) + ")",
                     json_result);
    }

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

    auto phantom_node_pairs = GetPhantomNodes(*facade, route_parameters);
    if (phantom_node_pairs.size() != route_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() == route_parameters.coordinates.size());

    auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);

    const bool continue_straight_at_waypoint = route_parameters.continue_straight
                                                   ? *route_parameters.continue_straight
                                                   : facade->GetContinueStraightDefault();

    InternalRouteResult raw_route;
    auto build_phantom_pairs = [&raw_route, continue_straight_at_waypoint](
        const PhantomNode &first_node, const PhantomNode &second_node) {
        raw_route.segment_end_coordinates.push_back(PhantomNodes{first_node, second_node});
        auto &last_inserted = raw_route.segment_end_coordinates.back();
        // enable forward direction if possible
        if (last_inserted.source_phantom.forward_segment_id.id != SPECIAL_SEGMENTID)
        {
            last_inserted.source_phantom.forward_segment_id.enabled |=
                !continue_straight_at_waypoint;
        }
        // enable reverse direction if possible
        if (last_inserted.source_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID)
        {
            last_inserted.source_phantom.reverse_segment_id.enabled |=
                !continue_straight_at_waypoint;
        }
    };
    util::for_each_pair(snapped_phantoms, build_phantom_pairs);

    if (1 == raw_route.segment_end_coordinates.size())
    {
        if (route_parameters.alternatives && facade->GetCoreSize() == 0)
        {
            alternative_path(*facade, raw_route.segment_end_coordinates.front(), raw_route);
        }
        else
        {
            direct_shortest_path(*facade, raw_route.segment_end_coordinates, raw_route);
        }
    }
    else
    {
        shortest_path(*facade,
                      raw_route.segment_end_coordinates,
                      route_parameters.continue_straight,
                      raw_route);
    }

    // we can only know this after the fact, different SCC ids still
    // allow for connection in one direction.
    if (raw_route.is_valid())
    {
        api::RouteAPI route_api{*facade, route_parameters};
        route_api.MakeResponse(raw_route, json_result);
    }
    else
    {
        auto first_component_id = snapped_phantoms.front().component.id;
        auto not_in_same_component = std::any_of(snapped_phantoms.begin(),
                                                 snapped_phantoms.end(),
                                                 [first_component_id](const PhantomNode &node) {
                                                     return node.component.id != first_component_id;
                                                 });

        if (not_in_same_component)
        {
            return Error("NoRoute", "Impossible route between points", json_result);
        }
        else
        {
            return Error("NoRoute", "No route found between points", json_result);
        }
    }

    return Status::Ok;
}
コード例 #3
0
ファイル: trip.cpp プロジェクト: yiqingj/osrm-backend
Status TripPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
                                 const RoutingAlgorithmsInterface &algorithms,
                                 const api::TripParameters &parameters,
                                 util::json::Object &json_result) const
{
    if (!algorithms.HasShortestPathSearch())
    {
        return Error("NotImplemented",
                     "Shortest path search is not implemented for the chosen search algorithm.",
                     json_result);
    }
    if (!algorithms.HasManyToManySearch())
    {
        return Error("NotImplemented",
                     "Many to many search is not implemented for the chosen search algorithm.",
                     json_result);
    }

    BOOST_ASSERT(parameters.IsValid());
    const auto number_of_locations = parameters.coordinates.size();

    std::size_t source_id = INVALID_INDEX;
    std::size_t destination_id = INVALID_INDEX;
    if (parameters.source == api::TripParameters::SourceType::First)
    {
        source_id = 0;
    }
    if (parameters.destination == api::TripParameters::DestinationType::Last)
    {
        BOOST_ASSERT(number_of_locations > 0);
        destination_id = number_of_locations - 1;
    }
    bool fixed_start = (source_id == 0);
    bool fixed_end = (destination_id == number_of_locations - 1);
    if (!IsSupportedParameterCombination(fixed_start, fixed_end, parameters.roundtrip))
    {
        return Error("NotImplemented", "This request is not supported", json_result);
    }

    // enforce maximum number of locations for performance reasons
    if (max_locations_trip > 0 && static_cast<int>(number_of_locations) > 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(facade, parameters);
    if (phantom_node_pairs.size() != number_of_locations)
    {
        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() == number_of_locations);

    if (fixed_start && fixed_end && (source_id >= parameters.coordinates.size() ||
                                     destination_id >= parameters.coordinates.size()))
    {
        return Error("InvalidValue", "Invalid source or destination value.", json_result);
    }

    auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);

    BOOST_ASSERT(snapped_phantoms.size() == number_of_locations);

    // compute the duration table of all phantom nodes
    auto result_table = util::DistTableWrapper<EdgeWeight>(
        algorithms.ManyToManySearch(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");

    if (!IsStronglyConnectedComponent(result_table))
    {
        return Error("NoTrips", "No trip visiting all destinations possible.", json_result);
    }

    if (fixed_start && fixed_end)
    {
        ManipulateTableForFSE(source_id, destination_id, result_table);
    }

    std::vector<NodeID> trip;
    trip.reserve(number_of_locations);
    // get an optimized order in which the destinations should be visited
    if (number_of_locations < BF_MAX_FEASABLE)
    {
        trip = trip::BruteForceTrip(number_of_locations, result_table);
    }
    else
    {
        trip = trip::FarthestInsertionTrip(number_of_locations, result_table);
    }

    // rotate result such that roundtrip starts at node with index 0
    // thist first if covers scenarios: !fixed_end || fixed_start || (fixed_start && fixed_end)
    if (!fixed_end || fixed_start)
    {
        auto desired_start_index = std::find(std::begin(trip), std::end(trip), 0);
        BOOST_ASSERT(desired_start_index != std::end(trip));
        std::rotate(std::begin(trip), desired_start_index, std::end(trip));
    }
    else if (fixed_end && !fixed_start && parameters.roundtrip)
    {
        auto desired_start_index = std::find(std::begin(trip), std::end(trip), destination_id);
        BOOST_ASSERT(desired_start_index != std::end(trip));
        std::rotate(std::begin(trip), desired_start_index, std::end(trip));
    }

    // get the route when visiting all destinations in optimized order
    InternalRouteResult route =
        ComputeRoute(algorithms, snapped_phantoms, trip, parameters.roundtrip);

    // get api response
    const std::vector<std::vector<NodeID>> trips = {trip};
    const std::vector<InternalRouteResult> routes = {route};
    api::TripAPI trip_api{facade, parameters};
    trip_api.MakeResponse(trips, routes, snapped_phantoms, json_result);

    return Status::Ok;
}
コード例 #4
0
ファイル: trip.cpp プロジェクト: Zhang-Yun/osrm-backend
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;
}