Tatooine
post_triangulation.h
Go to the documentation of this file.
1#ifndef TATOOINE_DETAIL_AUTONOMOUS_PARTICLE_POST_TRIANGULATION_H
2#define TATOOINE_DETAIL_AUTONOMOUS_PARTICLE_POST_TRIANGULATION_H
3//==============================================================================
4#include <tatooine/edgeset.h>
6
7#include <cstdint>
8#include <unordered_map>
9//==============================================================================
11//==============================================================================
12template <typename Real, std::size_t NumDimensions>
14//==============================================================================
16 std::uint64_t id;
17 std::uint64_t parent;
18};
19//==============================================================================
20template <typename Real, std::size_t NumDimensions>
21struct hierarchy {
25
26 std::uint64_t id = std::numeric_limits<std::uint64_t>::max();
28 std::vector<hierarchy> leafs = {};
29
30 public:
31 //============================================================================
32 explicit hierarchy(std::uint64_t const id_) : id{id_} {}
33 //----------------------------------------------------------------------------
34 hierarchy(std::uint64_t const id_, vertex_type const center_)
35 : id{id_}, center{center_} {}
36 //----------------------------------------------------------------------------
38 hierarchy(std::uint64_t const id_, std::vector<hierarchy_pair> const& hps,
39 std::unordered_map<std::uint64_t, vertex_type> const& centers,
40 edgeset_type const& edges)
41 : hierarchy{id_} {
42 build(hps, centers, edges);
43 if (!leafs.empty()) {
44 sort_leafs(edges);
45 center = leafs[leafs.size() / 2].center;
46 }
47 }
48 //----------------------------------------------------------------------------
50 hierarchy(std::vector<hierarchy_pair> const& hps,
51 std::unordered_map<std::uint64_t, vertex_type> const& centers,
52 edgeset_type const& edges) {
53 for (auto const& hp : hps) {
54 // search for initial nodes
55 if (hp.id == hp.parent) {
56 leafs.emplace_back(hp.parent, hps, centers, edges);
57 }
58 }
59 }
60 //----------------------------------------------------------------------------
61 auto is_root() const {
62 return id == std::numeric_limits<std::uint64_t>::max();
63 }
64 //----------------------------------------------------------------------------
65 auto find_by_id(std::uint64_t const& id) const -> auto const& {
66 for (auto const& l : leafs) {
67 if (id == l.id) {
68 return l;
69 }
70 }
71 return *this;
72 }
73
74 private:
75 //----------------------------------------------------------------------------
76 auto build(std::vector<hierarchy_pair> const& hps,
77 std::unordered_map<std::uint64_t, vertex_type> const& centers,
78 edgeset_type const& edges) -> void {
79 for (auto const& hp : hps) {
80 if (id == hp.parent && hp.parent != hp.id) {
81 leafs.emplace_back(hp.id, hps, centers, edges);
82 }
83 }
84 if (leafs.empty()) {
85 center = centers.at(id);
86 }
87 }
88 //----------------------------------------------------------------------------
89 auto sort_leafs(edgeset_type const& edges) -> void {
90 auto split_dir = calc_split_dir(edges);
91 auto dists = std::vector<std::pair<std::uint64_t, Real>>{};
92 dists.reserve(leafs.size());
93 dists.emplace_back(0, 0.0);
94 for (std::size_t i = 1; i < leafs.size(); ++i) {
95 auto offset = edges[leafs[i].center] - edges[leafs[0].center];
96 dists.emplace_back(i, std::copysign(squared_euclidean_length(offset),
97 dot(offset, split_dir)));
98 }
99 std::ranges::sort(dists, [](auto const& lhs, auto const& rhs) {
100 auto const& [i, idist] = lhs;
101 auto const& [j, jdist] = rhs;
102 return idist < jdist;
103 });
104 auto reordered_indices = std::vector<std::uint64_t>(leafs.size());
105 using namespace std::ranges;
106 copy(dists | views::transform([](auto const& x) { return x.first; }),
107 begin(reordered_indices));
108 reorder(leafs, reordered_indices);
109 }
110 //----------------------------------------------------------------------------
111 auto calc_split_dir(edgeset_type const& edges) -> vec_type {
112 if (leafs.empty()) {
113 return vec_type::zeros();
114 }
115 auto dir = normalize(edges[leafs.front().center] - edges[leafs.back().center]);
116 if (dir.x() < 0) {
117 dir = -dir;
118 }
119 return dir;
120 }
121};
122//==============================================================================
123template <typename Real, std::size_t NumDimensions>
125 edgeset<Real, NumDimensions> const& edges,
126 vec<Real, NumDimensions> const& other_center)
127 -> std::vector<vertex<Real, NumDimensions>> {
128 using namespace std::ranges;
129 if (h.leafs.empty()) {
130 return {h.center};
131 }
132 auto const split_dir = edges[h.leafs[1].center] - edges[h.leafs[0].center];
133 auto front = std::vector<vertex<Real, NumDimensions>>{};
134 auto constexpr angle_threshold = Real(20);
135 auto constexpr radians = gcem::cos(angle_threshold * M_PI / Real(180));
136 auto const offset_dir = other_center - edges[h.center];
137 auto ca = cos_angle(offset_dir, split_dir);
138 if (ca < 0) {
139 ca = cos_angle(offset_dir, -split_dir);
140 }
141 if (ca < radians) {
142 // copy all if center-center direction is perpendicular split direction
143 for (auto const& l : h.leafs) {
144 copy(get_front(l, edges, /*edges[l.center]*/ other_center),
145 std::back_inserter(front));
146 }
147 } else {
148 auto out_it = std::back_inserter(front);
149 // copy only nearest particle to front if center-center direction is
150 // parallel
151 if (squared_euclidean_distance(other_center,
152 edges[h.leafs.front().center]) <
153 squared_euclidean_distance(other_center,
154 edges[h.leafs.back().center])) {
155 copy(get_front(h.leafs.front(), edges, other_center/*edges[h.leafs.front().center]*/), out_it);
156 } else {
157 copy(get_front(h.leafs.back(), edges, other_center/*edges[h.leafs.back().center]*/), out_it);
158 }
159 }
160 return front;
161}
162//------------------------------------------------------------------------------
163template <typename Real, std::size_t NumDimensions>
165 std::vector<vertex<Real, NumDimensions>> & front1,
166 edgeset<Real, NumDimensions>& edges) -> void {
167 if (dot(edges[front0.back()] - edges[front0.front()],
168 edges[front1.back()] - edges[front1.front()]) < 0) {
169 std::ranges::reverse(front1);
170 }
171
172 auto it0 = begin(front0);
173 auto it1 = begin(front1);
174 auto end0 = end(front0);
175 auto end1 = end(front1);
176
177 edges.insert_edge(*it0, *it1);
178 while (next(it0) != end0 || next(it1) != end1) {
179 if (next(it0) == end0) {
180 ++it1;
181 edges.insert_edge(*it0, *it1);
182 } else if (next(it1) == end1) {
183 ++it0;
184 edges.insert_edge(*it0, *it1);
185 } else {
186 auto itn0 = next(it0);
187 auto itn1 = next(it1);
188 if (squared_euclidean_distance(edges[*it0], edges[*itn1]) <
189 squared_euclidean_distance(edges[*it1], edges[*itn0])) {
190 edges.insert_edge(*it0, *itn1);
191 ++it1;
192 } else {
193 edges.insert_edge(*it1, *itn0);
194 ++it0;
195 }
196 }
197 }
198}
199//------------------------------------------------------------------------------
201template <typename Real, std::size_t NumDimensions>
204 hierarchy<Real, NumDimensions> const& h1) -> void {
205 auto front0 = get_front(h0, edges, edges[h1.center]);
206 auto front1 = get_front(h1, edges, edges[h0.center]);
207 connect_fronts(front0, front1, edges);
208}
209//------------------------------------------------------------------------------
210template <typename Real, std::size_t NumDimensions>
213 for (auto const& l : h.leafs) {
214 triangulate_non_root(edges, l);
215 }
216}
217//------------------------------------------------------------------------------
218template <typename Real, std::size_t NumDimensions>
220 hierarchy<Real, NumDimensions> const& h) -> void {
221 if (!h.leafs.empty()) {
222 for (auto const& l : h.leafs) {
223 triangulate_non_root(edges, l);
224 }
225 for (std::size_t i = 0; i < h.leafs.size() - 1; ++i) {
226 triangulate(edges, h.leafs[i], h.leafs[i + 1]);
227 }
228 }
229}
230//------------------------------------------------------------------------------
232template <typename Real, std::size_t NumDimensions>
234 hierarchy<Real, NumDimensions> const& h) -> void {
235 if (h.is_root()) {
236 triangulate_root(edges, h);
237 } else {
238 triangulate_non_root(edges, h);
239 }
240}
241//==============================================================================
242inline auto total_num_particles(std::vector<hierarchy_pair> const& hps) {
243 std::size_t num = 0;
244 for (auto const& hp : hps) {
245 num = std::max(num, hp.id);
246 }
247 return num + 1;
248}
249//==============================================================================
250} // namespace tatooine::detail::autonomous_particle
251//==============================================================================
252#endif
Definition: post_triangulation.h:10
auto total_num_particles(std::vector< hierarchy_pair > const &hps)
Definition: post_triangulation.h:242
typename tatooine::edgeset< Real, NumDimensions >::vertex_handle vertex
Definition: post_triangulation.h:13
auto get_front(hierarchy< Real, NumDimensions > const &h, edgeset< Real, NumDimensions > const &edges, vec< Real, NumDimensions > const &other_center) -> std::vector< vertex< Real, NumDimensions > >
Definition: post_triangulation.h:124
auto triangulate_root(edgeset< Real, NumDimensions > &edges, hierarchy< Real, NumDimensions > const &h)
Definition: post_triangulation.h:211
auto triangulate(edgeset< Real, NumDimensions > &edges, hierarchy< Real, NumDimensions > const &h0, hierarchy< Real, NumDimensions > const &h1) -> void
Triangulates two particles.
Definition: post_triangulation.h:202
auto connect_fronts(std::vector< vertex< Real, NumDimensions > > &front0, std::vector< vertex< Real, NumDimensions > > &front1, edgeset< Real, NumDimensions > &edges) -> void
Definition: post_triangulation.h:164
auto triangulate_non_root(edgeset< Real, NumDimensions > &edges, hierarchy< Real, NumDimensions > const &h) -> void
Definition: post_triangulation.h:219
constexpr auto squared_euclidean_length(base_tensor< Tensor, T, N > const &t_in)
Definition: length.h:7
constexpr auto cos_angle(base_tensor< Tensor0, T0, N > const &v0, base_tensor< Tensor1, T1, N > const &v1)
Returns the cosine of the angle of two normalized vectors.
Definition: tensor_operations.h:32
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto reorder(std::ranges::range auto &data, std::ranges::range auto &order) -> void
reorders a range data with another range order
Definition: reorder.h:10
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto normalize(base_tensor< Tensor, T, N > const &t_in) -> vec< T, N >
Definition: tensor_operations.h:100
constexpr auto dot(base_tensor< Tensor0, T0, N > const &lhs, base_tensor< Tensor1, T1, N > const &rhs)
Definition: tensor_operations.h:120
auto next(Iter iter)
Definition: iterator_facade.h:325
constexpr auto squared_euclidean_distance(base_tensor< Tensor0, T0, N > const &lhs, base_tensor< Tensor1, T1, N > const &rhs)
Definition: distance.h:11
auto front(linspace< Real > const &l)
Definition: linspace.h:126
std::uint64_t id
Definition: post_triangulation.h:16
std::uint64_t parent
Definition: post_triangulation.h:17
Definition: post_triangulation.h:21
vertex< Real, NumDimensions > vertex_type
Definition: post_triangulation.h:22
std::vector< hierarchy > leafs
Definition: post_triangulation.h:28
hierarchy(std::uint64_t const id_)
Definition: post_triangulation.h:32
auto build(std::vector< hierarchy_pair > const &hps, std::unordered_map< std::uint64_t, vertex_type > const &centers, edgeset_type const &edges) -> void
Definition: post_triangulation.h:76
std::uint64_t id
Definition: post_triangulation.h:26
auto find_by_id(std::uint64_t const &id) const -> auto const &
Definition: post_triangulation.h:65
auto calc_split_dir(edgeset_type const &edges) -> vec_type
Definition: post_triangulation.h:111
hierarchy(std::uint64_t const id_, vertex_type const center_)
Definition: post_triangulation.h:34
hierarchy(std::vector< hierarchy_pair > const &hps, std::unordered_map< std::uint64_t, vertex_type > const &centers, edgeset_type const &edges)
as root node
Definition: post_triangulation.h:50
vertex_type center
Definition: post_triangulation.h:27
auto sort_leafs(edgeset_type const &edges) -> void
Definition: post_triangulation.h:89
auto is_root() const
Definition: post_triangulation.h:61
hierarchy(std::uint64_t const id_, std::vector< hierarchy_pair > const &hps, std::unordered_map< std::uint64_t, vertex_type > const &centers, edgeset_type const &edges)
as child node
Definition: post_triangulation.h:38
Definition: edgeset.h:9
static auto constexpr zeros()
Definition: vec.h:26