Lagrange
attribute_utils.h
1/*
2 * Copyright 2017 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 <vector>
15
16#include <lagrange/Mesh.h>
17#include <lagrange/MeshTrait.h>
18#include <lagrange/attributes/condense_indexed_attribute.h>
19#include <lagrange/common.h>
20#include <lagrange/compute_vertex_valence.h>
21#include <lagrange/legacy/inline.h>
22#include <lagrange/utils/assert.h>
23#include <lagrange/utils/range.h>
24
25namespace lagrange {
26LAGRANGE_LEGACY_INLINE
27namespace legacy {
28template <typename MeshType>
29void map_vertex_attribute_to_corner_attribute(MeshType& mesh, const std::string& attr_name)
30{
31 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
32
33 using Index = typename MeshType::Index;
34 la_runtime_assert(mesh.has_vertex_attribute(attr_name));
35
36 const Index num_facets = mesh.get_num_facets();
37 const Index vertex_per_facet = mesh.get_vertex_per_facet();
38
39 const auto& facets = mesh.get_facets();
40 auto vertex_attr = mesh.get_vertex_attribute_array(attr_name);
41
42 auto map_fn = [&](Eigen::Index ci, std::vector<std::pair<Eigen::Index, double>>& weights) {
43 weights.clear();
44 weights.emplace_back(
45 safe_cast<Eigen::Index>(facets(ci / vertex_per_facet, ci % vertex_per_facet)),
46 1.0);
47 };
48 auto corner_attr = to_shared_ptr(vertex_attr->row_slice(num_facets * vertex_per_facet, map_fn));
49
50 if (!mesh.has_corner_attribute(attr_name)) {
51 mesh.add_corner_attribute(attr_name);
52 }
53 mesh.set_corner_attribute_array(attr_name, std::move(corner_attr));
54}
55
56template <typename MeshType>
57void map_facet_attribute_to_corner_attribute(MeshType& mesh, const std::string& attr_name)
58{
59 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
60
61 using Index = typename MeshType::Index;
62 la_runtime_assert(mesh.has_facet_attribute(attr_name));
63
64 const Index num_facets = mesh.get_num_facets();
65 const Index vertex_per_facet = mesh.get_vertex_per_facet();
66
67 auto facet_attr = mesh.get_facet_attribute_array(attr_name);
68
69 auto map_fn = [&](Eigen::Index ci, std::vector<std::pair<Eigen::Index, double>>& weights) {
70 weights.clear();
71 weights.emplace_back(safe_cast<Eigen::Index>(ci / vertex_per_facet), 1.0);
72 };
73 auto corner_attr = to_shared_ptr(facet_attr->row_slice(num_facets * vertex_per_facet, map_fn));
74
75 if (!mesh.has_corner_attribute(attr_name)) {
76 mesh.add_corner_attribute(attr_name);
77 }
78 mesh.set_corner_attribute_array(attr_name, std::move(corner_attr));
79}
80
81template <typename MeshType>
82void map_corner_attribute_to_vertex_attribute(MeshType& mesh, const std::string& attr_name)
83{
84 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
85
86 using Index = typename MeshType::Index;
87 la_runtime_assert(mesh.has_corner_attribute(attr_name));
88
89 const Index num_vertices = mesh.get_num_vertices();
90 const Index num_facets = mesh.get_num_facets();
91 const Index vertex_per_facet = mesh.get_vertex_per_facet();
92
93 const auto& facets = mesh.get_facets();
94 auto corner_attr = mesh.get_corner_attribute_array(attr_name);
95
96 if (!mesh.has_vertex_attribute("valence")) {
98 }
99 const auto& valence = mesh.get_vertex_attribute("valence");
100 la_runtime_assert(valence.rows() == num_vertices);
101
102 std::vector<std::vector<std::pair<Eigen::Index, double>>> weights(num_vertices);
103 for (Index i = 0; i < num_facets; i++) {
104 for (Index j = 0; j < vertex_per_facet; j++) {
105 const double w = 1.0 / valence(facets(i, j), 0);
106 weights[facets(i, j)].emplace_back(i * vertex_per_facet + j, w);
107 }
108 }
109
110 auto mapping_fn = [&](Eigen::Index i, std::vector<std::pair<Eigen::Index, double>>& wts) {
111 wts.clear();
112 wts = weights[i];
113 };
114 auto vertex_attr = to_shared_ptr(corner_attr->row_slice(num_vertices, mapping_fn));
115
116 if (!mesh.has_vertex_attribute(attr_name)) {
117 mesh.add_vertex_attribute(attr_name);
118 }
119 mesh.set_vertex_attribute_array(attr_name, std::move(vertex_attr));
120}
121
122template <typename MeshType>
123void map_corner_attribute_to_facet_attribute(MeshType& mesh, const std::string& attr_name)
124{
125 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
126
127 using Index = typename MeshType::Index;
128 la_runtime_assert(mesh.has_corner_attribute(attr_name));
129
130 const Index num_facets = mesh.get_num_facets();
131 const Index vertex_per_facet = mesh.get_vertex_per_facet();
132
133 auto corner_attr = mesh.get_corner_attribute_array(attr_name);
134
135 auto mapping_fn = [&](Eigen::Index i, std::vector<std::pair<Eigen::Index, double>>& weights) {
136 weights.clear();
137 for (auto j : range(vertex_per_facet)) {
138 weights.emplace_back(i * vertex_per_facet + j, 1.0 / vertex_per_facet);
139 }
140 };
141
142 auto facet_attr = corner_attr->row_slice(num_facets, mapping_fn);
143
144 if (!mesh.has_facet_attribute(attr_name)) {
145 mesh.add_facet_attribute(attr_name);
146 }
147 mesh.set_facet_attribute_array(attr_name, std::move(facet_attr));
148}
149
150template <typename MeshType>
151void map_vertex_attribute_to_indexed_attribute(MeshType& mesh, const std::string& attr_name)
152{
153 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
154
155 la_runtime_assert(mesh.has_vertex_attribute(attr_name));
156
157 const auto& attr_values = mesh.get_vertex_attribute(attr_name);
158 const auto& attr_indices = mesh.get_facets();
159
160 if (!mesh.has_indexed_attribute(attr_name)) {
161 mesh.add_indexed_attribute(attr_name);
162 }
163 mesh.set_indexed_attribute(attr_name, attr_values, attr_indices);
164 condense_indexed_attribute(mesh, attr_name);
165}
166
167template <typename MeshType>
168void map_facet_attribute_to_indexed_attribute(MeshType& mesh, const std::string& attr_name)
169{
170 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
171
172 using IndexArray = typename MeshType::IndexArray;
173 la_runtime_assert(mesh.has_facet_attribute(attr_name));
174
175 const auto num_facets = mesh.get_num_facets();
176 const auto vertex_per_facet = mesh.get_vertex_per_facet();
177 auto attr_values = mesh.get_facet_attribute(attr_name);
178 IndexArray attr_indices(num_facets, vertex_per_facet);
179 for (auto i : range(num_facets)) {
180 attr_indices.row(i).setConstant(i);
181 }
182
183 if (!mesh.has_indexed_attribute(attr_name)) {
184 mesh.add_indexed_attribute(attr_name);
185 }
186 mesh.import_indexed_attribute(attr_name, attr_values, attr_indices);
187 condense_indexed_attribute(mesh, attr_name);
188}
189
190template <typename MeshType>
191void map_corner_attribute_to_indexed_attribute(MeshType& mesh, const std::string& attr_name)
192{
193 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
194
195 using IndexArray = typename MeshType::IndexArray;
196 la_runtime_assert(mesh.has_corner_attribute(attr_name));
197
198 const auto num_facets = mesh.get_num_facets();
199 const auto vertex_per_facet = mesh.get_vertex_per_facet();
200 auto attr_values = mesh.get_corner_attribute(attr_name);
201 IndexArray attr_indices(num_facets, vertex_per_facet);
202 for (auto i : range(num_facets)) {
203 for (auto j : range(vertex_per_facet)) {
204 attr_indices(i, j) = i * vertex_per_facet + j;
205 }
206 }
207
208 if (!mesh.has_indexed_attribute(attr_name)) {
209 mesh.add_indexed_attribute(attr_name);
210 }
211 mesh.import_indexed_attribute(attr_name, attr_values, attr_indices);
212 condense_indexed_attribute(mesh, attr_name);
213}
214
215template <typename MeshType>
216void map_indexed_attribute_to_vertex_attribute(MeshType& mesh, const std::string& attr_name)
217{
218 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
219 la_runtime_assert(mesh.has_indexed_attribute(attr_name));
220
221 using AttributeArray = typename MeshType::AttributeArray;
222 using Scalar = typename MeshType::Scalar;
223
224 const auto entry = mesh.get_indexed_attribute(attr_name);
225 const auto& attr_values = std::get<0>(entry);
226 const auto& attr_indices = std::get<1>(entry);
227
228 const auto num_vertices = mesh.get_num_vertices();
229 const auto num_facets = mesh.get_num_facets();
230 const auto vertex_per_facet = mesh.get_vertex_per_facet();
231 const auto& facets = mesh.get_facets();
232 AttributeArray vertex_attr(num_vertices, attr_values.cols());
233 vertex_attr.setZero();
234 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> valence(num_vertices);
235 valence.setZero();
236 for (auto i : range(num_facets)) {
237 for (auto j : range(vertex_per_facet)) {
238 vertex_attr.row(facets(i, j)) += attr_values.row(attr_indices(i, j));
239 valence[facets(i, j)] += 1;
240 }
241 }
242 vertex_attr.array().colwise() /= valence.array();
243
244 if (!mesh.has_vertex_attribute(attr_name)) {
245 mesh.add_vertex_attribute(attr_name);
246 }
247 mesh.import_vertex_attribute(attr_name, vertex_attr);
248}
249
250template <typename MeshType>
251void map_indexed_attribute_to_facet_attribute(MeshType& mesh, const std::string& attr_name)
252{
253 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
254 la_runtime_assert(mesh.has_indexed_attribute(attr_name));
255
256 using AttributeArray = typename MeshType::AttributeArray;
257
258 const auto entry = mesh.get_indexed_attribute(attr_name);
259 const auto& attr_values = std::get<0>(entry);
260 const auto& attr_indices = std::get<1>(entry);
261
262 const auto num_facets = mesh.get_num_facets();
263 const auto vertex_per_facet = mesh.get_vertex_per_facet();
264 AttributeArray facet_attr(num_facets, attr_values.cols());
265 facet_attr.setZero();
266 for (auto i : range(num_facets)) {
267 for (auto j : range(vertex_per_facet)) {
268 facet_attr.row(i) += attr_values.row(attr_indices(i, j)) / vertex_per_facet;
269 }
270 }
271
272 if (!mesh.has_facet_attribute(attr_name)) {
273 mesh.add_facet_attribute(attr_name);
274 }
275 mesh.import_facet_attribute(attr_name, facet_attr);
276}
277
278template <typename MeshType>
279void map_indexed_attribute_to_corner_attribute(MeshType& mesh, const std::string& attr_name)
280{
281 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
282 la_runtime_assert(mesh.has_indexed_attribute(attr_name));
283
284 using AttributeArray = typename MeshType::AttributeArray;
285 using Index = typename MeshType::Index;
286
287 const auto entry = mesh.get_indexed_attribute(attr_name);
288 const auto& attr_values = std::get<0>(entry);
289 const auto& attr_indices = std::get<1>(entry);
290
291 const auto num_facets = mesh.get_num_facets();
292 const auto vertex_per_facet = mesh.get_vertex_per_facet();
293 AttributeArray corner_attr(num_facets * vertex_per_facet, attr_values.cols());
294 corner_attr.setZero();
295 for (auto i : range(num_facets)) {
296 for (auto j : range(vertex_per_facet)) {
297 if (attr_indices(i, j) != invalid<Index>()) {
298 corner_attr.row(i * vertex_per_facet + j) = attr_values.row(attr_indices(i, j));
299 }
300 }
301 }
302
303 if (!mesh.has_corner_attribute(attr_name)) {
304 mesh.add_corner_attribute(attr_name);
305 }
306 mesh.import_corner_attribute(attr_name, corner_attr);
307}
308
309} // namespace legacy
310} // namespace lagrange
Definition: Mesh.h:48
AttributeId compute_vertex_valence(SurfaceMesh< Scalar, Index > &mesh, VertexValenceOptions options={})
Compute vertex valence.
Definition: compute_vertex_valence.cpp:25
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
internal::Range< Index > range(Index end)
Returns an iterable object representing the range [0, end).
Definition: range.h:176
Main namespace for Lagrange.
Definition: AABBIGL.h:30
std::shared_ptr< T > to_shared_ptr(std::unique_ptr< T > &&ptr)
Helper for automatic type deduction for unique_ptr to shared_ptr conversion.
Definition: common.h:88