23#include <boost/graph/adjacency_list.hpp>
24#include <boost/graph/depth_first_search.hpp>
25#include <boost/graph/dijkstra_shortest_paths.hpp>
26#include <boost/property_map/transform_value_property_map.hpp>
36 bool isVisibleForFaction = [&]
46 if (!isVisibleForFaction)
47 return std::numeric_limits<uint16>::max();
50 return std::numeric_limits<uint16>::max();
56typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, uint32>, boost::property<boost::edge_weight_t, EdgeCost>> Graph;
57typedef boost::property_map<Graph, boost::edge_weight_t>::type WeightMap;
58typedef Graph::vertex_descriptor vertex_descriptor;
59typedef Graph::edge_descriptor edge_descriptor;
60typedef std::pair<vertex_descriptor, vertex_descriptor> edge;
63std::vector<TaxiNodesEntry const*> m_nodesByVertex;
64std::unordered_map<uint32, vertex_descriptor> m_verticesByNode;
68 if (!
DB2Manager::GetUiMapPosition(position.
X, position.
Y, position.
Z, mapId, 0, 0, 0,
UI_MAP_SYSTEM_ADVENTURE,
false, uiMapId, uiMapPosition))
69 DB2Manager::GetUiMapPosition(position.
X, position.
Y, position.
Z, mapId, 0, 0, 0,
UI_MAP_SYSTEM_TAXI,
false, uiMapId, uiMapPosition);
72vertex_descriptor CreateVertexFromFromNodeInfoIfNeeded(
TaxiNodesEntry const* node)
74 auto itr = m_verticesByNode.find(node->
ID);
75 if (itr == m_verticesByNode.end())
77 itr = m_verticesByNode.emplace(node->
ID, m_nodesByVertex.size()).first;
78 m_nodesByVertex.push_back(node);
88 vertex_descriptor fromVertexID = CreateVertexFromFromNodeInfoIfNeeded(from);
89 vertex_descriptor toVertexID = CreateVertexFromFromNodeInfoIfNeeded(to);
91 float totalDist = 0.0f;
95 edges.emplace_back(edge(fromVertexID, toVertexID), EdgeCost{ to, 0xFFFF });
99 std::size_t last = nodes.size();
100 std::size_t first = 0;
101 if (nodes.size() > 2)
107 for (std::size_t i = first + 1; i < last; ++i)
115 GetTaxiMapPosition(nodes[i - 1]->Loc, nodes[i - 1]->ContinentID, &pos1, &uiMap1);
116 GetTaxiMapPosition(nodes[i]->Loc, nodes[i]->ContinentID, &pos2, &uiMap2);
118 if (uiMap1 != uiMap2)
121 totalDist += std::sqrt(
122 std::pow(pos2.
X - pos1.
X, 2) +
123 std::pow(pos2.
Y - pos1.
Y, 2));
130 edges.emplace_back(edge(fromVertexID, toVertexID), EdgeCost{ to, dist });
134vertex_descriptor
const* GetVertexIDFromNodeID(
TaxiNodesEntry const* node)
139uint32 GetNodeIDFromVertexID(vertex_descriptor vertexID)
141 if (vertexID < m_nodesByVertex.size())
142 return m_nodesByVertex[vertexID]->ID;
144 return std::numeric_limits<uint32>::max();
148struct DiscoverVertexVisitor :
public boost::base_visitor<DiscoverVertexVisitor<T>>
150 using event_filter = boost::on_discover_vertex;
152 DiscoverVertexVisitor(T&& func) : _func(
std::forward<T>(func)) { }
154 template <
class Vertex,
class Graph>
155 void operator()(Vertex v, Graph& )
165auto make_discover_vertex_dfs_visitor(T&& t)
167 return boost::make_dfs_visitor(DiscoverVertexVisitor<T>(std::forward<T>(t)));
173 if (boost::num_vertices(m_graph) > 0)
176 std::vector<std::pair<edge, EdgeCost>> edges;
184 AddVerticeAndEdgeFromNodeInfo(from, to, path->
ID, edges);
188 m_graph = Graph(m_nodesByVertex.size());
189 WeightMap weightmap = boost::get(boost::edge_weight, m_graph);
191 for (std::size_t j = 0; j < edges.size(); ++j)
193 edge_descriptor e = boost::add_edge(edges[j].first.first, edges[j].first.second, m_graph).first;
194 weightmap[e] = edges[j].second;
213 shortestPath = { from->
ID, to->
ID };
216 shortestPath.clear();
218 vertex_descriptor
const* fromVertexId = GetVertexIDFromNodeID(from);
219 vertex_descriptor
const* toVertexId = GetVertexIDFromNodeID(to);
220 if (fromVertexId && toVertexId)
222 std::vector<vertex_descriptor> p(boost::num_vertices(m_graph));
223 std::vector<uint32> d(boost::num_vertices(m_graph));
225 boost::dijkstra_shortest_paths(m_graph, *fromVertexId,
226 boost::predecessor_map(boost::make_iterator_property_map(p.begin(), boost::get(boost::vertex_index, m_graph)))
227 .distance_map(boost::make_iterator_property_map(d.begin(), boost::get(boost::vertex_index, m_graph)))
228 .vertex_index_map(boost::get(boost::vertex_index, m_graph))
229 .distance_compare(std::less<uint32>())
230 .distance_combine(boost::closed_plus<uint32>())
231 .distance_inf(std::numeric_limits<uint32>::max())
233 .visitor(boost::dijkstra_visitor<boost::null_visitor>())
234 .weight_map(boost::make_transform_value_property_map(
235 [player](EdgeCost
const& edgeCost) { return edgeCost.EvaluateDistance(player); },
236 boost::get(boost::edge_weight, m_graph))));
239 for (vertex_descriptor v = *toVertexId; ; v = p[v])
241 shortestPath.push_back(GetNodeIDFromVertexID(v));
246 std::reverse(shortestPath.begin(), shortestPath.end());
250 return shortestPath.size();
255 vertex_descriptor
const* vertexId = GetVertexIDFromNodeID(from);
259 boost::vector_property_map<boost::default_color_type> color(boost::num_vertices(m_graph));
260 std::fill(color.storage_begin(), color.storage_end(), boost::white_color);
261 boost::depth_first_visit(m_graph, *vertexId, make_discover_vertex_dfs_visitor([mask](vertex_descriptor vertex)
264 (*mask)[(taxiNode->ID - 1) / 8] |= 1 << ((taxiNode->ID - 1) % 8);
DB2Storage< TaxiNodesEntry > sTaxiNodesStore("TaxiNodes.db2", &TaxiNodesLoadInfo::Instance)
TaxiPathNodesByPath sTaxiPathNodesByPath
DB2Storage< TaxiPathEntry > sTaxiPathStore("TaxiPath.db2", &TaxiPathLoadInfo::Instance)
std::vector< TaxiPathNodeEntry const * > TaxiPathNodeList
@ UI_MAP_SYSTEM_ADVENTURE
@ TAXI_PATH_NODE_FLAG_TELEPORT
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
static bool GetUiMapPosition(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId, UiMapSystem system, bool local, uint32 *uiMapId=nullptr, DBCPosition2D *newPos=nullptr)
void GetReachableNodesMask(TaxiNodesEntry const *from, TaxiMask *mask)
std::size_t GetCompleteNodeRoute(TaxiNodesEntry const *from, TaxiNodesEntry const *to, Player const *player, std::vector< uint32 > &shortestPath)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
EnumFlag< TaxiNodeFlags > GetFlags() const
bool IsPartOfTaxiNetwork() const