qHexWalker 0.0.1
Hexagonal Grid Pathfinding & Maze Visualization on Interactive Maps
Loading...
Searching...
No Matches
helper.h
Go to the documentation of this file.
1#ifndef QHEXWALKER_HELPER_H
2#define QHEXWALKER_HELPER_H
3
4namespace H3_VIEWER {
5struct Helper {
6 static std::optional<QVariantList> indexToPolygon(const H3Index index) {
7 CellBoundary childBoundary{};
8 if (const auto errB = cellToBoundary(index, &childBoundary); errB != E_SUCCESS) {
9 return std::nullopt;
10 }
11
12 if (childBoundary.numVerts == 0) {
13 return std::nullopt;
14 }
15
16 QVariantList polygon;
17 //+1 для завершения полигона
18 polygon.reserve(childBoundary.numVerts + 1);
19
20 // Конвертируем первую точку
21 const double firstLat = radsToDegs(childBoundary.verts[0].lat);
22 const double firstLng = radsToDegs(childBoundary.verts[0].lng);
23
24 polygon.emplace_back(QVariant::fromValue(QGeoCoordinate{firstLat, firstLng, 0}));
25
26 double prevLng = firstLng;
27
28 // Обрабатываем остальные точки
29 for (auto i = 1; i < childBoundary.numVerts; ++i) {
30 const double lat = radsToDegs(childBoundary.verts[i].lat);
31 double lng = radsToDegs(childBoundary.verts[i].lng);
32
33 // Проверяем скачок через антимеридиан
34 // Если разница больше 180°, значит пересекли антимеридиан
35 if (const double delta = lng - prevLng; delta > 180.0) {
36 // Скачок с востока на запад: уменьшаем текущую долготу
37 lng -= 360.0;
38 } else if (delta < -180.0) {
39 // Скачок с запада на восток: увеличиваем текущую долготу
40 lng += 360.0;
41 }
42
43 polygon.emplace_back(QVariant::fromValue(QGeoCoordinate{lat, lng, 0}));
44 prevLng = lng;
45 }
46
47 // Замыкаем полигон - используем первую точку
48 polygon.emplace_back(QVariant::fromValue(QGeoCoordinate{firstLat, firstLng, 0}));
49
50 return polygon;
51 }
52
53 // Находит общее ребро (2 вершины) между двумя соседними ячейками H3
54 static std::optional<QVariantList> getSharedEdge(const H3Index cell1, const H3Index cell2) {
55 CellBoundary boundary1{}, boundary2{};
56
57 if (cellToBoundary(cell1, &boundary1) != E_SUCCESS || cellToBoundary(cell2, &boundary2) != E_SUCCESS) {
58 return std::nullopt;
59 }
60
61 if (boundary1.numVerts == 0 || boundary2.numVerts == 0) {
62 return std::nullopt;
63 }
64
65 // Находим общие вершины (должно быть ровно 2 для соседних шестиугольников)
66 std::vector<LatLng> sharedVertices;
67
68 for (int i = 0; i < boundary1.numVerts; ++i) {
69 for (int j = 0; j < boundary2.numVerts; ++j) {
70 const double latDiff = std::abs(boundary1.verts[i].lat - boundary2.verts[j].lat);
71 const double lngDiff = std::abs(boundary1.verts[i].lng - boundary2.verts[j].lng);
72
73 if (constexpr double EPSILON = 1e-9; latDiff < EPSILON && lngDiff < EPSILON) {
74 sharedVertices.emplace_back(boundary1.verts[i]);
75 break;
76 }
77 }
78 }
79
80 if (sharedVertices.size() != 2) {
81 // Не соседи или ошибка
82 return std::nullopt;
83 }
84
85 // Создаем линию из двух точек
86 QVariantList line;
87 line.reserve(2);
88
89 const double lat1 = radsToDegs(sharedVertices[0].lat);
90 const double lng1 = radsToDegs(sharedVertices[0].lng);
91 const double lat2 = radsToDegs(sharedVertices[1].lat);
92 double lng2 = radsToDegs(sharedVertices[1].lng);
93
94 // Обрабатываем антимеридиан
95 if (const double delta = lng2 - lng1; delta > 180.0) {
96 lng2 -= 360.0;
97 } else if (delta < -180.0) {
98 lng2 += 360.0;
99 }
100
101 line.emplace_back(QVariant::fromValue(QGeoCoordinate{lat1, lng1, 0}));
102 line.emplace_back(QVariant::fromValue(QGeoCoordinate{lat2, lng2, 0}));
103
104 return line;
105 }
106};
107} // namespace H3_VIEWER
108
109#endif // QHEXWALKER_HELPER_H
Namespace containing H3 visualization components.
Definition h3Model.h:20
static std::optional< QVariantList > getSharedEdge(const H3Index cell1, const H3Index cell2)
Definition helper.h:54
static std::optional< QVariantList > indexToPolygon(const H3Index index)
Definition helper.h:6