Lagrange
IndexedAttributeManager.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <map>
15#include <string>
16
17#include <lagrange/Logger.h>
18#include <lagrange/common.h>
19#include <lagrange/experimental/IndexedAttribute.h>
20#include <lagrange/utils/assert.h>
21
22namespace lagrange {
23namespace experimental {
24
26{
27public:
28 std::vector<std::string> get_names() const
29 {
30 std::vector<std::string> names;
31 for (const auto& itr : m_data) {
32 names.push_back(itr.first);
33 }
34 return names;
35 }
36
37 size_t get_size() const {
38 return m_data.size();
39 }
40
41 bool has(const std::string& name) const { return m_data.find(name) != m_data.end(); }
42
43 void add(const std::string& name)
44 {
45 m_data.emplace(name, std::make_unique<IndexedAttribute>());
46 }
47
48 template <typename ValueDerived, typename IndexDerived>
49 void add(const std::string& name, ValueDerived&& values, IndexDerived&& indices)
50 {
51 auto attr = std::make_unique<IndexedAttribute>(
52 std::forward<ValueDerived>(values),
53 std::forward<IndexDerived>(indices));
54 m_data.emplace(name, std::move(attr));
55 }
56
57 template <typename ValueDerived, typename IndexDerived>
58 void set(const std::string& name, ValueDerived&& values, IndexDerived&& indices)
59 {
60 auto itr = m_data.find(name);
61 la_runtime_assert(itr != m_data.end(), "Indexed attribute " + name + " does not exist.");
62 if (itr->second == nullptr) {
63 itr->second = std::make_unique<IndexedAttribute>(
64 std::forward<ValueDerived>(values),
65 std::forward<IndexDerived>(indices));
66 } else {
67 itr->second->set_values(std::forward<ValueDerived>(values));
68 itr->second->set_indices(std::forward<IndexDerived>(indices));
69 }
70 }
71
72 IndexedAttribute* get(const std::string& name)
73 {
74 auto itr = m_data.find(name);
75 la_runtime_assert(itr != m_data.end(), "Indexed attribute " + name + " does not exist.");
76 return itr->second.get();
77 }
78
79 const IndexedAttribute* get(const std::string& name) const
80 {
81 auto itr = m_data.find(name);
82 la_runtime_assert(itr != m_data.end(), "Indexed attribute " + name + " does not exist.");
83 return itr->second.get();
84 }
85
86 template <typename Derived>
87 decltype(auto) get_values(const std::string& name)
88 {
89 auto ptr = get(name);
90 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
91 return ptr->get_values<Derived>();
92 }
93
94 template <typename Derived>
95 decltype(auto) get_values(const std::string& name) const
96 {
97 const auto ptr = get(name);
98 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
99 return ptr->get_values<Derived>();
100 }
101
102 template <typename Derived>
103 decltype(auto) get_indices(const std::string& name)
104 {
105 auto ptr = get(name);
106 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
107 return ptr->get_indices<Derived>();
108 }
109
110 template <typename Derived>
111 decltype(auto) get_indices(const std::string& name) const
112 {
113 const auto ptr = get(name);
114 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
115 return ptr->get_indices<Derived>();
116 }
117
118 template <typename Derived>
119 decltype(auto) view_values(const std::string& name)
120 {
121 auto ptr = get(name);
122 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
123 return ptr->view_values<Derived>();
124 }
125
126 template <typename Derived>
127 decltype(auto) view_values(const std::string& name) const
128 {
129 const auto ptr = get(name);
130 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
131 return ptr->view_values<Derived>();
132 }
133
134 template <typename Derived>
135 decltype(auto) view_indices(const std::string& name)
136 {
137 auto ptr = get(name);
138 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
139 return ptr->view_indices<Derived>();
140 }
141
142 template <typename Derived>
143 decltype(auto) view_indices(const std::string& name) const
144 {
145 const auto ptr = get(name);
146 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
147 return ptr->view_indices<Derived>();
148 }
149
150 template <typename ValueDerived, typename IndexDerived>
151 void import_data(const std::string& name, ValueDerived&& values, IndexDerived&& indices)
152 {
153 set(name, std::move(values.derived()), std::move(indices.derived()));
154 }
155
156 template <typename ValueDerived, typename IndexDerived>
157 void export_data(
158 const std::string& name,
159 Eigen::PlainObjectBase<ValueDerived>& values,
160 Eigen::PlainObjectBase<IndexDerived>& indices)
161 {
162 auto attr = get(name);
163 la_runtime_assert(attr != nullptr, "Attribute " + name + " is null.");
164 auto value_array = attr->get_values();
165 auto index_array = attr->get_indices();
166 la_runtime_assert(value_array != nullptr);
167 la_runtime_assert(index_array != nullptr);
168
169#ifndef NDEBUG
170 bool validate = true;
171 void* value_ptr = value_array->data();
172 void* index_ptr = index_array->data();
173#endif
174 try {
175 ValueDerived& value_matrix = value_array->template get<ValueDerived>();
176 IndexDerived& index_matrix = index_array->template get<IndexDerived>();
177 values.swap(value_matrix);
178 indices.swap(index_matrix);
179 } catch (std::runtime_error& e) {
180 // It seems ValueDerived or IndexDerived are not exact match to the
181 // Eigen type used for creating the attribute. A copy is necessary.
182 logger().warn("Export cannot be done without coping: {}", e.what());
183 values = value_array->view<ValueDerived>();
184 indices = index_array->view<IndexDerived>();
185#ifndef NDEBUG
186 validate = false;
187#endif
188 }
189
190#ifndef NDEBUG
191 if (validate) {
192 la_runtime_assert(value_ptr == values.data(), "Export values fall back to copying.");
193 la_runtime_assert(index_ptr == indices.data(), "Export indices fall back to copying.");
194 }
195#endif
196 }
197
198 void remove(const std::string& name)
199 {
200 auto itr = m_data.find(name);
201 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
202 m_data.erase(itr);
203 }
204
205 template <typename Archive>
206 void serialize_impl(Archive& ar)
207 {
209 enum { DATA = 0 };
210 ar.object([&](auto& ar) {
211 ar("data", DATA) & m_data;
212 });
213 LA_IGNORE_SHADOW_WARNING_END
214 }
215
216private:
217 std::map<std::string, std::unique_ptr<IndexedAttribute>> m_data;
218};
219
221
222template <typename Archive>
223void serialize(std::pair<std::string, IndexedAttribute>& entry, Archive& ar)
224{
225 enum { KEY = 0, VALUE = 1 };
226
227 ar.object([&](auto& ar) {
228 ar("key", KEY) & entry.first;
229 ar("value", VALUE) & entry.second;
230 });
231}
232
233template <typename Archive>
234void serialize(
235 std::map<std::string, std::unique_ptr<IndexedAttribute>>& attrs,
236 Archive& ar)
237{
238 std::vector<std::pair<std::string, ::lagrange::experimental::IndexedAttribute>> data;
239 if (!ar.is_input()) {
240 for (auto& itr : attrs) {
241 data.emplace_back(itr.first, *itr.second);
242 }
243 }
244
245 serialize(data, ar);
246
247 if (ar.is_input()) {
248 attrs.clear();
249 for (const auto& itr : data) {
250 attrs[itr.first] = std::make_unique<IndexedAttribute>(itr.second);
251 }
252 }
253}
254
255template <typename Archive>
256void serialize(IndexedAttributeManager& attributes, Archive& ar)
257{
258 attributes.serialize_impl(ar);
259}
260
261LA_IGNORE_SHADOW_WARNING_END
262
263} // namespace experimental
264} // namespace lagrange
Definition: IndexedAttribute.h:22
Definition: IndexedAttributeManager.h:26
Smart pointer with value semantics.
Definition: value_ptr.h:134
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:40
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
#define LA_IGNORE_SHADOW_WARNING_BEGIN
Ignore shadow warnings.
Definition: warning.h:68
Main namespace for Lagrange.
Definition: AABBIGL.h:30