VIPRA Documentation
Loading...
Searching...
No Matches
grid.hpp
1#pragma once
2
3#include <array>
4#include <limits>
5#include <queue>
6
7#include "vipra/geometry/circle.hpp"
8#include "vipra/geometry/f3d.hpp"
9
10#include "vipra/types/float.hpp"
11#include "vipra/types/idx.hpp"
12#include "vipra/types/size.hpp"
13
14#include "density_grid.hpp"
15#include "vipra/logging/logging.hpp"
16
17// TODO: Generalize Grid and inherit Grid for this class.
18
19namespace VIPRA::Goals {
20
21class Grid {
22 public:
23 struct GridPoint {
24 VIPRA::f3d direction;
25 VIPRA::f3d end{VIPRA::_emptyf3d_};
26 VIPRA::f_pnt distance{std::numeric_limits<VIPRA::f_pnt>::max()};
27 };
28
29 void intialize(auto const& map, VIPRA::f_pnt gridSize)
30 {
31 _gridSize = gridSize;
32 construct_grid(map);
33 }
34
35 [[nodiscard]] auto get_grid(VIPRA::f3d pos) -> GridPoint&
36 {
37 return _grid[get_closest_grid_idx(pos)];
38 }
39 [[nodiscard]] auto get_grid(VIPRA::f3d pos) const -> GridPoint const&
40 {
41 return _grid[get_closest_grid_idx(pos)];
42 }
43
44 [[nodiscard]] auto get_x_count() const -> size_t { return _xCount; }
45 [[nodiscard]] auto get_y_count() const -> size_t { return _xCount; }
46
47 [[nodiscard]] auto begin() -> std::vector<GridPoint>::iterator { return _grid.begin(); }
48 [[nodiscard]] auto end() -> std::vector<GridPoint>::iterator { return _grid.end(); }
49
50 void flood_fill(VIPRA::f3d start, auto const& map)
51 {
52 const VIPRA::f3d dimensions = map.get_dimensions();
53 std::queue<VIPRA::f3d> next;
54 VIPRA::f_pnt dist = 0;
55
56 get_grid(start).distance = 0;
57 next.push(grid_center(start));
58
59 while ( ! next.empty() ) {
60 VIPRA::f3d currPos = next.front();
61 next.pop();
62
63 if ( map.collision(Geometry::Circle{grid_center(currPos), _gridSize}) ) continue;
64
65 add_neighbors(currPos, start, next, 0);
66 }
67 }
68
69 void flood_fill(VIPRA::f3d start, auto const& map, DensityGrid const& densityGrid)
70 {
71 const VIPRA::f3d dimensions = map.get_dimensions();
72 std::queue<VIPRA::f3d> next;
73 VIPRA::f_pnt dist = 0;
74
75 get_grid(start).distance = 0;
76 next.push(grid_center(start));
77
78 while ( ! next.empty() ) {
79 VIPRA::f3d currPos = next.front();
80 next.pop();
81
82 if ( map.collision(Geometry::Circle{grid_center(currPos), _gridSize}) ) continue;
83
84 VIPRA::idx densityGridIndex = densityGrid.get_closest_grid_idx(currPos);
85 int pedCount = densityGrid.get_ped_count_at_idx(densityGridIndex);
86 add_neighbors(currPos, start, next, pedCount);
87 }
88 }
89
96 [[nodiscard]] auto get_closest_grid_idx(VIPRA::f3d pos) const -> VIPRA::idx
97 {
98 auto gridX = static_cast<VIPRA::idx>(std::floor(pos.x / _gridSize));
99 auto gridY = static_cast<VIPRA::idx>(std::floor(pos.y / _gridSize));
100
101 auto const idx = get_index(gridX, gridY, _xCount);
102
103 if ( out_of_bounds(gridX, gridY) ) {
104 VIPRA::Log::error("Grid index is out of bounds Pos: ({}, {})", pos.x, pos.y);
105 throw std::runtime_error("Grid index is out of bounds");
106 }
107
108 return idx;
109 }
110
111 [[nodiscard]] auto grid_center(VIPRA::f3d pos) const -> VIPRA::f3d
112 {
113 auto gridX = static_cast<VIPRA::idx>(std::floor(pos.x / _gridSize));
114 auto gridY = static_cast<VIPRA::idx>(std::floor(pos.y / _gridSize));
115
116 return VIPRA::f3d{_gridSize * static_cast<VIPRA::f_pnt>(gridX),
117 _gridSize * static_cast<VIPRA::f_pnt>(gridY)};
118 }
119
120 private:
121 VIPRA::size _xCount{};
122 VIPRA::size _yCount{};
123 VIPRA::f_pnt _gridSize{};
124
125 std::vector<GridPoint> _grid;
126
132 void set_grid_counts(auto const& map)
133 {
134 const VIPRA::f3d dimensions = map.get_dimensions();
135
136 assert(dimensions.x > 0 && dimensions.y > 0);
137 assert(_gridSize > 0);
138
139 _xCount = static_cast<VIPRA::idx>(std::ceil(dimensions.x / _gridSize) + 1);
140 _yCount = static_cast<VIPRA::idx>(std::ceil(dimensions.y / _gridSize) + 1);
141 }
142
151 [[nodiscard]] static auto get_index(VIPRA::size gridX, VIPRA::size gridY,
152 VIPRA::size xCount) noexcept -> VIPRA::idx
153 {
154 return gridX + (gridY * xCount);
155 }
156
162 void construct_grid(auto const& map)
163 {
164 set_grid_counts(map);
165
166 assert(_xCount > 0 && _yCount > 0);
167
168 _grid = std::vector<GridPoint>(_xCount * _yCount);
169 }
170
171 [[nodiscard]] VIPRA_INLINE auto out_of_bounds(VIPRA::f_pnt gridX,
172 VIPRA::f_pnt gridY) const -> bool
173 {
174 return gridX < 0 || gridX >= static_cast<VIPRA::f_pnt>(_xCount) * _gridSize ||
175 gridY < 0 || gridY >= static_cast<VIPRA::f_pnt>(_yCount) * _gridSize;
176 }
177
178 [[nodiscard]] VIPRA_INLINE auto out_of_bounds(size_t gridX, size_t gridY) const -> bool
179 {
180 return gridX < 0 || gridX >= _xCount || gridY < 0 || gridY >= _yCount;
181 }
182
183 void add_neighbors(VIPRA::f3d curr, VIPRA::f3d end, std::queue<VIPRA::f3d>& queue,
184 VIPRA::f_pnt weight)
185 {
186 std::array<std::pair<int, int>, 8> const directions{
187 {{-1, 1}, {0, 1}, {1, 1}, {-1, 0}, {1, 0}, {-1, -1}, {0, -1}, {1, -1}}};
188
189 auto& currGrid = get_grid(curr);
190
191 for ( auto [i, j] : directions ) {
192 if ( i == 0 && i == j ) continue;
193
194 VIPRA::f3d nextPos = VIPRA::f3d{curr.x + i * _gridSize, curr.y + j * _gridSize};
195
196 if ( out_of_bounds(nextPos.x, nextPos.y) ) continue;
197
198 auto& grid = get_grid(nextPos);
199
200 VIPRA::f_pnt dist = currGrid.distance + curr.distance_to_sqrd(nextPos) + weight;
201
202 if ( grid.distance <= dist ) continue;
203
204 grid.direction = (curr - nextPos).unit();
205 grid.end = end;
206 grid.distance = dist;
207
208 queue.emplace(nextPos);
209 }
210 }
211
212 public:
213 Grid() = default;
214 Grid(const Grid&) = default;
215 Grid(Grid&&) noexcept = default;
216 auto operator=(const Grid&) -> Grid& = default;
217 auto operator=(Grid&&) noexcept -> Grid& = default;
218 ~Grid() = default;
219};
220} // namespace VIPRA::Goals
auto get_closest_grid_idx(VIPRA::f3d pos) const -> VIPRA::idx
Gets the closest grid index to the coordinate.
Definition grid.hpp:96
static VIPRA_INLINE void error(fmt::format_string< param_ts... > message, param_ts &&... params)
Calls the provided Logger with Level DEBUG.
Definition logging.hpp:102
Definition pathing_graph.hpp:14
Definition grid.hpp:23
Definition f3d.hpp:27