diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 0ef32a12a..95a40569b 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -94,8 +94,12 @@ class RouteAPI : public BaseAPI const bool reversed_source = source_traversed_in_reverse[idx]; const bool reversed_target = target_traversed_in_reverse[idx]; - auto leg_geometry = guidance::assembleGeometry( - BaseAPI::facade, path_data, phantoms.source_phantom, phantoms.target_phantom); + auto leg_geometry = guidance::assembleGeometry(BaseAPI::facade, + path_data, + phantoms.source_phantom, + phantoms.target_phantom, + reversed_source, + reversed_target); auto leg = guidance::assembleLeg(facade, path_data, leg_geometry, diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index fb9e8fa43..14e6b5a95 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -35,7 +35,9 @@ namespace guidance inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, const std::vector &leg_data, const PhantomNode &source_node, - const PhantomNode &target_node) + const PhantomNode &target_node, + const bool reversed_source, + const bool reversed_target) { LegGeometry geometry; @@ -43,16 +45,30 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, geometry.segment_offsets.push_back(0); geometry.locations.push_back(source_node.location); - // Need to get the node ID preceding the source phantom node - // TODO: check if this was traversed in reverse? - std::vector reverse_geometry; - facade.GetUncompressedGeometry(source_node.reverse_packed_geometry_id, reverse_geometry); - geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode( - reverse_geometry[reverse_geometry.size() - source_node.fwd_segment_position - 1])); + // u * v + // 0 -- 1 -- 2 -- 3 + // fwd_segment_position: 1 + // source node fwd: 1 1 -> 2 -> 3 + // source node rev: 2 0 <- 1 <- 2 + const auto source_segment_start_coordinate = + source_node.fwd_segment_position + (reversed_source ? 1 : 0); - std::vector forward_datasource_vector; - facade.GetUncompressedDatasources(source_node.forward_packed_geometry_id, - forward_datasource_vector); + // we don't save the first node id in the forward geometry, we need to get it as last coordinate from the reverse + // geometry + if (source_segment_start_coordinate == 0) + { + std::vector source_geometry; + facade.GetUncompressedGeometry(source_node.reverse_packed_geometry_id, source_geometry); + geometry.osm_node_ids.push_back( + facade.GetOSMNodeIDOfNode(source_geometry.back())); + } + else + { + std::vector source_geometry; + facade.GetUncompressedGeometry(source_node.forward_packed_geometry_id, source_geometry); + geometry.osm_node_ids.push_back( + facade.GetOSMNodeIDOfNode(source_geometry[source_segment_start_coordinate - 1])); + } auto cumulative_distance = 0.; auto current_distance = 0.; @@ -94,12 +110,29 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, geometry.segment_offsets.push_back(geometry.locations.size()); geometry.locations.push_back(target_node.location); - // Need to get the node ID following the destination phantom node - // TODO: check if this was traversed in reverse?? - std::vector forward_geometry; - facade.GetUncompressedGeometry(target_node.forward_packed_geometry_id, forward_geometry); - geometry.osm_node_ids.push_back( - facade.GetOSMNodeIDOfNode(forward_geometry[target_node.fwd_segment_position])); + // u * v + // 0 -- 1 -- 2 -- 3 + // fwd_segment_position: 1 + // target node fwd: 2 0 -> 1 -> 2 + // target node rev: 1 1 <- 2 <- 3 + const auto target_segment_end_coordinate = + target_node.fwd_segment_position + (reversed_target ? 0 : 1); + // we don't save the first node id in the forward geometry, we need to get it as last coordinate from the reverse + // geometry + if (target_segment_end_coordinate == 0) + { + std::vector target_geometry; + facade.GetUncompressedGeometry(target_node.reverse_packed_geometry_id, target_geometry); + geometry.osm_node_ids.push_back( + facade.GetOSMNodeIDOfNode(target_geometry.back())); + } + else + { + std::vector target_geometry; + facade.GetUncompressedGeometry(target_node.forward_packed_geometry_id, target_geometry); + geometry.osm_node_ids.push_back( + facade.GetOSMNodeIDOfNode(target_geometry[target_segment_end_coordinate - 1])); + } BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1); BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size()); diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 6951209d1..cec5bef13 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -215,12 +215,13 @@ template class BasicRoutingInterface const PhantomNodes &phantom_node_pair, std::vector &unpacked_path) const { + BOOST_ASSERT(std::distance(packed_path_begin, packed_path_end) > 0); + const bool start_traversed_in_reverse = (*packed_path_begin != phantom_node_pair.source_phantom.forward_segment_id.id); const bool target_traversed_in_reverse = (*std::prev(packed_path_end) != phantom_node_pair.target_phantom.forward_segment_id.id); - BOOST_ASSERT(std::distance(packed_path_begin, packed_path_end) > 0); std::stack> recursion_stack; // We have to push the path in reverse order onto the stack because it's LIFO.