diff --git a/generator/generator_tests/road_access_test.cpp b/generator/generator_tests/road_access_test.cpp index f0b7b94a63..54f0a83eaf 100644 --- a/generator/generator_tests/road_access_test.cpp +++ b/generator/generator_tests/road_access_test.cpp @@ -24,6 +24,7 @@ #include "base/logging.hpp" #include "base/string_utils.hpp" +#include #include #include @@ -58,7 +59,7 @@ void BuildTestMwmWithRoads(LocalCountryFile & country) } } -void LoadRoadAccess(string const & mwmFilePath, RoadAccess & roadAccess) +void LoadRoadAccess(string const & mwmFilePath, VehicleMask vehicleMask, RoadAccess & roadAccess) { FilesContainerR const cont(mwmFilePath); TEST(cont.IsExist(ROAD_ACCESS_FILE_TAG), ()); @@ -68,7 +69,7 @@ void LoadRoadAccess(string const & mwmFilePath, RoadAccess & roadAccess) FilesContainerR::TReader const reader = cont.GetReader(ROAD_ACCESS_FILE_TAG); ReaderSource src(reader); - RoadAccessSerializer::Deserialize(src, roadAccess); + RoadAccessSerializer::Deserialize(src, vehicleMask, roadAccess); } catch (Reader::OpenException const & e) { @@ -77,7 +78,8 @@ void LoadRoadAccess(string const & mwmFilePath, RoadAccess & roadAccess) } // todo(@m) This helper function is almost identical to the one in restriction_test.cpp. -RoadAccess SaveAndLoadRoadAccess(string const & roadAccessContent, string const & mappingContent) +map SaveAndLoadRoadAccess(string const & roadAccessContent, + string const & mappingContent) { classificator::Load(); @@ -108,12 +110,17 @@ RoadAccess SaveAndLoadRoadAccess(string const & roadAccessContent, string const BuildRoadAccessInfo(mwmFullPath, roadAccessFullPath, mappingFullPath); // Reading from mwm section and testing road access. - RoadAccess roadAccessFromMwm; - LoadRoadAccess(mwmFullPath, roadAccessFromMwm); + map roadAccessByMaskFromMwm; + for (auto const vehicleMask : RoadAccess::GetSupportedVehicleMasks()) + { + RoadAccess roadAccess; + LoadRoadAccess(mwmFullPath, vehicleMask, roadAccess); + roadAccessByMaskFromMwm.emplace(vehicleMask, roadAccess); + } RoadAccessCollector const collector(mwmFullPath, roadAccessFullPath, mappingFullPath); TEST(collector.IsValid(), ()); - TEST_EQUAL(roadAccessFromMwm, collector.GetRoadAccess(), ()); - return roadAccessFromMwm; + TEST_EQUAL(roadAccessByMaskFromMwm, collector.GetRoadAccessByMask(), ()); + return roadAccessByMaskFromMwm; } UNIT_TEST(RoadAccess_Smoke) @@ -127,8 +134,11 @@ UNIT_TEST(RoadAccess_AccessPrivate) { string const roadAccessContent = R"(Car Private 0)"; string const osmIdsToFeatureIdsContent = R"(0, 0,)"; - auto const roadAccess = SaveAndLoadRoadAccess(roadAccessContent, osmIdsToFeatureIdsContent); - TEST_EQUAL(roadAccess.GetType(kCarMask, Segment(0, 0, 0, false)), RoadAccess::Type::Private, ()); + auto const roadAccessByMask = SaveAndLoadRoadAccess(roadAccessContent, osmIdsToFeatureIdsContent); + auto const carIt = roadAccessByMask.find(kCarMask); + TEST(carIt != roadAccessByMask.end(), ()); + auto const carRoadAccess = carIt->second; + TEST_EQUAL(carRoadAccess.GetType(Segment(0, 0, 0, false)), RoadAccess::Type::Private, ()); } UNIT_TEST(RoadAccess_Access_Multiple_Vehicle_Masks) @@ -141,12 +151,17 @@ UNIT_TEST(RoadAccess_Access_Multiple_Vehicle_Masks) 20, 2, 30, 3, 40, 4,)"; - auto const roadAccess = SaveAndLoadRoadAccess(roadAccessContent, osmIdsToFeatureIdsContent); - TEST_EQUAL(roadAccess.GetType(kCarMask, Segment(0, 1, 0, false)), RoadAccess::Type::Private, ()); - TEST_EQUAL(roadAccess.GetType(kCarMask, Segment(0, 2, 2, true)), RoadAccess::Type::Private, ()); - TEST_EQUAL(roadAccess.GetType(kCarMask, Segment(0, 3, 1, true)), RoadAccess::Type::Yes, ()); - TEST_EQUAL(roadAccess.GetType(kCarMask, Segment(0, 4, 3, false)), RoadAccess::Type::Destination, - ()); - TEST_EQUAL(roadAccess.GetType(kBicycleMask, Segment(0, 3, 0, false)), RoadAccess::Type::No, ()); + auto const roadAccessByMask = SaveAndLoadRoadAccess(roadAccessContent, osmIdsToFeatureIdsContent); + auto const carIt = roadAccessByMask.find(kCarMask); + TEST(carIt != roadAccessByMask.end(), ()); + auto const carRoadAccess = carIt->second; + auto const bicycleIt = roadAccessByMask.find(kBicycleMask); + TEST(bicycleIt != roadAccessByMask.end(), ()); + auto const bicycleRoadAccess = bicycleIt->second; + TEST_EQUAL(carRoadAccess.GetType(Segment(0, 1, 0, false)), RoadAccess::Type::Private, ()); + TEST_EQUAL(carRoadAccess.GetType(Segment(0, 2, 2, true)), RoadAccess::Type::Private, ()); + TEST_EQUAL(carRoadAccess.GetType(Segment(0, 3, 1, true)), RoadAccess::Type::Yes, ()); + TEST_EQUAL(carRoadAccess.GetType(Segment(0, 4, 3, false)), RoadAccess::Type::Destination, ()); + TEST_EQUAL(bicycleRoadAccess.GetType(Segment(0, 3, 0, false)), RoadAccess::Type::No, ()); } } // namespace diff --git a/generator/road_access_generator.cpp b/generator/road_access_generator.cpp index 277288b409..9898670a69 100644 --- a/generator/road_access_generator.cpp +++ b/generator/road_access_generator.cpp @@ -80,7 +80,8 @@ string WriteVehicleMaskToString(VehicleMask vehicleMask) } bool ParseRoadAccess(string const & roadAccessPath, map const & osmIdToFeatureId, - FeaturesVector const & featuresVector, RoadAccess & roadAccess) + FeaturesVector const & featuresVector, + map & roadAccessByMask) { ifstream stream(roadAccessPath); if (!stream) @@ -146,7 +147,10 @@ bool ParseRoadAccess(string const & roadAccessPath, map const featuresVector.GetByIndex(featureId, ft); ft.ParseGeometry(FeatureType::BEST_GEOMETRY); - CHECK_GREATER(ft.GetPointsCount(), 1, ()); + // An area created from a way. + if (ft.GetPointsCount() == 0) + continue; + uint32_t const numSegments = static_cast(ft.GetPointsCount() - 1); // Set this road access type for the entire feature. @@ -159,8 +163,13 @@ bool ParseRoadAccess(string const & roadAccessPath, map const } } + roadAccessByMask.clear(); for (auto const vehicleMask : RoadAccess::GetSupportedVehicleMasks()) - roadAccess.SetTypes(vehicleMask, segmentType[vehicleMask]); + { + RoadAccess roadAccess; + roadAccess.SetTypes(segmentType[vehicleMask]); + roadAccessByMask.emplace(vehicleMask, roadAccess); + } return true; } @@ -244,8 +253,9 @@ RoadAccessCollector::RoadAccessCollector(string const & dataFilePath, string con FeaturesVectorTest featuresVector(dataFilePath); - RoadAccess roadAccess; - if (!ParseRoadAccess(roadAccessPath, osmIdToFeatureId, featuresVector.GetVector(), roadAccess)) + map roadAccessByMask; + if (!ParseRoadAccess(roadAccessPath, osmIdToFeatureId, featuresVector.GetVector(), + roadAccessByMask)) { LOG(LWARNING, ("An error happened while parsing road access from file:", roadAccessPath)); m_valid = false; @@ -253,7 +263,7 @@ RoadAccessCollector::RoadAccessCollector(string const & dataFilePath, string con } m_valid = true; - m_roadAccess.Swap(roadAccess); + m_roadAccessByMask.swap(roadAccessByMask); } // Functions ------------------------------------------------------------------ @@ -273,6 +283,6 @@ void BuildRoadAccessInfo(string const & dataFilePath, string const & roadAccessP FilesContainerW cont(dataFilePath, FileWriter::OP_WRITE_EXISTING); FileWriter writer = cont.GetWriter(ROAD_ACCESS_FILE_TAG); - RoadAccessSerializer::Serialize(writer, collector.GetRoadAccess()); + RoadAccessSerializer::Serialize(writer, collector.GetRoadAccessByMask()); } } // namespace routing diff --git a/generator/road_access_generator.hpp b/generator/road_access_generator.hpp index 0a4bba5cc5..66d915ce13 100644 --- a/generator/road_access_generator.hpp +++ b/generator/road_access_generator.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -56,12 +57,15 @@ public: RoadAccessCollector(std::string const & dataFilePath, std::string const & roadAccessPath, std::string const & osmIdsToFeatureIdsPath); - RoadAccess const & GetRoadAccess() const { return m_roadAccess; } + std::map const & GetRoadAccessByMask() const + { + return m_roadAccessByMask; + } bool IsValid() const { return m_valid; } private: - RoadAccess m_roadAccess; + std::map m_roadAccessByMask; bool m_valid = true; }; diff --git a/routing/road_access.cpp b/routing/road_access.cpp index 114d10687e..0f0768fc8c 100644 --- a/routing/road_access.cpp +++ b/routing/road_access.cpp @@ -1,5 +1,7 @@ #include "routing/road_access.hpp" +#include "base/assert.hpp" + #include #include @@ -21,11 +23,13 @@ vector const kSupportedVehicleMasks = { namespace routing { // RoadAccess -------------------------------------------------------------------------------------- -RoadAccess::RoadAccess() +RoadAccess::RoadAccess() : m_vehicleMask(kAllVehiclesMask) {} + +RoadAccess::RoadAccess(VehicleMask vehicleMask) : m_vehicleMask(vehicleMask) { - for (auto const vehicleMask : kSupportedVehicleMasks) - m_types.emplace(vehicleMask, map()); + CHECK(IsSupportedVehicleMask(vehicleMask), ()); } + // static vector const & RoadAccess::GetSupportedVehicleMasks() { @@ -39,29 +43,19 @@ bool RoadAccess::IsSupportedVehicleMask(VehicleMask vehicleMask) kSupportedVehicleMasks.end(); } -RoadAccess::Type const RoadAccess::GetType(VehicleMask vehicleMask, Segment const & segment) const +RoadAccess::Type const RoadAccess::GetType(Segment const & segment) const { - auto const & types = GetTypes(vehicleMask); Segment key(kFakeNumMwmId, segment.GetFeatureId(), segment.GetSegmentIdx(), segment.IsForward()); - auto const it = types.find(key); - if (it != types.end()) + auto const it = m_types.find(key); + if (it != m_types.end()) return it->second; return RoadAccess::Type::Yes; } -map const & RoadAccess::GetTypes(VehicleMask vehicleMask) const -{ - ASSERT(IsSupportedVehicleMask(vehicleMask), ()); - auto it = m_types.find(vehicleMask); - CHECK(it != m_types.end(), ()); - return it->second; -} - void RoadAccess::Clear() { - for (auto & kv : m_types) - kv.second.clear(); + m_types.clear(); } void RoadAccess::Swap(RoadAccess & rhs) @@ -103,29 +97,20 @@ string DebugPrint(RoadAccess const & r) { size_t const kMaxIdsToShow = 10; ostringstream oss; - oss << "RoadAccess ["; - bool firstMask = true; - for (auto const vehicleMask : RoadAccess::GetSupportedVehicleMasks()) + oss << "RoadAccess " << DebugPrint(r.GetVehicleMask()) << "[ "; + size_t id = 0; + for (auto const & kv : r.GetTypes()) { - if (!firstMask) + if (id > 0) oss << ", "; - firstMask = false; - auto const & types = r.GetTypes(vehicleMask); - oss << DebugPrint(vehicleMask) << " ["; - size_t id = 0; - for (auto const & kv : types) - { - if (id > 0) - oss << ", "; - oss << DebugPrint(kv.first) << " " << DebugPrint(kv.second); - ++id; - if (id == kMaxIdsToShow) - break; - } - if (types.size() > kMaxIdsToShow) - oss << "..."; - oss << "]"; + oss << DebugPrint(kv.first) << " " << DebugPrint(kv.second); + ++id; + if (id == kMaxIdsToShow) + break; } + if (r.GetTypes().size() > kMaxIdsToShow) + oss << "..."; + oss << "]"; return oss.str(); } diff --git a/routing/road_access.hpp b/routing/road_access.hpp index dfc6bec9a6..bf146173a2 100644 --- a/routing/road_access.hpp +++ b/routing/road_access.hpp @@ -13,8 +13,8 @@ namespace routing { // This class provides information about road access classes. -// For now, only restrictive types (such as barrier=gate and access=private) -// and only car routing are supported. +// One instance of RoadAccess holds information about one +// mwm and one router type (also known as VehicleMask). class RoadAccess final { public: @@ -42,18 +42,19 @@ public: RoadAccess(); + RoadAccess(VehicleMask vehicleMask); + static std::vector const & GetSupportedVehicleMasks(); static bool IsSupportedVehicleMask(VehicleMask vehicleMask); - Type const GetType(VehicleMask vehicleMask, Segment const & segment) const; - - std::map const & GetTypes(VehicleMask vehicleMask) const; + VehicleMask const GetVehicleMask() const { return m_vehicleMask; } + std::map const & GetTypes() const { return m_types; } + Type const GetType(Segment const & segment) const; template - void SetTypes(VehicleMask vehicleMask, V && v) + void SetTypes(V && v) { - CHECK(IsSupportedVehicleMask(vehicleMask), ()); - m_types[vehicleMask] = std::forward(v); + m_types = std::forward(v); } void Clear(); @@ -63,9 +64,11 @@ public: bool operator==(RoadAccess const & rhs) const; private: + VehicleMask m_vehicleMask; + // todo(@m) Segment's NumMwmId is not used here. Decouple it from // segment and use only (fid, idx, forward) in the map. - std::map> m_types; + std::map m_types; }; std::string ToString(RoadAccess::Type type); diff --git a/routing/road_access_serialization.hpp b/routing/road_access_serialization.hpp index 96da0e881a..bf8ab9b9e6 100644 --- a/routing/road_access_serialization.hpp +++ b/routing/road_access_serialization.hpp @@ -11,6 +11,7 @@ #include "coding/write_to_sink.hpp" #include "base/assert.hpp" +#include "base/checked_cast.hpp" #include #include @@ -28,26 +29,36 @@ public: RoadAccessSerializer() = delete; template - static void Serialize(Sink & sink, RoadAccess const & roadAccess) + static void Serialize(Sink & sink, std::map const & roadAccessByMask) { uint32_t const header = kLatestVersion; WriteToSink(sink, header); - for (auto const vehicleMask : RoadAccess::GetSupportedVehicleMasks()) - SerializeOneVehicleMask(sink, roadAccess.GetTypes(vehicleMask)); + uint32_t const numMasks = static_cast(roadAccessByMask.size()); + WriteToSink(sink, numMasks); + + for (auto const & kv : roadAccessByMask) + { + uint32_t const mask = static_cast(kv.first); + WriteToSink(sink, mask); + SerializeOneVehicleMask(sink, kv.second.GetTypes()); + } } template - static void Deserialize(Source & src, RoadAccess & roadAccess) + static void Deserialize(Source & src, VehicleMask vehicleMask, RoadAccess & roadAccess) { uint32_t const header = ReadPrimitiveFromSource(src); CHECK_EQUAL(header, kLatestVersion, ()); - for (auto const vehicleMask : RoadAccess::GetSupportedVehicleMasks()) + uint32_t const numMasks = ReadPrimitiveFromSource(src); + for (uint32_t i = 0; i < numMasks; ++i) { + uint32_t const vm = base::checked_cast(ReadPrimitiveFromSource(src)); RoadAccessTypesMap m; DeserializeOneVehicleMask(src, m); - roadAccess.SetTypes(vehicleMask, std::move(m)); + if (vehicleMask == vm) + roadAccess.SetTypes(std::move(m)); } } diff --git a/routing/routing_tests/road_access_test.cpp b/routing/routing_tests/road_access_test.cpp index 09cdde14e9..2090a70bcd 100644 --- a/routing/routing_tests/road_access_test.cpp +++ b/routing/routing_tests/road_access_test.cpp @@ -31,24 +31,43 @@ UNIT_TEST(RoadAccess_Serialization) {Segment(kFakeNumMwmId, 2, 0, true), RoadAccess::Type::Destination}, }; - RoadAccess roadAccess; - roadAccess.SetTypes(kCarMask, m0); - roadAccess.SetTypes(kPedestrianMask, m1); + RoadAccess roadAccessCar(kCarMask); + roadAccessCar.SetTypes(m0); + + RoadAccess roadAccessPedestrian(kPedestrianMask); + roadAccessPedestrian.SetTypes(m1); + + map const ms = { + {kCarMask, roadAccessCar}, + {kPedestrianMask, roadAccessPedestrian}, + }; vector buf; { MemWriter writer(buf); - RoadAccessSerializer::Serialize(writer, roadAccess); + RoadAccessSerializer::Serialize(writer, ms); } - RoadAccess deserializedRoadAccess; { + RoadAccess deserializedRoadAccess; + MemReader memReader(buf.data(), buf.size()); ReaderSource src(memReader); - RoadAccessSerializer::Deserialize(src, deserializedRoadAccess); + RoadAccessSerializer::Deserialize(src, kCarMask, deserializedRoadAccess); TEST_EQUAL(src.Size(), 0, ()); + + TEST_EQUAL(roadAccessCar, deserializedRoadAccess, ()); } - TEST_EQUAL(roadAccess, deserializedRoadAccess, ()); + { + RoadAccess deserializedRoadAccess; + + MemReader memReader(buf.data(), buf.size()); + ReaderSource src(memReader); + RoadAccessSerializer::Deserialize(src, kPedestrianMask, deserializedRoadAccess); + TEST_EQUAL(src.Size(), 0, ()); + + TEST_EQUAL(roadAccessPedestrian, deserializedRoadAccess, ()); + } } } // namespace