OpenVDB: PointAttribute.h Source File

OpenVDB 8.0.0

PointAttribute.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
9
10 #ifndef OPENVDB_POINTS_POINT_ATTRIBUTE_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_ATTRIBUTE_HAS_BEEN_INCLUDED
12
13 #include <openvdb/openvdb.h>
14
15 #include "AttributeArrayString.h"
16 #include "AttributeSet.h"
17 #include "AttributeGroup.h"
18 #include "PointDataGrid.h"
19
20
21 namespace openvdb {
22 OPENVDB_USE_VERSION_NAMESPACE
23 namespace OPENVDB_VERSION_NAME {
24 namespace points {
25
26 namespace point_attribute_internal {
27
28 template <typename ValueType>
29 struct Default
30 {
31 static inline ValueType value() { return zeroVal<ValueType>(); }
32 };
33
34 } // namespace point_attribute_internal
35
36
48 template <typename PointDataTreeT>
49 inline void appendAttribute(PointDataTreeT& tree,
50 const Name& name,
51 const NamePair& type,
52 const Index strideOrTotalSize = 1,
53 const bool constantStride = true,
54 const Metadata* defaultValue = nullptr,
55 const bool hidden = false,
56 const bool transient = false);
57
68 template <typename ValueType,
69 typename CodecType = NullCodec,
70 typename PointDataTreeT = PointDataTree>
71 inline void appendAttribute(PointDataTreeT& tree,
72 const std::string& name,
73 const ValueType& uniformValue =
74 point_attribute_internal::Default<ValueType>::value(),
75 const Index strideOrTotalSize = 1,
76 const bool constantStride = true,
77 const TypedMetadata<ValueType>* defaultValue = nullptr,
78 const bool hidden = false,
79 const bool transient = false);
80
86 template <typename ValueType, typename PointDataTreeT>
87 inline void collapseAttribute( PointDataTreeT& tree,
88 const Name& name,
89 const ValueType& uniformValue =
90 point_attribute_internal::Default<ValueType>::value());
91
96 template <typename PointDataTreeT>
97 inline void dropAttributes( PointDataTreeT& tree,
98 const std::vector<size_t>& indices);
99
104 template <typename PointDataTreeT>
105 inline void dropAttributes( PointDataTreeT& tree,
106 const std::vector<Name>& names);
107
112 template <typename PointDataTreeT>
113 inline void dropAttribute( PointDataTreeT& tree,
114 const size_t& index);
115
120 template <typename PointDataTreeT>
121 inline void dropAttribute( PointDataTreeT& tree,
122 const Name& name);
123
133 template <typename PointDataTreeT>
134 inline void renameAttributes(PointDataTreeT& tree,
135 const std::vector<Name>& oldNames,
136 const std::vector<Name>& newNames);
137
145 template <typename PointDataTreeT>
146 inline void renameAttribute(PointDataTreeT& tree,
147 const Name& oldName,
148 const Name& newName);
149
153 template <typename PointDataTreeT>
154 inline void compactAttributes(PointDataTreeT& tree);
155
156
158
159
160 namespace point_attribute_internal {
161
162
163 template <typename ValueType>
164 inline void collapseAttribute(AttributeArray& array,
165 const AttributeSet::Descriptor&, const ValueType& uniformValue)
166 {
167 AttributeWriteHandle<ValueType> handle(array);
168 handle.collapse(uniformValue);
169 }
170
171
172 inline void collapseAttribute(AttributeArray& array,
173 const AttributeSet::Descriptor& descriptor, const Name& uniformValue)
174 {
175 StringAttributeWriteHandle handle(array, descriptor.getMetadata());
176 handle.collapse(uniformValue);
177 }
178
179
181
182
183 template <typename ValueType, typename CodecType>
184 struct AttributeTypeConversion
185 {
186 static const NamePair& type() {
187 return TypedAttributeArray<ValueType, CodecType>::attributeType();
188 }
189 };
190
191
192 template <typename CodecType>
193 struct AttributeTypeConversion<Name, CodecType>
194 {
195 static const NamePair& type() { return StringAttributeArray::attributeType(); }
196 };
197
198
200
201
202 template <typename PointDataTreeT, typename ValueType>
203 struct MetadataStorage
204 {
205 static void add(PointDataTreeT&, const ValueType&) {}
206
207 template<typename AttributeListType>
208 static void add(PointDataTreeT&, const AttributeListType&) {}
209 };
210
211
212 template <typename PointDataTreeT>
213 struct MetadataStorage<PointDataTreeT, Name>
214 {
215 static void add(PointDataTreeT& tree, const Name& uniformValue) {
216 MetaMap& metadata = makeDescriptorUnique(tree)->getMetadata();
217 StringMetaInserter inserter(metadata);
218 inserter.insert(uniformValue);
219 }
220
221 template<typename AttributeListType>
222 static void add(PointDataTreeT& tree, const AttributeListType& data) {
223 MetaMap& metadata = makeDescriptorUnique(tree)->getMetadata();
224 StringMetaInserter inserter(metadata);
225 Name value;
226
227 for (size_t i = 0; i < data.size(); i++) {
228 data.get(value, i);
229 inserter.insert(value);
230 }
231 }
232 };
233
234
235 } // namespace point_attribute_internal
236
237
239
240
241 template <typename PointDataTreeT>
242 inline void appendAttribute(PointDataTreeT& tree,
243 const Name& name,
244 const NamePair& type,
245 const Index strideOrTotalSize,
246 const bool constantStride,
247 const Metadata* defaultValue,
248 const bool hidden,
249 const bool transient)
250 {
251 auto iter = tree.cbeginLeaf();
252
253 if (!iter) return;
254
255 // do not append a non-unique attribute
256
257 const auto& descriptor = iter->attributeSet().descriptor();
258 const size_t index = descriptor.find(name);
259
260 if (index != AttributeSet::INVALID_POS) {
261 OPENVDB_THROW(KeyError,
262 "Cannot append an attribute with a non-unique name - " << name << ".");
263 }
264
265 // create a new attribute descriptor
266
267 auto newDescriptor = descriptor.duplicateAppend(name, type);
268
269 // store the attribute default value in the descriptor metadata
270
271 if (defaultValue) {
272 newDescriptor->setDefaultValue(name, *defaultValue);
273 }
274
275 // extract new pos
276
277 const size_t pos = newDescriptor->find(name);
278
279 // acquire registry lock to avoid locking when appending attributes in parallel
280
281 AttributeArray::ScopedRegistryLock lock;
282
283 // insert attributes using the new descriptor
284
285 tree::LeafManager<PointDataTreeT> leafManager(tree);
286 leafManager.foreach(
287 [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
288 auto expected = leaf.attributeSet().descriptorPtr();
289
290 auto attribute = leaf.appendAttribute(*expected, newDescriptor,
291 pos, strideOrTotalSize, constantStride, defaultValue,
292 &lock);
293
294 if (hidden) attribute->setHidden(true);
295 if (transient) attribute->setTransient(true);
296 }, /*threaded=*/ true
297 );
298 }
299
300
302
303
304 template <typename ValueType, typename CodecType, typename PointDataTreeT>
305 inline void appendAttribute(PointDataTreeT& tree,
306 const std::string& name,
307 const ValueType& uniformValue,
308 const Index strideOrTotalSize,
309 const bool constantStride,
310 const TypedMetadata<ValueType>* defaultValue,
311 const bool hidden,
312 const bool transient)
313 {
314 static_assert(!std::is_base_of<AttributeArray, ValueType>::value,
315 "ValueType must not be derived from AttributeArray");
316
317 using point_attribute_internal::AttributeTypeConversion;
318 using point_attribute_internal::Default;
319 using point_attribute_internal::MetadataStorage;
320
321 appendAttribute(tree, name, AttributeTypeConversion<ValueType, CodecType>::type(),
322 strideOrTotalSize, constantStride, defaultValue, hidden, transient);
323
324 // if the uniform value is equal to either the default value provided
325 // through the metadata argument or the default value for this value type,
326 // it is not necessary to perform the collapse
327
328 const bool uniformIsDefault = math::isExactlyEqual(uniformValue,
329 bool(defaultValue) ? defaultValue->value() : Default<ValueType>::value());
330 if (!uniformIsDefault) {
331 MetadataStorage<PointDataTreeT, ValueType>::add(tree, uniformValue);
332 collapseAttribute<ValueType>(tree, name, uniformValue);
333 }
334 }
335
336
338
339
340 template <typename ValueType, typename PointDataTreeT>
341 inline void collapseAttribute( PointDataTreeT& tree,
342 const Name& name,
343 const ValueType& uniformValue)
344 {
345 static_assert(!std::is_base_of<AttributeArray, ValueType>::value,
346 "ValueType must not be derived from AttributeArray");
347
348 auto iter = tree.cbeginLeaf();
349
350 if (!iter) return;
351
352 const auto& descriptor = iter->attributeSet().descriptor();
353
354 // throw if attribute name does not exist
355
356 const size_t index = descriptor.find(name);
357 if (index == AttributeSet::INVALID_POS) {
358 OPENVDB_THROW(KeyError, "Cannot find attribute name in PointDataTree.");
359 }
360
361 tree::LeafManager<PointDataTreeT> leafManager(tree);
362 leafManager.foreach(
363 [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
364 assert(leaf.hasAttribute(index));
365 AttributeArray& array = leaf.attributeArray(index);
366 point_attribute_internal::collapseAttribute(
367 array, descriptor, uniformValue);
368 }, /*threaded=*/true
369 );
370 }
371
372
374
375
376 template <typename PointDataTreeT>
377 inline void dropAttributes( PointDataTreeT& tree,
378 const std::vector<size_t>& indices)
379 {
380 auto iter = tree.cbeginLeaf();
381
382 if (!iter) return;
383
384 const auto& descriptor = iter->attributeSet().descriptor();
385
386 // throw if position index present in the indices as this attribute is mandatory
387
388 const size_t positionIndex = descriptor.find("P");
389 if (positionIndex!= AttributeSet::INVALID_POS &&
390 std::find(indices.begin(), indices.end(), positionIndex) != indices.end()) {
391 OPENVDB_THROW(KeyError, "Cannot drop mandatory position attribute.");
392 }
393
394 // insert attributes using the new descriptor
395
396 auto newDescriptor = descriptor.duplicateDrop(indices);
397
398 tree::LeafManager<PointDataTreeT> leafManager(tree);
399 leafManager.foreach(
400 [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
401 auto expected = leaf.attributeSet().descriptorPtr();
402 leaf.dropAttributes(indices, *expected, newDescriptor);
403 }, /*threaded=*/true
404 );
405 }
406
407
409
410
411 template <typename PointDataTreeT>
412 inline void dropAttributes( PointDataTreeT& tree,
413 const std::vector<Name>& names)
414 {
415 auto iter = tree.cbeginLeaf();
416
417 if (!iter) return;
418
419 const AttributeSet& attributeSet = iter->attributeSet();
420 const AttributeSet::Descriptor& descriptor = attributeSet.descriptor();
421
422 std::vector<size_t> indices;
423
424 for (const Name& name : names) {
425 const size_t index = descriptor.find(name);
426
427 // do not attempt to drop an attribute that does not exist
428 if (index == AttributeSet::INVALID_POS) {
429 OPENVDB_THROW(KeyError,
430 "Cannot drop an attribute that does not exist - " << name << ".");
431 }
432
433 indices.push_back(index);
434 }
435
436 dropAttributes(tree, indices);
437 }
438
439
441
442
443 template <typename PointDataTreeT>
444 inline void dropAttribute( PointDataTreeT& tree,
445 const size_t& index)
446 {
447 std::vector<size_t> indices{index};
448 dropAttributes(tree, indices);
449 }
450
451
452 template <typename PointDataTreeT>
453 inline void dropAttribute( PointDataTreeT& tree,
454 const Name& name)
455 {
456 std::vector<Name> names{name};
457 dropAttributes(tree, names);
458 }
459
460
462
463
464 template <typename PointDataTreeT>
465 inline void renameAttributes( PointDataTreeT& tree,
466 const std::vector<Name>& oldNames,
467 const std::vector<Name>& newNames)
468 {
469 if (oldNames.size() != newNames.size()) {
470 OPENVDB_THROW(ValueError, "Mis-matching sizes of name vectors, cannot rename attributes.");
471 }
472
473 using Descriptor = AttributeSet::Descriptor;
474
475 auto iter = tree.beginLeaf();
476
477 if (!iter) return;
478
479 const AttributeSet& attributeSet = iter->attributeSet();
480 const Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
481 auto newDescriptor = std::make_shared<Descriptor>(*descriptor);
482
483 for (size_t i = 0; i < oldNames.size(); i++) {
484 const Name& oldName = oldNames[i];
485 if (descriptor->find(oldName) == AttributeSet::INVALID_POS) {
486 OPENVDB_THROW(KeyError, "Cannot find requested attribute - " << oldName << ".");
487 }
488
489 const Name& newName = newNames[i];
490 if (descriptor->find(newName) != AttributeSet::INVALID_POS) {
491 OPENVDB_THROW(KeyError,
492 "Cannot rename attribute as new name already exists - " << newName << ".");
493 }
494
495 const AttributeArray* array = attributeSet.getConst(oldName);
496 assert(array);
497
498 if (isGroup(*array)) {
499 OPENVDB_THROW(KeyError, "Cannot rename group attribute - " << oldName << ".");
500 }
501
502 newDescriptor->rename(oldName, newName);
503 }
504
505 for (; iter; ++iter) {
506 iter->renameAttributes(*descriptor, newDescriptor);
507 }
508 }
509
510
511 template <typename PointDataTreeT>
512 inline void renameAttribute(PointDataTreeT& tree,
513 const Name& oldName,
514 const Name& newName)
515 {
516 renameAttributes(tree, {oldName}, {newName});
517 }
518
519
521
522
523 template <typename PointDataTreeT>
524 inline void compactAttributes(PointDataTreeT& tree)
525 {
526 auto iter = tree.beginLeaf();
527 if (!iter) return;
528
529 tree::LeafManager<PointDataTreeT> leafManager(tree);
530 leafManager.foreach(
531 [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
532 leaf.compactAttributes();
533 }, /*threaded=*/ true
534 );
535 }
536
537
539
540
541 } // namespace points
542 } // namespace OPENVDB_VERSION_NAME
543 } // namespace openvdb
544
545 #endif // OPENVDB_POINTS_POINT_ATTRIBUTE_HAS_BEEN_INCLUDED
openvdb::v8_2::points::AttributeSet::descriptorPtr
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set's descriptor, which might be shared with other sets.
Definition: AttributeSet.h:108
openvdb::v8_2::points::dropAttribute
void dropAttribute(PointDataTreeT &tree, const Name &name)
Drop one attribute from the VDB tree (convenience method).
Definition: PointAttribute.h:453
openvdb::v8_2::points::point_attribute_internal::MetadataStorage< PointDataTreeT, Name >::add
static void add(PointDataTreeT &tree, const Name &uniformValue)
Definition: PointAttribute.h:215
openvdb::v8_2::points::point_attribute_internal::Default::value
static ValueType value()
Definition: PointAttribute.h:31
AttributeSet.h
Set of Attribute Arrays which tracks metadata about each array.
openvdb::v8_2::points::AttributeArray
Base class for storing attribute data.
Definition: AttributeArray.h:93
openvdb::v8_2::points::point_attribute_internal::AttributeTypeConversion
Definition: PointAttribute.h:185
openvdb::v8_2::points::point_attribute_internal::MetadataStorage::add
static void add(PointDataTreeT &, const ValueType &)
Definition: PointAttribute.h:205
openvdb::v8_2::points::point_attribute_internal::Default
Definition: PointAttribute.h:30
openvdb::v8_2::points::makeDescriptorUnique
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1571
openvdb::v8_2::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:39
openvdb::v8_2::points::StringMetaInserter
Class to help with insertion of keyed string values into metadata.
Definition: AttributeArrayString.h:89
openvdb::v8_2::Index
Index32 Index
Definition: openvdb/Types.h:32
openvdb::v8_2::TypedMetadata::value
T & value()
Return this metadata's value.
Definition: Metadata.h:249
openvdb::v8_2::NamePair
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:39
openvdb::v8_2::points::PointDataTree
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > >> PointDataTree
Point index tree configured to match the default VDB configurations.
Definition: PointDataGrid.h:185
openvdb::v8_2::points::AttributeArray::ScopedRegistryLock
Definition: AttributeArray.h:119
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
openvdb::v8_2::MetaMap
Container that maps names (strings) to values of arbitrary types.
Definition: MetaMap.h:20
openvdb::v8_2::points::AttributeSet::descriptor
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets.
Definition: AttributeSet.h:102
openvdb::v8_2::math::isExactlyEqual
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
openvdb::v8_2::points::AttributeWriteHandle
Write-able version of AttributeHandle.
Definition: AttributeArray.h:915
openvdb::v8_2::points::TypedAttributeArray
Typed class for storing attribute data.
Definition: AttributeArray.h:559
openvdb::v8_2::points::point_attribute_internal::AttributeTypeConversion< Name, CodecType >::type
static const NamePair & type()
Definition: PointAttribute.h:195
openvdb::v8_2::points::AttributeSet::getConst
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.
AttributeGroup.h
Attribute Group access and filtering for iteration.
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
openvdb::v8_2::points::point_attribute_internal::MetadataStorage::add
static void add(PointDataTreeT &, const AttributeListType &)
Definition: PointAttribute.h:208
openvdb::v8_2::points::appendAttribute
void appendAttribute(PointDataTreeT &tree, const std::string &name, const ValueType &uniformValue=point_attribute_internal::Default< ValueType >::value(), const Index strideOrTotalSize=1, const bool constantStride=true, const TypedMetadata< ValueType > *defaultValue=nullptr, const bool hidden=false, const bool transient=false)
Appends a new attribute to the VDB tree.
Definition: PointAttribute.h:305
openvdb::v8_2::Metadata
Base class for storing metadata information in a grid.
Definition: Metadata.h:24
openvdb::v8_2::tree::LeafManager::foreach
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:483
openvdb::v8_2::ValueError
Definition: openvdb/Exceptions.h:65
openvdb::v8_2::points::isGroup
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:63
openvdb::v8_2::points::dropAttributes
void dropAttributes(PointDataTreeT &tree, const std::vector< Name > &names)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:412
openvdb::v8_2::points::point_attribute_internal::AttributeTypeConversion::type
static const NamePair & type()
Definition: PointAttribute.h:186
openvdb::v8_2::TypedMetadata
Templated metadata class to hold specific types.
Definition: Metadata.h:122
openvdb::v8_2::tree::LeafManager
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
AttributeArrayString.h
Attribute array storage for string data using Descriptor Metadata.
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153
openvdb::v8_2::points::renameAttribute
void renameAttribute(PointDataTreeT &tree, const Name &oldName, const Name &newName)
Rename an attribute in a VDB tree.
Definition: PointAttribute.h:512
openvdb::v8_2::tree::Tree::LeafNodeType
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:183
openvdb::v8_2::points::compactAttributes
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition: PointAttribute.h:524
openvdb::v8_2::points::point_attribute_internal::MetadataStorage< PointDataTreeT, Name >::add
static void add(PointDataTreeT &tree, const AttributeListType &data)
Definition: PointAttribute.h:222
openvdb::v8_2::points::renameAttributes
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
Definition: PointAttribute.h:465
openvdb::v8_2::points::StringMetaInserter::insert
Index insert(const Name &name, Index hint=Index(0))
Insert the string into the metadata using the hint if non-zero.
openvdb::v8_2::points::point_attribute_internal::MetadataStorage
Definition: PointAttribute.h:204
openvdb::v8_2::points::StringAttributeWriteHandle::collapse
void collapse()
Set membership for the whole array and attempt to collapse.
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
openvdb::v8_2::points::point_attribute_internal::collapseAttribute
void collapseAttribute(AttributeArray &array, const AttributeSet::Descriptor &descriptor, const Name &uniformValue)
Definition: PointAttribute.h:172
openvdb::v8_2::KeyError
Definition: openvdb/Exceptions.h:59
openvdb::v8_2::points::StringAttributeWriteHandle
Definition: AttributeArrayString.h:187
openvdb
Definition: openvdb/Exceptions.h:13
openvdb.h
openvdb::v8_2::Name
std::string Name
Definition: Name.h:17
openvdb::v8_2::points::AttributeWriteHandle::collapse
void collapse()
Replace the existing array with a uniform value (zero if none provided).
Definition: AttributeArray.h:2268