#pragma once #include "drape_frontend/color_constants.hpp" #include "drape_frontend/map_shape.hpp" #include "drape_frontend/render_state_extension.hpp" #include "drape_frontend/shape_view_params.hpp" #include "drape/render_bucket.hpp" #include "drape/utils/vertex_decl.hpp" #include "drape/pointers.hpp" #include "traffic/speed_groups.hpp" #include "geometry/polyline2d.hpp" #include #include #include namespace df { double const kArrowSize = 0.0008; // Constants below depend on arrow texture. double const kArrowTextureWidth = 74.0; double const kArrowTextureHeight = 44.0; double const kArrowBodyHeight = 24.0; double const kArrowHeadTextureWidth = 32.0; double const kArrowTailTextureWidth = 4.0; double const kArrowHeadSize = kArrowHeadTextureWidth / kArrowTextureWidth; float const kArrowHeadFactor = static_cast(2.0 * kArrowHeadTextureWidth / kArrowTextureHeight); double const kArrowTailSize = kArrowTailTextureWidth / kArrowTextureWidth; float const kArrowTailFactor = static_cast(2.0 * kArrowTailTextureWidth / kArrowTextureHeight); double const kArrowHeightFactor = kArrowTextureHeight / kArrowBodyHeight; double const kArrowAspect = kArrowTextureWidth / kArrowTextureHeight; extern std::vector const kRouteHalfWidthInPixelCar; extern std::vector const kRouteHalfWidthInPixelTransit; extern std::vector const kRouteHalfWidthInPixelOthers; enum class RouteType : uint8_t { Car, Pedestrian, Bicycle, Taxi, Transit }; struct RoutePattern { RoutePattern() = default; RoutePattern(double dashLength, double gapLength) : m_isDashed(true) , m_dashLength(dashLength) , m_gapLength(gapLength) {} bool operator == (RoutePattern const & pattern) const { double const kEps = 1e-5; return m_isDashed == pattern.m_isDashed && std::fabs(m_dashLength - pattern.m_dashLength) < kEps && std::fabs(m_gapLength - pattern.m_gapLength) < kEps; } bool m_isDashed = false; double m_dashLength = 0.0; double m_gapLength = 0.0; }; enum class SubrouteStyleType { Single = 0, Multiple }; struct SubrouteStyle { SubrouteStyle() = default; explicit SubrouteStyle(df::ColorConstant const & color) : m_color(color) , m_outlineColor(color) {} SubrouteStyle(df::ColorConstant const & color, df::ColorConstant const & outlineColor) : m_color(color) , m_outlineColor(outlineColor) {} SubrouteStyle(df::ColorConstant const & color, df::RoutePattern const & pattern) : m_color(color) , m_outlineColor(color) , m_pattern(pattern) {} SubrouteStyle(df::ColorConstant const & color, df::ColorConstant const & outlineColor, df::RoutePattern const & pattern) : m_color(color) , m_outlineColor(outlineColor) , m_pattern(pattern) {} bool operator==(SubrouteStyle const & style) const { return m_color == style.m_color && m_outlineColor == style.m_outlineColor && m_pattern == style.m_pattern; } bool operator!=(SubrouteStyle const & style) const { return !operator==(style); } df::ColorConstant m_color; df::ColorConstant m_outlineColor; df::RoutePattern m_pattern; size_t m_startIndex = 0; size_t m_endIndex = 0; }; // Colored circle on the subroute. struct SubrouteMarker { // Position in mercator. m2::PointD m_position = {}; // Distance from the beginning of route. double m_distance = 0.0; // Array of colors in range [0;2]. std::vector m_colors; // Color of inner circle. df::ColorConstant m_innerColor; // Normalized up vector to determine rotation of circle. m2::PointD m_up = m2::PointD(0.0, 1.0); // Scale (1.0 when the radius is equal to route line half-width). float m_scale = 1.0f; }; struct Subroute { void AddStyle(SubrouteStyle const & style); df::RouteType m_routeType; m2::PolylineD m_polyline; std::vector m_turns; std::vector m_traffic; double m_baseDistance = 0.0; double m_baseDepthIndex = 0.0; float m_maxPixelWidth = -1.0f; SubrouteStyleType m_styleType = SubrouteStyleType::Single; std::vector m_style; std::vector m_markers; }; using SubrouteConstPtr = std::shared_ptr; struct RouteRenderProperty { RouteRenderProperty() : m_state(CreateRenderState(gpu::Program::Route, DepthLayer::GeometryLayer)) {} dp::RenderState m_state; std::vector> m_buckets; std::vector m_boundingBoxes; }; struct BaseSubrouteData { dp::DrapeID m_subrouteId = 0; m2::PointD m_pivot = m2::PointD(0.0, 0.0); int m_recacheId = -1; RouteRenderProperty m_renderProperty; }; struct SubrouteData : public BaseSubrouteData { SubrouteConstPtr m_subroute; size_t m_startPointIndex = 0; size_t m_endPointIndex = 0; size_t m_styleIndex = 0; double m_distanceOffset = 0.0; }; struct SubrouteArrowsData : public BaseSubrouteData {}; struct SubrouteMarkersData : public BaseSubrouteData {}; struct ArrowBorders { double m_startDistance = 0.0; double m_endDistance = 0.0; int m_groupIndex = 0; }; class RouteShape { public: using RV = gpu::RouteVertex; using GeometryBuffer = buffer_vector; using AV = gpu::SolidTexturingVertex; using ArrowGeometryBuffer = buffer_vector; using MV = gpu::RouteMarkerVertex; using MarkersGeometryBuffer = buffer_vector; static drape_ptr CacheRoute(ref_ptr context, dp::DrapeID subrouteId, SubrouteConstPtr subroute, size_t styleIndex, int recacheId, ref_ptr textures); static drape_ptr CacheMarkers(ref_ptr context, dp::DrapeID subrouteId, SubrouteConstPtr subroute, int recacheId, ref_ptr textures); static void CacheRouteArrows(ref_ptr context, ref_ptr mng, m2::PolylineD const & polyline, std::vector const & borders, double baseDepthIndex, SubrouteArrowsData & routeArrowsData); private: template struct GeometryBufferData { GeometryBufferData() : m_boundingBox(m2::RectD::GetEmptyRect()) {} GeometryBufferType m_geometry; GeometryBufferType m_joinsGeometry; m2::RectD m_boundingBox; }; static void PrepareGeometry(std::vector const & path, m2::PointD const & pivot, std::vector const & segmentsColors, float baseDepth, std::vector> & geometryBufferData); static void PrepareArrowGeometry(std::vector const & path, m2::PointD const & pivot, m2::RectF const & texRect, float depthStep, float depth, GeometryBufferData & geometryBufferData); static void PrepareMarkersGeometry(std::vector const & markers, m2::PointD const & pivot, float baseDepth, MarkersGeometryBuffer & geometry); static void BatchGeometry(ref_ptr context, dp::RenderState const & state, ref_ptr geometry, uint32_t geomSize, ref_ptr joinsGeometry, uint32_t joinsGeomSize, m2::RectD const & boundingBox, dp::BindingInfo const & bindingInfo, RouteRenderProperty & property); }; } // namespace df