Lagrange
Loading...
Searching...
No Matches
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(
63 function_ref<void(AttributeId)> cb);
64
65template <
66 std::underlying_type_t<AttributeElement> mask,
67 Ordering ordering,
68 Access access,
69 typename MeshType,
70 typename Visitor>
71void internal_foreach_named_attribute(
72 MeshType& mesh,
73 Visitor&& vis,
75{
76 auto cb = [&](std::string_view name, AttributeId id) {
77 constexpr auto filter = BitField<AttributeElement>(mask);
78#define LA_X_match_attribute(_, T) \
79 if (mesh.template is_attribute_type<T>(id)) { \
80 if constexpr (filter.test(AttributeElement::Indexed)) { \
81 if (mesh.is_attribute_indexed(id)) { \
82 auto& attr = mesh.template get_indexed_attribute<T>(id); \
83 if (filter.test(attr.get_element_type())) { \
84 if constexpr (access == Access::Write) { \
85 vis(name, mesh.template ref_indexed_attribute<T>(id)); \
86 } else { \
87 vis(name, attr); \
88 } \
89 } \
90 } \
91 } \
92 if constexpr (filter.test_any(~AttributeElement::Indexed)) { \
93 if (!mesh.is_attribute_indexed(id)) { \
94 auto& attr = mesh.template get_attribute<T>(id); \
95 if (filter.test(attr.get_element_type())) { \
96 if constexpr (access == Access::Write) { \
97 vis(name, mesh.template ref_attribute<T>(id)); \
98 } else { \
99 vis(name, attr); \
100 } \
101 } \
102 } \
103 } \
104 }
105 LA_ATTRIBUTE_X(match_attribute, 0)
106#undef LA_X_match_attribute
107 };
108 if constexpr (ordering == Ordering::Sequential) {
109 if (ids.empty()) {
111 } else {
112 std::for_each(ids.begin(), ids.end(), [&](AttributeId id) {
113 cb(mesh.get_attribute_name(id), id);
114 });
115 }
116 } else {
117 if (ids.empty()) {
119 } else {
120 par_foreach_attribute_id(ids, [&](AttributeId id) {
121 cb(mesh.get_attribute_name(id), id);
122 });
123 }
124 }
125}
126
127template <
128 std::underlying_type_t<AttributeElement> mask,
129 Ordering ordering,
130 Access access,
131 typename MeshType,
132 typename Visitor>
133void internal_foreach_attribute(MeshType& mesh, Visitor&& vis, span<const AttributeId> ids = {})
134{
135 auto cb = [&](AttributeId id) {
136 constexpr auto filter = BitField<AttributeElement>(mask);
137#define LA_X_match_attribute(_, T) \
138 if (mesh.template is_attribute_type<T>(id)) { \
139 if constexpr (filter.test(AttributeElement::Indexed)) { \
140 if (mesh.is_attribute_indexed(id)) { \
141 auto& attr = mesh.template get_indexed_attribute<T>(id); \
142 if (filter.test(attr.get_element_type())) { \
143 if constexpr (access == Access::Write) { \
144 vis(mesh.template ref_indexed_attribute<T>(id)); \
145 } else { \
146 vis(attr); \
147 } \
148 } \
149 } \
150 } \
151 if constexpr (filter.test_any(~AttributeElement::Indexed)) { \
152 if (!mesh.is_attribute_indexed(id)) { \
153 auto& attr = mesh.template get_attribute<T>(id); \
154 if (filter.test(attr.get_element_type())) { \
155 if constexpr (access == Access::Write) { \
156 vis(mesh.template ref_attribute<T>(id)); \
157 } else { \
158 vis(attr); \
159 } \
160 } \
161 } \
162 } \
163 }
164 LA_ATTRIBUTE_X(match_attribute, 0)
165#undef LA_X_match_attribute
166 };
167 if constexpr (ordering == Ordering::Sequential) {
168 if (ids.empty()) {
170 } else {
171 std::for_each(ids.begin(), ids.end(), cb);
172 }
173 } else {
174 if (ids.empty()) {
176 } else {
177 par_foreach_attribute_id(ids, cb);
178 }
179 }
180}
181
182} // namespace details
184
189
203template <
204 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
205 typename Visitor,
206 typename Scalar,
207 typename Index>
209{
210 using namespace details;
211 internal_foreach_named_attribute<mask, Ordering::Sequential, Access::Read>(
212 mesh,
213 std::forward<Visitor>(vis));
214}
215
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
261template <
262 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
263 typename Visitor,
264 typename Scalar,
265 typename Index>
267{
268 using namespace details;
269 internal_foreach_named_attribute<mask, Ordering::Sequential, Access::Write>(
270 mesh,
271 std::forward<Visitor>(vis));
272}
273
287template <
288 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
289 typename Visitor,
290 typename Scalar,
291 typename Index>
293{
294 using namespace details;
295 internal_foreach_attribute<mask, Ordering::Sequential, Access::Write>(
296 mesh,
297 std::forward<Visitor>(vis));
298}
299
305
319template <
320 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
321 typename Visitor,
322 typename Scalar,
323 typename Index>
325{
326 using namespace details;
327 internal_foreach_named_attribute<mask, Ordering::Parallel, Access::Read>(
328 mesh,
329 std::forward<Visitor>(vis));
330}
331
344template <
345 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
346 typename Visitor,
347 typename Scalar,
348 typename Index>
350{
351 using namespace details;
352 internal_foreach_attribute<mask, Ordering::Parallel, Access::Read>(
353 mesh,
354 std::forward<Visitor>(vis));
355}
356
362
377template <
378 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
379 typename Visitor,
380 typename Scalar,
381 typename Index>
383{
384 using namespace details;
385 internal_foreach_named_attribute<mask, Ordering::Parallel, Access::Write>(
386 mesh,
387 std::forward<Visitor>(vis));
388}
389
403template <
404 std::underlying_type_t<AttributeElement> mask = BitField<AttributeElement>::all(),
405 typename Visitor,
406 typename Scalar,
407 typename Index>
409{
410 using namespace details;
411 internal_foreach_attribute<mask, Ordering::Parallel, Access::Write>(
412 mesh,
413 std::forward<Visitor>(vis));
414}
415
418
419} // namespace lagrange
static constexpr BitField all()
Named constructor returning a bitfield set to 1.
Definition BitField.h:76
A general purpose polygonal mesh class.
Definition SurfaceMesh.h:66
void par_foreach_attribute_id(function_ref< void(AttributeId)> func) const
Iterates over all attribute ids in parallel.
Definition SurfaceMesh.cpp:1262
std::string_view get_attribute_name(AttributeId id) const
Retrieve attribute name from its id.
Definition SurfaceMesh.cpp:355
void seq_foreach_attribute_id(function_ref< void(AttributeId)> func) const
Iterates over all attribute ids sequentially.
Definition SurfaceMesh.cpp:1248
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
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
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:382
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:349
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:408
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:266
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:208
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:324
void seq_foreach_attribute_write(SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition foreach_attribute.h:292
function_ref(R(*)(Args...)) -> function_ref< R(Args...)>
Deduce function_ref type from a function pointer.
::nonstd::span< T, Extent > span
A bounds-safe view for sequences of objects.
Definition span.h:27
Main namespace for Lagrange.