OpenVDB  8.0.1
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 {
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 =
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 =
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>
165  const AttributeSet::Descriptor&, const ValueType& uniformValue)
166 {
167  AttributeWriteHandle<ValueType> handle(array);
168  handle.collapse(uniformValue);
169 }
170 
171 
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>
185 {
186  static const NamePair& type() {
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>
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) {
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 
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 
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);
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) {
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) {
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
Attribute Group access and filtering for iteration.
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
static void add(PointDataTreeT &tree, const Name &uniformValue)
Definition: PointAttribute.h:215
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set&#39;s descriptor, which might be shared with other sets...
Definition: AttributeSet.h:108
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:39
Descriptor & descriptor()
Return a reference to this attribute set&#39;s descriptor, which might be shared with other sets...
Definition: AttributeSet.h:102
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition: PointAttribute.h:524
void collapse()
Replace the existing array with a uniform value (zero if none provided).
Definition: AttributeArray.h:2268
static ValueType value()
Definition: PointAttribute.h:31
Write-able version of AttributeHandle.
Definition: AttributeArray.h:914
Definition: Tree.h:174
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1571
Class to help with insertion of keyed string values into metadata.
Definition: AttributeArrayString.h:88
Index insert(const Name &name, Index hint=Index(0))
Insert the string into the metadata using the hint if non-zero.
Base class for storing metadata information in a grid.
Definition: Metadata.h:23
Definition: openvdb/Exceptions.h:59
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
Container that maps names (strings) to values of arbitrary types.
Definition: MetaMap.h:19
void dropAttributes(PointDataTreeT &tree, const std::vector< Name > &names)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:412
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...
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
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
Templated metadata class to hold specific types.
Definition: Metadata.h:121
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:38
T & value()
Return this metadata&#39;s value.
Definition: Metadata.h:249
static void add(PointDataTreeT &, const AttributeListType &)
Definition: PointAttribute.h:208
void collapse()
Set membership for the whole array and attempt to collapse.
Definition: openvdb/Exceptions.h:13
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
Definition: PointAttribute.h:465
Definition: AttributeArray.h:479
Typed class for storing attribute data.
Definition: AttributeArray.h:555
void dropAttribute(PointDataTreeT &tree, const Name &name)
Drop one attribute from the VDB tree (convenience method).
Definition: PointAttribute.h:453
Definition: openvdb/Exceptions.h:65
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Definition: AttributeArrayString.h:186
void collapseAttribute(AttributeArray &array, const AttributeSet::Descriptor &descriptor, const Name &uniformValue)
Definition: PointAttribute.h:172
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:63
std::string Name
Definition: Name.h:17
Attribute array storage for string data using Descriptor Metadata.
Base class for storing attribute data.
Definition: AttributeArray.h:92
static const NamePair & type()
Definition: PointAttribute.h:186
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:183
void renameAttribute(PointDataTreeT &tree, const Name &oldName, const Name &newName)
Rename an attribute in a VDB tree.
Definition: PointAttribute.h:512
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153
static void add(PointDataTreeT &, const ValueType &)
Definition: PointAttribute.h:205
Set of Attribute Arrays which tracks metadata about each array.
static void add(PointDataTreeT &tree, const AttributeListType &data)
Definition: PointAttribute.h:222
Index32 Index
Definition: openvdb/Types.h:32