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; }
void operator()(const DataFacadeT &facade, const std::vector<PhantomNodes> &phantom_nodes_vector, InternalRouteResult &raw_route_data) const { // Get weight to next pair of target nodes. BOOST_ASSERT_MSG(1 == phantom_nodes_vector.size(), "Direct Shortest Path Query only accepts a single source and target pair. " "Multiple ones have been specified."); const auto &phantom_node_pair = phantom_nodes_vector.front(); const auto &source_phantom = phantom_node_pair.source_phantom; const auto &target_phantom = phantom_node_pair.target_phantom; engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); forward_heap.Clear(); reverse_heap.Clear(); BOOST_ASSERT(source_phantom.IsValid()); BOOST_ASSERT(target_phantom.IsValid()); if (source_phantom.forward_segment_id.enabled) { forward_heap.Insert(source_phantom.forward_segment_id.id, -source_phantom.GetForwardWeightPlusOffset(), source_phantom.forward_segment_id.id); } if (source_phantom.reverse_segment_id.enabled) { forward_heap.Insert(source_phantom.reverse_segment_id.id, -source_phantom.GetReverseWeightPlusOffset(), source_phantom.reverse_segment_id.id); } if (target_phantom.forward_segment_id.enabled) { reverse_heap.Insert(target_phantom.forward_segment_id.id, target_phantom.GetForwardWeightPlusOffset(), target_phantom.forward_segment_id.id); } if (target_phantom.reverse_segment_id.enabled) { reverse_heap.Insert(target_phantom.reverse_segment_id.id, target_phantom.GetReverseWeightPlusOffset(), target_phantom.reverse_segment_id.id); } int weight = INVALID_EDGE_WEIGHT; std::vector<NodeID> packed_leg; const bool constexpr DO_NOT_FORCE_LOOPS = false; // prevents forcing of loops, since offsets are set correctly if (facade.GetCoreSize() > 0) { engine_working_data.InitializeOrClearSecondThreadLocalStorage( facade.GetNumberOfNodes()); QueryHeap &forward_core_heap = *(engine_working_data.forward_heap_2); QueryHeap &reverse_core_heap = *(engine_working_data.reverse_heap_2); forward_core_heap.Clear(); reverse_core_heap.Clear(); super::SearchWithCore(facade, forward_heap, reverse_heap, forward_core_heap, reverse_core_heap, weight, packed_leg, DO_NOT_FORCE_LOOPS, DO_NOT_FORCE_LOOPS); } else { super::Search(facade, forward_heap, reverse_heap, weight, packed_leg, DO_NOT_FORCE_LOOPS, DO_NOT_FORCE_LOOPS); } // No path found for both target nodes? if (INVALID_EDGE_WEIGHT == weight) { raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT; raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT; return; } BOOST_ASSERT_MSG(!packed_leg.empty(), "packed path empty"); raw_route_data.shortest_path_length = weight; raw_route_data.unpacked_path_segments.resize(1); raw_route_data.source_traversed_in_reverse.push_back( (packed_leg.front() != phantom_node_pair.source_phantom.forward_segment_id.id)); raw_route_data.target_traversed_in_reverse.push_back( (packed_leg.back() != phantom_node_pair.target_phantom.forward_segment_id.id)); super::UnpackPath(facade, packed_leg.begin(), packed_leg.end(), phantom_node_pair, raw_route_data.unpacked_path_segments.front()); }
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; }
std::vector<EdgeWeight> operator()(const DataFacadeT &facade, const std::vector<PhantomNode> &phantom_nodes, const std::vector<std::size_t> &source_indices, const std::vector<std::size_t> &target_indices) const { const auto number_of_sources = source_indices.empty() ? phantom_nodes.size() : source_indices.size(); const auto number_of_targets = target_indices.empty() ? phantom_nodes.size() : target_indices.size(); const auto number_of_entries = number_of_sources * number_of_targets; std::vector<EdgeWeight> result_table(number_of_entries, std::numeric_limits<EdgeWeight>::max()); engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); QueryHeap &query_heap = *(engine_working_data.forward_heap_1); SearchSpaceWithBuckets search_space_with_buckets; unsigned column_idx = 0; const auto search_target_phantom = [&](const PhantomNode &phantom) { query_heap.Clear(); // insert target(s) at weight 0 if (phantom.forward_segment_id.enabled) { query_heap.Insert(phantom.forward_segment_id.id, phantom.GetForwardWeightPlusOffset(), phantom.forward_segment_id.id); } if (phantom.reverse_segment_id.enabled) { query_heap.Insert(phantom.reverse_segment_id.id, phantom.GetReverseWeightPlusOffset(), phantom.reverse_segment_id.id); } // explore search space while (!query_heap.Empty()) { BackwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets); } ++column_idx; }; // for each source do forward search unsigned row_idx = 0; const auto search_source_phantom = [&](const PhantomNode &phantom) { query_heap.Clear(); // insert target(s) at weight 0 if (phantom.forward_segment_id.enabled) { query_heap.Insert(phantom.forward_segment_id.id, -phantom.GetForwardWeightPlusOffset(), phantom.forward_segment_id.id); } if (phantom.reverse_segment_id.enabled) { query_heap.Insert(phantom.reverse_segment_id.id, -phantom.GetReverseWeightPlusOffset(), phantom.reverse_segment_id.id); } // explore search space while (!query_heap.Empty()) { ForwardRoutingStep(facade, row_idx, number_of_targets, query_heap, search_space_with_buckets, result_table); } ++row_idx; }; if (target_indices.empty()) { for (const auto &phantom : phantom_nodes) { search_target_phantom(phantom); } } else { for (const auto index : target_indices) { const auto &phantom = phantom_nodes[index]; search_target_phantom(phantom); } } if (source_indices.empty()) { for (const auto &phantom : phantom_nodes) { search_source_phantom(phantom); } } else { for (const auto index : source_indices) { const auto &phantom = phantom_nodes[index]; search_source_phantom(phantom); } } return result_table; }