OpenVDB: PointGroup.h Source File

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 {
57 OPENVDB_USE_VERSION_NAMESPACE
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
162 using LeafManagerT = typename tree::LeafManager<PointDataTreeType>;
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
187 const GroupIndex mTargetIndex;
188 const GroupIndex mSourceIndex;
189 };
190
191
193 template <typename PointDataTree, bool Member>
194 struct SetGroupOp
195 {
196 using LeafManagerT = typename tree::LeafManager<PointDataTree>;
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
218 const GroupIndex& mIndex;
219 }; // struct SetGroupOp
220
221
222 template <typename PointDataTree, typename PointIndexTree, bool Remove>
223 struct SetGroupFromIndexOp
224 {
225 using LeafManagerT = typename tree::LeafManager<PointDataTree>;
226 using LeafRangeT = typename LeafManagerT::LeafRange;
227 using PointIndexLeafNode = typename PointIndexTree::LeafNodeType;
228 using IndexArray = typename PointIndexLeafNode::IndexArray;
229 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
230 using MembershipArray = std::vector<short>;
231
232 SetGroupFromIndexOp(const PointIndexTree& indexTree,
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
276 const PointIndexTree& mIndexTree;
277 const MembershipArray& mMembership;
278 const GroupIndex& mIndex;
279 }; // struct SetGroupFromIndexOp
280
281
282 template <typename PointDataTree, typename FilterT, typename IterT = typename PointDataTree::LeafNodeType::ValueAllCIter>
283 struct SetGroupByFilterOp
284 {
285 using LeafManagerT = typename tree::LeafManager<PointDataTree>;
286 using LeafRangeT = typename LeafManagerT::LeafRange;
287 using LeafNodeT = typename PointDataTree::LeafNodeType;
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
316 const GroupIndex& mIndex;
317 const FilterT& mFilter; // beginIndex takes a copy of mFilter
318 }; // struct SetGroupByFilterOp
319
320
322
323
325 class GroupInfo
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
461 using point_attribute_internal::AppendAttributeOp;
462 using point_group_internal::GroupInfo;
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
601 using point_group_internal::GroupInfo;
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
637 using point_group_internal::CopyGroupOp;
638 using point_group_internal::GroupInfo;
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>;
701 using point_group_internal::SetGroupFromIndexOp;
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
770 using point_group_internal::SetGroupOp;
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
804 using point_group_internal::SetGroupByFilterOp;
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>
832 inline void setGroupByRandomTarget( PointDataTree& tree,
833 const Name& group,
834 const Index64 targetPoints,
835 const unsigned int seed = 0)
836 {
837 using RandomFilter = RandomLeafFilter<PointDataTree, std::mt19937>;
838
839 RandomFilter filter(tree, targetPoints, seed);
840
841 setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
842 }
843
844
846
847
848 template <typename PointDataTree>
849 inline void setGroupByRandomPercentage( PointDataTree& tree,
850 const Name& group,
851 const float percentage = 10.0f,
852 const unsigned int seed = 0)
853 {
854 using RandomFilter = RandomLeafFilter<PointDataTree, std::mt19937>;
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/ )
openvdb::v6_1::points::point_group_internal::GroupInfo::populateGroupIndices
std::vector< size_t > populateGroupIndices() const
Return vector of indices correlating to the group attribute arrays.
Definition: PointGroup.h:393
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp
Definition: PointGroup.h:223
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::GroupIndex
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:288
openvdb::v6_1::points::point_group_internal::SetGroupOp::mIndex
const GroupIndex & mIndex
Definition: PointGroup.h:218
openvdb::v6_1::points::GroupHandle::get
bool get(Index n) const
openvdb::v6_1::points::appendGroup
void appendGroup(PointDataTree &tree, const Name &group)
Appends a new empty group to the VDB tree.
Definition: PointGroup.h:456
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::SetGroupByFilterOp
SetGroupByFilterOp(const GroupIndex &index, const FilterT &filter)
Definition: PointGroup.h:290
openvdb::v6_1::KeyError
Definition: Exceptions.h:86
openvdb::v6_1::points::point_group_internal::GroupInfo::groupBits
static size_t groupBits()
Return the number of bits in a group (typically 8)
Definition: PointGroup.h:334
openvdb::v6_1::points::point_group_internal::GroupInfo::GroupInfo
GroupInfo(const AttributeSet &attributeSet)
Definition: PointGroup.h:330
openvdb::v6_1::points::deleteMissingPointGroups
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
openvdb::v6_1::points::appendGroups
void appendGroups(PointDataTree &tree, const std::vector< Name > &groups)
Appends new empty groups to the VDB tree.
Definition: PointGroup.h:531
openvdb::v6_1::points::point_group_internal::GroupInfo::Descriptor
AttributeSet::Descriptor Descriptor
Definition: PointGroup.h:328
openvdb.h
openvdb::v6_1::points::point_move_internal::IndexArray
std::vector< Index > IndexArray
Definition: PointMove.h:188
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
openvdb::v6_1::points::GroupHandle
Definition: AttributeGroup.h:102
PointCount.h
Methods for counting points in VDB Point grids.
openvdb::v6_1::points::point_group_internal::SetGroupOp::operator()
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:202
openvdb::v6_1::points::setGroupByFilter
void setGroupByFilter(PointDataTree &tree, const Name &group, const FilterT &filter)
Sets group membership based on a provided filter.
Definition: PointGroup.h:797
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::LeafManagerT
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:285
openvdb::v6_1::points::point_group_internal::CopyGroupOp::GroupIndex
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:164
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::operator()
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:294
openvdb::v6_1::points::point_group_internal::GroupInfo::requiresMove
bool requiresMove(Name &sourceName, size_t &sourceOffset, size_t &targetOffset) const
Definition: PointGroup.h:411
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::GroupIndex
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:229
openvdb::v6_1::points::AttributeArray
Base class for storing attribute data.
Definition: AttributeArray.h:118
openvdb::v6_1::Name
std::string Name
Definition: Name.h:44
openvdb::v6_1::points::point_attribute_internal::AppendAttributeOp
Definition: PointAttribute.h:190
PointAttribute.h
Point attribute manipulation in a VDB Point Grid.
openvdb::v6_1::points::makeDescriptorUnique
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1610
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::PointIndexLeafNode
typename PointIndexTree::LeafNodeType PointIndexLeafNode
Definition: PointGroup.h:227
openvdb::v6_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:109
IndexFilter.h
Index filters primarily designed to be used with a FilterIndexIter.
openvdb::v6_1::points::setGroupByRandomPercentage
void setGroupByRandomPercentage(PointDataTree &tree, const Name &group, const float percentage=10.0f, const unsigned int seed=0)
Definition: PointGroup.h:849
openvdb::v6_1::points::GroupWriteHandle
Definition: AttributeGroup.h:130
openvdb::v6_1::points::point_group_internal::CopyGroupOp::mTargetIndex
const GroupIndex mTargetIndex
Definition: PointGroup.h:187
openvdb::v6_1::points::point_group_internal::CopyGroupOp::LeafManagerT
typename tree::LeafManager< PointDataTreeType > LeafManagerT
Definition: PointGroup.h:162
openvdb::v6_1::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
openvdb::v6_1::points::point_group_internal::SetGroupOp::GroupIndex
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:197
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::MembershipArray
std::vector< short > MembershipArray
Definition: PointGroup.h:230
openvdb::v6_1::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
openvdb::v6_1::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:216
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
openvdb::v6_1::points::dropAttributes
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:529
openvdb::v6_1::points::compactGroups
void compactGroups(PointDataTree &tree)
Compacts existing groups of a VDB Tree to use less memory if possible.
Definition: PointGroup.h:631
openvdb::v6_1::points::dropGroup
void dropGroup(PointDataTree &tree, const Name &group, const bool compact=true)
Drops an existing group from the VDB tree.
Definition: PointGroup.h:547
openvdb::v6_1::points::point_group_internal::SetGroupOp::SetGroupOp
SetGroupOp(const AttributeSet::Descriptor::GroupIndex &index)
Definition: PointGroup.h:199
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::LeafRangeT
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:286
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::SetGroupFromIndexOp
SetGroupFromIndexOp(const PointIndexTree &indexTree, const MembershipArray &membership, const GroupIndex &index)
Definition: PointGroup.h:232
openvdb::v6_1::points::dropGroups
void dropGroups(PointDataTree &tree)
Drops all existing groups from the VDB tree, the tree is compacted after dropping.
Definition: PointGroup.h:597
openvdb::v6_1::points::point_group_internal::CopyGroupOp::mSourceIndex
const GroupIndex mSourceIndex
Definition: PointGroup.h:188
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::LeafNodeT
typename PointDataTree::LeafNodeType LeafNodeT
Definition: PointGroup.h:287
openvdb::v6_1::Index64
uint64_t Index64
Definition: Types.h:60
openvdb::v6_1::points::point_group_internal::CopyGroupOp
Copy a group attribute value from one group offset to another.
Definition: PointGroup.h:160
openvdb::v6_1::points::point_group_internal::GroupInfo::nextUnusedOffset
size_t nextUnusedOffset() const
Return the next empty group slot.
Definition: PointGroup.h:367
openvdb::v6_1::points::setGroupByRandomTarget
void setGroupByRandomTarget(PointDataTree &tree, const Name &group, const Index64 targetPoints, const unsigned int seed=0)
Definition: PointGroup.h:832
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp
Definition: PointGroup.h:283
openvdb::v6_1::points::point_group_internal::CopyGroupOp::operator()
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:171
openvdb
Definition: Exceptions.h:40
openvdb::v6_1::points::point_group_internal::SetGroupOp::LeafManagerT
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:196
openvdb::v6_1::IndexError
Definition: Exceptions.h:84
IndexIterator.h
Index Iterators.
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::mIndexTree
const PointIndexTree & mIndexTree
Definition: PointGroup.h:276
openvdb::v6_1::points::point_group_internal::GroupInfo::unusedGroups
size_t unusedGroups() const
Definition: PointGroup.h:338
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::IndexArray
typename PointIndexLeafNode::IndexArray IndexArray
Definition: PointGroup.h:228
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::LeafRangeT
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:226
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::mFilter
const FilterT & mFilter
Definition: PointGroup.h:317
openvdb::v6_1::points::pointCount
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
openvdb::v6_1::points::isGroup
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:93
openvdb::v6_1::points::point_group_internal::GroupInfo::canCompactGroups
bool canCompactGroups() const
Return true if there are sufficient empty slots to allow compacting.
Definition: PointGroup.h:359
openvdb::v6_1::tree::Tree::LeafNodeType
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:212
openvdb::v6_1::tree::Tree
Definition: Tree.h:203
openvdb::v6_1::points::GroupWriteHandle::collapse
bool collapse(bool on)
Set membership for the whole array and attempt to collapse.
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
openvdb::v6_1::points::GroupWriteHandle::set
void set(Index n, bool on)
openvdb::v6_1::points::GroupType
uint8_t GroupType
Definition: AttributeGroup.h:50
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::mMembership
const MembershipArray & mMembership
Definition: PointGroup.h:277
openvdb::v6_1::points::point_group_internal::GroupInfo
Convenience class with methods for analyzing group data.
Definition: PointGroup.h:325
openvdb::v6_1::tree::Tree::cbeginLeaf
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1181
openvdb::v6_1::points::RandomLeafFilter
Definition: IndexFilter.h:254
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::operator()
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:239
openvdb::v6_1::points::setGroup
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
openvdb::v6_1::points::point_group_internal::CopyGroupOp::CopyGroupOp
CopyGroupOp(const GroupIndex &targetIndex, const GroupIndex &sourceIndex)
Definition: PointGroup.h:166
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
openvdb::v6_1::points::AttributeSet::groupIndex
Util::GroupIndex groupIndex(const Name &groupName) const
Return the group index from the name of the group.
openvdb::v6_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:121
openvdb::v6_1::LookupError
Definition: Exceptions.h:87
openvdb::v6_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:127
openvdb::v6_1::points::point_group_internal::SetGroupOp
Set membership on or off for the specified group.
Definition: PointGroup.h:194
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::mIndex
const GroupIndex & mIndex
Definition: PointGroup.h:278
openvdb::v6_1::points::point_group_internal::CopyGroupOp::LeafRangeT
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:163
openvdb::v6_1::points::point_group_internal::SetGroupByFilterOp::mIndex
const GroupIndex & mIndex
Definition: PointGroup.h:316
AttributeSet.h
Set of Attribute Arrays which tracks metadata about each array.
openvdb::v6_1::math::Round
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:773
openvdb::v6_1::tools::PointIndexTree
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
openvdb::v6_1::points::point_group_internal::SetGroupFromIndexOp::LeafManagerT
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:225