VIPRA Documentation
Loading...
Searching...
No Matches
map.hpp
1#pragma once
2
3#include <map>
4#include <stdexcept>
5#include <string>
6#include <vector>
7
8#include "vipra/geometry/geometry.hpp"
9
10#include "vipra/geometry/polygon.hpp"
11#include "vipra/logging/logging.hpp"
12#include "vipra/macros/module.hpp"
13#include "vipra/modules/map_input.hpp"
14#include "vipra/types/float.hpp"
15
16#include "vipra/macros/map.hpp"
17
18namespace VIPRA::Modules {
23class Map {
24 public:
25 // FORWARD_REGISTER_PARAMS;
26
27 virtual VIPRA_MAP_INIT = 0;
28 virtual VIPRA_MAP_RESET = 0;
29
30 void reset_module()
31 {
32 _obstacles.clear();
33 _objectives.clear();
34 _spawns.clear();
35 _areas.clear();
36 _objectiveTypes.clear();
37 }
38
39 virtual void obstacle_added(VIPRA::Geometry::Polygon const& obstacle) {}
40 virtual void objective_added(std::string const& type,
41 VIPRA::Geometry::Polygon const& objective)
42 {
43 }
44 virtual void area_added(std::string const& name,
45 VIPRA::Geometry::Polygon const& polygon)
46 {
47 }
48
49 [[nodiscard]] virtual auto collision(VIPRA::f3d point) const -> bool
50 {
51 return std::any_of(_obstacles.begin(), _obstacles.end(), [&](auto const& obstacle) {
52 return obstacle.is_point_inside(point);
53 });
54 }
55 [[nodiscard]] virtual auto collision(VIPRA::Geometry::Circle const& radius) const
56 -> bool
57 {
58 if ( collision(radius.center()) ) return true;
59
60 return std::any_of(_obstacles.begin(), _obstacles.end(),
61 [&](Geometry::Polygon const& obstacle) {
62 return Geometry::do_intersect(obstacle, radius);
63 });
64 }
65
66 [[nodiscard]] virtual auto ray_hit(VIPRA::f3d start,
67 VIPRA::f3d end) const -> VIPRA::f_pnt
68 {
69 VIPRA::f_pnt hit = std::numeric_limits<VIPRA::f_pnt>::max();
70 for ( auto const& obstacle : _obstacles ) {
71 for ( auto const& edge : obstacle.sides() ) {
72 if ( ! edge.does_intersect({start, end}) ) continue;
73 auto intersection = edge.intersection_point({start, end});
74 hit = std::min(hit, start.distance_to(intersection));
75 }
76 }
77 return hit;
78 }
79
80 void add_obstacle(VIPRA::Geometry::Polygon const& obstacle)
81 {
82 VIPRA::Log::debug("Adding Obstacle at {}, {}, {}", obstacle.center().x,
83 obstacle.center().y, obstacle.center().z);
84 _obstacles.push_back(obstacle);
85
86 if ( _initialized ) obstacle_added(obstacle);
87 }
88 void add_objective(std::string const& type, VIPRA::Geometry::Polygon const& objective)
89 {
90 VIPRA::Log::debug("Adding Objective at {}, {}, {}", objective.center().x,
91 objective.center().y, objective.center().z);
92 if ( ! _objectives.contains(type) ) _objectives[type] = {};
93
94 _objectives[type].push_back(objective);
95
96 if ( _initialized ) objective_added(type, objective);
97 }
98 void add_spawn(VIPRA::Geometry::Polygon const& spawn)
99 {
100 VIPRA::Log::debug("Adding Spawn at {}, {}, {}", spawn.center().x, spawn.center().y,
101 spawn.center().z);
102 _spawns.push_back(spawn);
103 }
104 void add_area(std::string const& name, VIPRA::Geometry::Polygon const& polygon)
105 {
106 VIPRA::Log::debug("Adding Area at {}, {}, {}", polygon.center().x, polygon.center().y,
107 polygon.center().z);
108 _areas[name] = polygon;
109
110 if ( _initialized ) area_added(name, polygon);
111 }
112
113 [[nodiscard]] auto get_objectives() const
114 -> std::map<std::string, std::vector<VIPRA::Geometry::Polygon>> const&
115 {
116 return _objectives;
117 }
118 [[nodiscard]] auto get_objectives(std::string const& type) const
119 -> std::vector<VIPRA::Geometry::Polygon> const&
120 {
121 auto iter = _objectives.find(type);
122 if ( iter == _objectives.end() ) {
123 VIPRA_BASE_MODULE_ERROR("Map", "Map does NOT have objectives of type: {}", type);
124 }
125
126 return iter->second;
127 }
128
129 [[nodiscard]] auto get_dimensions() const -> VIPRA::f3d { return _dimensions; }
130 [[nodiscard]] auto get_objective_types() const -> std::vector<std::string> const&
131 {
132 return _objectiveTypes;
133 }
134 [[nodiscard]] auto get_obstacles() const -> std::vector<VIPRA::Geometry::Polygon> const&
135 {
136 return _obstacles;
137 }
138 [[nodiscard]] auto get_spawns() const -> std::vector<VIPRA::Geometry::Polygon> const&
139 {
140 return _spawns;
141 }
142 [[nodiscard]] auto get_areas() const -> std::map<std::string, VIPRA::Geometry::Polygon>
143 {
144 return _areas;
145 }
146
147 void initialize(VIPRA::Modules::MapInput& input)
148 {
149 VIPRA::Log::debug("Initializing Map");
150
151 auto obstacles = input.get_obstacles();
152 if ( ! obstacles )
153 VIPRA_BASE_MODULE_ERROR("Map", "Input Module failed to load map obstacles");
154
155 auto objectives = input.get_objectives();
156 if ( ! objectives )
157 VIPRA_BASE_MODULE_ERROR("Map", "Input Module failed to load map objectives");
158
159 auto spawns = input.get_spawns();
160 if ( ! spawns )
161 VIPRA_BASE_MODULE_ERROR("Map",
162 "Input Module failed to load map pedestrians spawn areas");
163
164 auto areas = input.get_areas();
165 if ( ! areas )
166 VIPRA_BASE_MODULE_ERROR("Map", "Input Module failed to load map areas");
167
168 _obstacles = std::move(obstacles.value());
169 _objectives = std::move(objectives.value());
170 _spawns = std::move(spawns.value());
171 _areas = std::move(areas.value());
172
173 for ( auto const& [type, _] : _objectives ) {
174 _objectiveTypes.push_back(type);
175 }
176
177 find_dimensions(_obstacles, _objectives, _spawns, _areas);
178 VIPRA::Log::debug("Map: {} Obstacles, {} Spawns, {} Areas", _obstacles.size(),
179 _spawns.size(), _areas.size());
180
181 // initialize derived obstacles module
182 init_step(_obstacles, _objectives, _spawns, _areas);
183
184 VIPRA::Log::debug("Map Initialized");
185 }
186
187 private:
188 std::vector<VIPRA::Geometry::Polygon> _obstacles;
189 std::map<std::string, std::vector<VIPRA::Geometry::Polygon>> _objectives;
190 std::vector<VIPRA::Geometry::Polygon> _spawns;
191 std::map<std::string, VIPRA::Geometry::Polygon> _areas;
192 std::vector<std::string> _objectiveTypes;
193
194 bool _initialized{false};
195 VIPRA::f3d _dimensions;
196
197 void find_dimensions(
198 std::vector<VIPRA::Geometry::Polygon> const& obstacles,
199 std::map<std::string, std::vector<VIPRA::Geometry::Polygon>> const& objectives,
200 std::vector<VIPRA::Geometry::Polygon> const& spawns,
201 std::map<std::string, VIPRA::Geometry::Polygon> const& areas)
202 {
203 auto setToMax = [&](auto const& polygon) {
204 for ( auto const& edge : polygon.sides() ) {
205 _dimensions.x = std::max({_dimensions.x, edge.start.x, edge.end.x});
206 _dimensions.y = std::max({_dimensions.y, edge.start.y, edge.end.y});
207 _dimensions.z = std::max({_dimensions.z, edge.start.z, edge.end.z});
208 }
209 };
210
211 auto setToAllMax = [&](auto const& polygons) {
212 for ( auto const& polygon : polygons ) {
213 setToMax(polygon);
214 }
215 };
216
217 setToAllMax(obstacles);
218 setToAllMax(spawns);
219
220 for ( auto const& [_, polygons] : objectives ) {
221 setToAllMax(polygons);
222 };
223
224 for ( auto const& [_, polygon] : areas ) {
225 setToMax(polygon);
226 };
227
228 VIPRA::Log::debug("Map Dimensions: {}, {}, {}", _dimensions.x, _dimensions.y,
229 _dimensions.z);
230 }
231
232 public:
233 virtual ~Map() = default;
234 Map() = default;
235 Map(const Map&) = default;
236 Map(Map&&) noexcept = default;
237 auto operator=(const Map&) -> Map& = default;
238 auto operator=(Map&&) noexcept -> Map& = default;
239};
240} // namespace VIPRA::Modules
Definition circle.hpp:9
Definition polygon.hpp:18
static VIPRA_INLINE void debug(fmt::format_string< param_ts... > message, param_ts &&... params)
Calls the provided Logger with Level DEBUG.
Definition logging.hpp:85
Base MapInput Module.
Definition map_input.hpp:15
virtual auto get_spawns() const -> std::optional< std::vector< VIPRA::Geometry::Polygon > >=0
Returns polygons as loaded from the input module, std::nullopt if incorrect type / doesn't exist.
virtual auto get_areas() const -> std::optional< std::map< std::string, VIPRA::Geometry::Polygon > >=0
Returns polygons as loaded from the input module, std::nullopt if incorrect type / doesn't exist.
virtual auto get_obstacles() const -> std::optional< std::vector< VIPRA::Geometry::Polygon > >=0
Returns polygons as loaded from the input module, std::nullopt if incorrect type / doesn't exist.
virtual auto get_objectives() const -> std::optional< std::map< std::string, std::vector< VIPRA::Geometry::Polygon > > >=0
Returns polygons as loaded from the input module, std::nullopt if incorrect type / doesn't exist.
Definition f3d.hpp:27