OpenVDB 12.0.0
 
Loading...
Searching...
No Matches
PointAttributeImpl.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @author Dan Bailey, Khang Ngo
5///
6/// @file PointAttributeImpl.h
7///
8
9#ifndef OPENVDB_POINTS_POINT_ATTRIBUTE_IMPL_HAS_BEEN_INCLUDED
10#define OPENVDB_POINTS_POINT_ATTRIBUTE_IMPL_HAS_BEEN_INCLUDED
11
12namespace openvdb {
14namespace OPENVDB_VERSION_NAME {
15namespace points {
16
17/// @cond OPENVDB_DOCS_INTERNAL
18
19namespace point_attribute_internal {
20
21
22template <typename ValueType>
23inline void collapseAttribute(AttributeArray& array,
24 const AttributeSet::Descriptor&, const ValueType& uniformValue)
25{
26 AttributeWriteHandle<ValueType> handle(array);
27 handle.collapse(uniformValue);
28}
29
30
31inline void collapseAttribute(AttributeArray& array,
32 const AttributeSet::Descriptor& descriptor, const Name& uniformValue)
33{
34 StringAttributeWriteHandle handle(array, descriptor.getMetadata());
35 handle.collapse(uniformValue);
36}
37
38
39////////////////////////////////////////
40
41
42template <typename ValueType, typename CodecType>
43struct AttributeTypeConversion
44{
45 static const NamePair& type() {
46 return TypedAttributeArray<ValueType, CodecType>::attributeType();
47 }
48};
49
50
51template <typename CodecType>
52struct AttributeTypeConversion<Name, CodecType>
53{
54 static const NamePair& type() { return StringAttributeArray::attributeType(); }
55};
56
57
58////////////////////////////////////////
59
60
61template <typename PointDataTreeT, typename ValueType>
62struct MetadataStorage
63{
64 static void add(PointDataTreeT&, const ValueType&) {}
65
66 template<typename AttributeListType>
67 static void add(PointDataTreeT&, const AttributeListType&) {}
68};
69
70
71template <typename PointDataTreeT>
72struct MetadataStorage<PointDataTreeT, Name>
73{
74 static void add(PointDataTreeT& tree, const Name& uniformValue) {
75 MetaMap& metadata = makeDescriptorUnique(tree)->getMetadata();
76 StringMetaInserter inserter(metadata);
77 inserter.insert(uniformValue);
78 }
79
80 template<typename AttributeListType>
81 static void add(PointDataTreeT& tree, const AttributeListType& data) {
82 MetaMap& metadata = makeDescriptorUnique(tree)->getMetadata();
83 StringMetaInserter inserter(metadata);
84 Name value;
85
86 for (size_t i = 0; i < data.size(); i++) {
87 data.get(value, i);
88 inserter.insert(value);
89 }
90 }
91};
92
93
94} // namespace point_attribute_internal
95
96/// @endcond
97
98
99////////////////////////////////////////
100
101
102template <typename PointDataTreeT>
103inline void appendAttribute(PointDataTreeT& tree,
104 const Name& name,
105 const NamePair& type,
106 const Index strideOrTotalSize,
107 const bool constantStride,
108 const Metadata* defaultValue,
109 const bool hidden,
110 const bool transient)
111{
112 auto iter = tree.cbeginLeaf();
113
114 if (!iter) return;
115
116 // do not append a non-unique attribute
117
118 const auto& descriptor = iter->attributeSet().descriptor();
119 const size_t index = descriptor.find(name);
120
123 "Cannot append an attribute with a non-unique name - " << name << ".");
124 }
125
126 // create a new attribute descriptor
127
128 auto newDescriptor = descriptor.duplicateAppend(name, type);
129
130 // store the attribute default value in the descriptor metadata
131
132 if (defaultValue) {
133 newDescriptor->setDefaultValue(name, *defaultValue);
134 }
135
136 // extract new pos
137
138 const size_t pos = newDescriptor->find(name);
139
140 // acquire registry lock to avoid locking when appending attributes in parallel
141
143
144 // insert attributes using the new descriptor
145
147 leafManager.foreach(
148 [&](typename PointDataTreeT::LeafNodeType& leaf, size_t /*idx*/) {
149 auto expected = leaf.attributeSet().descriptorPtr();
150
151 auto attribute = leaf.appendAttribute(*expected, newDescriptor,
152 pos, strideOrTotalSize, constantStride, defaultValue,
153 &lock);
154
155 if (hidden) attribute->setHidden(true);
156 if (transient) attribute->setTransient(true);
157 }, /*threaded=*/ true
158 );
159}
160
161
162////////////////////////////////////////
163
164
165template <typename ValueType, typename CodecType, typename PointDataTreeT>
166inline void appendAttribute(PointDataTreeT& tree,
167 const std::string& name,
168 const ValueType& uniformValue,
169 const Index strideOrTotalSize,
170 const bool constantStride,
171 const TypedMetadata<ValueType>* defaultValue,
172 const bool hidden,
173 const bool transient)
174{
175 static_assert(!std::is_base_of<AttributeArray, ValueType>::value,
176 "ValueType must not be derived from AttributeArray");
177
178 using point_attribute_internal::AttributeTypeConversion;
180 using point_attribute_internal::MetadataStorage;
181
182 appendAttribute(tree, name, AttributeTypeConversion<ValueType, CodecType>::type(),
183 strideOrTotalSize, constantStride, defaultValue, hidden, transient);
184
185 // if the uniform value is equal to either the default value provided
186 // through the metadata argument or the default value for this value type,
187 // it is not necessary to perform the collapse
188
189 const bool uniformIsDefault = math::isExactlyEqual(uniformValue,
190 bool(defaultValue) ? defaultValue->value() : Default<ValueType>::value());
191 if (!uniformIsDefault) {
192 MetadataStorage<PointDataTreeT, ValueType>::add(tree, uniformValue);
193 collapseAttribute<ValueType>(tree, name, uniformValue);
194 }
195}
196
197
198////////////////////////////////////////
199
200
201template <typename ValueType, typename PointDataTreeT>
202inline void collapseAttribute( PointDataTreeT& tree,
203 const Name& name,
204 const ValueType& uniformValue)
205{
206 static_assert(!std::is_base_of<AttributeArray, ValueType>::value,
207 "ValueType must not be derived from AttributeArray");
208
209 auto iter = tree.cbeginLeaf();
210
211 if (!iter) return;
212
213 const auto& descriptor = iter->attributeSet().descriptor();
214
215 // throw if attribute name does not exist
216
217 const size_t index = descriptor.find(name);
219 OPENVDB_THROW(KeyError, "Cannot find attribute name in PointDataTree.");
220 }
221
223 leafManager.foreach(
224 [&](typename PointDataTreeT::LeafNodeType& leaf, size_t /*idx*/) {
225 OPENVDB_ASSERT(leaf.hasAttribute(index));
226 AttributeArray& array = leaf.attributeArray(index);
227 point_attribute_internal::collapseAttribute(
228 array, descriptor, uniformValue);
229 }, /*threaded=*/true
230 );
231}
232
233
234////////////////////////////////////////
235
236
237template <typename PointDataTreeT>
238inline void dropAttributes( PointDataTreeT& tree,
239 const std::vector<size_t>& indices)
240{
241 auto iter = tree.cbeginLeaf();
242
243 if (!iter) return;
244
245 const auto& descriptor = iter->attributeSet().descriptor();
246
247 // throw if position index present in the indices as this attribute is mandatory
248
249 const size_t positionIndex = descriptor.find("P");
250 if (positionIndex!= AttributeSet::INVALID_POS &&
251 std::find(indices.begin(), indices.end(), positionIndex) != indices.end()) {
252 OPENVDB_THROW(KeyError, "Cannot drop mandatory position attribute.");
253 }
254
255 // insert attributes using the new descriptor
256
257 auto newDescriptor = descriptor.duplicateDrop(indices);
258
260 leafManager.foreach(
261 [&](typename PointDataTreeT::LeafNodeType& leaf, size_t /*idx*/) {
262 auto expected = leaf.attributeSet().descriptorPtr();
263 leaf.dropAttributes(indices, *expected, newDescriptor);
264 }, /*threaded=*/true
265 );
266}
267
268
269////////////////////////////////////////
270
271
272template <typename PointDataTreeT>
273inline void dropAttributes( PointDataTreeT& tree,
274 const std::vector<Name>& names)
275{
276 auto iter = tree.cbeginLeaf();
277
278 if (!iter) return;
279
280 const AttributeSet& attributeSet = iter->attributeSet();
281 const AttributeSet::Descriptor& descriptor = attributeSet.descriptor();
282
283 std::vector<size_t> indices;
284
285 for (const Name& name : names) {
286 const size_t index = descriptor.find(name);
287
288 // do not attempt to drop an attribute that does not exist
291 "Cannot drop an attribute that does not exist - " << name << ".");
292 }
293
294 indices.push_back(index);
295 }
296
297 dropAttributes(tree, indices);
298}
299
300
301////////////////////////////////////////
302
303
304template <typename PointDataTreeT>
305inline void dropAttribute( PointDataTreeT& tree,
306 const size_t& index)
307{
308 std::vector<size_t> indices{index};
309 dropAttributes(tree, indices);
310}
311
312
313template <typename PointDataTreeT>
314inline void dropAttribute( PointDataTreeT& tree,
315 const Name& name)
316{
317 std::vector<Name> names{name};
318 dropAttributes(tree, names);
319}
320
321
322////////////////////////////////////////
323
324
325template <typename PointDataTreeT>
326inline void renameAttributes( PointDataTreeT& tree,
327 const std::vector<Name>& oldNames,
328 const std::vector<Name>& newNames)
329{
330 if (oldNames.size() != newNames.size()) {
331 OPENVDB_THROW(ValueError, "Mis-matching sizes of name vectors, cannot rename attributes.");
332 }
333
334 using Descriptor = AttributeSet::Descriptor;
335
336 auto iter = tree.beginLeaf();
337
338 if (!iter) return;
339
340 const AttributeSet& attributeSet = iter->attributeSet();
341 const Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
342 auto newDescriptor = std::make_shared<Descriptor>(*descriptor);
343
344 for (size_t i = 0; i < oldNames.size(); i++) {
345 const Name& oldName = oldNames[i];
346 if (descriptor->find(oldName) == AttributeSet::INVALID_POS) {
347 OPENVDB_THROW(KeyError, "Cannot find requested attribute - " << oldName << ".");
348 }
349
350 const Name& newName = newNames[i];
351 if (descriptor->find(newName) != AttributeSet::INVALID_POS) {
353 "Cannot rename attribute as new name already exists - " << newName << ".");
354 }
355
356 const AttributeArray* array = attributeSet.getConst(oldName);
357 OPENVDB_ASSERT(array);
358
359 if (isGroup(*array)) {
360 OPENVDB_THROW(KeyError, "Cannot rename group attribute - " << oldName << ".");
361 }
362
363 newDescriptor->rename(oldName, newName);
364 }
365
366 for (; iter; ++iter) {
367 iter->renameAttributes(*descriptor, newDescriptor);
368 }
369}
370
371
372template <typename PointDataTreeT>
373inline void renameAttribute(PointDataTreeT& tree,
374 const Name& oldName,
375 const Name& newName)
376{
377 renameAttributes(tree, {oldName}, {newName});
378}
379
380
381////////////////////////////////////////
382
383
384template <typename PointDataTreeT>
385inline void compactAttributes(PointDataTreeT& tree)
386{
387 auto iter = tree.beginLeaf();
388 if (!iter) return;
389
391 leafManager.foreach(
392 [&](typename PointDataTreeT::LeafNodeType& leaf, size_t /*idx*/) {
393 leaf.compactAttributes();
394 }, /*threaded=*/ true
395 );
396}
397
398
399////////////////////////////////////////
400
401
402} // namespace points
403} // namespace OPENVDB_VERSION_NAME
404} // namespace openvdb
405
406#endif // OPENVDB_POINTS_POINT_ATTRIBUTE_IMPL_HAS_BEEN_INCLUDED
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Definition Exceptions.h:59
Base class for storing metadata information in a grid.
Definition Metadata.h:25
Templated metadata class to hold specific types.
Definition Metadata.h:123
T & value()
Return this metadata's value.
Definition Metadata.h:250
Definition Exceptions.h:65
Base class for storing attribute data.
Definition AttributeArray.h:94
An immutable object that stores name, type and AttributeSet position for a constant collection of att...
Definition AttributeSet.h:311
size_t find(const std::string &name) const
Return the position of the attribute array whose name is name, or INVALID_POS if no match is found.
Ordered collection of uniquely-named attribute arrays.
Definition AttributeSet.h:40
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set's descriptor, which might be shared with other sets.
Definition AttributeSet.h:109
const AttributeArray * getConst(const std::string &name) const
Return a pointer to the attribute array whose name is name or a null pointer if no match is found.
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets.
Definition AttributeSet.h:103
@ INVALID_POS
Definition AttributeSet.h:42
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition LeafManager.h:484
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:443
Definition IndexIterator.h:35
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition PointAttributeImpl.h:385
void dropAttribute(PointDataTreeT &tree, const size_t &index)
Drop one attribute from the VDB tree (convenience method).
Definition PointAttributeImpl.h:305
void collapseAttribute(PointDataTreeT &tree, const Name &name, const ValueType &uniformValue=point_attribute_internal::Default< ValueType >::value())
Collapse the attribute into a uniform value.
Definition PointAttributeImpl.h:202
bool isGroup(const AttributeArray &array)
Definition AttributeGroup.h:64
void appendAttribute(PointDataTreeT &tree, const Name &name, const NamePair &type, const Index strideOrTotalSize=1, const bool constantStride=true, const Metadata *defaultValue=nullptr, const bool hidden=false, const bool transient=false)
Appends a new attribute to the VDB tree (this method does not require a templated AttributeType)
Definition PointAttributeImpl.h:103
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition PointAttributeImpl.h:238
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
Definition PointAttributeImpl.h:326
void renameAttribute(PointDataTreeT &tree, const Name &oldName, const Name &newName)
Rename an attribute in a VDB tree.
Definition PointAttributeImpl.h:373
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition PointDataGrid.h:1586
Definition PointDataGrid.h:170
std::string Name
Definition Name.h:19
Index32 Index
Definition Types.h:54
std::pair< Name, Name > NamePair
Definition AttributeArray.h:40
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218