qHexWalker 0.0.1
Hexagonal Grid Pathfinding & Maze Visualization on Interactive Maps
Loading...
Searching...
No Matches
h3Worker.cpp
Go to the documentation of this file.
1#include "h3Worker.h"
2
3#include <helper.h>
4
5using namespace H3_VIEWER;
6using namespace std::chrono_literals;
7
8H3Worker::H3Worker(QObject *parent) : QObject(parent) {
9 astar_ = new H3AStar(this);
10
11 // Подключаем сигнал A* для визуализации процесса поиска
12 connect(astar_, &H3AStar::newCell, this, &H3Worker::onAStarNewCell, Qt::DirectConnection);
13}
14
15H3Worker::~H3Worker() = default;
16
18 while (!QThread::currentThread()->isInterruptionRequested()) {
19 {
20 std::unique_lock lk(mutex_);
21 cv_.wait(lk, [this] { return isRequested.load(); });
22 }
23
24 // Скопировать запрос и сбросить флаг
26 {
27 std::lock_guard lk(mutex_);
28 req = pending_;
29 pending_.has = false;
30 }
31
32 if (!req.has) {
33 continue;
34 }
35
36 // Сброс счётчика и засекаем время
37 exploredCellsCount_.store(0);
38 auto startTime = std::chrono::high_resolution_clock::now();
39
40 H3Index prevIndex = req.indexes.front();
41 std::vector<H3Index> path;
42 path.reserve(req.indexes.size());
43 int totalPathLength = 0;
44
45 for (size_t indexId = 1; indexId < req.indexes.size(); indexId++) {
46 try {
47 path = astar_->findShortestPath(prevIndex, req.indexes.at(indexId));
48 prevIndex = req.indexes.at(indexId);
49 totalPathLength += static_cast<int>(path.size());
50
51 for (const auto index : path) {
52 auto childPolygon = Helper::indexToPolygon(index);
53 if (!childPolygon.has_value()) {
54 break;
55 }
56 emit cellComputed(getResolution(index), index, childPolygon.value(), true);
57 }
58 } catch (const std::exception &e) {
59 spdlog::warn("{}", e.what());
60 }
61 }
62
63 // Вычисляем время поиска
64 auto endTime = std::chrono::high_resolution_clock::now();
65 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);
66 const auto timeMs = static_cast<double>(duration.count()) / 1000.0;
67
68 // Эмитим статистику
69 emit searchStats(exploredCellsCount_.load(), timeMs, totalPathLength);
70
71 {
72 std::lock_guard lk(mutex_);
73 isRequested.store(false);
74 }
75 }
76 emit finished();
77}
78
79void H3Worker::requestCell(const std::vector<H3Index> &index) {
80 {
81 std::lock_guard lk(mutex_);
82 if (isRequested.load()) {
83 SPDLOG_WARN("cancel <requestCell>");
84 return;
85 }
86 pending_.indexes = index;
87 pending_.has = true;
88 isRequested.store(true);
89 }
90 cv_.notify_one();
91}
92
93void H3Worker::setWalls(const std::unordered_set<H3Index> &mazeWalls) {
94 std::lock_guard lk(mutex_);
95 walls = mazeWalls;
96
97 if (astar_) {
99 }
100
101 spdlog::info("H3Worker: Walls updated for A* algorithm, {} wall cells", walls.size());
102}
103
104void H3Worker::onAStarNewCell(const H3Index cell) {
105 // Увеличиваем счётчик исследованных ячеек для статистики
106 exploredCellsCount_.fetch_add(1, std::memory_order_relaxed);
107
108 // Throttling: показываем каждую N-ую ячейку для плавной анимации
109 static int counter = 0;
110 static constexpr int THROTTLE_FACTOR = 25; // Показываем каждую 25-ю ячейку
111
112 if (++counter % THROTTLE_FACTOR != 0) {
113 return;
114 }
115
116 // Конвертируем H3Index в полигон
117 const auto polygon = Helper::indexToPolygon(cell);
118 if (!polygon.has_value()) {
119 return;
120 }
121
122 // Эмитим сигнал с флагом isSearching=false (исследуемая ячейка, не финальный путь)
123 emit cellComputed(getResolution(cell), cell, polygon.value(), false);
124}
Bidirectional A* pathfinding algorithm for H3 hexagonal cells.
Definition astar.h:45
std::vector< H3Index > findShortestPath(H3Index start, H3Index end)
Finds the shortest path between two H3 cells.
Definition astar.cpp:12
void setBlockedCells(const std::unordered_set< H3Index > &blocked)
Sets cells that cannot be traversed (obstacles).
Definition astar.cpp:10
std::condition_variable cv_
Condition variable for efficient waiting.
Definition h3Worker.h:176
void requestCell(const std::vector< H3Index > &index)
Requests computation for a set of H3 cells.
Definition h3Worker.cpp:79
std::atomic< int > exploredCellsCount_
Counter for explored cells during current search.
Definition h3Worker.h:182
void onAStarNewCell(H3Index cell)
Handles cell exploration events from A* algorithm.
Definition h3Worker.cpp:104
H3AStar * astar_
A* pathfinding algorithm instance.
Definition h3Worker.h:167
void searchStats(int exploredCells, double timeMs, int pathLength)
Emitted with pathfinding statistics after search completes.
void cellComputed(quint8 res, H3Index id, const QVariantList &polygon, bool isSearching)
Emitted when a single cell computation completes.
std::atomic_bool isRequested
Flag indicating a request is pending.
Definition h3Worker.h:170
void setWalls(const std::unordered_set< H3Index > &mazeWalls)
Sets maze walls for pathfinding obstacle avoidance.
Definition h3Worker.cpp:93
~H3Worker() override
Destructor.
bool has
Flag indicating pending request.
Definition h3Worker.h:76
void doWork()
Main work loop executed in the worker thread.
Definition h3Worker.cpp:17
std::unordered_set< H3Index > walls
Maze wall cells for obstacle avoidance.
Definition h3Worker.h:164
PendingRequest pending_
Currently pending request.
Definition h3Worker.h:179
std::mutex mutex_
Mutex for thread synchronization.
Definition h3Worker.h:173
H3Worker(QObject *parent=nullptr)
Constructs an H3Worker.
Definition h3Worker.cpp:8
std::vector< H3Index > indexes
Cell indices to process.
Definition h3Worker.h:75
Structure holding queued cell computation requests.
Definition h3Worker.h:74
Worker thread for asynchronous H3 cell processing and pathfinding.
Namespace containing H3 visualization components.
Definition h3Model.h:20
static std::optional< QVariantList > indexToPolygon(const H3Index index)
Definition helper.h:6