diff --git a/generator/transit_generator.cpp b/generator/transit_generator.cpp index e817c2c037..23ed24df60 100644 --- a/generator/transit_generator.cpp +++ b/generator/transit_generator.cpp @@ -49,18 +49,12 @@ using namespace std; namespace { -bool LessById(Stop const & s1, Stop const & s2) -{ - return s1.GetId() < s2.GetId(); -} - /// \returns ref to a stop at |stops| by |stopId|. Stop const & FindStopById(vector const & stops, StopId stopId) { - ASSERT(is_sorted(stops.cbegin(), stops.cend(), LessById), ()); + ASSERT(is_sorted(stops.cbegin(), stops.cend()), ()); auto s1Id = equal_range(stops.cbegin(), stops.cend(), - Stop(stopId, kInvalidOsmId, kInvalidFeatureId, kInvalidTransferId, {}, m2::PointD(), {}), - LessById); + Stop(stopId, kInvalidOsmId, kInvalidFeatureId, kInvalidTransferId, {}, m2::PointD(), {})); CHECK(s1Id.first != stops.cend(), ("No a stop with id:", stopId, "in stops:", stops)); CHECK_EQUAL(distance(s1Id.first, s1Id.second), 1, ("A stop with id:", stopId, "is not unique in stops:", stops)); return *s1Id.first; @@ -238,15 +232,26 @@ void GraphData::Clear() bool GraphData::IsValid() const { + if (!IsUnique()) + return false; + return ::IsValid(m_stops) && ::IsValid(m_gates) && ::IsValid(m_edges) && ::IsValid(m_transfers) && ::IsValid(m_lines) && ::IsValid(m_shapes) && ::IsValid(m_networks); } -void GraphData::SortStops() { sort(m_stops.begin(), m_stops.end(), LessById); } +void GraphData::Sort() +{ + sort(m_stops.begin(), m_stops.end()); + sort(m_gates.begin(), m_gates.end()); + sort(m_transfers.begin(), m_transfers.end()); + sort(m_lines.begin(), m_lines.end()); + sort(m_shapes.begin(), m_shapes.end()); + sort(m_networks.begin(), m_networks.end()); +} void GraphData::CalculateEdgeWeight() { - CHECK(is_sorted(m_stops.cbegin(), m_stops.cend(), LessById), ()); + CHECK(is_sorted(m_stops.cbegin(), m_stops.cend()), ()); for (auto & e : m_edges) { @@ -318,6 +323,24 @@ void GraphData::CalculateBestPedestrianSegment(string const & mwmPath, string co void GraphData::ClipGraphByMwm(std::vector const & mwmBorders) { // @todo(bykoianko) Rules for graph clipping should be implemented here. + +} + +bool GraphData::IsUnique() const +{ + if (adjacent_find(m_stops.begin(), m_stops.end()) != m_stops.end()) + return false; + if (adjacent_find(m_gates.begin(), m_gates.end()) != m_gates.end()) + return false; + if (adjacent_find(m_transfers.begin(), m_transfers.end()) != m_transfers.end()) + return false; + if (adjacent_find(m_lines.begin(), m_lines.end()) != m_lines.end()) + return false; + if (adjacent_find(m_shapes.begin(), m_shapes.end()) != m_shapes.end()) + return false; + if (adjacent_find(m_networks.begin(), m_networks.end()) != m_networks.end()) + return false; + return true; } void DeserializeFromJson(OsmIdToFeatureIdsMap const & mapping, @@ -350,7 +373,7 @@ void ProcessGraph(string const & mwmPath, string const & countryId, OsmIdToFeatureIdsMap const & osmIdToFeatureIdsMap, GraphData & data) { data.CalculateBestPedestrianSegment(mwmPath, countryId); - data.SortStops(); + data.Sort(); data.CalculateEdgeWeight(); CHECK(data.IsValid(), (mwmPath)); } @@ -382,6 +405,8 @@ void BuildTransit(string const & mwmDir, string const & countryId, jointData.Append(data); } + jointData.Sort(); + CHECK(jointData.IsValid(), (mwmPath, countryId)); jointData.SerializeToMwm(mwmPath); } } // namespace transit diff --git a/generator/transit_generator.hpp b/generator/transit_generator.hpp index 03371b19cf..7d0c39db00 100644 --- a/generator/transit_generator.hpp +++ b/generator/transit_generator.hpp @@ -114,7 +114,8 @@ public: void Clear(); bool IsValid() const; - void SortStops(); + /// \brief Sorts all class fields execpt for |m_edges| by their ids. + void Sort(); /// \brief Calculates and updates |m_edges| by adding valid value for Edge::m_weight /// if it's not valid. /// \note |m_stops|, Edge::m_stop1Id and Edge::m_stop2Id in |m_edges| should be valid before call. @@ -135,6 +136,8 @@ public: std::vector const & GetNetworks() const { return m_networks; } private: + bool IsUnique() const; + std::vector m_stops; std::vector m_gates; std::vector m_edges; diff --git a/routing_common/transit_types.cpp b/routing_common/transit_types.cpp index 556a4173a7..d72f85825b 100644 --- a/routing_common/transit_types.cpp +++ b/routing_common/transit_types.cpp @@ -165,6 +165,13 @@ bool Gate::IsValid() const } // ShapeId ---------------------------------------------------------------------------------------- +bool ShapeId::operator<(ShapeId const & rhs) const +{ + if (m_stop1Id != rhs.m_stop1Id) + return rhs.m_stop1Id < m_stop1Id; + return m_stop2Id < rhs.m_stop2Id; +} + bool ShapeId::operator==(ShapeId const & rhs) const { return m_stop1Id == rhs.m_stop1Id && m_stop2Id == rhs.m_stop2Id; diff --git a/routing_common/transit_types.hpp b/routing_common/transit_types.hpp index 4e3efc503e..ff53d3c489 100644 --- a/routing_common/transit_types.hpp +++ b/routing_common/transit_types.hpp @@ -87,6 +87,8 @@ public: explicit FeatureIdentifiers(bool serializeFeatureIdOnly); FeatureIdentifiers(OsmId osmId, FeatureId const & featureId, bool serializeFeatureIdOnly); + bool operator<(FeatureIdentifiers const & rhs) const { return m_osmId < rhs.m_osmId; } + bool operator==(FeatureIdentifiers const & rhs) const { return m_osmId == rhs.m_osmId; } bool IsEqualForTesting(FeatureIdentifiers const & rhs) const { return m_featureId == rhs.m_featureId; } bool IsValid() const { return m_featureId != kInvalidFeatureId; } void SetOsmId(OsmId osmId) { m_osmId = osmId; } @@ -136,6 +138,8 @@ public: std::vector const & lineIds, m2::PointD const & point, std::vector const & titleAnchors); + bool operator<(Stop const & rhs) const { return m_id < rhs.m_id; } + bool operator==(Stop const & rhs) const { return m_id == rhs.m_id; } bool IsEqualForTesting(Stop const & stop) const; bool IsValid() const; @@ -191,6 +195,8 @@ public: Gate(OsmId osmId, FeatureId featureId, bool entrance, bool exit, double weight, std::vector const & stopIds, m2::PointD const & point); + bool operator<(Gate const & rhs) const { return m_featureIdentifiers < rhs.m_featureIdentifiers; } + bool operator==(Gate const & rhs) const { return m_featureIdentifiers == rhs.m_featureIdentifiers; } bool IsEqualForTesting(Gate const & gate) const; bool IsValid() const; void SetBestPedestrianSegment(SingleMwmSegment const & s) { m_bestPedestrianSegment = s; }; @@ -230,6 +236,7 @@ public: ShapeId() = default; ShapeId(StopId stop1Id, StopId stop2Id) : m_stop1Id(stop1Id), m_stop2Id(stop2Id) {} + bool operator<(ShapeId const & rhs) const; bool operator==(ShapeId const & rhs) const; bool IsEqualForTesting(ShapeId const & rhs) const { return *this == rhs; } @@ -286,6 +293,8 @@ public: Transfer(StopId id, m2::PointD const & point, std::vector const & stopIds, std::vector const & titleAnchors); + bool operator<(Transfer const & rhs) const { return m_id < rhs.m_id; } + bool operator==(Transfer const & rhs) const { return m_id == rhs.m_id; } bool IsEqualForTesting(Transfer const & transfer) const; bool IsValid() const; @@ -331,6 +340,8 @@ public: Line(LineId id, std::string const & number, std::string const & title, std::string const & type, std::string const & color, NetworkId networkId, Ranges const & stopIds); + bool operator<(Line const & rhs) const { return m_id < rhs.m_id; } + bool operator==(Line const & rhs) const { return m_id == rhs.m_id; } bool IsEqualForTesting(Line const & line) const; bool IsValid() const; @@ -364,6 +375,8 @@ public: Shape() = default; Shape(ShapeId const & id, std::vector const & polyline) : m_id(id), m_polyline(polyline) {} + bool operator<(Shape const & rhs) const { return m_id < rhs.m_id; } + bool operator==(Shape const & rhs) const { return m_id == rhs.m_id; } bool IsEqualForTesting(Shape const & shape) const; bool IsValid() const { return m_id.IsValid() && m_polyline.size() > 1; } @@ -384,6 +397,8 @@ public: Network() = default; Network(NetworkId id, std::string const & title); + bool operator<(Network const & rhs) const { return m_id < rhs.m_id; } + bool operator==(Network const & rhs) const { return m_id == rhs.m_id; } bool IsEqualForTesting(Network const & shape) const; bool IsValid() const;