Lagrange
foreach_attribute.h
1/*
2 * Copyright 2022 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 <lagrange/Attribute.h>
15#include <lagrange/AttributeTypes.h>
16#include <lagrange/IndexedAttribute.h>
17#include <lagrange/SurfaceMesh.h>
18#include <lagrange/utils/BitField.h>
19
20#include <algorithm>
21
22namespace lagrange {
23
54
56namespace details {
57
58enum class Ordering { Sequential, Parallel };
59enum class Access { Write, Read };
60
61LA_CORE_API void par_foreach_attribute_id(span<const AttributeId> ids, function_ref<void(AttributeId)> cb);
62
63template <
64 std::underlying_type_t<AttributeElement> mask,
65 Ordering ordering,
66 Access access,
67 typename MeshType,
68 typename Visitor>
69void internal_foreach_named_attribute(
70 MeshType& mesh,
71 Visitor&& vis,
72 span<const AttributeId> ids = {})
73{
74 auto cb = [&](std::string_view name, AttributeId id) {
75 constexpr auto filter = BitField<AttributeElement>(mask);
76#define LA_X_match_attribute(_, T) \
77 if (mesh.template is_attribute_type<T>(id)) { \
78 if constexpr (filter.test(AttributeElement::Indexed)) { \
79 if (mesh.is_attribute_indexed(id)) { \
80 auto& attr = mesh.template get_indexed_attribute<T>(id); \
81 if (filter.test(attr.get_element_type())) { \
82 if constexpr (access == Access::Write) { \
83 vis(name, mesh.template ref_indexed_attribute<T>(id)); \
84 } else { \
85 vis(name, attr); \
86 } \
87 } \
88 } \
89 } \
90 if constexpr (filter.test_any(~AttributeElement::Indexed)) { \
91 if (!mesh.is_attribute_indexed(id)) { \
92 auto& attr = mesh.template get_attribute<T>(id); \
93 if (filter.test(attr.get_element_type())) { \
94 if constexpr (access == Access::Write) { \
95 vis(name, mesh.template ref_attribute<T>(id)); \
96 } else { \
97 vis(name, attr); \
98 } \
99 } \
100 } \
101 } \
102 }
103 LA_ATTRIBUTE_X(match_attribute, 0)
104#undef LA_X_match_attribute
105 };
106 if constexpr (ordering == Ordering::Sequential) {
107 if (ids.empty()) {
108 mesh.seq_foreach_attribute_id(cb);
109 } else {
110 std::for_each(ids.begin(), ids.end(), [&](AttributeId id) {
111 cb(mesh.get_attribute_name(id), id);
112 });
113 }
114 } else {
115 if (ids.empty()) {
116 mesh.par_foreach_attribute_id(cb);
117 } else {
118 par_foreach_attribute_id(ids, [&](AttributeId id) {
119 cb(mesh.get_attribute_name(id), id);
120 });
121 }
122 }
123}
124
125template <
126 std::underlying_type_t<AttributeElement> mask,
127 Ordering ordering,
128 Access access,
129 typename MeshType,
130 typename Visitor>
131void internal_foreach_attribute(MeshType& mesh, Visitor&& vis, span<const AttributeId> ids = {})
132{
133 auto cb = [&](AttributeId id) {
134 constexpr auto filter = BitField<AttributeElement>(mask);
135#define LA_X_match_attribute(_, T) \
136 if (mesh.template is_attribute_type<T>(id)) { \
137 if constexpr (filter.test(AttributeElement::Indexed)) { \
138 if (mesh.is_attribute_indexed(id)) { \
139 auto& attr = mesh.template get_indexed_attribute<T>(id); \
140 if (filter.test(attr.get_element_type())) { \
141 if constexpr (access == Access::Write) { \
142 vis(mesh.template ref_indexed_attribute<T>(id)); \
143 } else { \
144 vis(attr); \
145 } \
146 } \
147 } \
148 } \
149 if constexpr (filter.test_any(~AttributeElement::Indexed)) { \
150 if (!mesh.is_attribute_indexed(id)) { \
151 auto& attr = mesh.template get_attribute<T>(id); \
152 if (filter.test(attr.get_element_type())) { \
153 if constexpr (access == Access::Write) { \
154 vis(mesh.template ref_attribute<T>(id)); \
155 } else { \
156 vis(attr); \
157 } \
158 } \
159 } \
160 } \
161 }
162 LA_ATTRIBUTE_X(match_attribute, 0)
163#undef LA_X_match_attribute
164 };
165 if constexpr (ordering == Ordering::Sequential) {
166 if (ids.empty()) {
167 mesh.seq_foreach_attribute_id(cb);
168 } else {
169 std::for_each(ids.begin(), ids.end(), cb);
170 }
171 } else {
172 if (ids.empty()) {
173 mesh.par_foreach_attribute_id(cb);
174 } else {
175 par_foreach_attribute_id(ids, cb);
176 }
177 }
178}
179
180} // namespace details
182
187
202template <
203 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
204 typename Visitor,
205 typename Scalar,
206 typename Index>
208{
209 using namespace details;
210 internal_foreach_named_attribute<mask, Ordering::Sequential, Access::Read>(
211 mesh,
212 std::forward<Visitor>(vis));
213}
214
228template <
229 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
230 typename Visitor,
231 typename Scalar,
232 typename Index>
234{
235 using namespace details;
236 internal_foreach_attribute<mask, Ordering::Sequential, Access::Read>(
237 mesh,
238 std::forward<Visitor>(vis));
239}
240
246
262template <
263 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
264 typename Visitor,
265 typename Scalar,
266 typename Index>
268{
269 using namespace details;
270 internal_foreach_named_attribute<mask, Ordering::Sequential, Access::Write>(
271 mesh,
272 std::forward<Visitor>(vis));
273}
274
289template <
290 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
291 typename Visitor,
292 typename Scalar,
293 typename Index>
295{
296 using namespace details;
297 internal_foreach_attribute<mask, Ordering::Sequential, Access::Write>(
298 mesh,
299 std::forward<Visitor>(vis));
300}
301
307
322template <
323 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
324 typename Visitor,
325 typename Scalar,
326 typename Index>
328{
329 using namespace details;
330 internal_foreach_named_attribute<mask, Ordering::Parallel, Access::Read>(
331 mesh,
332 std::forward<Visitor>(vis));
333}
334
348template <
349 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
350 typename Visitor,
351 typename Scalar,
352 typename Index>
354{
355 using namespace details;
356 internal_foreach_attribute<mask, Ordering::Parallel, Access::Read>(
357 mesh,
358 std::forward<Visitor>(vis));
359}
360
366
382template <
383 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
384 typename Visitor,
385 typename Scalar,
386 typename Index>
388{
389 using namespace details;
390 internal_foreach_named_attribute<mask, Ordering::Parallel, Access::Write>(
391 mesh,
392 std::forward<Visitor>(vis));
393}
394
409template <
410 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
411 typename Visitor,
412 typename Scalar,
413 typename Index>
415{
416 using namespace details;
417 internal_foreach_attribute<mask, Ordering::Parallel, Access::Write>(
418 mesh,
419 std::forward<Visitor>(vis));
420}
421
424
425} // namespace lagrange
static constexpr BitField all()
Named constructor returning a bitfield set to 1.
Definition: BitField.h:76
Definition: Mesh.h:48
uint32_t AttributeId
Identified to be used to access an attribute.
Definition: AttributeFwd.h:73
#define LA_ATTRIBUTE_X(mode, data)
X Macro arguments for the Attribute<> class.
Definition: AttributeTypes.h:48
void par_foreach_named_attribute_write(SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function in parallel to each attribute of a mesh.
Definition: foreach_attribute.h:387
void par_foreach_attribute_read(const SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function in parallel to each attribute of a mesh.
Definition: foreach_attribute.h:353
void par_foreach_attribute_write(SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function in parallel to each attribute of a mesh.
Definition: foreach_attribute.h:414
void seq_foreach_attribute_read(const SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition: foreach_attribute.h:233
void seq_foreach_named_attribute_write(SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition: foreach_attribute.h:267
void seq_foreach_named_attribute_read(const SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition: foreach_attribute.h:207
void par_foreach_named_attribute_read(const SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function in parallel to each attribute of a mesh.
Definition: foreach_attribute.h:327
void seq_foreach_attribute_write(SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition: foreach_attribute.h:294
function_ref(R(*)(Args...)) -> function_ref< R(Args...)>
Deduce function_ref type from a function pointer.
Main namespace for Lagrange.
Definition: AABBIGL.h:30