OpenVDB  12.0.0
PointDeleteImpl.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @author Nick Avramoussis, Francisco Gochez, Dan Bailey
5 ///
6 /// @file PointDeleteImpl.h
7 ///
8 
9 #ifndef OPENVDB_POINTS_POINT_DELETE_IMPL_HAS_BEEN_INCLUDED
10 #define OPENVDB_POINTS_POINT_DELETE_IMPL_HAS_BEEN_INCLUDED
11 
12 namespace openvdb {
14 namespace OPENVDB_VERSION_NAME {
15 namespace points {
16 
17 /// @cond OPENVDB_DOCS_INTERNAL
18 
19 namespace point_delete_internal {
20 
21 struct VectorWrapper
22 {
23  using T = std::vector<std::pair<Index, Index>>;
24 
25  VectorWrapper(const T& _data) : data(_data) { }
26  operator bool() const { return index < data.size(); }
27  VectorWrapper& operator++() { index++; return *this; }
28  Index sourceIndex() const { OPENVDB_ASSERT(*this); return data[index].first; }
29  Index targetIndex() const { OPENVDB_ASSERT(*this); return data[index].second; }
30 
31 private:
32  const T& data;
33  T::size_type index = 0;
34 }; // struct VectorWrapper
35 
36 
37 template <typename PointDataTreeT, typename FilterT>
38 struct DeleteByFilterOp
39 {
40  using LeafManagerT = tree::LeafManager<PointDataTreeT>;
41  using LeafRangeT = typename LeafManagerT::LeafRange;
42  using LeafNodeT = typename PointDataTreeT::LeafNodeType;
43  using ValueType = typename LeafNodeT::ValueType;
44 
45  DeleteByFilterOp(const FilterT& filter,
46  const AttributeArray::ScopedRegistryLock* lock)
47  : mFilter(filter)
48  , mLock(lock) { }
49 
50  void operator()(const LeafRangeT& range) const
51  {
52  for (auto leaf = range.begin(); leaf != range.end(); ++leaf) {
53 
54  const size_t newSize =
55  iterCount(leaf->template beginIndexAll<FilterT>(mFilter));
56 
57  // if all points are being deleted, clear the leaf attributes
58  if (newSize == 0) {
59  leaf->clearAttributes(/*updateValueMask=*/true, mLock);
60  continue;
61  }
62 
63  // early exit if no points are being deleted
64 
65  const size_t currentSize = leaf->getLastValue();
66  if (newSize == currentSize) continue;
67 
68  const AttributeSet& existingAttributeSet = leaf->attributeSet();
69  AttributeSet* newAttributeSet = new AttributeSet(
70  existingAttributeSet, static_cast<Index>(newSize), mLock);
71  const size_t attributeSetSize = existingAttributeSet.size();
72 
73  // cache the attribute arrays for efficiency
74 
75  std::vector<AttributeArray*> newAttributeArrays;
76  std::vector<const AttributeArray*> existingAttributeArrays;
77 
78  for (size_t i = 0; i < attributeSetSize; i++) {
79  AttributeArray* newArray = newAttributeSet->get(i);
80  const AttributeArray* existingArray = existingAttributeSet.getConst(i);
81 
82  if (!newArray->hasConstantStride() || !existingArray->hasConstantStride()) {
84  "Transfer of attribute values for dynamic arrays not currently supported.");
85  }
86 
87  if (newArray->stride() != existingArray->stride()) {
89  "Cannot transfer attribute values with mis-matching strides.");
90  }
91 
92  newAttributeArrays.push_back(newArray);
93  existingAttributeArrays.push_back(existingArray);
94  }
95 
96  Index attributeIndex = 0;
97  std::vector<ValueType> endOffsets;
98 
99  endOffsets.reserve(LeafNodeT::NUM_VALUES);
100 
101  // now construct new attribute arrays which exclude data from deleted points
102 
103  std::vector<std::pair<Index, Index>> indexMapping;
104  indexMapping.reserve(newSize);
105 
106  for (auto voxel = leaf->cbeginValueAll(); voxel; ++voxel) {
107  for (auto iter = leaf->beginIndexVoxel(voxel.getCoord(), mFilter);
108  iter; ++iter) {
109  indexMapping.emplace_back(*iter, attributeIndex++);
110  }
111  endOffsets.push_back(static_cast<ValueType>(attributeIndex));
112  }
113 
114  for (size_t i = 0; i < attributeSetSize; i++) {
115  VectorWrapper indexMappingWrapper(indexMapping);
116  newAttributeArrays[i]->copyValues(*(existingAttributeArrays[i]), indexMappingWrapper);
117  }
118 
119  leaf->replaceAttributeSet(newAttributeSet);
120  leaf->setOffsets(endOffsets);
121  }
122  }
123 
124 private:
125  const FilterT& mFilter;
126  const AttributeArray::ScopedRegistryLock* mLock;
127 }; // struct DeleteByFilterOp
128 
129 } // namespace point_delete_internal
130 
131 /// @endcond
132 
133 ////////////////////////////////////////
134 
135 template <typename PointDataTreeT>
136 inline void deleteFromGroups(PointDataTreeT& pointTree,
137  const std::vector<std::string>& groups,
138  bool invert,
139  bool drop)
140 {
141  const typename PointDataTreeT::LeafCIter leafIter = pointTree.cbeginLeaf();
142 
143  if (!leafIter) return;
144 
145  const openvdb::points::AttributeSet& attributeSet = leafIter->attributeSet();
146  const AttributeSet::Descriptor& descriptor = attributeSet.descriptor();
147  std::vector<std::string> availableGroups;
148 
149  // determine which of the requested groups exist, and early exit
150  // if none are present in the tree
151 
152  for (const auto& groupName : groups) {
153  if (descriptor.hasGroup(groupName)) {
154  availableGroups.push_back(groupName);
155  }
156  }
157 
158  if (availableGroups.empty()) return;
159 
160  std::vector<std::string> empty;
161  std::unique_ptr<MultiGroupFilter> filter;
162  if (invert) {
163  filter.reset(new MultiGroupFilter(groups, empty, leafIter->attributeSet()));
164  }
165  else {
166  filter.reset(new MultiGroupFilter(empty, groups, leafIter->attributeSet()));
167  }
168 
169  { // acquire registry lock to avoid locking when appending attributes in parallel
170 
172 
173  tree::LeafManager<PointDataTreeT> leafManager(pointTree);
174  point_delete_internal::DeleteByFilterOp<PointDataTreeT, MultiGroupFilter> deleteOp(
175  *filter, &lock);
176  tbb::parallel_for(leafManager.leafRange(), deleteOp);
177  }
178 
179  // remove empty leaf nodes
180 
181  tools::pruneInactive(pointTree);
182 
183  // drop the now-empty groups if requested (unless invert = true)
184 
185  if (drop && !invert) {
186  dropGroups(pointTree, availableGroups);
187  }
188 }
189 
190 template <typename PointDataTreeT>
191 inline void deleteFromGroup(PointDataTreeT& pointTree,
192  const std::string& group,
193  bool invert,
194  bool drop)
195 {
196  std::vector<std::string> groups(1, group);
197 
198  deleteFromGroups(pointTree, groups, invert, drop);
199 }
200 
201 
202 ////////////////////////////////////////
203 
204 
205 } // namespace points
206 } // namespace OPENVDB_VERSION_NAME
207 } // namespace openvdb
208 
209 #endif // OPENVDB_POINTS_POINT_DELETE_IMPL_HAS_BEEN_INCLUDED
Definition: Exceptions.h:60
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Definition: IndexFilter.h:138
Index32 Index
Definition: Types.h:54
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:315
void dropGroups(PointDataTreeT &tree, const std::vector< Name > &groups)
Drops existing groups from the VDB tree, the tree is compacted after dropping.
Definition: PointGroupImpl.h:329
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:346
bool empty(const char *str)
tests if a c-string str is empty, that is its first value is &#39;\0&#39;
Definition: Util.h:144
Definition: Exceptions.h:13
OutGridT const XformOp bool bool
Definition: ValueTransformer.h:609
void deleteFromGroups(PointDataTreeT &pointTree, const std::vector< std::string > &groups, bool invert=false, bool drop=true)
Delete points that are members of specific groups.
Definition: PointDeleteImpl.h:136
Definition: Exceptions.h:61
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
void deleteFromGroup(PointDataTreeT &pointTree, const std::string &group, bool invert=false, bool drop=true)
Delete points that are members of a group.
Definition: PointDeleteImpl.h:191
void pruneInactive(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with background tiles any nodes whose values are a...
Definition: Prune.h:355
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218