diff --git a/generator/routing_index_generator.cpp b/generator/routing_index_generator.cpp index c93d9b3151..7d5d9a9a36 100644 --- a/generator/routing_index_generator.cpp +++ b/generator/routing_index_generator.cpp @@ -15,6 +15,7 @@ #include "routing/index_graph_starter_joints.hpp" #include "routing/joint_segment.hpp" #include "routing/vehicle_mask.hpp" +#include "routing/world_graph.hpp" #include "transit/experimental/transit_data.hpp" #include "transit/transit_graph_data.hpp" @@ -183,7 +184,7 @@ public: routing::IndexGraph::Parents const & /* forwardParents */, routing::JointSegment const & /* commonVertex */, routing::IndexGraph::Parents const & /* backwardParents */, - function && /* fakeFeatureConverter */) + WorldGraph::FakeConverterT const & /* fakeFeatureConverter */) { return true; } diff --git a/routing/index_graph_starter.hpp b/routing/index_graph_starter.hpp index 8e18f7c6a6..920804a57a 100644 --- a/routing/index_graph_starter.hpp +++ b/routing/index_graph_starter.hpp @@ -143,7 +143,7 @@ public: bool AreWavesConnectible(Parents & forwardParents, Vertex const & commonVertex, Parents & backwardParents) override { - return m_graph.AreWavesConnectible(forwardParents, commonVertex, backwardParents, nullptr); + return m_graph.AreWavesConnectible(forwardParents, commonVertex, backwardParents); } RouteWeight GetAStarWeightEpsilon() override; @@ -174,10 +174,9 @@ public: bool AreWavesConnectible(Parents & forwardParents, JointSegment const & commonVertex, Parents & backwardParents, - std::function && fakeFeatureConverter) + WorldGraph::FakeConverterT const & fakeFeatureConverter) { - return m_graph.AreWavesConnectible(forwardParents, commonVertex, backwardParents, - std::move(fakeFeatureConverter)); + return m_graph.AreWavesConnectible(forwardParents, commonVertex, backwardParents, fakeFeatureConverter); } bool IsJoint(Segment const & segment, bool fromStart) diff --git a/routing/index_graph_starter_joints.hpp b/routing/index_graph_starter_joints.hpp index b55bd342f8..1454308148 100644 --- a/routing/index_graph_starter_joints.hpp +++ b/routing/index_graph_starter_joints.hpp @@ -72,23 +72,22 @@ public: bool AreWavesConnectible(Parents & forwardParents, Vertex const & commonVertex, Parents & backwardParents) override { - auto converter = [&](JointSegment const & vertex) + auto const converter = [&](JointSegment & vertex) { - ASSERT(!vertex.IsRealSegment(), ()); + if (!vertex.IsFake()) + return; auto const it = m_fakeJointSegments.find(vertex); ASSERT(it != m_fakeJointSegments.cend(), ()); auto const & first = it->second.GetSegment(true /* start */); if (first.IsRealSegment()) - return first.GetFeatureId(); - - auto const & second = it->second.GetSegment(false /* start */); - return second.GetFeatureId(); + vertex.AssignID(first); + else + vertex.AssignID(it->second.GetSegment(false /* start */)); }; - return m_graph.AreWavesConnectible(forwardParents, commonVertex, backwardParents, - std::move(converter)); + return m_graph.AreWavesConnectible(forwardParents, commonVertex, backwardParents, converter); } RouteWeight GetAStarWeightEpsilon() override { return m_graph.GetAStarWeightEpsilon(); } diff --git a/routing/joint_segment.cpp b/routing/joint_segment.cpp index a943ce77ef..2b5e6787b8 100644 --- a/routing/joint_segment.cpp +++ b/routing/joint_segment.cpp @@ -12,13 +12,15 @@ namespace routing { JointSegment::JointSegment(Segment const & from, Segment const & to) { - CHECK(!from.IsFakeCreated() && !to.IsFakeCreated(), - ("Segments of joints can not be fake. Only through ToFake() method.")); + static_assert(sizeof(JointSegment) == 16, ""); - CHECK_EQUAL(from.GetMwmId(), to.GetMwmId(), ("Different mwmIds in segments for JointSegment")); + CHECK(!from.IsFakeCreated() && !to.IsFakeCreated(), + ("Segments of joints can not be fake. Only through MakeFake() function.")); + + CHECK_EQUAL(from.GetMwmId(), to.GetMwmId(), ()); m_numMwmId = from.GetMwmId(); - CHECK_EQUAL(from.IsForward(), to.IsForward(), ("Different forward in segments for JointSegment")); + CHECK_EQUAL(from.IsForward(), to.IsForward(), ()); m_forward = from.IsForward(); CHECK_EQUAL(from.GetFeatureId(), to.GetFeatureId(), ()); @@ -28,6 +30,18 @@ JointSegment::JointSegment(Segment const & from, Segment const & to) m_endSegmentId = to.GetSegmentIdx(); } +void JointSegment::AssignID(Segment const & seg) +{ + m_numMwmId = seg.GetMwmId(); + m_featureId = seg.GetFeatureId(); +} + +void JointSegment::AssignID(JointSegment const & seg) +{ + m_numMwmId = seg.m_numMwmId; + m_featureId = seg.m_featureId; +} + JointSegment JointSegment::MakeFake(uint32_t fakeId, uint32_t featureId/* = kInvalidFeatureId*/) { JointSegment res; diff --git a/routing/joint_segment.hpp b/routing/joint_segment.hpp index d8b61c72a4..9954dd2e96 100644 --- a/routing/joint_segment.hpp +++ b/routing/joint_segment.hpp @@ -20,18 +20,18 @@ public: JointSegment() = default; JointSegment(Segment const & from, Segment const & to); - void SetFeatureId(uint32_t id) { m_featureId = id; } uint32_t GetFeatureId() const { return m_featureId; } NumMwmId GetMwmId() const { return m_numMwmId; } - void SetMwmId(NumMwmId id) { m_numMwmId = id; } uint32_t GetStartSegmentId() const { return m_startSegmentId; } uint32_t GetEndSegmentId() const { return m_endSegmentId; } uint32_t GetSegmentId(bool start) const { return start ? m_startSegmentId : m_endSegmentId; } bool IsForward() const { return m_forward; } + void AssignID(Segment const & seg); + void AssignID(JointSegment const & seg); + static JointSegment MakeFake(uint32_t fakeId, uint32_t featureId = kInvalidFeatureId); bool IsFake() const; - bool IsRealSegment() const { return !IsFake(); } Segment GetSegment(bool start) const; diff --git a/routing/routing_integration_tests/route_test.cpp b/routing/routing_integration_tests/route_test.cpp index bd877ab01d..c09b8d3243 100644 --- a/routing/routing_integration_tests/route_test.cpp +++ b/routing/routing_integration_tests/route_test.cpp @@ -664,4 +664,18 @@ namespace mercator::FromLatLon(35.6233244, -78.3917262), {0., 0.}, mercator::FromLatLon(36.0081839, -81.5245347), 333425); } + + // https://github.com/organicmaps/organicmaps/issues/1565 + UNIT_TEST(Cyprus_NoUTurnFromFake) + { + integration::CalculateRouteAndTestRouteLength( + integration::GetVehicleComponents(VehicleType::Car), + mercator::FromLatLon(34.70639, 33.1184951), {0., 0.}, + mercator::FromLatLon(34.7065239, 33.1184222), 384.238); + + integration::CalculateRouteAndTestRouteLength( + integration::GetVehicleComponents(VehicleType::Car), + mercator::FromLatLon(34.7068976, 33.1199084), {0., 0.}, + mercator::FromLatLon(34.7070505, 33.1198391), 670.077); + } } // namespace diff --git a/routing/segment.hpp b/routing/segment.hpp index 24670c8f8d..a9468c90bd 100644 --- a/routing/segment.hpp +++ b/routing/segment.hpp @@ -32,7 +32,6 @@ public: Segment const & GetSegment(bool /* start */) const { return *this; } NumMwmId GetMwmId() const { return m_mwmId; } uint32_t GetFeatureId() const { return m_featureId; } - void SetFeatureId(uint32_t id) { m_featureId = id; } uint32_t GetSegmentIdx() const { return m_segmentIdx; } bool IsForward() const { return m_forward; } diff --git a/routing/single_vehicle_world_graph.cpp b/routing/single_vehicle_world_graph.cpp index b84f2099fe..915e7150d0 100644 --- a/routing/single_vehicle_world_graph.cpp +++ b/routing/single_vehicle_world_graph.cpp @@ -61,10 +61,7 @@ void SingleVehicleWorldGraph::CheckAndProcessTransitFeatures(Segment const & par for (auto const & twin : twins) { NumMwmId const twinMwmId = twin.GetMwmId(); - - uint32_t const twinFeatureId = twin.GetFeatureId(); - - Segment const start(twinMwmId, twinFeatureId, target.GetSegmentId(!opposite), target.IsForward()); + Segment const start(twinMwmId, twin.GetFeatureId(), target.GetSegmentId(!opposite), target.IsForward()); auto & twinIndexGraph = GetIndexGraph(twinMwmId); @@ -77,10 +74,8 @@ void SingleVehicleWorldGraph::CheckAndProcessTransitFeatures(Segment const & par isOutgoing, lastPoints.back())) { newCrossMwmEdges.emplace_back(*edge); - newCrossMwmEdges.back().GetTarget().SetFeatureId(twinFeatureId); - newCrossMwmEdges.back().GetTarget().SetMwmId(twinMwmId); - newCrossMwmEdges.back().GetWeight() += - m_hierarchyHandler.GetCrossBorderPenalty(mwmId, twinMwmId); + newCrossMwmEdges.back().GetTarget().AssignID(twin); + newCrossMwmEdges.back().GetWeight() += m_hierarchyHandler.GetCrossBorderPenalty(mwmId, twinMwmId); parentWeights.push_back(parentWeights[i]); } @@ -277,12 +272,11 @@ NumMwmId GetCommonMwmInChain(vector const & chain) return mwmId; } -template -bool +template bool SingleVehicleWorldGraph::AreWavesConnectibleImpl(Parents const & forwardParents, VertexType const & commonVertex, Parents const & backwardParents, - function && fakeFeatureConverter) + ConverterT const & fakeConverter) { if (IsRegionsGraphMode()) return true; @@ -326,14 +320,7 @@ SingleVehicleWorldGraph::AreWavesConnectibleImpl(Parents const & for fillParents(commonVertex, backwardParents); - if (fakeFeatureConverter) - { - for (size_t i = 0; i < chain.size(); ++i) - { - if (!chain[i].IsRealSegment()) - chain[i].SetFeatureId(fakeFeatureConverter(chain[i])); - } - } + fakeConverter(chain); NumMwmId const mwmId = GetCommonMwmInChain(chain); if (mwmId == kFakeNumMwmId) @@ -363,17 +350,22 @@ SingleVehicleWorldGraph::AreWavesConnectibleImpl(Parents const & for bool SingleVehicleWorldGraph::AreWavesConnectible(Parents & forwardParents, Segment const & commonVertex, - Parents & backwardParents, - function && fakeFeatureConverter) + Parents & backwardParents) { - return AreWavesConnectibleImpl(forwardParents, commonVertex, backwardParents, move(fakeFeatureConverter)); + return AreWavesConnectibleImpl(forwardParents, commonVertex, backwardParents, + [](vector &) {}); } bool SingleVehicleWorldGraph::AreWavesConnectible(Parents & forwardParents, JointSegment const & commonVertex, Parents & backwardParents, - function && fakeFeatureConverter) + FakeConverterT const & fakeFeatureConverter) { - return AreWavesConnectibleImpl(forwardParents, commonVertex, backwardParents, move(fakeFeatureConverter)); + return AreWavesConnectibleImpl(forwardParents, commonVertex, backwardParents, + [&fakeFeatureConverter](vector & chain) + { + for (auto & vertex : chain) + fakeFeatureConverter(vertex); + }); } } // namespace routing diff --git a/routing/single_vehicle_world_graph.hpp b/routing/single_vehicle_world_graph.hpp index ccd38bf3c3..01b68d42c2 100644 --- a/routing/single_vehicle_world_graph.hpp +++ b/routing/single_vehicle_world_graph.hpp @@ -88,11 +88,10 @@ public: void DropAStarParents() override; bool AreWavesConnectible(Parents & forwardParents, Segment const & commonVertex, - Parents & backwardParents, - std::function && fakeFeatureConverter) override; + Parents & backwardParents) override; bool AreWavesConnectible(Parents & forwardParents, JointSegment const & commonVertex, Parents & backwardParents, - std::function && fakeFeatureConverter) override; + FakeConverterT const & fakeFeatureConverter) override; // @} // This method should be used for tests only @@ -108,11 +107,11 @@ private: /// parents' featureIds from backward wave. /// \return The result chain of fetureIds are used to find restrictions on it and understand whether /// waves are connectable or not. - template + template bool AreWavesConnectibleImpl(Parents const & forwardParents, VertexType const & commonVertex, Parents const & backwardParents, - std::function && fakeFeatureConverter); + ConverterT const & fakeConverter); // Retrieves the same |jointEdges|, but into others mwms. // If they are cross mwm edges, of course. diff --git a/routing/world_graph.cpp b/routing/world_graph.cpp index 640fe809cb..fda24b456d 100644 --- a/routing/world_graph.cpp +++ b/routing/world_graph.cpp @@ -48,15 +48,14 @@ void WorldGraph::SetAStarParents(bool forward, Parents & parents) void WorldGraph::DropAStarParents() {} bool WorldGraph::AreWavesConnectible(Parents & forwardParents, Segment const & commonVertex, - Parents & backwardParents, - std::function && fakeFeatureConverter) + Parents & backwardParents) { return true; } bool WorldGraph::AreWavesConnectible(Parents & forwardParents, JointSegment const & commonVertex, Parents & backwardParents, - std::function && fakeFeatureConverter) + FakeConverterT const & fakeFeatureConverter) { return true; } diff --git a/routing/world_graph.hpp b/routing/world_graph.hpp index 1ca32d64c9..82ad20213e 100644 --- a/routing/world_graph.hpp +++ b/routing/world_graph.hpp @@ -108,11 +108,12 @@ public: virtual void DropAStarParents(); virtual bool AreWavesConnectible(Parents & forwardParents, Segment const & commonVertex, - Parents & backwardParents, - std::function && fakeFeatureConverter); + Parents & backwardParents); + + using FakeConverterT = std::function; virtual bool AreWavesConnectible(Parents & forwardParents, JointSegment const & commonVertex, Parents & backwardParents, - std::function && fakeFeatureConverter); + FakeConverterT const & fakeFeatureConverter); /// \returns transit-specific information for segment. For nontransit segments returns nullptr. virtual std::unique_ptr GetTransitInfo(Segment const & segment) = 0;