OpenVDB  9.0.1
PointDelete.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 Nick Avramoussis, Francisco Gochez, Dan Bailey
5 ///
6 /// @file PointDelete.h
7 ///
8 /// @brief Methods for deleting points based on group membership
9 
10 #ifndef OPENVDB_POINTS_POINT_DELETE_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_DELETE_HAS_BEEN_INCLUDED
12 
13 #include "PointDataGrid.h"
14 #include "PointGroup.h"
15 #include "IndexIterator.h"
16 #include "IndexFilter.h"
17 
18 #include <openvdb/tools/Prune.h>
20 
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 
26 namespace openvdb {
28 namespace OPENVDB_VERSION_NAME {
29 namespace points {
30 
31 
32 /// @brief Delete points that are members of specific groups
33 ///
34 /// @details This method will delete points which are members of any of the supplied groups and
35 /// will optionally drop the groups from the tree. An invert flag can be used to
36 /// delete points that belong to none of the groups.
37 ///
38 /// @param pointTree the point tree
39 /// @param groups the groups from which to delete points
40 /// @param invert if enabled, points not belonging to any of the groups will be deleted
41 /// @param drop if enabled and invert is disabled, the groups will be dropped from the tree
42 ///
43 /// @note If the invert flag is true, none of the groups will be dropped after deleting points
44 /// regardless of the value of the drop parameter.
45 
46 template <typename PointDataTreeT>
47 inline void deleteFromGroups(PointDataTreeT& pointTree,
48  const std::vector<std::string>& groups,
49  bool invert = false,
50  bool drop = true);
51 
52 /// @brief Delete points that are members of a group
53 ///
54 /// @details This method will delete points which are members of the supplied group and will
55 /// optionally drop the group from the tree. An invert flag can be used to
56 /// delete points that belong to none of the groups.
57 ///
58 /// @param pointTree the point tree with the group to delete
59 /// @param group the name of the group to delete
60 /// @param invert if enabled, points not belonging to any of the groups will be deleted
61 /// @param drop if enabled and invert is disabled, the group will be dropped from the tree
62 ///
63 /// @note If the invert flag is true, the group will not be dropped after deleting points
64 /// regardless of the value of the drop parameter.
65 
66 template <typename PointDataTreeT>
67 inline void deleteFromGroup(PointDataTreeT& pointTree,
68  const std::string& group,
69  bool invert = false,
70  bool drop = true);
71 
72 
73 ////////////////////////////////////////
74 
75 /// @cond OPENVDB_DOCS_INTERNAL
76 
77 namespace point_delete_internal {
78 
79 
80 struct VectorWrapper
81 {
82  using T = std::vector<std::pair<Index, Index>>;
83 
84  VectorWrapper(const T& _data) : data(_data) { }
85  operator bool() const { return index < data.size(); }
86  VectorWrapper& operator++() { index++; return *this; }
87  Index sourceIndex() const { assert(*this); return data[index].first; }
88  Index targetIndex() const { assert(*this); return data[index].second; }
89 
90 private:
91  const T& data;
92  T::size_type index = 0;
93 }; // struct VectorWrapper
94 
95 
96 template <typename PointDataTreeT, typename FilterT>
97 struct DeleteByFilterOp
98 {
99  using LeafManagerT = tree::LeafManager<PointDataTreeT>;
100  using LeafRangeT = typename LeafManagerT::LeafRange;
101  using LeafNodeT = typename PointDataTreeT::LeafNodeType;
102  using ValueType = typename LeafNodeT::ValueType;
103 
104  DeleteByFilterOp(const FilterT& filter,
105  const AttributeArray::ScopedRegistryLock* lock)
106  : mFilter(filter)
107  , mLock(lock) { }
108 
109  void operator()(const LeafRangeT& range) const
110  {
111  for (auto leaf = range.begin(); leaf != range.end(); ++leaf) {
112 
113  const size_t newSize =
114  iterCount(leaf->template beginIndexAll<FilterT>(mFilter));
115 
116  // if all points are being deleted, clear the leaf attributes
117  if (newSize == 0) {
118  leaf->clearAttributes(/*updateValueMask=*/true, mLock);
119  continue;
120  }
121 
122  // early exit if no points are being deleted
123 
124  const size_t currentSize = leaf->getLastValue();
125  if (newSize == currentSize) continue;
126 
127  const AttributeSet& existingAttributeSet = leaf->attributeSet();
128  AttributeSet* newAttributeSet = new AttributeSet(
129  existingAttributeSet, static_cast<Index>(newSize), mLock);
130  const size_t attributeSetSize = existingAttributeSet.size();
131 
132  // cache the attribute arrays for efficiency
133 
134  std::vector<AttributeArray*> newAttributeArrays;
135  std::vector<const AttributeArray*> existingAttributeArrays;
136 
137  for (size_t i = 0; i < attributeSetSize; i++) {
138  AttributeArray* newArray = newAttributeSet->get(i);
139  const AttributeArray* existingArray = existingAttributeSet.getConst(i);
140 
141  if (!newArray->hasConstantStride() || !existingArray->hasConstantStride()) {
143  "Transfer of attribute values for dynamic arrays not currently supported.");
144  }
145 
146  if (newArray->stride() != existingArray->stride()) {
148  "Cannot transfer attribute values with mis-matching strides.");
149  }
150 
151  newAttributeArrays.push_back(newArray);
152  existingAttributeArrays.push_back(existingArray);
153  }
154 
155  Index attributeIndex = 0;
156  std::vector<ValueType> endOffsets;
157 
158  endOffsets.reserve(LeafNodeT::NUM_VALUES);
159 
160  // now construct new attribute arrays which exclude data from deleted points
161 
162  std::vector<std::pair<Index, Index>> indexMapping;
163  indexMapping.reserve(newSize);
164 
165  for (auto voxel = leaf->cbeginValueAll(); voxel; ++voxel) {
166  for (auto iter = leaf->beginIndexVoxel(voxel.getCoord(), mFilter);
167  iter; ++iter) {
168  indexMapping.emplace_back(*iter, attributeIndex++);
169  }
170  endOffsets.push_back(static_cast<ValueType>(attributeIndex));
171  }
172 
173  for (size_t i = 0; i < attributeSetSize; i++) {
174  VectorWrapper indexMappingWrapper(indexMapping);
175  newAttributeArrays[i]->copyValues(*(existingAttributeArrays[i]), indexMappingWrapper);
176  }
177 
178  leaf->replaceAttributeSet(newAttributeSet);
179  leaf->setOffsets(endOffsets);
180  }
181  }
182 
183 private:
184  const FilterT& mFilter;
185  const AttributeArray::ScopedRegistryLock* mLock;
186 }; // struct DeleteByFilterOp
187 
188 } // namespace point_delete_internal
189 
190 /// @endcond
191 
192 ////////////////////////////////////////
193 
194 
195 template <typename PointDataTreeT>
196 inline void deleteFromGroups(PointDataTreeT& pointTree,
197  const std::vector<std::string>& groups,
198  bool invert,
199  bool drop)
200 {
201  const typename PointDataTreeT::LeafCIter leafIter = pointTree.cbeginLeaf();
202 
203  if (!leafIter) return;
204 
205  const openvdb::points::AttributeSet& attributeSet = leafIter->attributeSet();
206  const AttributeSet::Descriptor& descriptor = attributeSet.descriptor();
207  std::vector<std::string> availableGroups;
208 
209  // determine which of the requested groups exist, and early exit
210  // if none are present in the tree
211 
212  for (const auto& groupName : groups) {
213  if (descriptor.hasGroup(groupName)) {
214  availableGroups.push_back(groupName);
215  }
216  }
217 
218  if (availableGroups.empty()) return;
219 
220  std::vector<std::string> empty;
221  std::unique_ptr<MultiGroupFilter> filter;
222  if (invert) {
223  filter.reset(new MultiGroupFilter(groups, empty, leafIter->attributeSet()));
224  }
225  else {
226  filter.reset(new MultiGroupFilter(empty, groups, leafIter->attributeSet()));
227  }
228 
229  { // acquire registry lock to avoid locking when appending attributes in parallel
230 
232 
233  tree::LeafManager<PointDataTreeT> leafManager(pointTree);
234  point_delete_internal::DeleteByFilterOp<PointDataTreeT, MultiGroupFilter> deleteOp(
235  *filter, &lock);
236  tbb::parallel_for(leafManager.leafRange(), deleteOp);
237  }
238 
239  // remove empty leaf nodes
240 
241  tools::pruneInactive(pointTree);
242 
243  // drop the now-empty groups if requested (unless invert = true)
244 
245  if (drop && !invert) {
246  dropGroups(pointTree, availableGroups);
247  }
248 }
249 
250 template <typename PointDataTreeT>
251 inline void deleteFromGroup(PointDataTreeT& pointTree,
252  const std::string& group,
253  bool invert,
254  bool drop)
255 {
256  std::vector<std::string> groups(1, group);
257 
258  deleteFromGroups(pointTree, groups, invert, drop);
259 }
260 
261 
262 } // namespace points
263 } // namespace OPENVDB_VERSION_NAME
264 } // namespace openvdb
265 
266 #endif // OPENVDB_POINTS_POINT_DELETE_HAS_BEEN_INCLUDED
Definition: Exceptions.h:61
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Definition: Exceptions.h:60
Defined various multi-threaded utility functions for trees.
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: PointDelete.h:196
Point group manipulation in a VDB Point Grid.
Index filters primarily designed to be used with a FilterIndexIter.
Definition: Exceptions.h:13
Definition: IndexFilter.h:137
void dropGroups(PointDataTreeT &tree, const std::vector< Name > &groups)
Drops existing groups from the VDB tree, the tree is compacted after dropping.
Definition: PointGroup.h:439
Index Iterators.
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
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
Index32 Index
Definition: Types.h:54
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:314
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
void deleteFromGroup(PointDataTreeT &pointTree, const std::string &group, bool invert=false, bool drop=true)
Delete points that are members of a group.
Definition: PointDelete.h:251
A LeafManager manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional au...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202