From 5474f1a4271c1b7e0755661d212803837506f195 Mon Sep 17 00:00:00 2001 From: tatiana-yan Date: Wed, 24 Feb 2021 15:16:42 +0300 Subject: [PATCH] [transit][world_feed] Choose stop index based on previous stop index for multiple shape projections. --- transit/world_feed/world_feed.cpp | 93 +++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 12 deletions(-) diff --git a/transit/world_feed/world_feed.cpp b/transit/world_feed/world_feed.cpp index 2a385cb5d2..c6dbd61c66 100644 --- a/transit/world_feed/world_feed.cpp +++ b/transit/world_feed/world_feed.cpp @@ -211,19 +211,41 @@ struct StopOnShape size_t m_index = 0; }; -size_t GetStopIndex(std::unordered_map> const & stopIndexes, - transit::TransitId id, size_t index = 0) +enum class Direction +{ + Forward, + Backward +}; + +std::optional GetStopIndex( + std::unordered_map> const & stopIndexes, + transit::TransitId id, size_t fromIndex, Direction direction) { auto it = stopIndexes.find(id); CHECK(it != stopIndexes.end(), (id)); - CHECK(index < it->second.size(), (index, it->second.size())); - return *(it->second.begin() + index); + auto stops = it->second; + std::sort(stops.begin(), stops.end()); + + if (direction == Direction::Forward) + { + auto const stopIt = + std::find_if(stops.begin(), stops.end(), [&](size_t index) { return index >= fromIndex; }); + if (stopIt == stops.end()) + return {}; + return *stopIt; + } + + auto const stopIt = + std::find_if(stops.rbegin(), stops.rend(), [&](size_t index) { return index <= fromIndex; }); + if (stopIt == stops.rend()) + return {}; + return *stopIt; } -std::pair GetStopPairOnShape( +std::optional> GetStopPairOnShape( std::unordered_map> const & stopIndexes, - transit::StopsOnLines const & stopsOnLines, size_t index) + transit::StopsOnLines const & stopsOnLines, size_t index, size_t fromIndex, Direction direction) { auto const & stopIds = stopsOnLines.m_stopSeq; @@ -238,11 +260,16 @@ std::pair GetStopPairOnShape( if (stopsOnLines.m_isValid) { - stop1.m_index = GetStopIndex(stopIndexes, stop1.m_id); - stop2.m_index = stop1.m_id == stop2.m_id ? GetStopIndex(stopIndexes, stop1.m_id, 1) - : GetStopIndex(stopIndexes, stop2.m_id); + auto const index1 = GetStopIndex(stopIndexes, stop1.m_id, fromIndex, direction); + if (!index1) + return {}; + stop1.m_index = *index1; + auto const index2 = GetStopIndex(stopIndexes, stop2.m_id, *index1, direction); + if (!index2) + return {}; + stop2.m_index = *index2; } - return {stop1, stop2}; + return std::pair(stop1, stop2); } struct Link @@ -257,6 +284,35 @@ Link::Link(transit::TransitId lineId, transit::TransitId shapeId, size_t shapeSi : m_lineId(lineId), m_shapeId(shapeId), m_shapeSize(shapeSize) { } + +Direction GetDirection( + transit::StopsOnLines const & stopsOnLines, + std::unordered_map> const & stopIndexes) +{ + auto const & stopIds = stopsOnLines.m_stopSeq; + + if (stopIds.size() <= 1 || !stopsOnLines.m_isValid) + return Direction::Forward; + + for (size_t i = 0; i < stopIds.size() - 1; ++i) + { + auto const id1 = stopIds[i]; + auto const id2 = stopIds[i + 1]; + auto const indexes1 = stopIndexes.find(id1); + auto const indexes2 = stopIndexes.find(id2); + CHECK(indexes1 != stopIndexes.end(), ()); + CHECK(indexes2 != stopIndexes.end(), ()); + if (indexes1->second.size() != 1 || indexes2->second.size() != 1) + continue; + auto const index1 = indexes1->second[0]; + auto const index2 = indexes2->second[0]; + if (index2 == index1) + continue; + return index2 > index1 ? Direction::Forward : Direction::Backward; + } + + return Direction::Forward; +} } // namespace namespace transit @@ -1027,15 +1083,28 @@ size_t WorldFeed::ModifyShapes() return invalidStopSequences; } - for (auto const & stopsOnLines : stopsLists) + for (auto & stopsOnLines : stopsLists) { IdList const & stopIds = stopsOnLines.m_stopSeq; auto const & lineIds = stopsOnLines.m_lines; auto indexes = stopToShapeIndex; + auto const direction = GetDirection(stopsOnLines, indexes); + + size_t lastIndex = direction == Direction::Forward ? 0 : std::numeric_limits::max(); for (size_t i = 0; i < stopIds.size() - 1; ++i) { - auto const [stop1, stop2] = GetStopPairOnShape(indexes, stopsOnLines, i); + auto const stops = GetStopPairOnShape(indexes, stopsOnLines, i, lastIndex, direction); + if (!stops) + { + stopsOnLines.m_isValid = false; + ++invalidStopSequences; + + if (invalidStopSequences > kMaxInvalidShapesCount) + return invalidStopSequences; + } + auto const [stop1, stop2] = *stops; + lastIndex = stop2.m_index; for (auto const lineId : lineIds) {