44#include " omath/pathfinding/a_star.hpp"
55#include < algorithm>
66#include < optional>
7+ #include < queue>
78#include < unordered_map>
89#include < unordered_set>
910
11+ namespace
12+ {
13+ struct OpenListNode final
14+ {
15+ omath::Vector3<float > position;
16+ float f_cost;
17+
18+ [[nodiscard]]
19+ bool operator >(const OpenListNode& other) const noexcept
20+ {
21+ return f_cost > other.f_cost ;
22+ }
23+ };
24+ }
25+
1026namespace omath ::pathfinding
1127{
1228 struct PathNode final
@@ -37,23 +53,13 @@ namespace omath::pathfinding
3753 std::ranges::reverse (path);
3854 return path;
3955 }
40- auto Astar::get_perfect_node (const std::unordered_map<Vector3<float >, PathNode>& open_list,
41- const Vector3<float >& end_vertex) noexcept
42- {
43- return std::ranges::min_element (open_list,
44- [&end_vertex](const auto & a, const auto & b)
45- {
46- const float fa = a.second .g_cost + a.first .distance_to (end_vertex);
47- const float fb = b.second .g_cost + b.first .distance_to (end_vertex);
48- return fa < fb;
49- });
50- }
5156
5257 std::vector<Vector3<float >> Astar::find_path (const Vector3<float >& start, const Vector3<float >& end,
5358 const NavigationMesh& nav_mesh) noexcept
5459 {
5560 std::unordered_map<Vector3<float >, PathNode> closed_list;
56- std::unordered_map<Vector3<float >, PathNode> open_list;
61+ std::unordered_map<Vector3<float >, PathNode> node_data;
62+ std::priority_queue<OpenListNode, std::vector<OpenListNode>, std::greater<>> open_list;
5763
5864 auto maybe_start_vertex = nav_mesh.get_closest_vertex (start);
5965 auto maybe_end_vertex = nav_mesh.get_closest_vertex (end);
@@ -64,20 +70,27 @@ namespace omath::pathfinding
6470 const auto start_vertex = maybe_start_vertex.value ();
6571 const auto end_vertex = maybe_end_vertex.value ();
6672
67- open_list.emplace (start_vertex, PathNode{std::nullopt , 0 .f });
73+ node_data.emplace (start_vertex, PathNode{std::nullopt , 0 .f });
74+ open_list.push ({start_vertex, start_vertex.distance_to (end_vertex)});
6875
6976 while (!open_list.empty ())
7077 {
71- auto current_it = get_perfect_node (open_list, end_vertex);
78+ auto current = open_list.top ().position ;
79+ open_list.pop ();
80+
81+ if (closed_list.contains (current))
82+ continue ;
83+
84+ auto current_node_it = node_data.find (current);
85+ if (current_node_it == node_data.end ())
86+ continue ;
7287
73- const auto current = current_it->first ;
74- const auto current_node = current_it->second ;
88+ const auto current_node = current_node_it->second ;
7589
7690 if (current == end_vertex)
7791 return reconstruct_final_path (closed_list, current);
7892
7993 closed_list.emplace (current, current_node);
80- open_list.erase (current_it);
8194
8295 for (const auto & neighbor: nav_mesh.get_neighbors (current))
8396 {
@@ -86,11 +99,14 @@ namespace omath::pathfinding
8699
87100 const float tentative_g_cost = current_node.g_cost + neighbor.distance_to (current);
88101
89- // ReSharper disable once CppTooWideScopeInitStatement
90- const auto open_it = open_list.find (neighbor);
102+ auto node_it = node_data.find (neighbor);
91103
92- if (open_it == open_list.end () || tentative_g_cost < open_it->second .g_cost )
93- open_list[neighbor] = PathNode{current, tentative_g_cost};
104+ if (node_it == node_data.end () || tentative_g_cost < node_it->second .g_cost )
105+ {
106+ node_data[neighbor] = PathNode{current, tentative_g_cost};
107+ const float f_cost = tentative_g_cost + neighbor.distance_to (end_vertex);
108+ open_list.push ({neighbor, f_cost});
109+ }
94110 }
95111 }
96112
0 commit comments