OpenVDB  6.1.0
PointGroup.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 
36 
37 #ifndef OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
39 
40 #include <openvdb/openvdb.h>
41 
42 #include "IndexIterator.h" // FilterTraits
43 #include "IndexFilter.h" // FilterTraits
44 #include "AttributeSet.h"
45 #include "PointDataGrid.h"
46 #include "PointAttribute.h"
47 #include "PointCount.h"
48 
49 #include <tbb/parallel_reduce.h>
50 
51 #include <algorithm>
52 #include <random>
53 #include <string>
54 #include <vector>
55 
56 namespace openvdb {
58 namespace OPENVDB_VERSION_NAME {
59 namespace points {
60 
65 inline void deleteMissingPointGroups( std::vector<std::string>& groups,
66  const AttributeSet::Descriptor& descriptor);
67 
72 template <typename PointDataTree>
73 inline void appendGroup(PointDataTree& tree,
74  const Name& group);
75 
80 template <typename PointDataTree>
81 inline void appendGroups(PointDataTree& tree,
82  const std::vector<Name>& groups);
83 
90 template <typename PointDataTree>
91 inline void dropGroup( PointDataTree& tree,
92  const Name& group,
93  const bool compact = true);
94 
99 template <typename PointDataTree>
100 inline void dropGroups( PointDataTree& tree,
101  const std::vector<Name>& groups);
102 
106 template <typename PointDataTree>
107 inline void dropGroups( PointDataTree& tree);
108 
112 template <typename PointDataTree>
113 inline void compactGroups(PointDataTree& tree);
114 
124 template <typename PointDataTree, typename PointIndexTree>
125 inline void setGroup( PointDataTree& tree,
126  const PointIndexTree& indexTree,
127  const std::vector<short>& membership,
128  const Name& group,
129  const bool remove = false);
130 
136 template <typename PointDataTree>
137 inline void setGroup( PointDataTree& tree,
138  const Name& group,
139  const bool member = true);
140 
146 template <typename PointDataTree, typename FilterT>
147 inline void setGroupByFilter( PointDataTree& tree,
148  const Name& group,
149  const FilterT& filter);
150 
151 
153 
154 
155 namespace point_group_internal {
156 
157 
159 template<typename PointDataTreeType>
160 struct CopyGroupOp {
161 
163  using LeafRangeT = typename LeafManagerT::LeafRange;
164  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
165 
166  CopyGroupOp(const GroupIndex& targetIndex,
167  const GroupIndex& sourceIndex)
168  : mTargetIndex(targetIndex)
169  , mSourceIndex(sourceIndex) { }
170 
171  void operator()(const typename LeafManagerT::LeafRange& range) const {
172 
173  for (auto leaf = range.begin(); leaf; ++leaf) {
174 
175  GroupHandle sourceGroup = leaf->groupHandle(mSourceIndex);
176  GroupWriteHandle targetGroup = leaf->groupWriteHandle(mTargetIndex);
177 
178  for (auto iter = leaf->beginIndexAll(); iter; ++iter) {
179  const bool groupOn = sourceGroup.get(*iter);
180  targetGroup.set(*iter, groupOn);
181  }
182  }
183  }
184 
186 
189 };
190 
191 
193 template <typename PointDataTree, bool Member>
195 {
197  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
198 
199  SetGroupOp(const AttributeSet::Descriptor::GroupIndex& index)
200  : mIndex(index) { }
201 
202  void operator()(const typename LeafManagerT::LeafRange& range) const
203  {
204  for (auto leaf = range.begin(); leaf; ++leaf) {
205 
206  // obtain the group attribute array
207 
208  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
209 
210  // set the group value
211 
212  group.collapse(Member);
213  }
214  }
215 
217 
219 }; // struct SetGroupOp
220 
221 
222 template <typename PointDataTree, typename PointIndexTree, bool Remove>
224 {
226  using LeafRangeT = typename LeafManagerT::LeafRange;
227  using PointIndexLeafNode = typename PointIndexTree::LeafNodeType;
229  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
230  using MembershipArray = std::vector<short>;
231 
233  const MembershipArray& membership,
234  const GroupIndex& index)
235  : mIndexTree(indexTree)
236  , mMembership(membership)
237  , mIndex(index) { }
238 
239  void operator()(const typename LeafManagerT::LeafRange& range) const
240  {
241  for (auto leaf = range.begin(); leaf; ++leaf) {
242 
243  // obtain the PointIndexLeafNode (using the origin of the current leaf)
244 
245  const PointIndexLeafNode* pointIndexLeaf = mIndexTree.probeConstLeaf(leaf->origin());
246 
247  if (!pointIndexLeaf) continue;
248 
249  // obtain the group attribute array
250 
251  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
252 
253  // initialise the attribute storage
254 
255  Index64 index = 0;
256 
257  const IndexArray& indices = pointIndexLeaf->indices();
258 
259  for (const Index64 i: indices) {
260  if (Remove) {
261  group.set(static_cast<Index>(index), mMembership[i]);
262  } else if (mMembership[i] == short(1)) {
263  group.set(static_cast<Index>(index), short(1));
264  }
265  index++;
266  }
267 
268  // attempt to compact the array
269 
270  group.compact();
271  }
272  }
273 
275 
279 }; // struct SetGroupFromIndexOp
280 
281 
282 template <typename PointDataTree, typename FilterT, typename IterT = typename PointDataTree::LeafNodeType::ValueAllCIter>
284 {
286  using LeafRangeT = typename LeafManagerT::LeafRange;
288  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
289 
290  SetGroupByFilterOp( const GroupIndex& index, const FilterT& filter)
291  : mIndex(index)
292  , mFilter(filter) { }
293 
294  void operator()(const typename LeafManagerT::LeafRange& range) const
295  {
296  for (auto leaf = range.begin(); leaf; ++leaf) {
297 
298  // obtain the group attribute array
299 
300  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
301 
302  auto iter = leaf->template beginIndex<IterT, FilterT>(mFilter);
303 
304  for (; iter; ++iter) {
305  group.set(*iter, true);
306  }
307 
308  // attempt to compact the array
309 
310  group.compact();
311  }
312  }
313 
315 
317  const FilterT& mFilter; // beginIndex takes a copy of mFilter
318 }; // struct SetGroupByFilterOp
319 
320 
322 
323 
326 {
327 public:
328  using Descriptor = AttributeSet::Descriptor;
329 
330  GroupInfo(const AttributeSet& attributeSet)
331  : mAttributeSet(attributeSet) { }
332 
334  static size_t groupBits() { return sizeof(GroupType) * CHAR_BIT; }
335 
338  size_t unusedGroups() const
339  {
340  const Descriptor& descriptor = mAttributeSet.descriptor();
341 
342  // compute total slots (one slot per bit of the group attributes)
343 
344  const size_t groupAttributes = descriptor.count(GroupAttributeArray::attributeType());
345 
346  if (groupAttributes == 0) return 0;
347 
348  const size_t totalSlots = groupAttributes * this->groupBits();
349 
350  // compute slots in use
351 
352  const AttributeSet::Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
353  const size_t usedSlots = groupMap.size();
354 
355  return totalSlots - usedSlots;
356  }
357 
359  bool canCompactGroups() const
360  {
361  // can compact if more unused groups than in one group attribute array
362 
363  return this->unusedGroups() >= this->groupBits();
364  }
365 
367  size_t nextUnusedOffset() const
368  {
369  const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
370 
371  // build a list of group indices
372 
373  std::vector<size_t> indices;
374  indices.reserve(groupMap.size());
375  for (const auto& namePos : groupMap) {
376  indices.push_back(namePos.second);
377  }
378 
379  std::sort(indices.begin(), indices.end());
380 
381  // return first index not present
382 
383  size_t offset = 0;
384  for (const size_t& index : indices) {
385  if (index != offset) break;
386  offset++;
387  }
388 
389  return offset;
390  }
391 
393  std::vector<size_t> populateGroupIndices() const
394  {
395  std::vector<size_t> indices;
396 
397  const Descriptor::NameToPosMap& map = mAttributeSet.descriptor().map();
398 
399  for (const auto& namePos : map) {
400  const AttributeArray* array = mAttributeSet.getConst(namePos.first);
401  if (isGroup(*array)) {
402  indices.push_back(namePos.second);
403  }
404  }
405 
406  return indices;
407  }
408 
411  bool requiresMove(Name& sourceName, size_t& sourceOffset, size_t& targetOffset) const {
412 
413  targetOffset = this->nextUnusedOffset();
414 
415  const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
416 
417  for (const auto& namePos : groupMap) {
418 
419  // move only required if source comes after the target
420 
421  if (namePos.second >= targetOffset) {
422  sourceName = namePos.first;
423  sourceOffset = namePos.second;
424  return true;
425  }
426  }
427 
428  return false;
429  }
430 
431 private:
432  const AttributeSet& mAttributeSet;
433 }; // class GroupInfo
434 
435 
436 } // namespace point_group_internal
437 
438 
440 
441 
442 inline void deleteMissingPointGroups( std::vector<std::string>& groups,
443  const AttributeSet::Descriptor& descriptor)
444 {
445  for (auto it = groups.begin(); it != groups.end();) {
446  if (!descriptor.hasGroup(*it)) it = groups.erase(it);
447  else ++it;
448  }
449 }
450 
451 
453 
454 
455 template <typename PointDataTree>
456 inline void appendGroup(PointDataTree& tree, const Name& group)
457 {
458  using Descriptor = AttributeSet::Descriptor;
459  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
460 
463 
464  if (group.empty()) {
465  OPENVDB_THROW(KeyError, "Cannot use an empty group name as a key.");
466  }
467 
468  auto iter = tree.cbeginLeaf();
469 
470  if (!iter) return;
471 
472  const AttributeSet& attributeSet = iter->attributeSet();
473  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
474  GroupInfo groupInfo(attributeSet);
475 
476  // don't add if group already exists
477 
478  if (descriptor->hasGroup(group)) return;
479 
480  const bool hasUnusedGroup = groupInfo.unusedGroups() > 0;
481 
482  // add a new group attribute if there are no unused groups
483 
484  if (!hasUnusedGroup) {
485 
486  // find a new internal group name
487 
488  const Name groupName = descriptor->uniqueName("__group");
489 
490  descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
491 
492  const size_t pos = descriptor->find(groupName);
493 
494  // insert new group attribute
495 
496  AppendAttributeOp<PointDataTree> append(descriptor, pos);
497  LeafManagerT leafManager(tree);
498  tbb::parallel_for(leafManager.leafRange(), append);
499  }
500  else {
501  // make the descriptor unique before we modify the group map
502 
503  makeDescriptorUnique(tree);
504  descriptor = attributeSet.descriptorPtr();
505  }
506 
507  // ensure that there are now available groups
508 
509  assert(groupInfo.unusedGroups() > 0);
510 
511  // find next unused offset
512 
513  const size_t offset = groupInfo.nextUnusedOffset();
514 
515  // add the group mapping to the descriptor
516 
517  descriptor->setGroup(group, offset);
518 
519  // if there was an unused group then we did not need to append a new attribute, so
520  // we must manually clear membership in the new group as its bits may have been
521  // previously set
522 
523  if (hasUnusedGroup) setGroup(tree, group, false);
524 }
525 
526 
528 
529 
530 template <typename PointDataTree>
531 inline void appendGroups(PointDataTree& tree,
532  const std::vector<Name>& groups)
533 {
534  // TODO: could be more efficient by appending multiple groups at once
535  // instead of one-by-one, however this is likely not that common a use case
536 
537  for (const Name& name : groups) {
538  appendGroup(tree, name);
539  }
540 }
541 
542 
544 
545 
546 template <typename PointDataTree>
547 inline void dropGroup(PointDataTree& tree, const Name& group, const bool compact)
548 {
549  using Descriptor = AttributeSet::Descriptor;
550 
551  if (group.empty()) {
552  OPENVDB_THROW(KeyError, "Cannot use an empty group name as a key.");
553  }
554 
555  auto iter = tree.cbeginLeaf();
556 
557  if (!iter) return;
558 
559  const AttributeSet& attributeSet = iter->attributeSet();
560 
561  // make the descriptor unique before we modify the group map
562 
563  makeDescriptorUnique(tree);
564  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
565 
566  // now drop the group
567 
568  descriptor->dropGroup(group);
569 
570  if (compact) {
571  compactGroups(tree);
572  }
573 }
574 
575 
577 
578 
579 template <typename PointDataTree>
580 inline void dropGroups( PointDataTree& tree,
581  const std::vector<Name>& groups)
582 {
583  for (const Name& name : groups) {
584  dropGroup(tree, name, /*compact=*/false);
585  }
586 
587  // compaction done once for efficiency
588 
589  compactGroups(tree);
590 }
591 
592 
594 
595 
596 template <typename PointDataTree>
597 inline void dropGroups( PointDataTree& tree)
598 {
599  using Descriptor = AttributeSet::Descriptor;
600 
602 
603  auto iter = tree.cbeginLeaf();
604 
605  if (!iter) return;
606 
607  const AttributeSet& attributeSet = iter->attributeSet();
608  GroupInfo groupInfo(attributeSet);
609 
610  // make the descriptor unique before we modify the group map
611 
612  makeDescriptorUnique(tree);
613  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
614 
615  descriptor->clearGroups();
616 
617  // find all indices for group attribute arrays
618 
619  std::vector<size_t> indices = groupInfo.populateGroupIndices();
620 
621  // drop these attributes arrays
622 
623  dropAttributes(tree, indices);
624 }
625 
626 
628 
629 
630 template <typename PointDataTree>
631 inline void compactGroups(PointDataTree& tree)
632 {
633  using Descriptor = AttributeSet::Descriptor;
634  using GroupIndex = Descriptor::GroupIndex;
635  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
636 
639 
640  auto iter = tree.cbeginLeaf();
641 
642  if (!iter) return;
643 
644  const AttributeSet& attributeSet = iter->attributeSet();
645  GroupInfo groupInfo(attributeSet);
646 
647  // early exit if not possible to compact
648 
649  if (!groupInfo.canCompactGroups()) return;
650 
651  // make the descriptor unique before we modify the group map
652 
653  makeDescriptorUnique(tree);
654  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
655 
656  // generate a list of group offsets and move them (one-by-one)
657  // TODO: improve this algorithm to move multiple groups per array at once
658  // though this is likely not that common a use case
659 
660  Name sourceName;
661  size_t sourceOffset, targetOffset;
662 
663  while (groupInfo.requiresMove(sourceName, sourceOffset, targetOffset)) {
664 
665  const GroupIndex sourceIndex = attributeSet.groupIndex(sourceOffset);
666  const GroupIndex targetIndex = attributeSet.groupIndex(targetOffset);
667 
668  CopyGroupOp<PointDataTree> copy(targetIndex, sourceIndex);
669  LeafManagerT leafManager(tree);
670  tbb::parallel_for(leafManager.leafRange(), copy);
671 
672  descriptor->setGroup(sourceName, targetOffset);
673  }
674 
675  // drop unused attribute arrays
676 
677  std::vector<size_t> indices = groupInfo.populateGroupIndices();
678 
679  const size_t totalAttributesToDrop = groupInfo.unusedGroups() / groupInfo.groupBits();
680 
681  assert(totalAttributesToDrop <= indices.size());
682 
683  std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop, indices.end());
684 
685  dropAttributes(tree, indicesToDrop);
686 }
687 
688 
690 
691 
692 template <typename PointDataTree, typename PointIndexTree>
693 inline void setGroup( PointDataTree& tree,
694  const PointIndexTree& indexTree,
695  const std::vector<short>& membership,
696  const Name& group,
697  const bool remove)
698 {
699  using Descriptor = AttributeSet::Descriptor;
700  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
702 
703  auto iter = tree.cbeginLeaf();
704  if (!iter) return;
705 
706  const AttributeSet& attributeSet = iter->attributeSet();
707  const Descriptor& descriptor = attributeSet.descriptor();
708 
709  if (!descriptor.hasGroup(group)) {
710  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
711  }
712 
713  {
714  // Check that that the largest index in the PointIndexTree is smaller than the size
715  // of the membership vector. The index tree will be used to lookup membership
716  // values. If the index tree was constructed with nan positions, this index will
717  // differ from the PointDataTree count
718 
719  using IndexTreeManager = tree::LeafManager<const PointIndexTree>;
720  IndexTreeManager leafManager(indexTree);
721 
722  const int64_t max = tbb::parallel_reduce(leafManager.leafRange(), -1,
723  [](const typename IndexTreeManager::LeafRange& range, int64_t value) -> int64_t {
724  for (auto leaf = range.begin(); leaf; ++leaf) {
725  auto it = std::max_element(leaf->indices().begin(), leaf->indices().end());
726  value = std::max(value, static_cast<int64_t>(*it));
727  }
728  return value;
729  },
730  [](const int64_t a, const int64_t b) {
731  return std::max(a, b);
732  }
733  );
734 
735  if (max != -1 && membership.size() <= static_cast<size_t>(max)) {
736  OPENVDB_THROW(IndexError, "Group membership vector size must be larger than "
737  " the maximum index within the provided index tree.");
738  }
739  }
740 
741  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
742  LeafManagerT leafManager(tree);
743 
744  // set membership
745 
746  if (remove) {
747  SetGroupFromIndexOp<PointDataTree, PointIndexTree, true>
748  set(indexTree, membership, index);
749  tbb::parallel_for(leafManager.leafRange(), set);
750  }
751  else {
752  SetGroupFromIndexOp<PointDataTree, PointIndexTree, false>
753  set(indexTree, membership, index);
754  tbb::parallel_for(leafManager.leafRange(), set);
755  }
756 }
757 
758 
760 
761 
762 template <typename PointDataTree>
763 inline void setGroup( PointDataTree& tree,
764  const Name& group,
765  const bool member)
766 {
767  using Descriptor = AttributeSet::Descriptor;
768  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
769 
771 
772  auto iter = tree.cbeginLeaf();
773 
774  if (!iter) return;
775 
776  const AttributeSet& attributeSet = iter->attributeSet();
777  const Descriptor& descriptor = attributeSet.descriptor();
778 
779  if (!descriptor.hasGroup(group)) {
780  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
781  }
782 
783  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
784  LeafManagerT leafManager(tree);
785 
786  // set membership based on member variable
787 
788  if (member) tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, true>(index));
789  else tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, false>(index));
790 }
791 
792 
794 
795 
796 template <typename PointDataTree, typename FilterT>
797 inline void setGroupByFilter( PointDataTree& tree,
798  const Name& group,
799  const FilterT& filter)
800 {
801  using Descriptor = AttributeSet::Descriptor;
802  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
803 
805 
806  auto iter = tree.cbeginLeaf();
807 
808  if (!iter) return;
809 
810  const AttributeSet& attributeSet = iter->attributeSet();
811  const Descriptor& descriptor = attributeSet.descriptor();
812 
813  if (!descriptor.hasGroup(group)) {
814  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
815  }
816 
817  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
818 
819  // set membership using filter
820 
821  SetGroupByFilterOp<PointDataTree, FilterT> set(index, filter);
822  LeafManagerT leafManager(tree);
823 
824  tbb::parallel_for(leafManager.leafRange(), set);
825 }
826 
827 
829 
830 
831 template <typename PointDataTree>
833  const Name& group,
834  const Index64 targetPoints,
835  const unsigned int seed = 0)
836 {
838 
839  RandomFilter filter(tree, targetPoints, seed);
840 
841  setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
842 }
843 
844 
846 
847 
848 template <typename PointDataTree>
850  const Name& group,
851  const float percentage = 10.0f,
852  const unsigned int seed = 0)
853 {
855 
856  const int currentPoints = static_cast<int>(pointCount(tree));
857  const int targetPoints = int(math::Round((percentage * float(currentPoints))/100.0f));
858 
859  RandomFilter filter(tree, targetPoints, seed);
860 
861  setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
862 }
863 
864 
866 
867 
868 } // namespace points
869 } // namespace OPENVDB_VERSION_NAME
870 } // namespace openvdb
871 
872 
873 #endif // OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
874 
875 // Copyright (c) 2012-2018 DreamWorks Animation LLC
876 // All rights reserved. This software is distributed under the
877 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:288
const GroupIndex & mIndex
Definition: PointGroup.h:218
void appendGroup(PointDataTree &tree, const Name &group)
Appends a new empty group to the VDB tree.
Definition: PointGroup.h:456
SetGroupByFilterOp(const GroupIndex &index, const FilterT &filter)
Definition: PointGroup.h:290
Definition: Exceptions.h:86
static size_t groupBits()
Return the number of bits in a group (typically 8)
Definition: PointGroup.h:334
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set&#39;s descriptor, which might be shared with other sets...
Definition: AttributeSet.h:127
GroupInfo(const AttributeSet &attributeSet)
Definition: PointGroup.h:330
void deleteMissingPointGroups(std::vector< std::string > &groups, const AttributeSet::Descriptor &descriptor)
Delete any group that is not present in the Descriptor.
Definition: PointGroup.h:442
void appendGroups(PointDataTree &tree, const std::vector< Name > &groups)
Appends new empty groups to the VDB tree.
Definition: PointGroup.h:531
AttributeSet::Descriptor Descriptor
Definition: PointGroup.h:328
std::vector< Index > IndexArray
Definition: PointMove.h:188
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
Definition: AttributeGroup.h:102
Methods for counting points in VDB Point grids.
void setGroupByFilter(PointDataTree &tree, const Name &group, const FilterT &filter)
Sets group membership based on a provided filter.
Definition: PointGroup.h:797
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:285
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:164
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1181
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:229
Base class for storing attribute data.
Definition: AttributeArray.h:118
std::string Name
Definition: Name.h:44
Point attribute manipulation in a VDB Point Grid.
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1610
typename PointIndexTree::LeafNodeType PointIndexLeafNode
Definition: PointGroup.h:227
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
Index filters primarily designed to be used with a FilterIndexIter.
void setGroupByRandomPercentage(PointDataTree &tree, const Name &group, const float percentage=10.0f, const unsigned int seed=0)
Definition: PointGroup.h:849
Definition: AttributeGroup.h:130
const GroupIndex mTargetIndex
Definition: PointGroup.h:187
typename tree::LeafManager< PointDataTreeType > LeafManagerT
Definition: PointGroup.h:162
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:197
std::vector< short > MembershipArray
Definition: PointGroup.h:230
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:529
void compactGroups(PointDataTree &tree)
Compacts existing groups of a VDB Tree to use less memory if possible.
Definition: PointGroup.h:631
void dropGroup(PointDataTree &tree, const Name &group, const bool compact=true)
Drops an existing group from the VDB tree.
Definition: PointGroup.h:547
SetGroupOp(const AttributeSet::Descriptor::GroupIndex &index)
Definition: PointGroup.h:199
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:286
SetGroupFromIndexOp(const PointIndexTree &indexTree, const MembershipArray &membership, const GroupIndex &index)
Definition: PointGroup.h:232
void dropGroups(PointDataTree &tree)
Drops all existing groups from the VDB tree, the tree is compacted after dropping.
Definition: PointGroup.h:597
const GroupIndex mSourceIndex
Definition: PointGroup.h:188
typename PointDataTree::LeafNodeType LeafNodeT
Definition: PointGroup.h:287
uint64_t Index64
Definition: Types.h:60
Copy a group attribute value from one group offset to another.
Definition: PointGroup.h:160
void setGroupByRandomTarget(PointDataTree &tree, const Name &group, const Index64 targetPoints, const unsigned int seed=0)
Definition: PointGroup.h:832
Util::GroupIndex groupIndex(const Name &groupName) const
Return the group index from the name of the group.
Definition: Exceptions.h:40
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:196
Definition: Exceptions.h:84
Index Iterators.
const PointIndexTree & mIndexTree
Definition: PointGroup.h:276
typename PointIndexLeafNode::IndexArray IndexArray
Definition: PointGroup.h:228
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:226
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:202
const FilterT & mFilter
Definition: PointGroup.h:317
bool requiresMove(Name &sourceName, size_t &sourceOffset, size_t &targetOffset) const
Definition: PointGroup.h:411
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:115
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:93
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:171
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:212
size_t unusedGroups() const
Definition: PointGroup.h:338
Definition: Tree.h:203
bool collapse(bool on)
Set membership for the whole array and attempt to collapse.
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
uint8_t GroupType
Definition: AttributeGroup.h:50
const MembershipArray & mMembership
Definition: PointGroup.h:277
Convenience class with methods for analyzing group data.
Definition: PointGroup.h:325
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointIndexLeafNode< PointIndex32, 3 >, 4 >, 5 >>> PointIndexTree
Point index tree configured to match the default OpenVDB tree configuration.
Definition: PointIndexGrid.h:83
Definition: IndexFilter.h:254
size_t nextUnusedOffset() const
Return the next empty group slot.
Definition: PointGroup.h:367
void setGroup(PointDataTree &tree, const Name &group, const bool member=true)
Sets membership for the specified group for all points (on/off).
Definition: PointGroup.h:763
CopyGroupOp(const GroupIndex &targetIndex, const GroupIndex &sourceIndex)
Definition: PointGroup.h:166
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:239
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
Descriptor & descriptor()
Return a reference to this attribute set&#39;s descriptor, which might be shared with other sets...
Definition: AttributeSet.h:121
bool canCompactGroups() const
Return true if there are sufficient empty slots to allow compacting.
Definition: PointGroup.h:359
Definition: Exceptions.h:87
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:294
Set membership on or off for the specified group.
Definition: PointGroup.h:194
const GroupIndex & mIndex
Definition: PointGroup.h:278
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:163
const GroupIndex & mIndex
Definition: PointGroup.h:316
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:216
Set of Attribute Arrays which tracks metadata about each array.
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:773
std::vector< size_t > populateGroupIndices() const
Return vector of indices correlating to the group attribute arrays.
Definition: PointGroup.h:393
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:225