diff --git a/data_structures/edge_based_node.hpp b/data_structures/edge_based_node.hpp index 027644d7b..3f0ee316e 100644 --- a/data_structures/edge_based_node.hpp +++ b/data_structures/edge_based_node.hpp @@ -46,7 +46,7 @@ struct EdgeBasedNode u(SPECIAL_NODEID), v(SPECIAL_NODEID), name_id(0), forward_weight(INVALID_EDGE_WEIGHT >> 1), reverse_weight(INVALID_EDGE_WEIGHT >> 1), forward_offset(0), reverse_offset(0), packed_geometry_id(SPECIAL_EDGEID), - component_id(-1), fwd_segment_position(std::numeric_limits::max()), + component{false, INVALID_COMPONENTID}, fwd_segment_position(std::numeric_limits::max()), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) { @@ -62,6 +62,7 @@ struct EdgeBasedNode int forward_offset, int reverse_offset, unsigned packed_geometry_id, + bool is_tiny_component, unsigned component_id, unsigned short fwd_segment_position, TravelMode forward_travel_mode, @@ -70,7 +71,7 @@ struct EdgeBasedNode reverse_edge_based_node_id(reverse_edge_based_node_id), u(u), v(v), name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight), forward_offset(forward_offset), reverse_offset(reverse_offset), - packed_geometry_id(packed_geometry_id), component_id(component_id), + packed_geometry_id(packed_geometry_id), component{is_tiny_component, component_id}, fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode) { @@ -90,8 +91,6 @@ struct EdgeBasedNode bool IsCompressed() const { return packed_geometry_id != SPECIAL_EDGEID; } - bool is_in_tiny_cc() const { return 0 != component_id; } - NodeID forward_edge_based_node_id; // needed for edge-expanded graph NodeID reverse_edge_based_node_id; // needed for edge-expanded graph NodeID u; // indices into the coordinates array @@ -102,7 +101,10 @@ struct EdgeBasedNode int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice unsigned packed_geometry_id; // if set, then the edge represents a packed geometry - unsigned component_id; + struct { + bool is_tiny : 1; + unsigned id : 31; + } component; unsigned short fwd_segment_position; // segment id in a compressed geometry TravelMode forward_travel_mode : 4; TravelMode backward_travel_mode : 4; diff --git a/data_structures/phantom_node.cpp b/data_structures/phantom_node.cpp index eba6492cd..f6deb0530 100644 --- a/data_structures/phantom_node.cpp +++ b/data_structures/phantom_node.cpp @@ -42,6 +42,7 @@ PhantomNode::PhantomNode(NodeID forward_node_id, int forward_offset, int reverse_offset, unsigned packed_geometry_id, + bool is_tiny_component, unsigned component_id, FixedPointCoordinate &location, unsigned short fwd_segment_position, @@ -50,7 +51,7 @@ PhantomNode::PhantomNode(NodeID forward_node_id, : forward_node_id(forward_node_id), reverse_node_id(reverse_node_id), name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight), forward_offset(forward_offset), reverse_offset(reverse_offset), - packed_geometry_id(packed_geometry_id), component_id(component_id), location(location), + packed_geometry_id(packed_geometry_id), component{is_tiny_component, component_id}, location(location), fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode) { @@ -60,7 +61,7 @@ PhantomNode::PhantomNode() : forward_node_id(SPECIAL_NODEID), reverse_node_id(SPECIAL_NODEID), name_id(std::numeric_limits::max()), forward_weight(INVALID_EDGE_WEIGHT), reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0), - packed_geometry_id(SPECIAL_EDGEID), component_id(std::numeric_limits::max()), + packed_geometry_id(SPECIAL_EDGEID), component{false, INVALID_COMPONENTID}, fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) { @@ -96,11 +97,9 @@ bool PhantomNode::is_valid(const unsigned number_of_nodes) const return location.is_valid() && ((forward_node_id < number_of_nodes) || (reverse_node_id < number_of_nodes)) && ((forward_weight != INVALID_EDGE_WEIGHT) || (reverse_weight != INVALID_EDGE_WEIGHT)) && - (name_id != INVALID_NAMEID); + (component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID); } -bool PhantomNode::is_in_tiny_component() const { return component_id != 0; } - bool PhantomNode::is_valid() const { return location.is_valid() && (name_id != INVALID_NAMEID); } bool PhantomNode::operator==(const PhantomNode &other) const { return location == other.location; } diff --git a/data_structures/phantom_node.hpp b/data_structures/phantom_node.hpp index 670408961..e3e4fb77e 100644 --- a/data_structures/phantom_node.hpp +++ b/data_structures/phantom_node.hpp @@ -47,6 +47,7 @@ struct PhantomNode int forward_offset, int reverse_offset, unsigned packed_geometry_id, + bool is_tiny_component, unsigned component_id, FixedPointCoordinate &location, unsigned short fwd_segment_position, @@ -68,7 +69,9 @@ struct PhantomNode reverse_offset = other.reverse_offset; packed_geometry_id = other.packed_geometry_id; - component_id = other.component_id; + + component.id = other.component.id; + component.is_tiny = other.component.is_tiny; location = foot_point; fwd_segment_position = other.fwd_segment_position; @@ -85,7 +88,10 @@ struct PhantomNode int forward_offset; int reverse_offset; unsigned packed_geometry_id; - unsigned component_id; + struct { + bool is_tiny : 1; + unsigned id : 31; + } component; FixedPointCoordinate location; unsigned short fwd_segment_position; // note 4 bits would suffice for each, @@ -105,8 +111,6 @@ struct PhantomNode bool is_valid() const; - bool is_in_tiny_component() const; - bool operator==(const PhantomNode &other) const; }; @@ -147,7 +151,7 @@ inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn) << "fwd-o: " << pn.forward_offset << ", " << "rev-o: " << pn.reverse_offset << ", " << "geom: " << pn.packed_geometry_id << ", " - << "comp: " << pn.component_id << ", " + << "comp: " << pn.component.is_tiny << " / " << pn.component.id << ", " << "pos: " << pn.fwd_segment_position << ", " << "loc: " << pn.location; return out; diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index 14fe1efbc..9d2ca7804 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -603,7 +603,7 @@ class StaticRTree for (uint32_t i = 0; i < current_leaf_node.object_count; ++i) { EdgeDataT const ¤t_edge = current_leaf_node.objects[i]; - if (ignore_tiny_components && current_edge.component_id != 0) + if (ignore_tiny_components && current_edge.component.is_tiny) { continue; } @@ -767,7 +767,7 @@ class StaticRTree // continue searching for the first segment from a big component if (number_of_elements_from_big_cc == 0 && number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes && - current_segment.is_in_tiny_cc()) + current_segment.component.is_tiny) { continue; } @@ -821,7 +821,7 @@ class StaticRTree result_phantom_node_vector.back()); // update counts on what we found from which result class - if (current_segment.is_in_tiny_cc()) + if (current_segment.component.is_tiny) { // found an element in tiny component ++number_of_elements_from_tiny_cc; } @@ -976,14 +976,7 @@ class StaticRTree // store phantom node in result vector result_phantom_node_vector.emplace_back( - PhantomNode( - current_segment.forward_edge_based_node_id, - current_segment.reverse_edge_based_node_id, current_segment.name_id, - current_segment.forward_weight, current_segment.reverse_weight, - current_segment.forward_offset, current_segment.reverse_offset, - current_segment.packed_geometry_id, current_segment.component_id, - foot_point_coordinate_on_segment, current_segment.fwd_segment_position, - current_segment.forward_travel_mode, current_segment.backward_travel_mode), + PhantomNode {current_segment, foot_point_coordinate_on_segment}, current_perpendicular_distance); if (!forward_bearing_valid) @@ -1043,7 +1036,7 @@ class StaticRTree for (uint32_t i = 0; i < current_leaf_node.object_count; ++i) { const EdgeDataT ¤t_edge = current_leaf_node.objects[i]; - if (ignore_tiny_components && current_edge.component_id != 0) + if (ignore_tiny_components && current_edge.component.is_tiny != 0) { continue; } @@ -1062,19 +1055,7 @@ class StaticRTree !osrm::epsilon_compare(current_perpendicular_distance, min_dist)) { // found a new minimum min_dist = current_perpendicular_distance; - result_phantom_node = {current_edge.forward_edge_based_node_id, - current_edge.reverse_edge_based_node_id, - current_edge.name_id, - current_edge.forward_weight, - current_edge.reverse_weight, - current_edge.forward_offset, - current_edge.reverse_offset, - current_edge.packed_geometry_id, - current_edge.component_id, - nearest, - current_edge.fwd_segment_position, - current_edge.forward_travel_mode, - current_edge.backward_travel_mode}; + result_phantom_node = {current_edge, nearest}; nearest_edge = current_edge; } } diff --git a/extractor/edge_based_graph_factory.cpp b/extractor/edge_based_graph_factory.cpp index 1f23f2535..8eaf5cb9c 100644 --- a/extractor/edge_based_graph_factory.cpp +++ b/extractor/edge_based_graph_factory.cpp @@ -164,7 +164,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, forward_data.name_id, forward_geometry[i].second, reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i], reverse_dist_prefix_sum[i], m_compressed_edge_container.GetPositionForID(edge_id_1), - INVALID_COMPONENTID, i, forward_data.travel_mode, reverse_data.travel_mode); + false, INVALID_COMPONENTID, i, forward_data.travel_mode, reverse_data.travel_mode); current_edge_source_coordinate_id = current_edge_target_coordinate_id; BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed()); @@ -207,7 +207,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, m_edge_based_node_list.emplace_back( forward_data.edge_id, reverse_data.edge_id, node_u, node_v, forward_data.name_id, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID, - INVALID_COMPONENTID, 0, forward_data.travel_mode, reverse_data.travel_mode); + false, INVALID_COMPONENTID, 0, forward_data.travel_mode, reverse_data.travel_mode); BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed()); } } diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 029c47c0a..a94795917 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -436,8 +436,8 @@ void extractor::FindComponents(unsigned max_edge_id, component_search.get_component_id(node.reverse_edge_based_node_id)); const unsigned component_size = component_search.get_component_size(forward_component); - const bool is_tiny_component = component_size < 1000; - node.component_id = is_tiny_component ? (1 + forward_component) : 0; + node.component.is_tiny = component_size < 1000; + node.component.id = 1 + forward_component; } } diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index 6e898e0a8..9aac0ea0b 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -117,9 +117,9 @@ template class ViaRoutePlugin final : public BasePlugin } } - auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair) + const auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair) { - return phantom_pair.first.is_in_tiny_component(); + return phantom_pair.first.component.is_tiny; }; const bool every_phantom_is_in_tiny_cc = @@ -127,31 +127,36 @@ template class ViaRoutePlugin final : public BasePlugin 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) + const auto check_all_in_same_component = [](const std::vector &nodes) { - return component_id == phantom_pair.first.component_id; - }; + const auto component_id = nodes.front().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); + return std::all_of(std::begin(nodes), std::end(nodes), + [component_id](const phantom_node_pair &phantom_pair) + { + return component_id == phantom_pair.first.component.id; + }); + }; auto swap_phantom_from_big_cc_into_front = [](phantom_node_pair &phantom_pair) { - if (0 != phantom_pair.first.component_id && 0 == phantom_pair.second.component_id) + if (phantom_pair.first.component.is_tiny && phantom_pair.second.is_valid() && !phantom_pair.second.component.is_tiny) { using namespace std; swap(phantom_pair.first, phantom_pair.second); } }; + auto all_in_same_component = check_all_in_same_component(phantom_node_pair_list); + // this case is true if we take phantoms from the big CC - if (!every_phantom_is_in_tiny_cc || !every_phantom_has_equal_id) + if (every_phantom_is_in_tiny_cc && !all_in_same_component) { std::for_each(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), swap_phantom_from_big_cc_into_front); + + // update check with new component ids + all_in_same_component = check_all_in_same_component(phantom_node_pair_list); } InternalRouteResult raw_route; @@ -182,7 +187,9 @@ template class ViaRoutePlugin final : public BasePlugin route_parameters.uturns, raw_route); } - if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) + bool no_route = INVALID_EDGE_WEIGHT == raw_route.shortest_path_length; + + if (no_route) { SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; } @@ -203,6 +210,15 @@ template class ViaRoutePlugin final : public BasePlugin 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 (!all_in_same_component && no_route) + { + json_result.values["status"] = "Impossible route"; + return 400; + } + return 200; } }; diff --git a/typedefs.h b/typedefs.h index a8b75aa74..242c4c55d 100644 --- a/typedefs.h +++ b/typedefs.h @@ -45,7 +45,7 @@ using EdgeWeight = int; static const NodeID SPECIAL_NODEID = std::numeric_limits::max(); static const EdgeID SPECIAL_EDGEID = std::numeric_limits::max(); static const unsigned INVALID_NAMEID = std::numeric_limits::max(); -static const unsigned INVALID_COMPONENTID = std::numeric_limits::max(); +static const unsigned INVALID_COMPONENTID = 0; static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits::max(); #endif /* TYPEDEFS_H */