#pragma once #include "routing/city_roads.hpp" #include "routing/road_point.hpp" #include "routing/road_graph.hpp" #include "routing_common/vehicle_model.hpp" #include "indexer/feature_altitude.hpp" #include "geometry/point2d.hpp" #include "base/buffer_vector.hpp" #include "base/fifo_cache.hpp" #include #include #include class DataSource; namespace routing { class RoadGeometry final { public: using Points = buffer_vector; RoadGeometry() = default; RoadGeometry(bool oneWay, double weightSpeedKMpH, double etaSpeedKMpH, Points const & points); void Load(VehicleModelInterface const & vehicleModel, FeatureType & feature, feature::TAltitudes const * altitudes, bool inCity); bool IsOneWay() const { return m_isOneWay; } VehicleModelInterface::SpeedKMpH const & GetSpeed() const { return m_speed; } bool IsPassThroughAllowed() const { return m_isPassThroughAllowed; } Junction const & GetJunction(uint32_t junctionId) const { ASSERT_LESS(junctionId, m_junctions.size(), ()); return m_junctions[junctionId]; } m2::PointD const & GetPoint(uint32_t pointId) const { return GetJunction(pointId).GetPoint(); } uint32_t GetPointsCount() const { return static_cast(m_junctions.size()); } // Note. It's possible that car_model was changed after the map was built. // For example, the map from 12.2016 contained highway=pedestrian // in car_model but this type of highways is removed as of 01.2017. // In such cases RoadGeometry is not valid. bool IsValid() const { return m_valid; } bool IsEndPointId(uint32_t pointId) const { ASSERT_LESS(pointId, m_junctions.size(), ()); return pointId == 0 || pointId + 1 == GetPointsCount(); } void SetPassThroughAllowedForTests(bool passThroughAllowed) { m_isPassThroughAllowed = passThroughAllowed; } private: buffer_vector m_junctions; VehicleModelInterface::SpeedKMpH m_speed; bool m_isOneWay = false; bool m_valid = false; bool m_isPassThroughAllowed = false; }; class GeometryLoader { public: virtual ~GeometryLoader() = default; virtual void Load(uint32_t featureId, RoadGeometry & road) = 0; // handle should be alive: it is caller responsibility to check it. static std::unique_ptr Create(DataSource const & dataSource, MwmSet::MwmHandle const & handle, std::shared_ptr vehicleModel, std::unique_ptr cityRoads, bool loadAltitudes); /// This is for stand-alone work. /// Use in generator_tool and unit tests. static std::unique_ptr CreateFromFile( std::string const & fileName, std::shared_ptr vehicleModel); }; /// \brief This class supports loading geometry of roads for routing. /// \note Loaded information about road geometry is kept in a fixed-size cache |m_featureIdToRoad|. /// On the other hand methods GetRoad() and GetPoint() return geometry information by reference. /// The reference may be invalid after the next call of GetRoad() or GetPoint() because the cache /// item which is referred by returned reference may be evicted. It's done for performance reasons. class Geometry final { public: Geometry() = default; explicit Geometry(std::unique_ptr loader); /// \note The reference returned by the method is valid until the next call of GetRoad() /// of GetPoint() methods. RoadGeometry const & GetRoad(uint32_t featureId); /// \note The reference returned by the method is valid until the next call of GetRoad() /// of GetPoint() methods. m2::PointD const & GetPoint(RoadPoint const & rp) { return GetRoad(rp.GetFeatureId()).GetPoint(rp.GetPointId()); } private: std::unique_ptr m_loader; std::unique_ptr> m_featureIdToRoad; }; } // namespace routing