diff --git a/generator/generator_tool/generator_tool.cpp b/generator/generator_tool/generator_tool.cpp index 06f5592585..1e2bcd0aed 100644 --- a/generator/generator_tool/generator_tool.cpp +++ b/generator/generator_tool/generator_tool.cpp @@ -43,6 +43,7 @@ #include #include +#include #include "defines.hpp" @@ -353,14 +354,14 @@ int main(int argc, char ** argv) if (FLAGS_make_cross_mwm) { - CHECK(routing::BuildCrossMwmSection(path, datFile, country, *countryParentGetter, - osmToFeatureFilename, FLAGS_disable_cross_mwm_progress), - ("Error generating cross mwm section.", path, datFile, country)); + routing::BuildRoutingCrossMwmSection(path, datFile, country, *countryParentGetter, + osmToFeatureFilename, FLAGS_disable_cross_mwm_progress); } if (FLAGS_make_transit_cross_mwm) { - ; // @todo(bykoianko) It's necessary to put here serialization of transit cross mwm section. + routing::BuildTransitCrossMwmSection(path, datFile, country, *countryParentGetter, + FLAGS_disable_cross_mwm_progress); } } diff --git a/generator/routing_index_generator.cpp b/generator/routing_index_generator.cpp index 613506fb78..4905c74e11 100644 --- a/generator/routing_index_generator.cpp +++ b/generator/routing_index_generator.cpp @@ -8,6 +8,7 @@ #include "routing/base/astar_algorithm.hpp" #include "routing/cross_mwm_connector.hpp" #include "routing/cross_mwm_connector_serialization.hpp" +#include "routing/cross_mwm_ids.hpp" #include "routing/index_graph.hpp" #include "routing/index_graph_loader.hpp" #include "routing/index_graph_serialization.hpp" @@ -175,8 +176,9 @@ private: // Calculate distance from the starting border point to the transition along the border. // It could be measured clockwise or counterclockwise, direction doesn't matter. +template double CalcDistanceAlongTheBorders(vector const & borders, - CrossMwmConnectorSerializer::Transition const & transition) + CrossMwmConnectorSerializer::Transition const & transition) { auto distance = GetAStarWeightZero(); @@ -207,20 +209,16 @@ double CalcDistanceAlongTheBorders(vector const & borders, return distance; } -void CalcCrossMwmTransitions(string const & path, string const & mwmFile, string const & country, - CountryParentNameGetterFn const & countryParentNameGetterFn, - map const & featureIdToOsmId, - vector & transitions, - CrossMwmConnectorPerVehicleType & connectors) +/// \brief Fills |transitions| for osm id case. That means for VehicleType::Pedestrian, +/// VehicleType::Bicycle and VehicleType::Car. +void CalcCrossMwmTransitions( + string const & mwmFile, string const & mappingFile, vector const & borders, + string const & country, CountryParentNameGetterFn const & countryParentNameGetterFn, + vector> & transitions) { - my::Timer timer; - string const polyFile = my::JoinPath(path, BORDERS_DIR, country + BORDERS_EXTENSION); - vector borders; - osm::LoadBorders(polyFile, borders); - VehicleMaskBuilder const maskMaker(country, countryParentNameGetterFn); - feature::ForEachFromDat(mwmFile, [&](FeatureType const & f, uint32_t featureId) { + ForEachFromDat(mwmFile, [&](FeatureType const & f, uint32_t featureId) { VehicleMask const roadMask = maskMaker.CalcRoadMask(f); if (roadMask == 0) return; @@ -230,9 +228,12 @@ void CalcCrossMwmTransitions(string const & path, string const & mwmFile, string if (pointsCount == 0) return; - auto osmIt = featureIdToOsmId.find(featureId); - CHECK(osmIt != featureIdToOsmId.end(), ("Can't find osm id for feature id", featureId)); - uint64_t const osmId = osmIt->second; + map featureIdToOsmId; + CHECK(ParseFeatureIdToOsmIdMapping(mappingFile, featureIdToOsmId), + ("Can't parse feature id to osm id mapping. File:", mappingFile)); + auto it = featureIdToOsmId.find(featureId); + CHECK(it != featureIdToOsmId.end(), ("Can't find osm id for feature id", featureId)); + auto const crossMwmId = it->second; bool prevPointIn = m2::RegionsContain(borders, f.GetPoint(0)); @@ -242,22 +243,63 @@ void CalcCrossMwmTransitions(string const & path, string const & mwmFile, string if (currPointIn == prevPointIn) continue; - uint32_t const segmentIdx = base::asserted_cast(i - 1); + auto const segmentIdx = base::asserted_cast(i - 1); VehicleMask const oneWayMask = maskMaker.CalcOneWayMask(f); - transitions.emplace_back(osmId, featureId, segmentIdx, roadMask, oneWayMask, currPointIn, + transitions.emplace_back(crossMwmId, featureId, segmentIdx, roadMask, oneWayMask, currPointIn, f.GetPoint(i - 1), f.GetPoint(i)); prevPointIn = currPointIn; } }); - LOG(LINFO, ("Transitions finished, transitions:", transitions.size(), ", elapsed:", - timer.ElapsedSeconds(), "seconds")); +} + +void CalcCrossMwmTransitions(string const & mwmFile, string const & mappingFile, + vector const & borders, string const & country, + CountryParentNameGetterFn const & countryParentNameGetterFn, + vector> & transitions) +{ + CHECK(mappingFile.empty(), ()); + NOTIMPLEMENTED(); + // @todo(bykoianko) Filling |transitions| based on transit section should be implemented. +} + +/// \brief Fills |transitions| and |connectors| fields. +/// \note This method fills only |connections| which are applicable for |CrossMwmId|. +/// For example |VehicleType::Pedestrian|, |VehicleType::Bicycle| and |VehicleType::Car| +/// are applicable for |connector::OsmId|. +/// And |VehicleType::Transit| is applicable for |connector::TransitId|. +template +void CalcCrossMwmConnectors( + string const & path, string const & mwmFile, string const & country, + CountryParentNameGetterFn const & countryParentNameGetterFn, string const & mappingFile, + vector> & transitions, + CrossMwmConnectorPerVehicleType & connectors) +{ + my::Timer timer; + string const polyFile = my::JoinPath(path, BORDERS_DIR, country + BORDERS_EXTENSION); + vector borders; + osm::LoadBorders(polyFile, borders); + + // Note 1. CalcCrossMwmTransitions() method fills vector |transitions|. + // There are two implementation of the method for |connector::OsmId| and for |connector::TransitId|. + // For all items in |transitions| |Transition::m_roadMask| may be set to any combination of masks: + // GetVehicleMask(VehicleType::Pedestrian), GetVehicleMask(VehicleType::Bicycle) and + // GetVehicleMask(VehicleType::Car) for |connector::OsmId| implementation. + // For all items in |transitions| |Transition::m_roadMask| is set to + // GetVehicleMask(VehicleType::Transit) for |connector::TransitId| implementation. + // Note 2. Taking into account note 1 it's clear that field |Transition::m_roadMask| + // is always set to |VehicleType::Transit| and field |Transition::m_roadMask| can't have + // |VehicleType::Transit| value. + CalcCrossMwmTransitions(mwmFile, mappingFile, borders, country, countryParentNameGetterFn, + transitions); + LOG(LINFO, ("Transitions finished, transitions:", transitions.size(), + ", elapsed:", timer.ElapsedSeconds(), "seconds")); timer.Reset(); sort(transitions.begin(), transitions.end(), - [&](CrossMwmConnectorSerializer::Transition const & lhs, - CrossMwmConnectorSerializer::Transition const & rhs) { + [&](CrossMwmConnectorSerializer::Transition const & lhs, + CrossMwmConnectorSerializer::Transition const & rhs) { return CalcDistanceAlongTheBorders(borders, lhs) < CalcDistanceAlongTheBorders(borders, rhs); }); @@ -272,11 +314,20 @@ void CalcCrossMwmTransitions(string const & path, string const & mwmFile, string CrossMwmConnectorSerializer::AddTransition(transition, mask, connectors[i]); } } + + for (size_t i = 0; i < connectors.size(); ++i) + { + auto const vehicleType = static_cast(i); + CrossMwmConnector const & connector = connectors[i]; + LOG(LINFO, (vehicleType, "model: enters:", connector.GetEnters().size(), ", exits:", + connector.GetExits().size())); + } } +template void FillWeights(string const & path, string const & mwmFile, string const & country, CountryParentNameGetterFn const & countryParentNameGetterFn, - bool disableCrossMwmProgress, CrossMwmConnector & connector) + bool disableCrossMwmProgress, CrossMwmConnector & connector) { my::Timer timer; @@ -324,11 +375,11 @@ void FillWeights(string const & path, string const & mwmFile, string const & cou connector.FillWeights([&](Segment const & enter, Segment const & exit) { auto it0 = weights.find(enter); if (it0 == weights.end()) - return CrossMwmConnector::kNoRoute; + return connector::kNoRoute; auto it1 = it0->second.find(exit); if (it1 == it0->second.end()) - return CrossMwmConnector::kNoRoute; + return connector::kNoRoute; return it1->second.ToCrossMwmWeight(); }); @@ -376,51 +427,58 @@ bool BuildRoutingIndex(string const & filename, string const & country, } } -bool BuildCrossMwmSection(string const & path, string const & mwmFile, string const & country, - CountryParentNameGetterFn const & countryParentNameGetterFn, - map const & featureIdToOsmId, bool disableCrossMwmProgress) +/// \brief Serializes all the cross mwm information to |sectionName| of |mwmFile| including: +/// * header +/// * transitions +/// * weight buffers if there are +template +void SerializeCrossMwm(string const & mwmFile, string const & sectionName, + CrossMwmConnectorPerVehicleType const & connectors, + vector> const & transitions) { - CrossMwmConnectorPerVehicleType connectors; + serial::CodingParams const codingParams = LoadCodingParams(mwmFile); + FilesContainerW cont(mwmFile, FileWriter::OP_WRITE_EXISTING); + FileWriter writer = cont.GetWriter(sectionName); + auto const startPos = writer.Pos(); + CrossMwmConnectorSerializer::Serialize(transitions, connectors, codingParams, writer); + auto const sectionSize = writer.Pos() - startPos; - vector transitions; - CalcCrossMwmTransitions(path, mwmFile, country, countryParentNameGetterFn, featureIdToOsmId, - transitions, connectors); + LOG(LINFO, ("Cross mwm section generated, size:", sectionSize, "bytes")); +} - for (size_t i = 0; i < connectors.size(); ++i) - { - VehicleType const vehicleType = static_cast(i); - CrossMwmConnector const & connector = connectors[i]; - LOG(LINFO, (vehicleType, "model: enters:", connector.GetEnters().size(), ", exits:", - connector.GetExits().size())); - } +void BuildRoutingCrossMwmSection(string const & path, string const & mwmFile, + string const & country, + CountryParentNameGetterFn const & countryParentNameGetterFn, + string const & osmToFeatureFile, bool disableCrossMwmProgress) +{ + LOG(LINFO, ("Building cross mwm section for", country)); + using CrossMwmId = connector::OsmId; + CrossMwmConnectorPerVehicleType connectors; + vector> transitions; + + CalcCrossMwmConnectors(path, mwmFile, country, countryParentNameGetterFn, osmToFeatureFile, + transitions, connectors); // We use leaps for cars only. To use leaps for other vehicle types add weights generation // here and change WorldGraph mode selection rule in IndexRouter::CalculateSubroute. FillWeights(path, mwmFile, country, countryParentNameGetterFn, disableCrossMwmProgress, connectors[static_cast(VehicleType::Car)]); - serial::CodingParams const codingParams = LoadCodingParams(mwmFile); - FilesContainerW cont(mwmFile, FileWriter::OP_WRITE_EXISTING); - FileWriter writer = cont.GetWriter(CROSS_MWM_FILE_TAG); - auto const startPos = writer.Pos(); - CrossMwmConnectorSerializer::Serialize(transitions, connectors, codingParams, writer); - auto const sectionSize = writer.Pos() - startPos; - - LOG(LINFO, ("Cross mwm section generated, size:", sectionSize, "bytes")); - return true; + SerializeCrossMwm(mwmFile, CROSS_MWM_FILE_TAG, connectors, transitions); } -bool BuildCrossMwmSection(string const & path, string const & mwmFile, string const & country, - CountryParentNameGetterFn const & countryParentNameGetterFn, - string const & osmToFeatureFile, bool disableCrossMwmProgress) +void BuildTransitCrossMwmSection(string const & path, string const & mwmFile, + string const & country, + CountryParentNameGetterFn const & countryParentNameGetterFn, + bool disableCrossMwmProgress) { - LOG(LINFO, ("Building cross mwm section for", country)); + LOG(LINFO, ("Building transit cross mwm section for", country)); + using CrossMwmId = connector::TransitId; + CrossMwmConnectorPerVehicleType connectors; + vector> transitions; - map featureIdToOsmId; - if (!ParseFeatureIdToOsmIdMapping(osmToFeatureFile, featureIdToOsmId)) - return false; - - return BuildCrossMwmSection(path, mwmFile, country, countryParentNameGetterFn, featureIdToOsmId, - disableCrossMwmProgress); + CalcCrossMwmConnectors(path, mwmFile, country, countryParentNameGetterFn, "" /* mapping file */, + transitions, connectors); + SerializeCrossMwm(mwmFile, TRANSIT_CROSS_MWM_FILE_TAG, connectors, transitions); } } // namespace routing diff --git a/generator/routing_index_generator.hpp b/generator/routing_index_generator.hpp index a56de1f066..53d6a86a6c 100644 --- a/generator/routing_index_generator.hpp +++ b/generator/routing_index_generator.hpp @@ -10,8 +10,13 @@ using CountryParentNameGetterFn = std::function::max(); -} // namespace - namespace routing { -// static -double constexpr CrossMwmConnector::kNoRoute; - -void CrossMwmConnector::AddTransition(uint64_t osmId, uint32_t featureId, uint32_t segmentIdx, - bool oneWay, bool forwardIsEnter, - m2::PointD const & backPoint, m2::PointD const & frontPoint) +namespace connector { - Transition transition(kFakeId, kFakeId, osmId, oneWay, forwardIsEnter, backPoint, frontPoint); - - if (forwardIsEnter) - { - transition.m_enterIdx = base::asserted_cast(m_enters.size()); - m_enters.emplace_back(m_mwmId, featureId, segmentIdx, true /* forward */); - } - else - { - transition.m_exitIdx = base::asserted_cast(m_exits.size()); - m_exits.emplace_back(m_mwmId, featureId, segmentIdx, true /* forward */); - } - - if (!oneWay) - { - if (forwardIsEnter) - { - transition.m_exitIdx = base::asserted_cast(m_exits.size()); - m_exits.emplace_back(m_mwmId, featureId, segmentIdx, false /* forward */); - } - else - { - transition.m_enterIdx = base::asserted_cast(m_enters.size()); - m_enters.emplace_back(m_mwmId, featureId, segmentIdx, false /* forward */); - } - } - - m_transitions[Key(featureId, segmentIdx)] = transition; - m_osmIdToFeatureId.emplace(osmId, featureId); -} - -bool CrossMwmConnector::IsTransition(Segment const & segment, bool isOutgoing) const -{ - auto it = m_transitions.find(Key(segment.GetFeatureId(), segment.GetSegmentIdx())); - if (it == m_transitions.cend()) - return false; - - Transition const & transition = it->second; - if (transition.m_oneWay && !segment.IsForward()) - return false; - - // Note. If |isOutgoing| == true |segment| should be an exit transition segment - // (|isEnter| == false) to be a transition segment. - // Otherwise |segment| should be an enter transition segment (|isEnter| == true) - // to be a transition segment. If not, |segment| is not a transition segment. - // Please see documentation on CrossMwmGraph::IsTransition() method for details. - bool const isEnter = (segment.IsForward() == transition.m_forwardIsEnter); - return isEnter != isOutgoing; -} - -Segment const * CrossMwmConnector::GetTransition(uint64_t osmId, uint32_t segmentIdx, - bool isEnter) const -{ - auto fIt = m_osmIdToFeatureId.find(osmId); - if (fIt == m_osmIdToFeatureId.cend()) - return nullptr; - - uint32_t const featureId = fIt->second; - - auto tIt = m_transitions.find(Key(featureId, segmentIdx)); - if (tIt == m_transitions.cend()) - return nullptr; - - Transition const & transition = tIt->second; - CHECK_EQUAL(transition.m_osmId, osmId, - ("feature:", featureId, ", segment:", segmentIdx, ", point:", - MercatorBounds::ToLatLon(transition.m_frontPoint))); - bool const isForward = transition.m_forwardIsEnter == isEnter; - if (transition.m_oneWay && !isForward) - return nullptr; - - Segment const & segment = - isEnter ? GetEnter(transition.m_enterIdx) : GetExit(transition.m_exitIdx); - CHECK_EQUAL(segment.IsForward(), isForward, ("osmId:", osmId, ", segment:", segment, ", point:", - MercatorBounds::ToLatLon(transition.m_frontPoint))); - return &segment; -} - -m2::PointD const & CrossMwmConnector::GetPoint(Segment const & segment, bool front) const -{ - Transition const & transition = GetTransition(segment); - return segment.IsForward() == front ? transition.m_frontPoint : transition.m_backPoint; -} - -void CrossMwmConnector::GetEdgeList(Segment const & segment, bool isOutgoing, - std::vector & edges) const -{ - Transition const & transition = GetTransition(segment); - if (isOutgoing) - { - ASSERT_NOT_EQUAL(transition.m_enterIdx, kFakeId, ()); - for (size_t exitIdx = 0; exitIdx < m_exits.size(); ++exitIdx) - { - Weight const weight = GetWeight(base::asserted_cast(transition.m_enterIdx), exitIdx); - AddEdge(m_exits[exitIdx], weight, edges); - } - } - else - { - ASSERT_NOT_EQUAL(transition.m_exitIdx, kFakeId, ()); - for (size_t enterIdx = 0; enterIdx < m_enters.size(); ++enterIdx) - { - Weight const weight = GetWeight(enterIdx, base::asserted_cast(transition.m_exitIdx)); - AddEdge(m_enters[enterIdx], weight, edges); - } - } -} - -bool CrossMwmConnector::WeightsWereLoaded() const -{ - switch (m_weightsLoadState) - { - case WeightsLoadState::Unknown: - case WeightsLoadState::ReadyToLoad: return false; - case WeightsLoadState::NotExists: - case WeightsLoadState::Loaded: return true; - } -} - -std::string DebugPrint(CrossMwmConnector::WeightsLoadState state) +std::string DebugPrint(WeightsLoadState state) { switch (state) { - case CrossMwmConnector::WeightsLoadState::Unknown: return "Unknown"; - case CrossMwmConnector::WeightsLoadState::ReadyToLoad: return "ReadyToLoad"; - case CrossMwmConnector::WeightsLoadState::NotExists: return "NotExists"; - case CrossMwmConnector::WeightsLoadState::Loaded: return "Loaded"; + case WeightsLoadState::Unknown: return "Unknown"; + case WeightsLoadState::ReadyToLoad: return "ReadyToLoad"; + case WeightsLoadState::NotExists: return "NotExists"; + case WeightsLoadState::Loaded: return "Loaded"; } } - -void CrossMwmConnector::AddEdge(Segment const & segment, Weight weight, - std::vector & edges) const -{ - if (weight != kNoRoute) - edges.emplace_back(segment, RouteWeight::FromCrossMwmWeight(weight)); -} - -CrossMwmConnector::Transition const & CrossMwmConnector::GetTransition( - Segment const & segment) const -{ - auto it = m_transitions.find(Key(segment.GetFeatureId(), segment.GetSegmentIdx())); - CHECK(it != m_transitions.cend(), ("Not a transition segment:", segment)); - return it->second; -} - -CrossMwmConnector::Weight CrossMwmConnector::GetWeight(size_t enterIdx, size_t exitIdx) const -{ - ASSERT_LESS(enterIdx, m_enters.size(), ()); - ASSERT_LESS(exitIdx, m_exits.size(), ()); - - size_t const i = enterIdx * m_exits.size() + exitIdx; - ASSERT_LESS(i, m_weights.size(), ()); - return m_weights[i]; -} +} // namespace connector } // namespace routing diff --git a/routing/cross_mwm_connector.hpp b/routing/cross_mwm_connector.hpp index 904ca0637c..cc9629112b 100644 --- a/routing/cross_mwm_connector.hpp +++ b/routing/cross_mwm_connector.hpp @@ -1,37 +1,164 @@ #pragma once +#include "routing/cross_mwm_ids.hpp" #include "routing/segment.hpp" +#include "geometry/mercator.hpp" #include "geometry/point2d.hpp" #include "base/assert.hpp" #include +#include #include +#include #include #include namespace routing { +namespace connector +{ +uint32_t constexpr kFakeId = std::numeric_limits::max(); +double constexpr kNoRoute = 0.0; + +using Weight = uint32_t; + +enum class WeightsLoadState +{ + Unknown, + NotExists, + ReadyToLoad, + Loaded +}; + +std::string DebugPrint(WeightsLoadState state); +} // namespace connector + +template class CrossMwmConnector final { public: - static double constexpr kNoRoute = 0.0; - CrossMwmConnector() : m_mwmId(kFakeNumMwmId) {} explicit CrossMwmConnector(NumMwmId mwmId) : m_mwmId(mwmId) {} - void AddTransition(uint64_t osmId, uint32_t featureId, uint32_t segmentIdx, bool oneWay, + void AddTransition(CrossMwmId const & crossMwmId, uint32_t featureId, uint32_t segmentIdx, bool oneWay, bool forwardIsEnter, m2::PointD const & backPoint, - m2::PointD const & frontPoint); + m2::PointD const & frontPoint) + { + Transition transition(connector::kFakeId, connector::kFakeId, crossMwmId, oneWay, + forwardIsEnter, backPoint, frontPoint); + + if (forwardIsEnter) + { + transition.m_enterIdx = base::asserted_cast(m_enters.size()); + m_enters.emplace_back(m_mwmId, featureId, segmentIdx, true /* forward */); + } + else + { + transition.m_exitIdx = base::asserted_cast(m_exits.size()); + m_exits.emplace_back(m_mwmId, featureId, segmentIdx, true /* forward */); + } + + if (!oneWay) + { + if (forwardIsEnter) + { + transition.m_exitIdx = base::asserted_cast(m_exits.size()); + m_exits.emplace_back(m_mwmId, featureId, segmentIdx, false /* forward */); + } + else + { + transition.m_enterIdx = base::asserted_cast(m_enters.size()); + m_enters.emplace_back(m_mwmId, featureId, segmentIdx, false /* forward */); + } + } + + m_transitions[Key(featureId, segmentIdx)] = transition; + m_crossMwmIdToFeatureId.emplace(crossMwmId, featureId); + } + + bool IsTransition(Segment const & segment, bool isOutgoing) const + { + auto const it = m_transitions.find(Key(segment.GetFeatureId(), segment.GetSegmentIdx())); + if (it == m_transitions.cend()) + return false; + + auto const & transition = it->second; + if (transition.m_oneWay && !segment.IsForward()) + return false; + + // Note. If |isOutgoing| == true |segment| should be an exit transition segment + // (|isEnter| == false) to be a transition segment. + // Otherwise |segment| should be an enter transition segment (|isEnter| == true) + // to be a transition segment. If not, |segment| is not a transition segment. + // Please see documentation on CrossMwmGraph::IsTransition() method for details. + bool const isEnter = (segment.IsForward() == transition.m_forwardIsEnter); + return isEnter != isOutgoing; + } + + CrossMwmId const & GetCrossMwmId(Segment const & segment) const + { + return GetTransition(segment).m_crossMwmId; + } - bool IsTransition(Segment const & segment, bool isOutgoing) const; - uint64_t GetOsmId(Segment const & segment) const { return GetTransition(segment).m_osmId; } // returns nullptr if there is no transition for such osm id. - Segment const * GetTransition(uint64_t osmId, uint32_t segmentIdx, bool isEnter) const; - m2::PointD const & GetPoint(Segment const & segment, bool front) const; - void GetEdgeList(Segment const & segment, bool isOutgoing, - std::vector & edges) const; + Segment const * GetTransition(CrossMwmId crossMwmId, uint32_t segmentIdx, bool isEnter) const + { + auto fIt = m_crossMwmIdToFeatureId.find(crossMwmId); + if (fIt == m_crossMwmIdToFeatureId.cend()) + return nullptr; + + uint32_t const featureId = fIt->second; + + auto tIt = m_transitions.find(Key(featureId, segmentIdx)); + if (tIt == m_transitions.cend()) + return nullptr; + + auto const & transition = tIt->second; + CHECK_EQUAL(transition.m_crossMwmId, crossMwmId, + ("feature:", featureId, ", segment:", segmentIdx, + ", point:", MercatorBounds::ToLatLon(transition.m_frontPoint))); + bool const isForward = transition.m_forwardIsEnter == isEnter; + if (transition.m_oneWay && !isForward) + return nullptr; + + Segment const & segment = + isEnter ? GetEnter(transition.m_enterIdx) : GetExit(transition.m_exitIdx); + CHECK_EQUAL(segment.IsForward(), isForward, + ("crossMwmId:", crossMwmId, ", segment:", segment, + ", point:", MercatorBounds::ToLatLon(transition.m_frontPoint))); + return &segment; + } + + m2::PointD const & GetPoint(Segment const & segment, bool front) const + { + auto const & transition = GetTransition(segment); + return segment.IsForward() == front ? transition.m_frontPoint : transition.m_backPoint; + } + + void GetEdgeList(Segment const & segment, bool isOutgoing, std::vector & edges) const + { + auto const & transition = GetTransition(segment); + if (isOutgoing) + { + ASSERT_NOT_EQUAL(transition.m_enterIdx, connector::kFakeId, ()); + for (size_t exitIdx = 0; exitIdx < m_exits.size(); ++exitIdx) + { + auto const weight = GetWeight(base::asserted_cast(transition.m_enterIdx), exitIdx); + AddEdge(m_exits[exitIdx], weight, edges); + } + } + else + { + ASSERT_NOT_EQUAL(transition.m_exitIdx, connector::kFakeId, ()); + for (size_t enterIdx = 0; enterIdx < m_enters.size(); ++enterIdx) + { + auto const weight = GetWeight(enterIdx, base::asserted_cast(transition.m_exitIdx)); + AddEdge(m_enters[enterIdx], weight, edges); + } + } + } std::vector const & GetEnters() const { return m_enters; } std::vector const & GetExits() const { return m_exits; } @@ -49,12 +176,22 @@ public: } bool HasWeights() const { return !m_weights.empty(); } - bool WeightsWereLoaded() const; + + bool WeightsWereLoaded() const + { + switch (m_weightsLoadState) + { + case connector::WeightsLoadState::Unknown: + case connector::WeightsLoadState::ReadyToLoad: return false; + case connector::WeightsLoadState::NotExists: + case connector::WeightsLoadState::Loaded: return true; + } + } template void FillWeights(CalcWeight && calcWeight) { - CHECK_EQUAL(m_weightsLoadState, WeightsLoadState::Unknown, ()); + CHECK_EQUAL(m_weightsLoadState, connector::WeightsLoadState::Unknown, ()); CHECK(m_weights.empty(), ()); m_weights.reserve(m_enters.size() * m_exits.size()); @@ -64,17 +201,12 @@ public: { auto const weight = calcWeight(enter, exit); // Edges weights should be >= astar heuristic, so use std::ceil. - m_weights.push_back(static_cast(std::ceil(weight))); + m_weights.push_back(static_cast(std::ceil(weight))); } } } private: - // This is an internal type for storing edges weights. - // Weight is the time requred for the route to pass. - // Weight is measured in seconds rounded upwards. - using Weight = uint32_t; - struct Key { Key() = default; @@ -101,15 +233,16 @@ private: } }; + template struct Transition { Transition() = default; - Transition(uint32_t enterIdx, uint32_t exitIdx, uint64_t osmId, bool oneWay, + Transition(uint32_t enterIdx, uint32_t exitIdx, CrossMwmIdInner const & crossMwmId, bool oneWay, bool forwardIsEnter, m2::PointD const & backPoint, m2::PointD const & frontPoint) : m_enterIdx(enterIdx) , m_exitIdx(exitIdx) - , m_osmId(osmId) + , m_crossMwmId(crossMwmId) , m_backPoint(backPoint) , m_frontPoint(frontPoint) , m_oneWay(oneWay) @@ -119,7 +252,7 @@ private: uint32_t m_enterIdx = 0; uint32_t m_exitIdx = 0; - uint64_t m_osmId = 0; + CrossMwmIdInner m_crossMwmId = CrossMwmIdInner(); // Endpoints of transition segment. // m_backPoint = points[segmentIdx] // m_frontPoint = points[segmentIdx + 1] @@ -132,29 +265,44 @@ private: bool m_forwardIsEnter = false; }; - enum class WeightsLoadState - { - Unknown, - NotExists, - ReadyToLoad, - Loaded - }; - friend class CrossMwmConnectorSerializer; - friend std::string DebugPrint(WeightsLoadState state); - void AddEdge(Segment const & segment, Weight weight, std::vector & edges) const; - Transition const & GetTransition(Segment const & segment) const; - Weight GetWeight(size_t enterIdx, size_t exitIdx) const; + void AddEdge(Segment const & segment, connector::Weight weight, + std::vector & edges) const + { + if (weight != connector::kNoRoute) + edges.emplace_back(segment, RouteWeight::FromCrossMwmWeight(weight)); + } + + CrossMwmConnector::Transition const & GetTransition( + Segment const & segment) const + { + auto const it = m_transitions.find(Key(segment.GetFeatureId(), segment.GetSegmentIdx())); + CHECK(it != m_transitions.cend(), ("Not a transition segment:", segment)); + return it->second; + } + + connector::Weight GetWeight(size_t enterIdx, size_t exitIdx) const + { + ASSERT_LESS(enterIdx, m_enters.size(), ()); + ASSERT_LESS(exitIdx, m_exits.size(), ()); + + size_t const i = enterIdx * m_exits.size() + exitIdx; + ASSERT_LESS(i, m_weights.size(), ()); + return m_weights[i]; + } NumMwmId const m_mwmId; std::vector m_enters; std::vector m_exits; - std::unordered_map m_transitions; - std::unordered_map m_osmIdToFeatureId; - WeightsLoadState m_weightsLoadState = WeightsLoadState::Unknown; + std::unordered_map, HashKey> m_transitions; + std::unordered_map m_crossMwmIdToFeatureId; + connector::WeightsLoadState m_weightsLoadState = connector::WeightsLoadState::Unknown; uint64_t m_weightsOffset = 0; - Weight m_granularity = 0; - std::vector m_weights; + connector::Weight m_granularity = 0; + // |m_weights| stores edge weights. + // Weight is the time required for the route to pass edges. + // Weight is measured in seconds rounded upwards. + std::vector m_weights; }; } // namespace routing diff --git a/routing/cross_mwm_connector_serialization.cpp b/routing/cross_mwm_connector_serialization.cpp index 4f8f75f785..c8a1ac4477 100644 --- a/routing/cross_mwm_connector_serialization.cpp +++ b/routing/cross_mwm_connector_serialization.cpp @@ -11,28 +11,6 @@ namespace routing // static uint32_t constexpr CrossMwmConnectorSerializer::kLastVersion; -// static -uint32_t CrossMwmConnectorSerializer::CalcBitsPerOsmId(std::vector const & transitions) -{ - uint64_t maxOsmId = 0; - for (Transition const & transition : transitions) - maxOsmId = std::max(maxOsmId, transition.GetOsmId()); - - return bits::NumUsedBits(maxOsmId); -} - -// static -void CrossMwmConnectorSerializer::WriteTransitions(vector const & transitions, - serial::CodingParams const & codingParams, - uint32_t bitsPerOsmId, uint8_t bitsPerMask, - vector & buffer) -{ - MemWriter> memWriter(buffer); - - for (Transition const & transition : transitions) - transition.Serialize(codingParams, bitsPerOsmId, bitsPerMask, memWriter); -} - // static void CrossMwmConnectorSerializer::WriteWeights(vector const & weights, vector & buffer) @@ -40,10 +18,10 @@ void CrossMwmConnectorSerializer::WriteWeights(vector const & weights, MemWriter> memWriter(buffer); BitWriter>> writer(memWriter); - CrossMwmConnector::Weight prevWeight = 1; + connector::Weight prevWeight = 1; for (auto const weight : weights) { - if (weight == CrossMwmConnector::kNoRoute) + if (weight == connector::kNoRoute) { writer.Write(kNoRouteBit, 1); continue; diff --git a/routing/cross_mwm_connector_serialization.hpp b/routing/cross_mwm_connector_serialization.hpp index 934f06d22b..ca83f3e4ea 100644 --- a/routing/cross_mwm_connector_serialization.hpp +++ b/routing/cross_mwm_connector_serialization.hpp @@ -5,6 +5,8 @@ #include "routing/routing_exceptions.hpp" #include "routing/vehicle_mask.hpp" +#include "routing_common/transit_types.hpp" + #include "indexer/coding_params.hpp" #include "indexer/geometry_serialization.hpp" @@ -21,21 +23,26 @@ namespace routing { +template using CrossMwmConnectorPerVehicleType = - std::array(VehicleType::Count)>; + std::array, static_cast(VehicleType::Count)>; class CrossMwmConnectorSerializer final { public: + static uint8_t constexpr stopIdBits = 64; + static uint8_t constexpr lineIdBits = 32; + + template class Transition final { public: Transition() = default; - Transition(uint64_t osmId, uint32_t featureId, uint32_t segmentIdx, VehicleMask roadMask, - VehicleMask oneWayMask, bool forwardIsEnter, m2::PointD const & backPoint, - m2::PointD const & frontPoint) - : m_osmId(osmId) + Transition(CrossMwmId const & crossMwmId, uint32_t featureId, uint32_t segmentIdx, + VehicleMask roadMask, VehicleMask oneWayMask, bool forwardIsEnter, + m2::PointD const & backPoint, m2::PointD const & frontPoint) + : m_crossMwmId(crossMwmId) , m_featureId(featureId) , m_segmentIdx(segmentIdx) , m_backPoint(backPoint) @@ -47,14 +54,28 @@ public: } template - void Serialize(serial::CodingParams const & codingParams, uint32_t bitsPerOsmId, + void WriteCrossMwmId(connector::OsmId const & id, uint8_t n, BitWriter & w) const + { + w.WriteAtMost64Bits(id, n); + } + + template + void WriteCrossMwmId(connector::TransitId const & id, uint8_t /* n */, BitWriter & w) const + { + w.WriteAtMost64Bits(id.m_stop1Id, stopIdBits); + w.WriteAtMost64Bits(id.m_stop2Id, stopIdBits); + w.WriteAtMost32Bits(id.m_lineId, lineIdBits); + } + + template + void Serialize(serial::CodingParams const & codingParams, uint32_t bitsPerCrossMwmId, uint8_t bitsPerMask, Sink & sink) const { serial::SavePoint(sink, m_backPoint, codingParams); serial::SavePoint(sink, m_frontPoint, codingParams); BitWriter writer(sink); - writer.WriteAtMost64Bits(m_osmId, bitsPerOsmId); + WriteCrossMwmId(m_crossMwmId, bitsPerCrossMwmId, writer); WriteDelta(writer, m_featureId + 1); WriteDelta(writer, m_segmentIdx + 1); writer.WriteAtMost32Bits(base::asserted_cast(m_roadMask), bitsPerMask); @@ -62,6 +83,20 @@ public: writer.Write(m_forwardIsEnter ? 0 : 1, 1); } + template + void ReadCrossMwmId(uint8_t /* n */, BitReader & reader, connector::TransitId & readed) + { + readed.m_stop1Id = reader.ReadAtMost64Bits(stopIdBits); + readed.m_stop2Id = reader.ReadAtMost64Bits(stopIdBits); + readed.m_lineId = reader.ReadAtMost32Bits(lineIdBits); + }; + + template + void ReadCrossMwmId(uint8_t n, BitReader & reader, connector::OsmId & readed) + { + readed = reader.ReadAtMost64Bits(n); + } + template void Deserialize(serial::CodingParams const & codingParams, uint32_t bitsPerOsmId, uint8_t bitsPerMask, Source & src) @@ -70,7 +105,7 @@ public: m_frontPoint = serial::LoadPoint(src, codingParams); BitReader reader(src); - m_osmId = reader.ReadAtMost64Bits(bitsPerOsmId); + ReadCrossMwmId(bitsPerOsmId, reader, m_crossMwmId); m_featureId = ReadDelta(reader) - 1; m_segmentIdx = ReadDelta(reader) - 1; m_roadMask = base::asserted_cast(reader.ReadAtMost32Bits(bitsPerMask)); @@ -78,7 +113,7 @@ public: m_forwardIsEnter = reader.Read(1) == 0; } - uint64_t GetOsmId() const { return m_osmId; } + CrossMwmId const & GetCrossMwmId() const { return m_crossMwmId; } uint32_t GetFeatureId() const { return m_featureId; } uint32_t GetSegmentIdx() const { return m_segmentIdx; } m2::PointD const & GetBackPoint() const { return m_backPoint; } @@ -88,7 +123,7 @@ public: VehicleMask GetOneWayMask() const { return m_oneWayMask; } private: - uint64_t m_osmId = 0; + CrossMwmId m_crossMwmId = 0; uint32_t m_featureId = 0; uint32_t m_segmentIdx = 0; m2::PointD m_backPoint = m2::PointD::Zero(); @@ -100,24 +135,24 @@ public: CrossMwmConnectorSerializer() = delete; - template - static void Serialize(std::vector const & transitions, - CrossMwmConnectorPerVehicleType const & connectors, + template + static void Serialize(std::vector> const & transitions, + CrossMwmConnectorPerVehicleType const & connectors, serial::CodingParams const & codingParams, Sink & sink) { - uint32_t const bitsPerOsmId = CalcBitsPerOsmId(transitions); + uint32_t const bitsPerCrossMwmId = CalcBitsPerCrossMwmId(transitions); auto const bitsPerMask = GetBitsPerMask(); std::vector transitionsBuf; - WriteTransitions(transitions, codingParams, bitsPerOsmId, bitsPerMask, transitionsBuf); + WriteTransitions(transitions, codingParams, bitsPerCrossMwmId, bitsPerMask, transitionsBuf); Header header(base::checked_cast(transitions.size()), - base::checked_cast(transitionsBuf.size()), codingParams, bitsPerOsmId, - bitsPerMask); + base::checked_cast(transitionsBuf.size()), codingParams, + bitsPerCrossMwmId, bitsPerMask); std::vector> weightBuffers(connectors.size()); for (size_t i = 0; i < connectors.size(); ++i) { - CrossMwmConnector const & connector = connectors[i]; + CrossMwmConnector const & connector = connectors[i]; if (connector.m_weights.empty()) continue; @@ -136,11 +171,11 @@ public: FlushBuffer(buffer, sink); } - template - static void DeserializeTransitions(VehicleType requiredVehicle, CrossMwmConnector & connector, + template + static void DeserializeTransitions(VehicleType requiredVehicle, CrossMwmConnector & connector, Source & src) { - CHECK(connector.m_weightsLoadState == WeightsLoadState::Unknown, ()); + CHECK(connector.m_weightsLoadState == connector::WeightsLoadState::Unknown, ()); Header header; header.Deserialize(src); @@ -151,7 +186,7 @@ public: for (size_t i = 0; i < numTransitions; ++i) { - Transition transition; + Transition transition; transition.Deserialize(header.GetCodingParams(), header.GetBitsPerOsmId(), header.GetBitsPerMask(), src); AddTransition(transition, requiredMask, connector); @@ -189,18 +224,18 @@ public: connector.m_weightsOffset = weightsOffset; connector.m_granularity = header.GetGranularity(); - connector.m_weightsLoadState = WeightsLoadState::ReadyToLoad; + connector.m_weightsLoadState = connector::WeightsLoadState::ReadyToLoad; return; } - connector.m_weightsLoadState = WeightsLoadState::NotExists; + connector.m_weightsLoadState = connector::WeightsLoadState::NotExists; } - template - static void DeserializeWeights(VehicleType /* vehicle */, CrossMwmConnector & connector, + template + static void DeserializeWeights(VehicleType /* vehicle */, CrossMwmConnector & connector, Source & src) { - CHECK(connector.m_weightsLoadState == WeightsLoadState::ReadyToLoad, ()); + CHECK(connector.m_weightsLoadState == connector::WeightsLoadState::ReadyToLoad, ()); CHECK_GREATER(connector.m_granularity, 0, ()); src.Skip(connector.m_weightsOffset); @@ -215,7 +250,7 @@ public: { if (reader.Read(1) == kNoRouteBit) { - connector.m_weights.push_back(CrossMwmConnector::kNoRoute); + connector.m_weights.push_back(connector::kNoRoute); continue; } @@ -225,24 +260,25 @@ public: prev = current; } - connector.m_weightsLoadState = WeightsLoadState::Loaded; + connector.m_weightsLoadState = connector::WeightsLoadState::Loaded; } - static void AddTransition(Transition const & transition, VehicleMask requiredMask, - CrossMwmConnector & connector) + template + static void AddTransition(Transition const & transition, VehicleMask requiredMask, + CrossMwmConnector & connector) { if ((transition.GetRoadMask() & requiredMask) == 0) return; bool const isOneWay = (transition.GetOneWayMask() & requiredMask) != 0; - connector.AddTransition(transition.GetOsmId(), transition.GetFeatureId(), + connector.AddTransition(transition.GetCrossMwmId(), transition.GetFeatureId(), transition.GetSegmentIdx(), isOneWay, transition.ForwardIsEnter(), transition.GetBackPoint(), transition.GetFrontPoint()); } private: - using Weight = CrossMwmConnector::Weight; - using WeightsLoadState = CrossMwmConnector::WeightsLoadState; + using Weight = connector::Weight; + using WeightsLoadState = connector::WeightsLoadState; static uint32_t constexpr kLastVersion = 0; static uint8_t constexpr kNoRouteBit = 0; @@ -294,17 +330,19 @@ private: VehicleType m_vehicleType = VehicleType::Pedestrian; }; + // @todo(bykoianko) It's necessary to consider implementation Header template class. + // For different cross mwm id may be needs different headers. For example without |bitsPerOsmId|. class Header final { public: Header() = default; Header(uint32_t numTransitions, uint64_t sizeTransitions, - serial::CodingParams const & codingParams, uint32_t bitsPerOsmId, uint8_t bitsPerMask) + serial::CodingParams const & codingParams, uint32_t bitsPerCrossMwmId, uint8_t bitsPerMask) : m_numTransitions(numTransitions) , m_sizeTransitions(sizeTransitions) , m_codingParams(codingParams) - , m_bitsPerOsmId(bitsPerOsmId) + , m_bitsPerCrossMwmId(bitsPerCrossMwmId) , m_bitsPerMask(bitsPerMask) { } @@ -317,7 +355,7 @@ private: WriteToSink(sink, m_sizeTransitions); WriteToSink(sink, m_granularity); m_codingParams.Save(sink); - WriteToSink(sink, m_bitsPerOsmId); + WriteToSink(sink, m_bitsPerCrossMwmId); WriteToSink(sink, m_bitsPerMask); WriteToSink(sink, base::checked_cast(m_sections.size())); @@ -339,7 +377,7 @@ private: m_sizeTransitions = ReadPrimitiveFromSource(src); m_granularity = ReadPrimitiveFromSource(src); m_codingParams.Load(src); - m_bitsPerOsmId = ReadPrimitiveFromSource(src); + m_bitsPerCrossMwmId = ReadPrimitiveFromSource(src); m_bitsPerMask = ReadPrimitiveFromSource(src); auto const sectionsSize = ReadPrimitiveFromSource(src); @@ -354,7 +392,7 @@ private: uint64_t GetSizeTransitions() const { return m_sizeTransitions; } Weight GetGranularity() const { return m_granularity; } serial::CodingParams const & GetCodingParams() const { return m_codingParams; } - uint8_t GetBitsPerOsmId() const { return m_bitsPerOsmId; } + uint8_t GetBitsPerOsmId() const { return m_bitsPerCrossMwmId; } uint8_t GetBitsPerMask() const { return m_bitsPerMask; } std::vector
const & GetSections() const { return m_sections; } @@ -364,12 +402,27 @@ private: uint64_t m_sizeTransitions = 0; Weight m_granularity = kGranularity; serial::CodingParams m_codingParams; - uint32_t m_bitsPerOsmId = 0; + uint32_t m_bitsPerCrossMwmId = 0; uint8_t m_bitsPerMask = 0; std::vector
m_sections; }; - static uint32_t CalcBitsPerOsmId(std::vector const & transitions); + static uint32_t CalcBitsPerCrossMwmId( + std::vector> const & transitions) + { + connector::OsmId osmId = 0; + for (Transition const & transition : transitions) + osmId = std::max(osmId, transition.GetCrossMwmId()); + + return bits::NumUsedBits(osmId); + } + + static uint32_t CalcBitsPerCrossMwmId( + std::vector> const & /* transitions */) + { + // Bit per osm id is not actual for TransitId case. + return 0; + } template static T GetBitsPerMask() @@ -387,10 +440,20 @@ private: buffer.clear(); } - static void WriteTransitions(std::vector const & transitions, + template + static void WriteTransitions(std::vector> const & transitions, serial::CodingParams const & codingParams, uint32_t bitsPerOsmId, - uint8_t bitsPerMask, std::vector & buffer); + uint8_t bitsPerMask, std::vector & buffer) + { + MemWriter> memWriter(buffer); + + for (auto const & transition : transitions) + transition.Serialize(codingParams, bitsPerOsmId, bitsPerMask, memWriter); + } static void WriteWeights(std::vector const & weights, std::vector & buffer); }; + +static_assert(sizeof(transit::StopId) * 8 == 64, "Wrong transit::StopId size"); +static_assert(sizeof(transit::LineId) * 8 == 32, "Wrong transit::LineId size"); } // namespace routing diff --git a/routing/cross_mwm_graph.cpp b/routing/cross_mwm_graph.cpp index 449942e1c5..07e428e878 100644 --- a/routing/cross_mwm_graph.cpp +++ b/routing/cross_mwm_graph.cpp @@ -153,7 +153,7 @@ void CrossMwmGraph::GetTwins(Segment const & s, bool isOutgoing, vector if (allNeighborsHaveCrossMwmSection && currentMwmStatus == MwmStatus::CrossMwmSectionExists) { DeserializeTransitions(neighbors); - m_crossMwmIndexGraph.GetTwinsByOsmId(s, isOutgoing, neighbors, twins); + m_crossMwmIndexGraph.GetTwinsByCrossMwmId(s, isOutgoing, neighbors, twins); } else { diff --git a/routing/cross_mwm_graph.hpp b/routing/cross_mwm_graph.hpp index d86820b50a..89036fae1b 100644 --- a/routing/cross_mwm_graph.hpp +++ b/routing/cross_mwm_graph.hpp @@ -1,5 +1,6 @@ #pragma once +#include "routing/cross_mwm_ids.hpp" #include "routing/cross_mwm_index_graph.hpp" #include "routing/cross_mwm_osrm_graph.hpp" #include "routing/segment.hpp" @@ -154,7 +155,9 @@ private: std::shared_ptr> m_numMwmTree; std::shared_ptr m_vehicleModelFactory; CourntryRectFn const & m_countryRectFn; - CrossMwmIndexGraph m_crossMwmIndexGraph; + // @todo(@tatiana-kondakova) For the time being CrossMwmGraph is implemented for osm id. + // To add cross mwm for transit graph it's necessary to add CrossMwmIndexGraph. + CrossMwmIndexGraph m_crossMwmIndexGraph; CrossMwmOsrmGraph m_crossMwmOsrmGraph; }; diff --git a/routing/cross_mwm_ids.hpp b/routing/cross_mwm_ids.hpp new file mode 100644 index 0000000000..6f6a716a64 --- /dev/null +++ b/routing/cross_mwm_ids.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "routing_common/transit_types.hpp" + +#include "base/visitor.hpp" + +#include + +namespace routing +{ +namespace connector +{ +// Identifier to find a border edge in neighbouring mwm while cross mwm transition +// for pedestrian, bicycle and car routing. +using OsmId = uint64_t; + +// Identifier to find a border edge in neighbouring mwm while cross mwm transition +// for transit routing. +struct TransitId +{ + DECLARE_VISITOR_AND_DEBUG_PRINT(TransitId, visitor(m_stop1Id, "stop1_id"), + visitor(m_stop2Id, "stop2_id"), visitor(m_lineId, "line_id")) + + bool operator==(TransitId const & rhs) const + { + return m_stop1Id == rhs.m_stop1Id && m_stop2Id == rhs.m_stop2Id && m_lineId == rhs.m_lineId; + } + + bool operator!=(TransitId const & rhs) const { return !(rhs == *this); } + + bool operator<(TransitId const & rhs) const + { + if (m_stop1Id != rhs.m_stop1Id) + return m_stop1Id < rhs.m_stop1Id; + if (m_stop2Id != rhs.m_stop2Id) + return m_stop2Id < rhs.m_stop2Id; + return m_lineId < rhs.m_lineId; + } + + bool operator>(TransitId const & rhs) const { return rhs < *this; } + bool operator<=(TransitId const & rhs) const { return !(rhs < *this); } + bool operator>=(TransitId const & rhs) const { return !(*this < rhs); } + + transit::StopId m_stop1Id = transit::kInvalidStopId; + transit::StopId m_stop2Id = transit::kInvalidStopId; + transit::LineId m_lineId = transit::kInvalidLineId; +}; + +struct HashKey +{ + size_t operator()(OsmId const & key) const + { + return std::hash()(key); + } + + size_t operator()(TransitId const & key) const + { + return std::hash()(key.m_stop1Id ^ key.m_stop2Id ^ + static_cast(key.m_lineId)); + } +}; +} // namespace connector +} // namespace routing diff --git a/routing/cross_mwm_index_graph.cpp b/routing/cross_mwm_index_graph.cpp deleted file mode 100644 index e6d8d167f2..0000000000 --- a/routing/cross_mwm_index_graph.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "routing/cross_mwm_index_graph.hpp" - -#include "routing/cross_mwm_connector_serialization.hpp" -#include "routing/cross_mwm_road_graph.hpp" - -using namespace std; - -namespace routing -{ -bool CrossMwmIndexGraph::IsTransition(Segment const & s, bool isOutgoing) -{ - CrossMwmConnector const & c = GetCrossMwmConnectorWithTransitions(s.GetMwmId()); - return c.IsTransition(s, isOutgoing); -} - -void CrossMwmIndexGraph::GetTwinsByOsmId(Segment const & s, bool isOutgoing, - vector const & neighbors, - vector & twins) -{ - uint64_t const osmId = GetCrossMwmConnectorWithTransitions(s.GetMwmId()).GetOsmId(s); - - for (NumMwmId const neighbor : neighbors) - { - auto const it = m_connectors.find(neighbor); - CHECK(it != m_connectors.cend(), ("Connector for", m_numMwmIds->GetFile(neighbor), "was not deserialized.")); - - CrossMwmConnector const & connector = it->second; - // Note. Last parameter in the method below (isEnter) should be set to |isOutgoing|. - // If |isOutgoing| == true |s| should be an exit transition segment and the method below searches enters - // and the last parameter (|isEnter|) should be set to true. - // If |isOutgoing| == false |s| should be an enter transition segment and the method below searches exits - // and the last parameter (|isEnter|) should be set to false. - Segment const * twinSeg = connector.GetTransition(osmId, s.GetSegmentIdx(), isOutgoing); - if (twinSeg == nullptr) - continue; - - CHECK_NOT_EQUAL(twinSeg->GetMwmId(), s.GetMwmId(), ()); - twins.push_back(*twinSeg); - } -} - -void CrossMwmIndexGraph::GetEdgeList(Segment const & s, bool isOutgoing, - vector & edges) -{ - CrossMwmConnector const & c = GetCrossMwmConnectorWithWeights(s.GetMwmId()); - c.GetEdgeList(s, isOutgoing, edges); -} - -CrossMwmConnector const & CrossMwmIndexGraph::GetCrossMwmConnectorWithTransitions(NumMwmId numMwmId) -{ - auto const it = m_connectors.find(numMwmId); - if (it != m_connectors.cend()) - return it->second; - - return Deserialize( - numMwmId, - CrossMwmConnectorSerializer::DeserializeTransitions); -} - -CrossMwmConnector const & CrossMwmIndexGraph::GetCrossMwmConnectorWithWeights(NumMwmId numMwmId) -{ - CrossMwmConnector const & c = GetCrossMwmConnectorWithTransitions(numMwmId); - if (c.WeightsWereLoaded()) - return c; - - return Deserialize( - numMwmId, - CrossMwmConnectorSerializer::DeserializeWeights); -} - -TransitionPoints CrossMwmIndexGraph::GetTransitionPoints(Segment const & s, bool isOutgoing) -{ - CrossMwmConnector const & connector = GetCrossMwmConnectorWithTransitions(s.GetMwmId()); - // In case of transition segments of index graph cross-mwm section the front point of segment - // is used as a point which corresponds to the segment. - return TransitionPoints({connector.GetPoint(s, true /* front */)}); -} -} // namespace routing diff --git a/routing/cross_mwm_index_graph.hpp b/routing/cross_mwm_index_graph.hpp index 91f56b33c0..9f48b46b10 100644 --- a/routing/cross_mwm_index_graph.hpp +++ b/routing/cross_mwm_index_graph.hpp @@ -1,8 +1,10 @@ #pragma once #include "routing/cross_mwm_connector.hpp" -#include "routing/segment.hpp" +#include "routing/cross_mwm_connector_serialization.hpp" +#include "routing/cross_mwm_road_graph.hpp" #include "routing/routing_exceptions.hpp" +#include "routing/segment.hpp" #include "routing/transition_points.hpp" #include "routing/vehicle_mask.hpp" @@ -20,6 +22,7 @@ namespace routing { +template class CrossMwmIndexGraph final { public: @@ -30,18 +33,69 @@ public: { } - bool IsTransition(Segment const & s, bool isOutgoing); + bool IsTransition(Segment const & s, bool isOutgoing) + { + CrossMwmConnector const & c = GetCrossMwmConnectorWithTransitions(s.GetMwmId()); + return c.IsTransition(s, isOutgoing); + } + /// \brief Fills |twins| based on transitions defined in cross_mwm section. /// \note In cross_mwm section transitions are defined by osm ids of theirs features. /// \note This method fills |twins| with all available twins iff all neighboring of mwm of |s| // have cross_mwm section. - void GetTwinsByOsmId(Segment const & s, bool isOutgoing, std::vector const & neighbors, - std::vector & twins); - void GetEdgeList(Segment const & s, bool isOutgoing, std::vector & edges); + void GetTwinsByCrossMwmId(Segment const & s, bool isOutgoing, vector const & neighbors, + vector & twins) + { + auto const & crossMwmId = GetCrossMwmConnectorWithTransitions(s.GetMwmId()).GetCrossMwmId(s); + + for (NumMwmId const neighbor : neighbors) + { + auto const it = m_connectors.find(neighbor); + CHECK(it != m_connectors.cend(), ("Connector for", m_numMwmIds->GetFile(neighbor), "was not deserialized.")); + + CrossMwmConnector const & connector = it->second; + // Note. Last parameter in the method below (isEnter) should be set to |isOutgoing|. + // If |isOutgoing| == true |s| should be an exit transition segment and the method below searches enters + // and the last parameter (|isEnter|) should be set to true. + // If |isOutgoing| == false |s| should be an enter transition segment and the method below searches exits + // and the last parameter (|isEnter|) should be set to false. + Segment const * twinSeg = connector.GetTransition(crossMwmId, s.GetSegmentIdx(), isOutgoing); + if (twinSeg == nullptr) + continue; + + CHECK_NOT_EQUAL(twinSeg->GetMwmId(), s.GetMwmId(), ()); + twins.push_back(*twinSeg); + } + } + + void GetEdgeList(Segment const & s, bool isOutgoing, vector & edges) + { + CrossMwmConnector const & c = GetCrossMwmConnectorWithWeights(s.GetMwmId()); + c.GetEdgeList(s, isOutgoing, edges); + } + void Clear() { m_connectors.clear(); } - TransitionPoints GetTransitionPoints(Segment const & s, bool isOutgoing); + + TransitionPoints GetTransitionPoints(Segment const & s, bool isOutgoing) + { + auto const & connector = GetCrossMwmConnectorWithTransitions(s.GetMwmId()); + // In case of transition segments of index graph cross-mwm section the front point of segment + // is used as a point which corresponds to the segment. + return TransitionPoints({connector.GetPoint(s, true /* front */)}); + } + bool InCache(NumMwmId numMwmId) const { return m_connectors.count(numMwmId) != 0; } - CrossMwmConnector const & GetCrossMwmConnectorWithTransitions(NumMwmId numMwmId); + + CrossMwmConnector const & GetCrossMwmConnectorWithTransitions(NumMwmId numMwmId) + { + auto const it = m_connectors.find(numMwmId); + if (it != m_connectors.cend()) + return it->second; + + return Deserialize( + numMwmId, + CrossMwmConnectorSerializer::DeserializeTransitions); + } template void ForEachTransition(NumMwmId numMwmId, bool isEnter, Fn && fn) @@ -52,7 +106,15 @@ public: } private: - CrossMwmConnector const & GetCrossMwmConnectorWithWeights(NumMwmId numMwmId); + CrossMwmConnector const & GetCrossMwmConnectorWithWeights(NumMwmId numMwmId) + { + auto const & c = GetCrossMwmConnectorWithTransitions(numMwmId); + if (c.WeightsWereLoaded()) + return c; + + return Deserialize( + numMwmId, CrossMwmConnectorSerializer::DeserializeWeights); + } /// \brief Deserializes connectors for an mwm with |numMwmId|. /// \param fn is a function implementing deserialization. @@ -60,7 +122,7 @@ private: /// The first one is transition deserialization and the second is weight deserialization. /// Transition deserialization is much faster and used more often. template - CrossMwmConnector const & Deserialize(NumMwmId numMwmId, Fn && fn) + CrossMwmConnector const & Deserialize(NumMwmId numMwmId, Fn && fn) { MwmSet::MwmHandle handle = m_index.GetMwmHandleByCountryFile(m_numMwmIds->GetFile(numMwmId)); if (!handle.IsAlive()) @@ -74,7 +136,7 @@ private: ReaderSourceFile src(reader); auto it = m_connectors.find(numMwmId); if (it == m_connectors.end()) - it = m_connectors.emplace(numMwmId, CrossMwmConnector(numMwmId)).first; + it = m_connectors.emplace(numMwmId, CrossMwmConnector(numMwmId)).first; fn(m_vehicleType, it->second, src); return it->second; @@ -91,6 +153,6 @@ private: /// * with loaded transition segments and with loaded weights /// (after a call to CrossMwmConnectorSerializer::DeserializeTransitions() /// and CrossMwmConnectorSerializer::DeserializeWeights()) - std::map m_connectors; + std::map> m_connectors; }; } // namespace routing diff --git a/routing/route_weight.cpp b/routing/route_weight.cpp index a70f0ef0b6..0fa67dd15a 100644 --- a/routing/route_weight.cpp +++ b/routing/route_weight.cpp @@ -9,7 +9,7 @@ namespace routing double RouteWeight::ToCrossMwmWeight() const { if (m_nonPassThroughCross > 0) - return CrossMwmConnector::kNoRoute; + return connector::kNoRoute; return GetWeight(); } diff --git a/routing/routing.pro b/routing/routing.pro index 5836211e2e..6c29648c4a 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -21,7 +21,6 @@ SOURCES += \ cross_mwm_connector.cpp \ cross_mwm_connector_serialization.cpp \ cross_mwm_graph.cpp \ - cross_mwm_index_graph.cpp \ cross_mwm_osrm_graph.cpp \ cross_mwm_road_graph.cpp \ cross_mwm_router.cpp \ diff --git a/routing/routing_tests/cross_mwm_connector_test.cpp b/routing/routing_tests/cross_mwm_connector_test.cpp index a7802b066a..cbea901f8c 100644 --- a/routing/routing_tests/cross_mwm_connector_test.cpp +++ b/routing/routing_tests/cross_mwm_connector_test.cpp @@ -1,17 +1,20 @@ #include "testing/testing.hpp" #include "routing/cross_mwm_connector_serialization.hpp" +#include "routing/cross_mwm_ids.hpp" #include "coding/writer.hpp" using namespace routing; +using namespace routing::connector; using namespace std; namespace { NumMwmId constexpr mwmId = 777; -void TestConnectorConsistency(CrossMwmConnector const & connector) +template +void TestConnectorConsistency(CrossMwmConnector const & connector) { for (Segment const & enter : connector.GetEnters()) { @@ -26,7 +29,8 @@ void TestConnectorConsistency(CrossMwmConnector const & connector) } } -void TestEdges(CrossMwmConnector const & connector, Segment const & from, bool isOutgoing, +template +void TestEdges(CrossMwmConnector const & connector, Segment const & from, bool isOutgoing, vector const & expectedEdges) { vector edges; @@ -39,10 +43,10 @@ namespace routing_test { UNIT_TEST(OneWayEnter) { - uint64_t constexpr osmId = 1; + OsmId constexpr osmId = 1; uint32_t constexpr featureId = 1; uint32_t constexpr segmentIdx = 1; - CrossMwmConnector connector(mwmId); + CrossMwmConnector connector(mwmId); connector.AddTransition(osmId, featureId, segmentIdx, true /* oneWay */, true /* forwardIsEnter */, {} /* backPoint */, {} /* frontPoint */); @@ -65,10 +69,10 @@ UNIT_TEST(OneWayEnter) UNIT_TEST(OneWayExit) { - uint64_t constexpr osmId = 1; + OsmId constexpr osmId = 1; uint32_t constexpr featureId = 1; uint32_t constexpr segmentIdx = 1; - CrossMwmConnector connector(mwmId); + CrossMwmConnector connector(mwmId); connector.AddTransition(osmId, featureId, segmentIdx, true /* oneWay */, false /* forwardIsEnter */, {} /* backPoint */, {} /* frontPoint */); @@ -91,10 +95,10 @@ UNIT_TEST(OneWayExit) UNIT_TEST(TwoWayEnter) { - uint64_t constexpr osmId = 1; + OsmId constexpr osmId = 1; uint32_t constexpr featureId = 1; uint32_t constexpr segmentIdx = 1; - CrossMwmConnector connector(mwmId); + CrossMwmConnector connector(mwmId); connector.AddTransition(osmId, featureId, segmentIdx, false /* oneWay */, true /* forwardIsEnter */, {} /* backPoint */, {} /* frontPoint */); @@ -117,10 +121,10 @@ UNIT_TEST(TwoWayEnter) UNIT_TEST(TwoWayExit) { - uint64_t constexpr osmId = 1; + OsmId constexpr osmId = 1; uint32_t constexpr featureId = 1; uint32_t constexpr segmentIdx = 1; - CrossMwmConnector connector(mwmId); + CrossMwmConnector connector(mwmId); connector.AddTransition(osmId, featureId, segmentIdx, false /* oneWay */, false /* forwardIsEnter */, {} /* backPoint */, {} /* frontPoint */); @@ -147,14 +151,14 @@ UNIT_TEST(Serialization) vector buffer; { - vector transitions = { + vector> transitions = { /* osmId featureId, segmentIdx, roadMask, oneWayMask, forwardIsEnter, backPoint, frontPoint */ {100, 10, 1, kCarMask, kCarMask, true, m2::PointD(1.1, 1.2), m2::PointD(1.3, 1.4)}, {200, 20, 2, kCarMask, 0, true, m2::PointD(2.1, 2.2), m2::PointD(2.3, 2.4)}, {300, 30, 3, kPedestrianMask, kCarMask, true, m2::PointD(3.1, 3.2), m2::PointD(3.3, 3.4)}}; - CrossMwmConnectorPerVehicleType connectors; - CrossMwmConnector & carConnector = connectors[static_cast(VehicleType::Car)]; + CrossMwmConnectorPerVehicleType connectors; + CrossMwmConnector & carConnector = connectors[static_cast(VehicleType::Car)]; for (auto const & transition : transitions) CrossMwmConnectorSerializer::AddTransition(transition, kCarMask, carConnector); @@ -166,7 +170,7 @@ UNIT_TEST(Serialization) CrossMwmConnectorSerializer::Serialize(transitions, connectors, codingParams, writer); } - CrossMwmConnector connector(mwmId); + CrossMwmConnector connector(mwmId); { MemReader reader(buffer.data(), buffer.size()); ReaderSource source(reader); @@ -248,13 +252,12 @@ UNIT_TEST(WeightsSerialization) { size_t constexpr kNumTransitions = 3; vector const weights = { - 4.0, 20.0, CrossMwmConnector::kNoRoute, 12.0, CrossMwmConnector::kNoRoute, 40.0, 48.0, - 24.0, 12.0}; + 4.0, 20.0, connector::kNoRoute, 12.0, connector::kNoRoute, 40.0, 48.0, 24.0, 12.0}; TEST_EQUAL(weights.size(), kNumTransitions * kNumTransitions, ()); vector buffer; { - vector transitions; + vector> transitions; for (uint32_t featureId = 0; featureId < kNumTransitions; ++featureId) { auto const osmId = static_cast(featureId * 10); @@ -262,8 +265,8 @@ UNIT_TEST(WeightsSerialization) true /* forwardIsEnter */, m2::PointD::Zero(), m2::PointD::Zero()); } - CrossMwmConnectorPerVehicleType connectors; - CrossMwmConnector & carConnector = connectors[static_cast(VehicleType::Car)]; + CrossMwmConnectorPerVehicleType connectors; + CrossMwmConnector & carConnector = connectors[static_cast(VehicleType::Car)]; for (auto const & transition : transitions) CrossMwmConnectorSerializer::AddTransition(transition, kCarMask, carConnector); @@ -276,7 +279,7 @@ UNIT_TEST(WeightsSerialization) CrossMwmConnectorSerializer::Serialize(transitions, connectors, codingParams, writer); } - CrossMwmConnector connector(mwmId); + CrossMwmConnector connector(mwmId); { MemReader reader(buffer.data(), buffer.size()); ReaderSource source(reader); @@ -308,7 +311,7 @@ UNIT_TEST(WeightsSerialization) for (uint32_t exitId = 0; exitId < kNumTransitions; ++exitId) { auto const weight = weights[weightIdx]; - if (weight != CrossMwmConnector::kNoRoute) + if (weight != connector::kNoRoute) { expectedEdges.emplace_back(Segment(mwmId, exitId, 1 /* segmentIdx */, false /* forward */), RouteWeight::FromCrossMwmWeight(weight)); diff --git a/xcode/routing/routing.xcodeproj/project.pbxproj b/xcode/routing/routing.xcodeproj/project.pbxproj index be2aa3f0b5..c18cb7bd1f 100644 --- a/xcode/routing/routing.xcodeproj/project.pbxproj +++ b/xcode/routing/routing.xcodeproj/project.pbxproj @@ -118,7 +118,6 @@ 56CA09E91E30F19800D05C9A /* libtraffic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56CA09E81E30F19800D05C9A /* libtraffic.a */; }; 56CA630A1F619C1000E6681B /* road_graph_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56CA63061F61206700E6681B /* road_graph_tests.cpp */; }; 56CC5A371E3884960016AC46 /* cross_mwm_index_graph.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56CC5A361E3884960016AC46 /* cross_mwm_index_graph.hpp */; }; - 56D637D61E4B12AA00B86D7B /* cross_mwm_index_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56D637D51E4B12AA00B86D7B /* cross_mwm_index_graph.cpp */; }; 56EA2FD51D8FD8590083F01A /* routing_helpers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56EA2FD41D8FD8590083F01A /* routing_helpers.hpp */; }; 56ED7DBD1F69425700B67156 /* turn_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 567E9F741F5850460064CB96 /* turn_test.cpp */; }; 56F0D7341D896A5300045886 /* libmap.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67BD35DE1C69F198003AA26F /* libmap.a */; }; @@ -152,6 +151,7 @@ 56F0D7591D896A5300045886 /* packed_polygons_obsolete.bin in Resources */ = {isa = PBXBuildFile; fileRef = 671182E81C7F0E1F00CB8177 /* packed_polygons_obsolete.bin */; }; 56F0D75A1D896A5300045886 /* classificator.txt in Resources */ = {isa = PBXBuildFile; fileRef = 6742AD531C68BB14009CB89E /* classificator.txt */; }; 56F0D75B1D896A5300045886 /* sound-strings in Resources */ = {isa = PBXBuildFile; fileRef = 6742AD611C68F747009CB89E /* sound-strings */; }; + 56FA20471FBF23A90045DE78 /* cross_mwm_ids.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56FA20461FBF23A90045DE78 /* cross_mwm_ids.hpp */; }; 670B84C01A9381D900CE4492 /* cross_routing_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670B84BE1A9381D900CE4492 /* cross_routing_context.cpp */; }; 670B84C11A9381D900CE4492 /* cross_routing_context.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670B84BF1A9381D900CE4492 /* cross_routing_context.hpp */; }; 670C62131AC5A15700C38A8C /* routing_mapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670C62111AC5A15700C38A8C /* routing_mapping.cpp */; }; @@ -414,9 +414,9 @@ 56CA09E81E30F19800D05C9A /* libtraffic.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtraffic.a; path = "/Users/vladimirbykoyanko/src_github_master/omim/xcode/traffic/../../../omim-build/xcode/Debug/libtraffic.a"; sourceTree = ""; }; 56CA63061F61206700E6681B /* road_graph_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = road_graph_tests.cpp; sourceTree = ""; }; 56CC5A361E3884960016AC46 /* cross_mwm_index_graph.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cross_mwm_index_graph.hpp; sourceTree = ""; }; - 56D637D51E4B12AA00B86D7B /* cross_mwm_index_graph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cross_mwm_index_graph.cpp; sourceTree = ""; }; 56EA2FD41D8FD8590083F01A /* routing_helpers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_helpers.hpp; sourceTree = ""; }; 56F0D75F1D896A5300045886 /* routing_benchmarks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = routing_benchmarks.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 56FA20461FBF23A90045DE78 /* cross_mwm_ids.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cross_mwm_ids.hpp; sourceTree = ""; }; 670B84BE1A9381D900CE4492 /* cross_routing_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cross_routing_context.cpp; sourceTree = ""; }; 670B84BF1A9381D900CE4492 /* cross_routing_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cross_routing_context.hpp; sourceTree = ""; }; 670C62111AC5A15700C38A8C /* routing_mapping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = routing_mapping.cpp; sourceTree = ""; }; @@ -811,6 +811,7 @@ 675343FA1A3F640D00A0A8C3 /* routing */ = { isa = PBXGroup; children = ( + 56FA20461FBF23A90045DE78 /* cross_mwm_ids.hpp */, 40BEC0801F99FFD600E06CA4 /* transit_info.hpp */, 5670595B1F3AF97F0062672D /* checkpoint_predictor.cpp */, 5670595C1F3AF97F0062672D /* checkpoint_predictor.hpp */, @@ -826,7 +827,6 @@ 56C439251E93BF8C00998E29 /* cross_mwm_graph.hpp */, 56C439261E93BF8C00998E29 /* cross_mwm_osrm_graph.cpp */, 56C439271E93BF8C00998E29 /* cross_mwm_osrm_graph.hpp */, - 56D637D51E4B12AA00B86D7B /* cross_mwm_index_graph.cpp */, 674F9BBA1B0A580E00704FFA /* async_router.cpp */, 674F9BBB1B0A580E00704FFA /* async_router.hpp */, 671F58BA1B874EA20032311E /* base */, @@ -1019,6 +1019,7 @@ 56099E341CC9247E00A7772A /* bicycle_directions.hpp in Headers */, 670EE55E1B6001E7001E8064 /* routing_session.hpp in Headers */, 56099E291CC7C97D00A7772A /* loaded_path_segment.hpp in Headers */, + 56FA20471FBF23A90045DE78 /* cross_mwm_ids.hpp in Headers */, 670EE55F1B6001E7001E8064 /* routing_settings.hpp in Headers */, 56CA09E61E30E73B00D05C9A /* index_graph_tools.hpp in Headers */, 0C81E1581F0258AA00DC66DF /* segmented_route.hpp in Headers */, @@ -1289,7 +1290,6 @@ 5694CECC1EBA25F7004576D3 /* road_access.cpp in Sources */, A1616E2B1B6B60AB003F078E /* router_delegate.cpp in Sources */, 6741AA9C1BF35331002C974C /* turns_notification_manager.cpp in Sources */, - 56D637D61E4B12AA00B86D7B /* cross_mwm_index_graph.cpp in Sources */, 0C0DF9211DE898B70055A22F /* index_graph_starter.cpp in Sources */, A120B3471B4A7BE5002F3808 /* cross_mwm_router.cpp in Sources */, 56C439281E93BF8C00998E29 /* cross_mwm_graph.cpp in Sources */,