#pragma once #include "coding/file_container.hpp" #include "geometry/latlon.hpp" #include "geometry/point2d.hpp" #include "geometry/rect2d.hpp" #include "geometry/tree4d.hpp" #include "std/function.hpp" #include "std/string.hpp" #include "std/vector.hpp" namespace routing { using TWrittenNodeId = uint32_t; using TWrittenEdgeWeight = uint32_t; TWrittenEdgeWeight constexpr kInvalidContextEdgeNodeId = std::numeric_limits::max(); TWrittenEdgeWeight constexpr kInvalidContextEdgeWeight = std::numeric_limits::max(); size_t constexpr kInvalidAdjacencyIndex = numeric_limits::max(); struct IngoingCrossNode { ms::LatLon m_point; TWrittenNodeId m_nodeId; size_t m_adjacencyIndex; IngoingCrossNode() : m_point(ms::LatLon::Zero()) , m_nodeId(kInvalidContextEdgeNodeId) , m_adjacencyIndex(kInvalidAdjacencyIndex) { } IngoingCrossNode(TWrittenNodeId nodeId, ms::LatLon const & point, size_t const adjacencyIndex) : m_point(point), m_nodeId(nodeId), m_adjacencyIndex(adjacencyIndex) { } void Save(Writer & w) const; size_t Load(Reader const & r, size_t pos, size_t adjacencyIndex); m2::RectD const GetLimitRect() const { return m2::RectD(m_point.lat, m_point.lon, m_point.lat, m_point.lon); } }; struct OutgoingCrossNode { ms::LatLon m_point; TWrittenNodeId m_nodeId; unsigned char m_outgoingIndex; size_t m_adjacencyIndex; OutgoingCrossNode() : m_point(ms::LatLon::Zero()) , m_nodeId(kInvalidContextEdgeNodeId) , m_outgoingIndex(0) , m_adjacencyIndex(kInvalidAdjacencyIndex) { } OutgoingCrossNode(TWrittenNodeId nodeId, size_t const index, ms::LatLon const & point, size_t const adjacencyIndex) : m_point(point) , m_nodeId(nodeId) , m_outgoingIndex(static_cast(index)) , m_adjacencyIndex(adjacencyIndex) { } void Save(Writer & w) const; size_t Load(Reader const & r, size_t pos, size_t adjacencyIndex); }; using IngoingEdgeIteratorT = vector::const_iterator; using OutgoingEdgeIteratorT = vector::const_iterator; /// Reader class from cross context section in mwm.routing file class CrossRoutingContextReader { vector m_outgoingNodes; vector m_neighborMwmList; vector m_adjacencyMatrix; m4::Tree m_ingoingIndex; public: void Load(Reader const & r); const string & GetOutgoingMwmName(OutgoingCrossNode const & mwmIndex) const; bool ForEachIngoingNodeNearPoint(ms::LatLon const & point, function && fn) const; TWrittenEdgeWeight GetAdjacencyCost(IngoingCrossNode const & ingoing, OutgoingCrossNode const & outgoing) const; template void ForEachIngoingNode(TFunctor f) const { m_ingoingIndex.ForEach(f); } template void ForEachOutgoingNode(TFunctor f) const { for_each(m_outgoingNodes.cbegin(), m_outgoingNodes.cend(), f); } }; /// Helper class to generate cross context section in mwm.routing file class CrossRoutingContextWriter { vector m_ingoingNodes; vector m_outgoingNodes; vector m_adjacencyMatrix; vector m_neighborMwmList; size_t GetIndexInAdjMatrix(IngoingEdgeIteratorT ingoing, OutgoingEdgeIteratorT outgoing) const; public: void Save(Writer & w) const; void AddIngoingNode(TWrittenNodeId const nodeId, ms::LatLon const & point); void AddOutgoingNode(TWrittenNodeId const nodeId, string const & targetMwm, ms::LatLon const & point); void ReserveAdjacencyMatrix(); void SetAdjacencyCost(IngoingEdgeIteratorT ingoing, OutgoingEdgeIteratorT outgoin, TWrittenEdgeWeight value); pair GetIngoingIterators() const; pair GetOutgoingIterators() const; }; }