Tatooine
grid_edge.h
Go to the documentation of this file.
1#ifndef TATOOINE_EDGE_H
2#define TATOOINE_EDGE_H
3//==============================================================================
4#include <iostream>
5#include <unordered_map>
6#include <unordered_set>
7
8#include "for_loop.h"
9#include "grid_vertex.h"
10#include "linspace.h"
11#include "math.h"
12//==============================================================================
13namespace tatooine {
14//==============================================================================
15template <rectilinear_grid_dimension... IndexableSpaces>
16class grid;
17template <typename Real, size_t N>
19template <typename Real, size_t N>
21template <typename Real, size_t N>
23 : public std::pair<grid_vertex<Real, N>, grid_vertex<Real, N>> {
24 using vertex_t = grid_vertex<Real, N>;
25 using parent_type = std::pair<vertex_t, vertex_t>;
26 //============================================================================
27 grid_edge(const vertex_t& v0, const vertex_t& v1)
28 : parent_type(std::min(v0, v1), std::max(v0, v1)) {}
29 //----------------------------------------------------------------------------
31 //----------------------------------------------------------------------------
32 grid_edge(grid_edge&& e) noexcept : parent_type(std::move(e)) {}
33 //----------------------------------------------------------------------------
34 auto operator=(const grid_edge& e) -> grid_edge& = default;
35 auto operator=(grid_edge&& e) noexcept -> grid_edge& = default;
36 //----------------------------------------------------------------------------
37 ~grid_edge() = default;
38 //----------------------------------------------------------------------------
39 auto as_position_pair() const {
40 return std::pair{*this->first, *this->second};
41 }
42 //----------------------------------------------------------------------------
43 auto operator*() const { return as_position_pair(); }
44 //----------------------------------------------------------------------------
45 auto operator==(const grid_edge& other) const -> bool {
46 return (this->first == other.second && this->second == other.first) ||
47 (this->first == other.first && this->second == other.second);
48 }
49 //----------------------------------------------------------------------------
50 auto operator!=(const grid_edge& other) const -> bool {
51 return !operator==(other);
52 }
53 //----------------------------------------------------------------------------
54 auto operator<(const grid_edge& other) const -> bool {
55 for (size_t i = 0; i < N; ++i) {
56 if (this->first.iterators[i].i() < other.first.iterators[i].i()) {
57 return true;
58 }
59 if (this->first.iterators[i].i() > other.first.iterators[i].i()) {
60 return false;
61 }
62 }
63 for (size_t i = 0; i < N; ++i) {
64 if (this->second.iterators[i].i() < other.second.iterators[i].i()) {
65 return true;
66 }
67 if (this->second.iterators[i].i() > other.second.iterators[i].i()) {
68 return false;
69 }
70 }
71 return false;
72 }
73 //----------------------------------------------------------------------------
74 auto operator<=(const grid_edge& other) const -> bool {
75 return operator==(other) || operator<(other);
76 }
77 //----------------------------------------------------------------------------
78 auto operator>(const grid_edge& other) const -> bool {
79 for (size_t i = 0; i < N; ++i) {
80 if (this->first.iterators[i].i > other.first.iterators[i].i) {
81 return true;
82 }
83 if (this->first.iterators[i].i < other.first.iterators[i].i) {
84 return false;
85 }
86 }
87 for (size_t i = 0; i < N; ++i) {
88 if (this->second.iterators[i].i > other.second.iterators[i].i) {
89 return true;
90 }
91 if (this->second.iterators[i].i < other.second.iterators[i].i) {
92 return false;
93 }
94 }
95 return false;
96 }
97 //----------------------------------------------------------------------------
98 auto operator>=(const grid_edge& other) const -> bool {
99 return operator==(other) || operator>(other);
100 }
101 //----------------------------------------------------------------------------
102 auto to_string() {
103 return this->first.to_string() + ' ' + this->second.to_string();
104 }
105};
106//==============================================================================
107template <typename Real, size_t N>
108inline auto operator<<(std::ostream& out, const grid_edge<Real, N>& e)
109 -> auto& {
110 out << e.first << " - " << e.second;
111 return out;
112}
113//==============================================================================
114template <typename Real, size_t N>
116 template <size_t... Is>
117 static constexpr size_t calc_max_num_edges_per_cell(
118 std::index_sequence<Is...> /*seq*/) {
119 return (ipow(3, Is) + ...);
120 }
121
122 static constexpr size_t calc_max_num_edges_per_cell() {
123 return calc_max_num_edges_per_cell(std::make_index_sequence<N>{});
124 }
125
126 template <size_t... Is>
127 static constexpr auto calc_edge_dirs(std::index_sequence<Is...> /*seq*/) {
128 auto dirs = make_array<vec<int, N>, max_num_edges_per_cell>();
129 size_t i = 0;
130 for_loop(
131 [&](auto... is) {
132 if (((is != 1) || ...)) {
133 dirs[i] = vec<int, N>{(2 - int(is) - 1)...};
134 for (size_t j = 0; j < N / 2; ++j) {
135 tat_swap(dirs[i](j), dirs[i][N - j - 1]);
136 }
137 ++i;
138 return true;
139 }
140 return false;
141 },
142 ((void)Is, 3)...);
143 return dirs;
144 }
145 static constexpr auto calc_edge_dirs() {
146 return calc_edge_dirs(std::make_index_sequence<N>{});
147 }
148
149 static constexpr auto calc_bases() {
150 auto bs = make_array<vec<size_t, N>, max_num_edges_per_cell>(
152 auto base_it = begin(bs);
153 for (const auto& dir : edge_dirs) {
154 for (size_t i = 0; i < N; ++i) {
155 if (dir(i) < 0) { base_it->at(i) = 1; }
156 }
157 ++base_it;
158 }
159 return bs;
160 }
161
162 public:
164 static constexpr auto edge_dirs = calc_edge_dirs();
165 static constexpr auto bases = calc_bases();
166
167 private:
169 grid_vertex_iterator<Real, N> m_vit;
171
172 public:
174 grid_vertex_iterator<Real, N>&& vit,
175 size_t edge_idx)
176 : m_grid{g}, m_vit{std::move(vit)}, m_edge_idx{edge_idx} {}
177 auto operator++() -> auto& {
178 do {
179 ++m_edge_idx;
181 m_edge_idx = 0;
182 ++m_vit;
183 }
184 } while (!is_valid());
185 return *this;
186 }
187 auto operator==(const grid_edge_iterator<Real, N>& other) const -> bool {
188 return m_grid == other.m_grid && m_vit == other.m_vit &&
189 m_edge_idx == other.m_edge_idx;
190 }
191 auto operator!=(const grid_edge_iterator<Real, N>& other) const -> bool {
192 return m_grid != other.m_grid || m_vit != other.m_vit ||
193 m_edge_idx != other.m_edge_idx;
194 }
195 auto operator<(const grid_edge_iterator<Real, N>& other) const -> bool{
196 if (m_vit < other.m_vit) { return true; }
197 if (m_vit > other.m_vit) { return false; }
198 return m_edge_idx < other.m_edge_idx;
199 }
200 auto operator*() const -> grid_edge<Real, N> {
201 auto v0 = *m_vit;
202 for (size_t i = 0; i < N; ++i) { v0.index(i) += bases[m_edge_idx](i); }
203 auto v1 = v0;
204 for (size_t i = 0; i < N; ++i) { v1.index(i) += edge_dirs[m_edge_idx](i); }
205 return grid_edge{std::move(v0), std::move(v1)};
206 }
207 auto is_valid() const -> bool {
208 auto v0 = *m_vit;
209 bool is_end = true;
210 for (size_t i = 0; i < N; ++i) {
211 if (i < N - 1) {
212 if (v0.index(i) != 0) {
213 is_end = false;
214 break;
215 }
216 } else {
217 if (v0.index(i) != m_grid->dimension(i).size()) {
218 is_end = false;
219 break;
220 }
221 }
222 }
223 if (is_end && m_edge_idx == 0) { return true; }
224
225 for (size_t i = 0; i < N; ++i) { v0.index(i) += bases[m_edge_idx](i); }
226 auto v1 = v0;
227 for (size_t i = 0; i < N; ++i) { v1.index(i) += edge_dirs[m_edge_idx](i); }
228
229 for (size_t i = 0; i < N; ++i) {
230 if (v0.index(i) >= m_grid->dimension(i).size()) { return false; }
231 }
232 for (size_t i = 0; i < N; ++i) {
233 if (v1.index(i) >= m_grid->dimension(i).size()) { return false; }
234 }
235 return true;
236 }
237};
238//==============================================================================
239template <typename Real, size_t N>
242
243 public:
244 explicit grid_edge_container(grid<Real, N>const* g) : m_grid{g} {}
245 auto begin() const {
246 return grid_edge_iterator{m_grid, m_grid->vertex_begin(), 0};
247 }
248 auto end() const {
249 return grid_edge_iterator{m_grid, m_grid->vertex_end(), 0};
250 }
251};
252//==============================================================================
253} // namespace tatooine
254//==============================================================================
255#endif
Definition: grid_edge.h:240
grid< Real, N > const * m_grid
Definition: grid_edge.h:241
auto begin() const
Definition: grid_edge.h:245
grid_edge_container(grid< Real, N >const *g)
Definition: grid_edge.h:244
auto end() const
Definition: grid_edge.h:248
Definition: grid_edge.h:115
auto operator<(const grid_edge_iterator< Real, N > &other) const -> bool
Definition: grid_edge.h:195
auto operator==(const grid_edge_iterator< Real, N > &other) const -> bool
Definition: grid_edge.h:187
static constexpr size_t calc_max_num_edges_per_cell()
Definition: grid_edge.h:122
auto is_valid() const -> bool
Definition: grid_edge.h:207
auto operator!=(const grid_edge_iterator< Real, N > &other) const -> bool
Definition: grid_edge.h:191
grid_vertex_iterator< Real, N > m_vit
Definition: grid_edge.h:169
auto operator++() -> auto &
Definition: grid_edge.h:177
static constexpr auto max_num_edges_per_cell
Definition: grid_edge.h:163
static constexpr auto calc_edge_dirs()
Definition: grid_edge.h:145
static constexpr size_t calc_max_num_edges_per_cell(std::index_sequence< Is... >)
Definition: grid_edge.h:117
grid< Real, N > const * m_grid
Definition: grid_edge.h:168
static constexpr auto calc_bases()
Definition: grid_edge.h:149
size_t m_edge_idx
Definition: grid_edge.h:170
static constexpr auto calc_edge_dirs(std::index_sequence< Is... >)
Definition: grid_edge.h:127
static constexpr auto bases
Definition: grid_edge.h:165
static constexpr auto edge_dirs
Definition: grid_edge.h:164
grid_edge_iterator(grid< Real, N >const *g, grid_vertex_iterator< Real, N > &&vit, size_t edge_idx)
Definition: grid_edge.h:173
auto operator*() const -> grid_edge< Real, N >
Definition: grid_edge.h:200
Definition: grid_edge.h:16
Definition: algorithm.h:6
auto operator<<(std::ostream &out, linspace< Real > const &l) -> auto &
Definition: linspace.h:165
auto begin(Range &&range)
Definition: iterator_facade.h:318
constexpr void tat_swap(T &t0, T &t1)
Definition: utility.h:81
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
constexpr auto ipow(integral auto const base, integral auto const exp)
Definition: math.h:97
constexpr auto min(A &&a, B &&b)
Definition: math.h:15
constexpr auto for_loop(Iteration &&iteration, execution_policy::sequential_t, Ranges(&&... ranges)[2]) -> void
Use this function for creating a sequential nested loop.
Definition: for_loop.h:336
Definition: grid_edge.h:23
auto operator<=(const grid_edge &other) const -> bool
Definition: grid_edge.h:74
auto operator<(const grid_edge &other) const -> bool
Definition: grid_edge.h:54
grid_edge(const vertex_t &v0, const vertex_t &v1)
Definition: grid_edge.h:27
grid_edge(const grid_edge &e)
Definition: grid_edge.h:30
auto operator!=(const grid_edge &other) const -> bool
Definition: grid_edge.h:50
auto operator==(const grid_edge &other) const -> bool
Definition: grid_edge.h:45
auto operator=(grid_edge &&e) noexcept -> grid_edge &=default
auto operator*() const
Definition: grid_edge.h:43
auto operator=(const grid_edge &e) -> grid_edge &=default
grid_edge(grid_edge &&e) noexcept
Definition: grid_edge.h:32
auto to_string()
Definition: grid_edge.h:102
auto operator>(const grid_edge &other) const -> bool
Definition: grid_edge.h:78
std::pair< vertex_t, vertex_t > parent_type
Definition: grid_edge.h:25
auto operator>=(const grid_edge &other) const -> bool
Definition: grid_edge.h:98
auto as_position_pair() const
Definition: grid_edge.h:39
grid_vertex< Real, N > vertex_t
Definition: grid_edge.h:24
Definition: vec.h:12
static auto constexpr zeros()
Definition: vec.h:26