From f9986681cfface0a893d18b89beb5d20d242343d Mon Sep 17 00:00:00 2001 From: tatiana-kondakova Date: Tue, 26 Dec 2017 18:16:59 +0300 Subject: [PATCH] Check nodes access in IndexGraph --- routing/index_graph.cpp | 11 ++++- routing/routing_tests/index_graph_tools.cpp | 30 +++++++++++-- routing/routing_tests/index_graph_tools.hpp | 8 ++++ routing/routing_tests/road_access_test.cpp | 50 ++++++++++++++++++++- 4 files changed, 94 insertions(+), 5 deletions(-) diff --git a/routing/index_graph.cpp b/routing/index_graph.cpp index 4ab2291f92..8cd879231b 100644 --- a/routing/index_graph.cpp +++ b/routing/index_graph.cpp @@ -163,6 +163,9 @@ void IndexGraph::GetNeighboringEdge(Segment const & from, Segment const & to, bo if (m_roadAccess.GetFeatureType(to.GetFeatureId()) == RoadAccess::Type::No) return; + if (m_roadAccess.GetPointType(rp) == RoadAccess::Type::No) + return; + RouteWeight const weight = CalcSegmentWeight(isOutgoing ? to : from) + GetPenalties(isOutgoing ? from : to, isOutgoing ? to : from); edges.emplace_back(to, weight); @@ -181,7 +184,13 @@ RouteWeight IndexGraph::GetPenalties(Segment const & u, Segment const & v) bool const toAccessAllowed = m_roadAccess.GetFeatureType(v.GetFeatureId()) == RoadAccess::Type::Yes; // Route crosses border of access=yes/access={private, destination} area if |u| and |v| have different // access restrictions. - int32_t const accessPenalty = fromAccessAllowed == toAccessAllowed ? 0 : 1; + int32_t accessPenalty = fromAccessAllowed == toAccessAllowed ? 0 : 1; + + // RoadPoint between u and v is front of u. + auto const rp = u.GetRoadPoint(true /* front */); + // No double penalty for barriers on the border of access=yes/access={private, destination} area. + if (m_roadAccess.GetPointType(rp) != RoadAccess::Type::Yes) + accessPenalty = 1; auto const uTurnPenalty = IsUTurn(u, v) ? m_estimator->GetUTurnPenalty() : 0.0; diff --git a/routing/routing_tests/index_graph_tools.cpp b/routing/routing_tests/index_graph_tools.cpp index ded2ab2290..f88dc70c54 100644 --- a/routing/routing_tests/index_graph_tools.cpp +++ b/routing/routing_tests/index_graph_tools.cpp @@ -135,6 +135,25 @@ void TestIndexGraphTopology::SetEdgeAccess(Vertex from, Vertex to, RoadAccess::T CHECK(false, ("Cannot set access for edge that is not in the graph", from, to)); } +void TestIndexGraphTopology::SetVertexAccess(Vertex v, RoadAccess::Type type) +{ + bool found = false; + for (auto & r : m_edgeRequests) + { + if (r.m_from == v) + { + r.m_fromAccessType = type; + found = true; + } + if (r.m_to == v) + { + r.m_toAccessType = type; + found = true; + } + } + CHECK(found, ("Cannot set access for vertex that is not in the graph", v)); +} + bool TestIndexGraphTopology::FindPath(Vertex start, Vertex finish, double & pathWeight, vector & pathEdges) const { @@ -255,16 +274,21 @@ void TestIndexGraphTopology::Builder::BuildJoints() void TestIndexGraphTopology::Builder::BuildGraphFromRequests(vector const & requests) { map featureTypes; + map pointTypes; for (auto const & request : requests) { BuildSegmentFromEdge(request); if (request.m_accessType != RoadAccess::Type::Yes) - { featureTypes[request.m_id] = request.m_accessType; - } + + // All features have 1 segment. |from| has point index 0, |to| has point index 1. + if (request.m_fromAccessType != RoadAccess::Type::Yes) + pointTypes[RoadPoint(request.m_id, 0 /* pointId */)] = request.m_fromAccessType; + if (request.m_toAccessType != RoadAccess::Type::Yes) + pointTypes[RoadPoint(request.m_id, 1 /* pointId */)] = request.m_toAccessType; } - m_roadAccess.SetFeatureTypesForTests(move(featureTypes)); + m_roadAccess.SetAccessTypes(move(featureTypes), move(pointTypes)); } void TestIndexGraphTopology::Builder::BuildSegmentFromEdge(EdgeRequest const & request) diff --git a/routing/routing_tests/index_graph_tools.hpp b/routing/routing_tests/index_graph_tools.hpp index 3189ef47d3..671948d73c 100644 --- a/routing/routing_tests/index_graph_tools.hpp +++ b/routing/routing_tests/index_graph_tools.hpp @@ -158,6 +158,9 @@ public: // Sets access for previously added edge. void SetEdgeAccess(Vertex from, Vertex to, RoadAccess::Type type); + // Sets access type for previously added point. + void SetVertexAccess(Vertex v, RoadAccess::Type type); + // Finds a path between the start and finish vertices. Returns true iff a path exists. bool FindPath(Vertex start, Vertex finish, double & pathWeight, vector & pathEdges) const; @@ -168,7 +171,12 @@ private: Vertex m_from = 0; Vertex m_to = 0; double m_weight = 0.0; + // Access type for edge. RoadAccess::Type m_accessType = RoadAccess::Type::Yes; + // Access type for vertex from. + RoadAccess::Type m_fromAccessType = RoadAccess::Type::Yes; + // Access type for vertex to. + RoadAccess::Type m_toAccessType = RoadAccess::Type::Yes; EdgeRequest(uint32_t id, Vertex from, Vertex to, double weight) : m_id(id), m_from(from), m_to(to), m_weight(weight) diff --git a/routing/routing_tests/road_access_test.cpp b/routing/routing_tests/road_access_test.cpp index 4e7dd613d9..a449beb167 100644 --- a/routing/routing_tests/road_access_test.cpp +++ b/routing/routing_tests/road_access_test.cpp @@ -92,7 +92,7 @@ UNIT_TEST(RoadAccess_WayBlocked) TestTopologyGraph(graph, 0, 3, false /* pathFound */, expectedWeight, expectedEdges); } -UNIT_TEST(RoadAccess_BarrierBypassing) +UNIT_TEST(RoadAccess_WayBlocking) { uint32_t const numVertices = 6; TestIndexGraphTopology graph(numVertices); @@ -139,4 +139,52 @@ UNIT_TEST(RoadAccess_BarrierBypassing) graph.SetEdgeAccess(3, 4, RoadAccess::Type::No); TestTopologyGraph(graph, 0, 5, false /* pathFound */, expectedWeight, expectedEdges); } + +UNIT_TEST(RoadAccess_BarrierBypassing) +{ + uint32_t const numVertices = 6; + TestIndexGraphTopology graph(numVertices); + + graph.AddDirectedEdge(0, 1, 1.0); + graph.AddDirectedEdge(1, 2, 1.0); + graph.AddDirectedEdge(2, 5, 1.0); + graph.AddDirectedEdge(0, 3, 1.0); + graph.AddDirectedEdge(3, 4, 2.0); + graph.AddDirectedEdge(4, 5, 1.0); + + double expectedWeight; + vector expectedEdges; + + expectedWeight = 3.0; + expectedEdges = {{0, 1}, {1, 2}, {2, 5}}; + TestTopologyGraph(graph, 0, 5, true /* pathFound */, expectedWeight, expectedEdges); + + // Test avoid access=private while we have route with RoadAccess::Type::Yes. + graph.SetVertexAccess(1, RoadAccess::Type::Private); + expectedWeight = 4.0; + expectedEdges = {{0, 3}, {3, 4}, {4, 5}}; + TestTopologyGraph(graph, 0, 5, true /* pathFound */, expectedWeight, expectedEdges); + + // Test avoid access=destination while we have route with RoadAccess::Type::Yes. + graph.SetVertexAccess(1, RoadAccess::Type::Destination); + TestTopologyGraph(graph, 0, 5, true /* pathFound */, expectedWeight, expectedEdges); + + // Test avoid access=no while we have route with RoadAccess::Type::Yes. + graph.SetVertexAccess(1, RoadAccess::Type::No); + TestTopologyGraph(graph, 0, 5, true /* pathFound */, expectedWeight, expectedEdges); + + // Test it's possible to build the route because private usage restriction is not strict: + // we use minimal possible number of access=yes/access={private, destination} crossing + // but allow to use private/destination if there is no other way. + graph.SetVertexAccess(3, RoadAccess::Type::Private); + TestTopologyGraph(graph, 0, 5, true /* pathFound */, expectedWeight, expectedEdges); + + // Test we have the same behaviour for access=destination. + graph.SetVertexAccess(3, RoadAccess::Type::Destination); + TestTopologyGraph(graph, 0, 5, true /* pathFound */, expectedWeight, expectedEdges); + + // Test we have strict restriction for access=no and can not build route. + graph.SetVertexAccess(3, RoadAccess::Type::No); + TestTopologyGraph(graph, 0, 5, false /* pathFound */, expectedWeight, expectedEdges); +} } // namespace