diff --git a/generator/generator_tests/transit_graph_test.cpp b/generator/generator_tests/transit_graph_test.cpp index 2993083a7b..066f04c2cf 100644 --- a/generator/generator_tests/transit_graph_test.cpp +++ b/generator/generator_tests/transit_graph_test.cpp @@ -78,15 +78,15 @@ void TestNetworks(vector const & networks) void TestEdges(vector const & edges) { vector const expectedEdges = { - {0 /* stop 1 id */, 1 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {0 /* stop 1 id */, 1 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{0, 1}} /* shape ids */}, - {1 /* stop 1 id */, 2 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {1 /* stop 1 id */, 2 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{1, 2}} /* shape ids */}, - {2 /* stop 1 id */, 3 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {2 /* stop 1 id */, 3 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{2, 3}} /* shape ids */}, - {3 /* stop 1 id */, 4 /* stop 2 id */, 10.0 /* weight */, 1 /* line id */, false /* transfer */, + {3 /* stop 1 id */, 4 /* stop 2 id */, 10 /* weight */, 1 /* line id */, false /* transfer */, {{3, 4}} /* shape ids */}, - {5 /* stop 1 id */, 6 /* stop 2 id */, 20.0 /* weight */, 2 /* line id */, false /* transfer */, + {5 /* stop 1 id */, 6 /* stop 2 id */, 20 /* weight */, 2 /* line id */, false /* transfer */, {{5, 6}} /* shape ids */} }; TestForEquivalence(edges, expectedEdges); @@ -439,11 +439,11 @@ UNIT_TEST(ClipGraph_OneLineTest) TestTransfers(graph->GetTransfers()); vector const expectedEdges = { - {0 /* stop 1 id */, 1 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {0 /* stop 1 id */, 1 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{0, 1}} /* shape ids */}, - {1 /* stop 1 id */, 2 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {1 /* stop 1 id */, 2 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{1, 2}} /* shape ids */}, - {2 /* stop 1 id */, 3 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {2 /* stop 1 id */, 3 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{2, 3}} /* shape ids */} }; TestForEquivalence(graph->GetEdges(), expectedEdges); @@ -520,11 +520,11 @@ UNIT_TEST(ClipGraph_TwoLinesTest) TestTransfers(graph->GetTransfers()); vector const expectedEdges = { - {1 /* stop 1 id */, 2 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {1 /* stop 1 id */, 2 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{1, 2}} /* shape ids */}, - {2 /* stop 1 id */, 3 /* stop 2 id */, 20.0 /* weight */, 1 /* line id */, false /* transfer */, + {2 /* stop 1 id */, 3 /* stop 2 id */, 20 /* weight */, 1 /* line id */, false /* transfer */, {{2, 3}} /* shape ids */}, - {5 /* stop 1 id */, 6 /* stop 2 id */, 20.0 /* weight */, 2 /* line id */, false /* transfer */, + {5 /* stop 1 id */, 6 /* stop 2 id */, 20 /* weight */, 2 /* line id */, false /* transfer */, {{5, 6}} /* shape ids */} }; TestForEquivalence(graph->GetEdges(), expectedEdges); diff --git a/generator/generator_tests/transit_test.cpp b/generator/generator_tests/transit_test.cpp index 07b10f72bb..3e07955667 100644 --- a/generator/generator_tests/transit_test.cpp +++ b/generator/generator_tests/transit_test.cpp @@ -138,10 +138,10 @@ UNIT_TEST(DeserializerFromJson_Gates) vector const expected = { Gate(46116860 /* osm id */, 0 /* feature id */, true /* entrance */, - true /* exit */, 60.0 /* weight */, {442018474} /* stop ids */, + true /* exit */, 60 /* weight */, {442018474} /* stop ids */, {43.8594864, 68.33320554776377} /* point */), Gate(18446744073709551615ULL /* osm id */, 2 /* feature id */, true /* entrance */, - true /* exit */, 60.0 /* weight */, {442018465} /* stop ids */, + true /* exit */, 60 /* weight */, {442018465} /* stop ids */, {43.9290544, 68.41120791512581} /* point */)}; OsmIdToFeatureIdsMap mapping; @@ -176,7 +176,7 @@ UNIT_TEST(DeserializerFromJson_Edges) "stop2_id": 442018446, "line_id": 72551680, "shape_ids": [], - "weight" : 345.6, + "weight" : 345, "stop1_id": 442018445, "transfer": false } @@ -186,7 +186,7 @@ UNIT_TEST(DeserializerFromJson_Edges) Edge(442018444 /* stop 1 id */, 442018445 /* stop 2 id */, kInvalidWeight /* weight */, 72551680 /* line id */, false /* transfer */, {ShapeId(209186407, 209186410), ShapeId(209186408, 209186411)}), - Edge(442018445 /* stop 1 id */, 442018446 /* stop 2 id */, 345.6 /* weight */, + Edge(442018445 /* stop 1 id */, 442018446 /* stop 2 id */, 345 /* weight */, 72551680 /* line id */, false /* transfer */, {} /* shape ids */)}; TestDeserializerFromJson(jsonBuffer, "edges", expected); @@ -261,11 +261,11 @@ UNIT_TEST(DeserializerFromJson_Lines) vector const expected = {Line(19207936 /* line id */, "1" /* number */, "Московская линия" /* title */, "subway" /* type */, "green" /* color */, 2 /* network id */, {{343262691, 343259523, 343252898, 209191847, 2947858576}} /* stop ids */, - 150.0 /* interval */), + 150 /* interval */), Line(19207937 /* line id */, "2" /* number */, "Московская линия" /* title */, "subway" /* type */, "red" /* color */, 2 /* network id */, {{246659391, 246659390, 209191855, 209191854, 209191853, - 209191852, 209191851}} /* stop ids */, 150.0 /* interval */)}; + 209191852, 209191851}} /* stop ids */, 150 /* interval */)}; TestDeserializerFromJson(jsonBuffer, "lines", expected); } diff --git a/generator/transit_generator.hpp b/generator/transit_generator.hpp index edabcccdd5..84a9c38d63 100644 --- a/generator/transit_generator.hpp +++ b/generator/transit_generator.hpp @@ -45,6 +45,16 @@ public: void operator()(FeatureIdentifiers & id, char const * name = nullptr); void operator()(StopIdRanges & rs, char const * name = nullptr); + template + typename std::enable_if::value || + std::is_same::value>::type + operator()(T & t, char const * name = nullptr) + { + typename T::RepType id; + operator()(id, name); + t.Set(id); + } + template void operator()(std::vector & vs, char const * name = nullptr) { @@ -64,8 +74,10 @@ public: } template - typename std::enable_if::value>::type operator()(T & t, - char const * name = nullptr) + typename std::enable_if::value && + !std::is_same::value && + !std::is_same::value>::type + operator()(T & t, char const * name = nullptr) { if (name != nullptr && json_is_object(m_node)) { diff --git a/routing_common/routing_common_tests/transit_test.cpp b/routing_common/routing_common_tests/transit_test.cpp index 9a6cc53423..8f75ef69bc 100644 --- a/routing_common/routing_common_tests/transit_test.cpp +++ b/routing_common/routing_common_tests/transit_test.cpp @@ -175,7 +175,7 @@ UNIT_TEST(Transit_SingleMwmSegmentSerialization) UNIT_TEST(Transit_GateSerialization) { Gate gate(12345678 /* osm id */, 12345 /* feature id */, true /* entrance */, false /* exit */, - 117.8 /* weight */, {1, 2, 3} /* stop ids */, {30.0, 50.0} /* point */); + 117 /* weight */, {1, 2, 3} /* stop ids */, {30.0, 50.0} /* point */); TestSerialization(gate); TEST(gate.IsValid(), (gate)); } @@ -186,21 +186,21 @@ UNIT_TEST(Transit_GatesRelational) 123 /* feature id */, true /* entrance */, false /* exit */, - 1.0 /* weight */, + 1 /* weight */, {1, 2, 3} /* stops ids */, m2::PointD(0.0, 0.0)}, {12345678 /* osm id */, 1234 /* feature id */, true /* entrance */, false /* exit */, - 1.0 /* weight */, + 1 /* weight */, {1, 2, 3} /* stops ids */, m2::PointD(0.0, 0.0)}, {12345678 /* osm id */, 1234 /* feature id */, true /* entrance */, false /* exit */, - 1.0 /* weight */, + 1 /* weight */, {1, 2, 3, 4} /* stops ids */, m2::PointD(0.0, 0.0)}}; TEST(is_sorted(gates.cbegin(), gates.cend()), ()); @@ -208,7 +208,7 @@ UNIT_TEST(Transit_GatesRelational) UNIT_TEST(Transit_EdgeSerialization) { - Edge edge(1 /* start stop id */, 2 /* finish stop id */, 123.4 /* weight */, 11 /* line id */, + Edge edge(1 /* start stop id */, 2 /* finish stop id */, 123 /* weight */, 11 /* line id */, false /* transfer */, {ShapeId(1, 2), ShapeId(3, 4), ShapeId(5, 6)} /* shape ids */); TestSerialization(edge); TEST(edge.IsValid(), (edge)); @@ -227,21 +227,21 @@ UNIT_TEST(Transit_LineSerialization) { Line line(1 /* line id */, "2" /* number */, "Линия" /* title */, "subway" /* type */, "red" /* color */, 3 /* network id */, {{1}} /* stop ids */, - 10.0 /* interval */); + 10 /* interval */); TestSerialization(line); TEST(line.IsValid(), (line)); } { Line line(10 /* line id */, "11" /* number */, "Линия" /* title */, "subway" /* type */, "green" /* color */, 12 /* network id */, - {{13, 14, 15}} /* stop ids */, 15.0 /* interval */); + {{13, 14, 15}} /* stop ids */, 15 /* interval */); TestSerialization(line); TEST(line.IsValid(), (line)); } { Line line(100 /* line id */, "101" /* number */, "Линия" /* title */, "subway" /* type */, "blue" /* color */, 103 /* network id */, - {{1, 2, 3}, {7, 8, 9}} /* stop ids */, 15.0 /* interval */); + {{1, 2, 3}, {7, 8, 9}} /* stop ids */, 15 /* interval */); TestSerialization(line); TEST(line.IsValid(), (line)); } diff --git a/routing_common/transit_serdes.hpp b/routing_common/transit_serdes.hpp index 869258293a..5a8406a86e 100644 --- a/routing_common/transit_serdes.hpp +++ b/routing_common/transit_serdes.hpp @@ -15,6 +15,7 @@ #include "base/assert.hpp" #include "base/exception.hpp" #include "base/macros.hpp" +#include "base/newtype.hpp" #include #include @@ -97,6 +98,20 @@ public: } } + void operator()(Edge::MonotoneEdgeId const & t, char const * /* name */ = nullptr) + { + CHECK_GREATER_OR_EQUAL(t.Get(), m_lastEncodedMonotoneEdgeId.Get(), ()); + WriteVarUint(m_sink, static_cast(t.Get() - m_lastEncodedMonotoneEdgeId.Get())); + m_lastEncodedMonotoneEdgeId = t; + } + + void operator()(Stop::MonotoneStopId const & t, char const * /* name */ = nullptr) + { + CHECK_GREATER_OR_EQUAL(t.Get(), m_lastEncodedMonotoneStopId.Get(), ()); + WriteVarUint(m_sink, static_cast(t.Get() - m_lastEncodedMonotoneStopId.Get())); + m_lastEncodedMonotoneStopId = t; + } + void operator()(FeatureIdentifiers const & id, char const * name = nullptr) { if (id.IsSerializeFeatureIdOnly()) @@ -122,6 +137,8 @@ public: private: Sink & m_sink; + Edge::MonotoneEdgeId m_lastEncodedMonotoneEdgeId = Edge::MonotoneEdgeId(0); + Stop::MonotoneStopId m_lastEncodedMonotoneStopId = Stop::MonotoneStopId(0); }; template @@ -174,6 +191,18 @@ public: p = Int64ToPoint(ReadVarInt(m_source), POINT_COORD_BITS); } + void operator()(Edge::MonotoneEdgeId & t, char const * /* name */ = nullptr) + { + t = m_lastDecodedMonotoneEdgeId + Edge::MonotoneEdgeId(ReadVarUint(m_source)); + m_lastDecodedMonotoneEdgeId = t; + } + + void operator()(Stop::MonotoneStopId & t, char const * /* name */ = nullptr) + { + t = m_lastDecodedMonotoneStopId + Stop::MonotoneStopId(ReadVarUint(m_source)); + m_lastDecodedMonotoneStopId = t; + } + void operator()(FeatureIdentifiers & id, char const * name = nullptr) { if (id.IsSerializeFeatureIdOnly()) @@ -210,14 +239,17 @@ public: (*this)(v); } - template - typename std::enable_if::value>::type operator()(T & t, char const * /* name */ = nullptr) + template + typename std::enable_if::value>::type + operator()(T & t, char const * /* name */ = nullptr) { t.Visit(*this); } private: Source & m_source; + Edge::MonotoneEdgeId m_lastDecodedMonotoneEdgeId = Edge::MonotoneEdgeId(0); + Stop::MonotoneStopId m_lastDecodedMonotoneStopId = Stop::MonotoneStopId(0); }; template diff --git a/routing_common/transit_types.cpp b/routing_common/transit_types.cpp index d31302ee7b..f54ad0a420 100644 --- a/routing_common/transit_types.cpp +++ b/routing_common/transit_types.cpp @@ -4,7 +4,6 @@ namespace { -double constexpr kWeightEqualEpsilon = 1e-2; double constexpr kPointsEqualEpsilon = 1e-6; } // namespace @@ -143,7 +142,7 @@ bool Stop::IsEqualForTesting(Stop const & stop) const bool Stop::IsValid() const { - return m_id != kInvalidStopId && !m_lineIds.empty(); + return m_id.Get() != kInvalidStopId && !m_lineIds.empty(); } // SingleMwmSegment ------------------------------------------------------------------------------- @@ -163,7 +162,7 @@ bool SingleMwmSegment::IsValid() const } // Gate ------------------------------------------------------------------------------------------- -Gate::Gate(OsmId osmId, FeatureId featureId, bool entrance, bool exit, double weight, +Gate::Gate(OsmId osmId, FeatureId featureId, bool entrance, bool exit, Weight weight, std::vector const & stopIds, m2::PointD const & point) : m_featureIdentifiers(osmId, featureId, false /* serializeFeatureIdOnly */) , m_entrance(entrance) @@ -196,10 +195,8 @@ bool Gate::operator==(Gate const & rhs) const bool Gate::IsEqualForTesting(Gate const & gate) const { - return m_featureIdentifiers == gate.m_featureIdentifiers && - m_entrance == gate.m_entrance && m_exit == gate.m_exit && - my::AlmostEqualAbs(m_weight, gate.m_weight, kWeightEqualEpsilon) && - m_stopIds == gate.m_stopIds && + return m_featureIdentifiers == gate.m_featureIdentifiers && m_entrance == gate.m_entrance && + m_exit == gate.m_exit && m_weight == gate.m_weight && m_stopIds == gate.m_stopIds && my::AlmostEqualAbs(m_point, gate.m_point, kPointsEqualEpsilon); } @@ -228,7 +225,7 @@ bool ShapeId::IsValid() const } // Edge ------------------------------------------------------------------------------------------- -Edge::Edge(StopId stop1Id, StopId stop2Id, double weight, LineId lineId, bool transfer, +Edge::Edge(StopId stop1Id, StopId stop2Id, Weight weight, LineId lineId, bool transfer, std::vector const & shapeIds) : m_stop1Id(stop1Id) , m_stop2Id(stop2Id) @@ -255,8 +252,7 @@ bool Edge::operator==(Edge const & rhs) const bool Edge::IsEqualForTesting(Edge const & edge) const { - return m_stop1Id == edge.m_stop1Id && m_stop2Id == edge.m_stop2Id && - my::AlmostEqualAbs(m_weight, edge.m_weight, kWeightEqualEpsilon) && + return m_stop1Id == edge.m_stop1Id && m_stop2Id == edge.m_stop2Id && m_weight == edge.m_weight && m_lineId == edge.m_lineId && m_transfer == edge.m_transfer && m_shapeIds == edge.m_shapeIds; } @@ -269,7 +265,7 @@ bool Edge::IsValid() const if (!m_transfer && m_lineId == kInvalidLineId) return false; - return m_stop1Id != kInvalidStopId && m_stop2Id != kInvalidStopId && m_weight != kInvalidWeight; + return m_stop1Id.Get() != kInvalidStopId && m_stop2Id != kInvalidStopId && m_weight != kInvalidWeight; } // Transfer --------------------------------------------------------------------------------------- @@ -310,7 +306,7 @@ bool Line::IsEqualForTesting(Line const & line) const { return m_id == line.m_id && m_number == line.m_number && m_title == line.m_title && m_type == line.m_type && m_color == line.m_color && m_networkId == line.m_networkId && - m_stopIds == line.m_stopIds && my::AlmostEqualAbs(m_interval, line.m_interval, kWeightEqualEpsilon); + m_stopIds == line.m_stopIds && m_interval == line.m_interval; } bool Line::IsValid() const diff --git a/routing_common/transit_types.hpp b/routing_common/transit_types.hpp index 1bbe1a005d..65293bb274 100644 --- a/routing_common/transit_types.hpp +++ b/routing_common/transit_types.hpp @@ -4,6 +4,7 @@ #include "geometry/point2d.hpp" +#include "base/newtype.hpp" #include "base/visitor.hpp" #include @@ -21,7 +22,7 @@ using NetworkId = uint32_t; using OsmId = uint64_t; using StopId = uint64_t; using TransferId = uint64_t; -using Weight = double; +using Weight = int32_t; using Ranges = std::vector>; Anchor constexpr kInvalidAnchor = std::numeric_limits::max(); @@ -32,9 +33,7 @@ NetworkId constexpr kInvalidNetworkId = std::numeric_limits::max(); OsmId constexpr kInvalidOsmId = std::numeric_limits::max(); StopId constexpr kInvalidStopId = std::numeric_limits::max(); TransferId constexpr kInvalidTransferId = std::numeric_limits::max(); -// Note. Weight may be a default param at json. The default value should be saved as uint32_t in mwm anyway. -// To convert double to uint32_t at better accuracy |kInvalidWeight| should be close to real weight. -Weight constexpr kInvalidWeight = -1.0; +Weight constexpr kInvalidWeight = std::numeric_limits::max(); #define DECLARE_TRANSIT_TYPE_FRIENDS \ template friend class Serializer; \ @@ -133,6 +132,8 @@ private: class Stop { public: + NEWTYPE(StopId, MonotoneStopId); + Stop() : m_featureIdentifiers(true /* serializeFeatureIdOnly */) {}; Stop(StopId id, OsmId osmId, FeatureId featureId, TransferId transferId, std::vector const & lineIds, m2::PointD const & point, @@ -144,7 +145,7 @@ public: bool IsEqualForTesting(Stop const & stop) const; bool IsValid() const; - StopId GetId() const { return m_id; } + StopId GetId() const { return m_id.Get(); } FeatureId GetFeatureId() const { return m_featureIdentifiers.GetFeatureId(); } TransferId GetTransferId() const { return m_transferId; } std::vector const & GetLineIds() const { return m_lineIds; } @@ -158,13 +159,14 @@ private: visitor(m_lineIds, "line_ids"), visitor(m_point, "point"), visitor(m_titleAnchors, "title_anchors")) - StopId m_id = kInvalidStopId; + MonotoneStopId m_id = MonotoneStopId(kInvalidStopId); FeatureIdentifiers m_featureIdentifiers; TransferId m_transferId = kInvalidTransferId; std::vector m_lineIds; m2::PointD m_point; std::vector m_titleAnchors; }; +NEWTYPE_SIMPLE_OUTPUT(Stop::MonotoneStopId) class SingleMwmSegment { @@ -193,7 +195,7 @@ class Gate { public: Gate() : m_featureIdentifiers(false /* serializeFeatureIdOnly */) {}; - Gate(OsmId osmId, FeatureId featureId, bool entrance, bool exit, double weight, + Gate(OsmId osmId, FeatureId featureId, bool entrance, bool exit, Weight weight, std::vector const & stopIds, m2::PointD const & point); bool operator<(Gate const & rhs) const; @@ -207,7 +209,7 @@ public: SingleMwmSegment const & GetBestPedestrianSegment() const { return m_bestPedestrianSegment; } bool GetEntrance() const { return m_entrance; } bool GetExit() const { return m_exit; } - double GetWeight() const { return m_weight; } + Weight GetWeight() const { return m_weight; } std::vector const & GetStopIds() const { return m_stopIds; } m2::PointD const & GetPoint() const { return m_point; } @@ -227,7 +229,7 @@ private: SingleMwmSegment m_bestPedestrianSegment; bool m_entrance = true; bool m_exit = true; - double m_weight = kInvalidWeight; + Weight m_weight = kInvalidWeight; std::vector m_stopIds; m2::PointD m_point; }; @@ -258,8 +260,10 @@ private: class Edge { public: + NEWTYPE(StopId, MonotoneEdgeId); + Edge() = default; - Edge(StopId stop1Id, StopId stop2Id, double weight, LineId lineId, bool transfer, + Edge(StopId stop1Id, StopId stop2Id, Weight weight, LineId lineId, bool transfer, std::vector const & shapeIds); bool operator<(Edge const & rhs) const; @@ -268,9 +272,9 @@ public: bool IsValid() const; void SetWeight(double weight) { m_weight = weight; } - StopId GetStop1Id() const { return m_stop1Id; } + StopId GetStop1Id() const { return m_stop1Id.Get(); } StopId GetStop2Id() const { return m_stop2Id; } - double GetWeight() const { return m_weight; } + Weight GetWeight() const { return m_weight; } LineId GetLineId() const { return m_lineId; } bool GetTransfer() const { return m_transfer; } std::vector const & GetShapeIds() const { return m_shapeIds; } @@ -282,13 +286,14 @@ private: visitor(m_weight, "weight"), visitor(m_lineId, "line_id"), visitor(m_transfer, "transfer"), visitor(m_shapeIds, "shape_ids")) - StopId m_stop1Id = kInvalidStopId; + MonotoneEdgeId m_stop1Id = MonotoneEdgeId(kInvalidStopId); StopId m_stop2Id = kInvalidStopId; - double m_weight = kInvalidWeight; // in seconds + Weight m_weight = kInvalidWeight; // in seconds LineId m_lineId = kInvalidLineId; bool m_transfer = false; std::vector m_shapeIds; }; +NEWTYPE_SIMPLE_OUTPUT(Edge::MonotoneEdgeId) class Transfer {