co-maps/libs/drape_frontend/route_shape.hpp
2025-11-22 13:58:55 +01:00

250 lines
8.4 KiB
C++

#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/pointers.hpp"
#include "drape/render_bucket.hpp"
#include "drape/utils/vertex_decl.hpp"
#include "traffic/speed_groups.hpp"
#include "geometry/polyline2d.hpp"
#include <array>
#include <cmath>
#include <memory>
#include <vector>
namespace df
{
double constexpr kArrowSize = 0.0008;
// Constants below depend on arrow texture.
double constexpr kArrowTextureWidth = 74.0;
double constexpr kArrowTextureHeight = 44.0;
double constexpr kArrowBodyHeight = 24.0;
double constexpr kArrowHeadTextureWidth = 32.0;
double constexpr kArrowTailTextureWidth = 4.0;
double constexpr kArrowHeadSize = kArrowHeadTextureWidth / kArrowTextureWidth;
float constexpr kArrowHeadFactor = static_cast<float>(2.0 * kArrowHeadTextureWidth / kArrowTextureHeight);
double constexpr kArrowTailSize = kArrowTailTextureWidth / kArrowTextureWidth;
float constexpr kArrowTailFactor = static_cast<float>(2.0 * kArrowTailTextureWidth / kArrowTextureHeight);
double constexpr kArrowHeightFactor = kArrowTextureHeight / kArrowBodyHeight;
double constexpr kArrowAspect = kArrowTextureWidth / kArrowTextureHeight;
std::array<float, 20> constexpr kRouteHalfWidthInPixelCar = {
// 1 2 3 4 5 6 7 8 9 10
1.0f, 1.2f, 1.5f, 1.5f, 1.7f, 2.0f, 2.0f, 2.3f, 2.5f, 2.7f,
// 11 12 13 14 15 16 17 18 19 20
3.0f, 3.5f, 4.5f, 5.5f, 7.0, 9.0f, 10.0f, 14.0f, 22.0f, 27.0f};
std::array<float, 20> constexpr kRouteHalfWidthInPixelTransit = {
// 1 2 3 4 5 6 7 8 9 10
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.7f,
// 11 12 13 14 15 16 17 18 19 20
1.8f, 2.1f, 2.5f, 2.8f, 3.5, 4.5f, 5.0f, 7.0f, 11.0f, 13.0f};
std::array<float, 20> constexpr kRouteHalfWidthInPixelOthers = {
// 1 2 3 4 5 6 7 8 9 10
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.1f, 1.2f, 1.3f,
// 11 12 13 14 15 16 17 18 19 20
1.5f, 1.7f, 2.3f, 2.7f, 3.5, 4.5f, 5.0f, 7.0f, 11.0f, 13.0f};
enum class RouteType : uint8_t
{
Car,
Pedestrian,
Bicycle,
Taxi,
Transit,
Ruler
};
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 constexpr 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<df::ColorConstant> 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<double> m_turns;
std::vector<traffic::SpeedGroup> m_traffic;
double m_baseDistance = 0.0;
double m_baseDepthIndex = 0.0;
float m_maxPixelWidth = -1.0f;
SubrouteStyleType m_styleType = SubrouteStyleType::Single;
std::vector<SubrouteStyle> m_style;
std::vector<SubrouteMarker> m_markers;
double m_headFakeDistance = 0.0;
double m_tailFakeDistance = 0.0;
};
using SubrouteConstPtr = std::shared_ptr<Subroute const>;
struct RouteRenderProperty
{
RouteRenderProperty() : m_state(CreateRenderState(gpu::Program::Route, DepthLayer::GeometryLayer)) {}
dp::RenderState m_state;
std::vector<drape_ptr<dp::RenderBucket>> m_buckets;
std::vector<m2::RectD> 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 = gpu::VBUnknownSizeT<RV>;
using AV = gpu::SolidTexturingVertex;
using ArrowGeometryBuffer = gpu::VBUnknownSizeT<AV>;
using MV = gpu::RouteMarkerVertex;
using MarkersGeometryBuffer = gpu::VBUnknownSizeT<MV>;
static drape_ptr<df::SubrouteData> CacheRoute(ref_ptr<dp::GraphicsContext> context, dp::DrapeID subrouteId,
SubrouteConstPtr subroute, size_t styleIndex, int recacheId);
static drape_ptr<df::SubrouteMarkersData> CacheMarkers(ref_ptr<dp::GraphicsContext> context, dp::DrapeID subrouteId,
SubrouteConstPtr subroute, int recacheId,
ref_ptr<dp::TextureManager> textures);
static void CacheRouteArrows(ref_ptr<dp::GraphicsContext> context, ref_ptr<dp::TextureManager> mng,
m2::PolylineD const & polyline, std::vector<ArrowBorders> const & borders,
double baseDepthIndex, SubrouteArrowsData & routeArrowsData);
private:
template <typename GeometryBufferType>
struct GeometryBufferData
{
GeometryBufferData() : m_boundingBox(m2::RectD::GetEmptyRect()) {}
GeometryBufferType m_geometry;
GeometryBufferType m_joinsGeometry;
m2::RectD m_boundingBox;
};
static void PrepareGeometry(std::vector<m2::PointD> const & path, m2::PointD const & pivot,
std::vector<glsl::vec4> const & segmentsColors, float baseDepth,
std::vector<GeometryBufferData<GeometryBuffer>> & geometryBufferData);
static void PrepareArrowGeometry(std::vector<m2::PointD> const & path, m2::PointD const & pivot,
m2::RectF const & texRect, float depthStep, float depth,
GeometryBufferData<ArrowGeometryBuffer> & geometryBufferData);
static void PrepareMarkersGeometry(std::vector<SubrouteMarker> const & markers, m2::PointD const & pivot,
float baseDepth, MarkersGeometryBuffer & geometry);
static void BatchGeometry(ref_ptr<dp::GraphicsContext> context, dp::RenderState const & state, ref_ptr<void> geometry,
uint32_t geomSize, ref_ptr<void> joinsGeometry, uint32_t joinsGeomSize,
m2::RectD const & boundingBox, dp::BindingInfo const & bindingInfo,
RouteRenderProperty & property);
};
} // namespace df