OpenVDB: openvdb/points/impl/PointAttributeImpl.h Source File

OpenVDB 10.1.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: MPL-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 {
13 OPENVDB_USE_VERSION_NAMESPACE
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>
103 inline 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
121 if (index != AttributeSet::INVALID_POS) {
122 OPENVDB_THROW(KeyError,
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
142 AttributeArray::ScopedRegistryLock lock;
143
144 // insert attributes using the new descriptor
145
146 tree::LeafManager<PointDataTreeT> leafManager(tree);
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>
166 inline 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;
179 using point_attribute_internal::Default;
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>
202 inline 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);
218 if (index == AttributeSet::INVALID_POS) {
219 OPENVDB_THROW(KeyError, "Cannot find attribute name in PointDataTree.");
220 }
221
222 tree::LeafManager<PointDataTreeT> leafManager(tree);
223 leafManager.foreach(
224 [&](typename PointDataTreeT::LeafNodeType& leaf, size_t /*idx*/) {
225 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>
238 inline 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
259 tree::LeafManager<PointDataTreeT> leafManager(tree);
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>
273 inline 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
289 if (index == AttributeSet::INVALID_POS) {
290 OPENVDB_THROW(KeyError,
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>
305 inline 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>
314 inline 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>
326 inline 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) {
352 OPENVDB_THROW(KeyError,
353 "Cannot rename attribute as new name already exists - " << newName << ".");
354 }
355
356 const AttributeArray* array = attributeSet.getConst(oldName);
357 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>
373 inline 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>
385 inline void compactAttributes(PointDataTreeT& tree)
386{
387 auto iter = tree.beginLeaf();
388 if (!iter) return;
389
390 tree::LeafManager<PointDataTreeT> leafManager(tree);
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
value
ValueT value
Definition GridBuilder.h:1290
openvdb::v10_1::KeyError
Definition Exceptions.h:59
openvdb::v10_1::Metadata
Base class for storing metadata information in a grid.
Definition Metadata.h:24
openvdb::v10_1::TypedMetadata
Templated metadata class to hold specific types.
Definition Metadata.h:122
openvdb::v10_1::TypedMetadata::value
T & value()
Return this metadata's value.
Definition Metadata.h:249
openvdb::v10_1::ValueError
Definition Exceptions.h:65
openvdb::v10_1::points::AttributeArray::ScopedRegistryLock
Definition AttributeArray.h:119
openvdb::v10_1::points::AttributeArray
Base class for storing attribute data.
Definition AttributeArray.h:93
openvdb::v10_1::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition AttributeSet.h:39
openvdb::v10_1::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::v10_1::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.
openvdb::v10_1::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::v10_1::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
openvdb::v10_1::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::v10_1::points::compactAttributes
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition PointAttributeImpl.h:385
openvdb::v10_1::points::dropAttribute
void dropAttribute(PointDataTreeT &tree, const size_t &index)
Drop one attribute from the VDB tree (convenience method).
Definition PointAttributeImpl.h:305
openvdb::v10_1::points::collapseAttribute
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
openvdb::v10_1::points::isGroup
bool isGroup(const AttributeArray &array)
Definition AttributeGroup.h:63
openvdb::v10_1::points::appendAttribute
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
openvdb::v10_1::points::dropAttributes
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition PointAttributeImpl.h:238
openvdb::v10_1::points::renameAttributes
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
Definition PointAttributeImpl.h:326
openvdb::v10_1::points::renameAttribute
void renameAttribute(PointDataTreeT &tree, const Name &oldName, const Name &newName)
Rename an attribute in a VDB tree.
Definition PointAttributeImpl.h:373
openvdb::v10_1::points::makeDescriptorUnique
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition PointDataGrid.h:1589
openvdb::v10_1::Name
std::string Name
Definition Name.h:19
openvdb::v10_1::Index
Index32 Index
Definition Types.h:54
openvdb::v10_1::NamePair
std::pair< Name, Name > NamePair
Definition AttributeArray.h:39
openvdb
Definition Exceptions.h:13
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
openvdb::v10_1::points::point_attribute_internal::Default
Definition PointAttribute.h:30
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212