header_utils
Loading...
Searching...
No Matches
squares.h
1
4
5#pragma once
6
7#include "direction.h"
8
10{
37
39
40 template <std::integral T>
41 constexpr bool is_surrounding(glm::tvec2<T> a, glm::tvec2<T> b) { const auto d = glm::abs_distance(a, b); return d.x < 2 && d.y < 2 && d.x + d.y > 0; }
42 template <std::integral T>
43 constexpr bool is_neighbor(glm::tvec2<T> a, glm::tvec2<T> b) { const auto d = glm::abs_distance(a, b); return d.x < 2 && d.y < 2 && d.x != d.y; }
44 template <std::integral T>
45 constexpr bool is_diagonal_neighbor(glm::tvec2<T> a, glm::tvec2<T> b) { const auto d = glm::abs_distance(a, b); return d.x < 2 && d.y < 2 && d.x == d.y; }
46
48 template <typename METRIC, typename T>
49 concept metric = std::integral<T> && requires (T t, glm::tvec2<T> vec) {
51 { METRIC::is_adjacent(vec, vec) } -> std::convertible_to<bool>;
53 { METRIC::is_adjacent(direction{}) } -> std::convertible_to<bool>;
57 { METRIC::distance(vec, vec) } -> std::convertible_to<T>;
58 };
59
62 {
63 template <std::integral T>
64 static constexpr auto is_adjacent(glm::tvec2<T> a, glm::tvec2<T> b)
65 {
66 return is_neighbor(a, b);
67 }
68
69 static constexpr auto is_adjacent(direction dir)
70 {
71 return is_cardinal(dir);
72 }
73
74 template <std::integral T>
75 static constexpr auto distance(glm::tvec2<T> a, glm::tvec2<T> b)
76 {
77 const auto d = glm::abs_distance(a, b);
78 return d.x + d.y;
79 }
80 };
81 using neighbor_metric = manhattan_metric;
82
85 {
86 template <std::integral T>
87 static constexpr bool is_adjacent(glm::tvec2<T> a, glm::tvec2<T> b)
88 {
89 return is_surrounding(a, b);
90 }
91
92 static constexpr bool is_adjacent(direction dir)
93 {
94 return is_valid(dir);
95 }
96
97 template <std::integral T>
98 static constexpr auto distance(glm::tvec2<T> a, glm::tvec2<T> b)
99 {
100 const auto d = glm::abs_distance(a, b);
101 return glm::max(d.x, d.y);
102 }
103 };
104 using surrounding_metric = chebyshev_metric;
105
107 template <std::integral T>
108 constexpr auto manhattan_distance(glm::tvec2<T> a, glm::tvec2<T> b)
109 {
110 return manhattan_metric::distance(a, b);
111 }
112 template <std::integral T>
113 constexpr auto neighbor_distance(glm::tvec2<T> a, glm::tvec2<T> b)
114 {
115 return neighbor_metric::distance(a, b);
116 }
117
118 template <std::integral T>
119 constexpr auto chebyshev_distance(glm::tvec2<T> a, glm::tvec2<T> b)
120 {
121 return chebyshev_metric::distance(a, b);
122 }
123 template <std::integral T>
124 constexpr auto surrounding_distance(glm::tvec2<T> a, glm::tvec2<T> b)
125 {
126 return surrounding_metric::distance(a, b);
127 }
128
129 template <std::integral I, std::floating_point F>
130 constexpr glm::tvec2<F> tile_pos_to_world_pos(glm::tvec2<I> tile_pos, glm::tvec2<F> tile_size) { return glm::tvec2<F>(tile_pos) * tile_size; }
131
132 template <std::integral I, std::floating_point F>
133 constexpr glm::tvec2<F> tile_pos_to_world_pos(glm::tvec2<I> tile_pos, F tile_size) { return glm::tvec2<F>(tile_pos) * tile_size; }
134
135 template <std::integral I, std::floating_point F>
136 constexpr trec2<F> world_rect_for_tile(glm::tvec2<I> pos, glm::tvec2<F> tile_size) { return trec2<F>::from_size(tile_pos_to_world_pos(pos, tile_size), tile_size); }
137
138 template <std::integral I, std::floating_point F>
139 constexpr trec2<F> world_rect_for_tile(glm::tvec2<I> pos, F tile_size) { return trec2<F>::from_size(tile_pos_to_world_pos(pos, tile_size), { tile_size, tile_size }); }
140
141 template <std::integral I = int, std::floating_point F>
142 inline glm::tvec2<I> world_pos_to_tile_pos(glm::tvec2<F> world_pos, glm::tvec2<F> tile_size) { return glm::tvec2<I>(glm::floor(world_pos / tile_size)); }
143
144 template <std::integral I = int, std::floating_point F>
145 inline glm::tvec2<I> world_pos_to_tile_pos(glm::tvec2<F> world_pos, F tile_size) { return glm::tvec2<I>(glm::floor(world_pos / tile_size)); }
146
147 template <std::integral I = int, std::floating_point F>
148 inline trec2<I> world_rect_to_tile_rect(trec2<F> const& world_rect, glm::tvec2<F> tile_size) { return trec2<I>{ glm::floor(world_rect.p1 / tile_size), glm::ceil(world_rect.p2 / tile_size) }; }
149
150 template <std::integral I = int, std::floating_point F>
151 inline trec2<I> world_rect_to_tile_rect(trec2<F> const& world_rect, F tile_size) { return trec2<I>{ glm::floor(world_rect.p1 / tile_size), glm::ceil(world_rect.p2 / tile_size) }; }
152
153 template <std::floating_point F>
154 inline glm::tvec2<F> snap_world_pos_to_tile_grid(glm::tvec2<F> world_pos, glm::tvec2<F> tile_size) {
155 return glm::floor((world_pos + (tile_size * 0.5f)) / tile_size) * tile_size;
156 }
157
159 template <std::integral I, std::floating_point F, metric<I> METRIC = chebyshev_metric>
161 {
162 using metric = METRIC;
163 using vec2 = glm::tvec2<F>;
164 using ivec2 = glm::tvec2<I>;
165 using rec2 = trec2<F>;
166 using irec2 = trec2<I>;
167
168 using tile_pos = named<vec2, "tile_pos", traits::location>;
169 using world_pos = named<ivec2, "world_pos", traits::location>;
170
171 using tile_rec = named<rec2, "tile_rec">;
172 using world_rec = named<irec2, "world_rec">;
173
174 vec2 tile_size{ F(1), F(1) };
175
176 constexpr vec2 to_world_pos(ivec2 tile_pos) const noexcept { return tile_pos_to_world_pos(tile_pos, tile_size); }
177 constexpr rec2 world_rect_for_tile(ivec2 tile_pos) const noexcept { return ghassanpl::geometry::squares::world_rect_for_tile(tile_pos, tile_size); }
178 constexpr ivec2 to_tile_pos(vec2 world_pos) const noexcept { return world_pos_to_tile_pos(world_pos, tile_size); }
179 constexpr irec2 to_tile_rect(rec2 const& world_rect) const noexcept { return world_rect_to_tile_rect(world_rect, tile_size); }
180
181 inline vec2 snap_to_grid(vec2 world_pos) const { return snap_world_pos_to_tile_grid(world_pos, tile_size); }
182
183 constexpr world_pos to_world_pos(tile_pos tile_pos) const noexcept { return to_world_pos(*tile_pos); }
184 constexpr world_rec world_rect_for_tile(tile_pos tile_pos) const noexcept { return world_rect_for_tile(*tile_pos); }
185 constexpr tile_pos to_tile_pos(world_pos world_pos) const noexcept { return to_tile_pos(*world_pos); }
186 constexpr tile_rec to_tile_rect(world_rec const& world_rect) const noexcept { return to_tile_rect(*world_rect); }
187
188 inline world_pos snap_to_grid(world_pos world_pos) const { return snap_to_grid(*world_pos); }
189
190 static constexpr auto is_adjacent(ivec2 a, ivec2 b) { return metric::is_adjacent(a, b); }
191 static constexpr auto is_adjacent(tile_pos a, tile_pos b) { return is_adjacent(*a, *b); }
192 static constexpr auto is_adjacent(direction dir) { return metric::is_adjacent(dir); }
193 static constexpr auto tile_distance(ivec2 a, ivec2 b) { return metric::distance(a, b); }
194 static constexpr auto tile_distance(tile_pos a, tile_pos b) { return distance(*a, *b); }
195 };
196
197 using chebyshev_tile_space = ttile_space<int, float, chebyshev_metric>;
198 using manhattan_tile_space = ttile_space<int, float, manhattan_metric>;
199
201 using tile_pos = named<glm::ivec2, "tile_pos", traits::location>;
203 using world_pos = named<glm::vec2, "world_pos", traits::location>;
204
206 using tile_rec = named<irec2, "tile_rec">;
208 using world_rec = named<rec2, "world_rec">;
209
211}
Any type that meets the criteria of a metric - specifying the adjacency/distances between squares.
Definition squares.h:49
named< glm::ivec2, "tile_pos", traits::location > tile_pos
Tile position with int values.
Definition squares.h:201
named< glm::vec2, "world_pos", traits::location > world_pos
World position with float values.
Definition squares.h:203
named< rec2, "world_rec"> world_rec
World rectangle with float values.
Definition squares.h:208
named< irec2, "tile_rec"> tile_rec
Tile rectangle with int values.
Definition squares.h:206
auto distance(S const &sh, glm::tvec2< T > pt)
Returns the distance between a shape and a point.
Metric in which the entire surrounding is adjacent.
Definition squares.h:85
Metric in which only neighbors are adjacent.
Definition squares.h:62
Combines a metric and tile size into a single type.
Definition squares.h:161
Represents a 2D rectangle polygon_shape.
Definition rec2.h:31
Used to create a strong typedef of T.
Definition named.h:133
This trait implies the named type is an affine type, that is, a type that does not have the addition ...
Definition named.h:57