inline osrm::json::Object BuildHintData(const InternalRouteResult& raw_route) const { osrm::json::Object json_hint_object; json_hint_object.values["checksum"] = facade->GetCheckSum(); osrm::json::Array json_location_hint_array; std::string hint; for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size())) { ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint); json_location_hint_array.values.push_back(hint); } ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint); json_location_hint_array.values.push_back(hint); json_hint_object.values["locations"] = json_location_hint_array; return json_hint_object; }
std::vector<PhantomNode> GetPhantomNodes(const RouteParameters &route_parameters) { const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); const auto &input_bearings = route_parameters.bearings; std::vector<PhantomNode> phantom_node_list; phantom_node_list.reserve(route_parameters.coordinates.size()); // find phantom nodes for all input coords for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size())) { // if client hints are helpful, encode hints if (checksum_OK && i < route_parameters.hints.size() && !route_parameters.hints[i].empty()) { PhantomNode current_phantom_node; ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node); if (current_phantom_node.is_valid(facade->GetNumberOfNodes())) { phantom_node_list.push_back(std::move(current_phantom_node)); continue; } } const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0; const int range = input_bearings.size() > 0 ? (input_bearings[i].second ? *input_bearings[i].second : 10) : 180; auto results = facade->NearestPhantomNodes(route_parameters.coordinates[i], 1, bearing, range); if (results.empty()) { break; } phantom_node_list.push_back(std::move(results.front().phantom_node)); BOOST_ASSERT(phantom_node_list.back().is_valid(facade->GetNumberOfNodes())); } return phantom_node_list; }
Status HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) override final { if (max_locations_viaroute > 0 && (static_cast<int>(route_parameters.coordinates.size()) > max_locations_viaroute)) { 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_viaroute) + ")"; return Status::Error; } 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 coordinate"; return Status::Error; } std::vector<PhantomNodePair> phantom_node_pair_list(route_parameters.coordinates.size()); const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size())) { if (checksum_OK && i < route_parameters.hints.size() && !route_parameters.hints[i].empty()) { ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], phantom_node_pair_list[i].first); if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())) { continue; } } const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0; const int range = input_bearings.size() > 0 ? (input_bearings[i].second ? *input_bearings[i].second : 10) : 180; phantom_node_pair_list[i] = facade->NearestPhantomNodeWithAlternativeFromBigComponent( route_parameters.coordinates[i], bearing, range); // we didn't found a fitting node, return error if (!phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())) { json_result.values["status_message"] = std::string("Could not find a matching segment for coordinate ") + std::to_string(i); return Status::NoSegment; } BOOST_ASSERT(phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())); BOOST_ASSERT(phantom_node_pair_list[i].second.is_valid(facade->GetNumberOfNodes())); } auto snapped_phantoms = snapPhantomNodes(phantom_node_pair_list); InternalRouteResult raw_route; auto build_phantom_pairs = [&raw_route](const PhantomNode &first_node, const PhantomNode &second_node) { raw_route.segment_end_coordinates.push_back(PhantomNodes{first_node, second_node}); }; osrm::for_each_pair(snapped_phantoms, build_phantom_pairs); if (1 == raw_route.segment_end_coordinates.size()) { if (route_parameters.alternate_route) { search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(), raw_route); } else { search_engine_ptr->direct_shortest_path(raw_route.segment_end_coordinates, route_parameters.uturns, raw_route); } } else { search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, route_parameters.uturns, raw_route); } bool no_route = INVALID_EDGE_WEIGHT == raw_route.shortest_path_length; std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor; switch (descriptor_table.get_id(route_parameters.output_format)) { case 1: descriptor = osrm::make_unique<GPXDescriptor<DataFacadeT>>(facade); break; // case 2: // descriptor = osrm::make_unique<GEOJSONDescriptor<DataFacadeT>>(); // break; default: descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade); break; } descriptor->SetConfig(route_parameters); descriptor->Run(raw_route, json_result); // we can only know this after the fact, different SCC ids still // allow for connection in one direction. if (no_route) { 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) { json_result.values["status_message"] = "Impossible route between points"; return Status::EmptyResult; } } else { json_result.values["status_message"] = "Found route between points"; } return Status::Ok; }
int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) override final { if (!check_all_coordinates(route_parameters.coordinates)) { return 400; } std::vector<phantom_node_pair> phantom_node_pair_list(route_parameters.coordinates.size()); const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size())) { if (checksum_OK && i < route_parameters.hints.size() && !route_parameters.hints[i].empty()) { ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], phantom_node_pair_list[i]); if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())) { continue; } } std::vector<PhantomNode> phantom_node_vector; if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], phantom_node_vector, 1)) { BOOST_ASSERT(!phantom_node_vector.empty()); phantom_node_pair_list[i].first = phantom_node_vector.front(); if (phantom_node_vector.size() > 1) { phantom_node_pair_list[i].second = phantom_node_vector.back(); } } } auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair) { return phantom_pair.first.component_id != 0; }; const bool every_phantom_is_in_tiny_cc = std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), check_component_id_is_tiny); // are all phantoms from a tiny cc? const auto component_id = phantom_node_pair_list.front().first.component_id; auto check_component_id_is_equal = [component_id](const phantom_node_pair &phantom_pair) { return component_id == phantom_pair.first.component_id; }; const bool every_phantom_has_equal_id = std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), check_component_id_is_equal); auto swap_phantom_from_big_cc_into_front = [](phantom_node_pair &phantom_pair) { if (0 != phantom_pair.first.component_id) { using namespace std; swap(phantom_pair.first, phantom_pair.second); } }; // this case is true if we take phantoms from the big CC if (!every_phantom_is_in_tiny_cc || !every_phantom_has_equal_id) { std::for_each(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), swap_phantom_from_big_cc_into_front); } InternalRouteResult raw_route; auto build_phantom_pairs = [&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair) { raw_route.segment_end_coordinates.emplace_back( PhantomNodes{first_pair.first, second_pair.first}); }; osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs); if (route_parameters.alternate_route && 1 == raw_route.segment_end_coordinates.size()) { search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(), raw_route); } else { search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, route_parameters.uturns, raw_route); } if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) { SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; } std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor; switch (descriptor_table.get_id(route_parameters.output_format)) { case 1: descriptor = osrm::make_unique<GPXDescriptor<DataFacadeT>>(facade); break; // case 2: // descriptor = osrm::make_unique<GEOJSONDescriptor<DataFacadeT>>(); // break; default: descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade); break; } DescriptorConfig config = route_parameters; descriptor->SetConfig(config); descriptor->Run(raw_route, json_result); return 200; }