Wildmeshing Toolkit
Loading...
Searching...
No Matches
MeshAttributes.cpp
Go to the documentation of this file.
1#include "MeshAttributes.hpp"
5
9
10#include <cassert>
11#include <functional>
12#include <stdexcept>
13#include <string>
14#include <utility>
15
16namespace wmtk::attribute {
17
18
19template <typename T>
20void MeshAttributes<T>::serialize(const int dim, MeshWriter& writer) const
21{
22 for (const auto& p : m_handles) {
23 const auto& handle = p.second;
24 const auto& attr_ptr = attribute(handle);
25 if (is_active(handle)) {
26 const auto& attr = *m_attributes[handle.index];
27 attr.serialize(p.first, dim, writer);
28 }
29 }
30}
31
32template <typename T>
33std::map<std::string, std::size_t> MeshAttributes<T>::child_hashes() const
34{
35 // default implementation pulls the child attributes (ie the attributes)
36 std::map<std::string, std::size_t> ret = wmtk::utils::MerkleTreeInteriorNode::child_hashes();
37
38 // hash handle data
39 for (const auto& [name, handle] : m_handles) {
40 ret["attr_handle_" + name] = std::hash<AttributeHandle>{}(handle);
41 }
42 return ret;
43}
44template <typename T>
45std::map<std::string, const wmtk::utils::Hashable*> MeshAttributes<T>::child_hashables() const
46
47{
48 std::map<std::string, const wmtk::utils::Hashable*> ret;
49 for (const auto& [name, handle] : m_handles) {
50 const auto& attr = attribute(handle);
51 ret["attr_" + name] = &attr;
52 }
53 return ret;
54}
55
56template <typename T>
58{
59 for (auto& attr_ptr : m_attributes) {
60 if (bool(attr_ptr)) {
61 attr_ptr->push_scope();
62 }
63 }
64}
65template <typename T>
66void MeshAttributes<T>::pop_scope(bool apply_updates)
67{
68 for (auto& attr_ptr : m_attributes) {
69 if (bool(attr_ptr)) {
70 attr_ptr->pop_scope(apply_updates);
71 }
72 }
73}
74template <typename T>
76{
77 for (auto& attr_ptr : m_attributes) {
78 if (bool(attr_ptr)) {
79 attr_ptr->rollback_current_scope();
80 }
81 }
82}
83template <typename T>
85{
86 for (const auto& attr_ptr : m_attributes) {
87 if (bool(attr_ptr)) {
88 auto& stack = attr_ptr->get_local_scope_stack();
89
90 stack.change_to_next_scope();
91 }
92 }
93}
94
95template <typename T>
97{
98 for (const auto& attr_ptr : m_attributes) {
99 if (bool(attr_ptr)) {
100 attr_ptr->get_local_scope_stack().change_to_previous_scope();
101 }
102 }
103}
104
105template <typename T>
107 const std::string& name,
108 int64_t dimension,
109 bool replace,
110 T default_value)
111{
112 if (!replace && m_handles.find(name) != m_handles.end()) {
114 "Cannot register attribute '{}' because it exists already. Set replace to true if you "
115 "want to overwrite the attribute",
116 name);
117 }
118
119 AttributeHandle handle;
120
121
122 if (replace && m_handles.find(name) != m_handles.end()) {
123 auto it = m_handles.find(name);
124 handle.index = it->second.index;
125 } else {
126 handle.index = m_attributes.size();
127 m_attributes.emplace_back(
128 std::make_unique<Attribute<T>>(name, dimension, default_value, reserved_size()));
129 }
130 m_handles[name] = handle;
131
132
133 return handle;
134}
135
136template <typename T>
138{
139 for (const auto& a : m_attributes) {
140 if (bool(a)) {
141 assert(a->reserved_size() >= cap);
142 }
143 }
144}
145template <typename T>
147{
148 return m_handles.at(name);
149}
150template <typename T>
151bool MeshAttributes<T>::has_attribute(const std::string& name) const
152{
153 auto it = m_handles.find(name);
154 return it != m_handles.end() && bool(m_attributes[it->second.index]);
155}
156
157template <typename T>
159{
160 if (m_handles != other.m_handles) {
161 return false;
162 }
163 if (m_attributes.size() != other.m_attributes.size()) {
164 return false;
165 }
166 for (size_t j = 0; j < m_attributes.size(); ++j) {
167 const bool exists = bool(m_attributes[j]);
168 const bool o_exists = bool(other.m_attributes[j]);
169 if (exists != o_exists) {
170 return false;
171 } else if (exists && o_exists && !(*m_attributes[j] == *other.m_attributes[j])) {
172 return false;
173 }
174 }
175 return true;
176}
177
178
179template <typename T>
180void MeshAttributes<T>::set(const AttributeHandle& handle, std::vector<T> val)
181{
182 // TODO: should we validate the size of val compared to the internally held data?
183 auto& attr_ptr = m_attributes[handle.index];
184 assert(bool(attr_ptr));
185 auto& attr = *attr_ptr;
186 attr.set(std::move(val));
187}
188
189template <typename T>
191{
192 auto& attr_ptr = m_attributes[handle.index];
193 assert(bool(attr_ptr));
194 return attr_ptr->reserved_size();
195}
196
197template <typename T>
199{
200 return m_reserved_size;
201}
202
203template <typename T>
205{
206 return active_attributes().size();
207}
208template <typename T>
210{
211 std::vector<AttributeHandle> handles;
212 handles.reserve(m_attributes.size());
213 for (size_t j = 0; j < m_attributes.size(); ++j) {
214 if (bool(m_attributes[j])) {
215 handles.emplace_back(j);
216 }
217 }
218
219 return handles;
220}
221template <typename T>
223{
224 const size_t index = h.index;
225 assert(index < m_attributes.size());
226 return bool(m_attributes[index]);
227}
228
229template <typename T>
230void MeshAttributes<T>::reserve(const int64_t size)
231{
232 m_reserved_size = size;
233 for (auto& attr_ptr : m_attributes) {
234 if (bool(attr_ptr)) {
235 attr_ptr->reserve(size);
236 }
237 }
238}
239
240template <typename T>
241void MeshAttributes<T>::reserve_more(const int64_t size)
242{
243 reserve(m_reserved_size + size);
244}
245
246template <typename T>
248{
249 if (size > m_reserved_size) {
250 // logger().warn("Pre-reserve enough simplices before your operation.");
251 reserve(size);
252 }
253}
254
255template <typename T>
257 const std::vector<AttributeHandle>& attributes,
258 bool invalidate_handles)
259{
260 if (attributes.empty()) {
261 return;
262 }
263 std::vector<int64_t> remove_indices;
264 std::transform(
265 attributes.begin(),
266 attributes.end(),
267 std::back_inserter(remove_indices),
268 [](const AttributeHandle& h) { return h.index; });
269 std::sort(remove_indices.begin(), remove_indices.end());
270 remove_indices.erase(
271 std::unique(remove_indices.begin(), remove_indices.end()),
272 remove_indices.end());
273
274
275 for (const int64_t& i : remove_indices) {
276 m_attributes[i].reset();
277 }
278
279
280 if (invalidate_handles) {
281 clear_dead_attributes();
282 }
283}
284
285
286template <typename T>
288{
289 m_attributes[attribute.index].reset();
290}
291
292template <typename T>
294{
295 size_t old_index = 0;
296 size_t new_index = 0;
297 std::vector<int64_t> old_to_new_id(m_attributes.size(), -1);
298 for (old_index = 0; old_index < m_attributes.size(); ++old_index) {
299 if (bool(m_attributes[old_index])) {
300 old_to_new_id[old_index] = new_index;
301 m_attributes[new_index++] = std::move(m_attributes[old_index]);
302 }
303 }
304 m_attributes.resize(new_index);
305
306 // clean up m_handles
307 for (auto it = m_handles.begin(); it != m_handles.end(); /* no increment */) {
308 if (int64_t new_ind = old_to_new_id[it->second.index]; new_ind == -1) {
309 it = m_handles.erase(it);
310 } else {
311 it->second.index = new_ind;
312 ++it;
313 }
314 }
315}
316template <typename T>
317std::string MeshAttributes<T>::get_name(const AttributeHandle& handle) const
318{
319 for (const auto& [key, value] : m_handles) {
320 if (value == handle) {
321 return key;
322 }
323 }
324 throw std::runtime_error("Could not find handle in MeshAttributes");
325 return "UNKNOWN";
326}
327
328template <typename T>
329void MeshAttributes<T>::set_name(const AttributeHandle& handle, const std::string& name)
330{
331 const std::string old_name = get_name(handle);
332
333 if (old_name == name) {
334 return;
335 }
336
337 auto& attr = m_attributes[handle.index];
338 assert(bool(attr));
339 assert(attr->m_name == old_name);
340
341 assert(m_handles.count(name) == 0); // name should not exist already
342
343 attr->m_name = name;
344 m_handles[name] = m_handles[old_name];
345 m_handles.erase(old_name);
346}
347
348template class MeshAttributes<char>;
349template class MeshAttributes<int64_t>;
350template class MeshAttributes<double>;
351template class MeshAttributes<Rational>;
352
353} // namespace wmtk::attribute
Internal handle representation used by MeshAttributes.
This class stores data of type T in a vector.
Definition Attribute.hpp:32
Contains all attributes of type T for a single mesh.
std::map< std::string, std::size_t > child_hashes() const override
size_t attribute_size(const AttributeHandle &handle) const
void clear_dead_attributes()
Clears and compactifies the attribute list. This invalidates all existing handles.
std::vector< std::unique_ptr< Attribute< T > > > m_attributes
bool is_active(const AttributeHandle &handle) const
std::map< std::string, AttributeHandle > m_handles
std::map< std::string, const wmtk::utils::Hashable * > child_hashables() const override
void remove_attributes(const std::vector< AttributeHandle > &attributes, bool invalidate_handles=true)
Remove all passed in attributes.
bool operator==(const MeshAttributes< T > &other) const
AttributeHandle attribute_handle(const std::string &name) const
std::vector< AttributeHandle > active_attributes() const
void remove_attribute(const AttributeHandle &attribute)
Remove a single attribute.
AttributeHandle register_attribute(const std::string &name, int64_t dimension, bool replace=false, T default_value=T(0))
void assert_capacity_valid(int64_t cap) const
void set(const AttributeHandle &handle, std::vector< T > val)
void reserve(const int64_t size)
void pop_scope(bool apply_updates=true)
bool has_attribute(const std::string &name) const
void set_name(const AttributeHandle &handle, const std::string &name)
std::string get_name(const AttributeHandle &handle) const
void serialize(const int dim, MeshWriter &writer) const
std::map< std::string, std::size_t > child_hashes() const override
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:101