OpenVDB  6.2.0
PointDelete.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 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_DELETE_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_DELETE_HAS_BEEN_INCLUDED
39 
40 #include "PointDataGrid.h"
41 #include "PointGroup.h"
42 #include "IndexIterator.h"
43 #include "IndexFilter.h"
44 
45 #include <openvdb/tools/Prune.h>
47 
48 #include <memory>
49 #include <string>
50 #include <vector>
51 
52 
53 namespace openvdb {
55 namespace OPENVDB_VERSION_NAME {
56 namespace points {
57 
58 
72 
73 template <typename PointDataTreeT>
74 inline void deleteFromGroups(PointDataTreeT& pointTree,
75  const std::vector<std::string>& groups,
76  bool invert = false,
77  bool drop = true);
78 
92 
93 template <typename PointDataTreeT>
94 inline void deleteFromGroup(PointDataTreeT& pointTree,
95  const std::string& group,
96  bool invert = false,
97  bool drop = true);
98 
99 
101 
102 
103 namespace point_delete_internal {
104 
105 
107 {
108  using T = std::vector<std::pair<Index, Index>>;
109 
110  VectorWrapper(const T& _data) : data(_data) { }
111  operator bool() const { return index < data.size(); }
112  VectorWrapper& operator++() { index++; return *this; }
113  Index sourceIndex() const { assert(*this); return data[index].first; }
114  Index targetIndex() const { assert(*this); return data[index].second; }
115 
116 private:
117  const T& data;
118  T::size_type index = 0;
119 }; // struct VectorWrapper
120 
121 
122 template <typename PointDataTreeT, typename FilterT>
124 {
127  using LeafNodeT = typename PointDataTreeT::LeafNodeType;
128  using ValueType = typename LeafNodeT::ValueType;
129 
130  DeleteByFilterOp(const FilterT& filter,
132  : mFilter(filter)
133  , mLock(lock) { }
134 
135  void operator()(const LeafRangeT& range) const
136  {
137  for (auto leaf = range.begin(); leaf != range.end(); ++leaf) {
138 
139  const size_t newSize =
140  iterCount(leaf->template beginIndexAll<FilterT>(mFilter));
141 
142  // if all points are being deleted, clear the leaf attributes
143  if (newSize == 0) {
144  leaf->clearAttributes(/*updateValueMask=*/true, mLock);
145  continue;
146  }
147 
148  // early exit if no points are being deleted
149 
150  const size_t currentSize = leaf->getLastValue();
151  if (newSize == currentSize) continue;
152 
153  const AttributeSet& existingAttributeSet = leaf->attributeSet();
154  AttributeSet* newAttributeSet = new AttributeSet(
155  existingAttributeSet, static_cast<Index>(newSize), mLock);
156  const size_t attributeSetSize = existingAttributeSet.size();
157 
158  // cache the attribute arrays for efficiency
159 
160  std::vector<AttributeArray*> newAttributeArrays;
161  std::vector<const AttributeArray*> existingAttributeArrays;
162 
163  for (size_t i = 0; i < attributeSetSize; i++) {
164  AttributeArray* newArray = newAttributeSet->get(i);
165  const AttributeArray* existingArray = existingAttributeSet.getConst(i);
166 
167  if (!newArray->hasConstantStride() || !existingArray->hasConstantStride()) {
169  "Transfer of attribute values for dynamic arrays not currently supported.");
170  }
171 
172  if (newArray->stride() != existingArray->stride()) {
174  "Cannot transfer attribute values with mis-matching strides.");
175  }
176 
177  newAttributeArrays.push_back(newArray);
178  existingAttributeArrays.push_back(existingArray);
179  }
180 
181  Index attributeIndex = 0;
182  std::vector<ValueType> endOffsets;
183 
184  endOffsets.reserve(LeafNodeT::NUM_VALUES);
185 
186  // now construct new attribute arrays which exclude data from deleted points
187 
188 #if OPENVDB_ABI_VERSION_NUMBER >= 6
189  std::vector<std::pair<Index, Index>> indexMapping;
190  indexMapping.reserve(newSize);
191 
192  for (auto voxel = leaf->cbeginValueAll(); voxel; ++voxel) {
193  for (auto iter = leaf->beginIndexVoxel(voxel.getCoord(), mFilter);
194  iter; ++iter) {
195  indexMapping.emplace_back(*iter, attributeIndex++);
196  }
197  endOffsets.push_back(static_cast<ValueType>(attributeIndex));
198  }
199 
200  for (size_t i = 0; i < attributeSetSize; i++) {
201  VectorWrapper indexMappingWrapper(indexMapping);
202  newAttributeArrays[i]->copyValues(*(existingAttributeArrays[i]), indexMappingWrapper);
203  }
204 #else
205  for (auto voxel = leaf->cbeginValueAll(); voxel; ++voxel) {
206  for (auto iter = leaf->beginIndexVoxel(voxel.getCoord(), mFilter);
207  iter; ++iter) {
208  for (size_t i = 0; i < attributeSetSize; i++) {
209  newAttributeArrays[i]->set(attributeIndex, *(existingAttributeArrays[i]),
210  *iter);
211  }
212  ++attributeIndex;
213  }
214  endOffsets.push_back(static_cast<ValueType>(attributeIndex));
215  }
216 #endif
217 
218  leaf->replaceAttributeSet(newAttributeSet);
219  leaf->setOffsets(endOffsets);
220  }
221  }
222 
223 private:
224  const FilterT& mFilter;
226 }; // struct DeleteByFilterOp
227 
228 } // namespace point_delete_internal
229 
230 
232 
233 
234 template <typename PointDataTreeT>
235 inline void deleteFromGroups(PointDataTreeT& pointTree,
236  const std::vector<std::string>& groups,
237  bool invert,
238  bool drop)
239 {
240  const typename PointDataTreeT::LeafCIter leafIter = pointTree.cbeginLeaf();
241 
242  if (!leafIter) return;
243 
244  const openvdb::points::AttributeSet& attributeSet = leafIter->attributeSet();
245  const AttributeSet::Descriptor& descriptor = attributeSet.descriptor();
246  std::vector<std::string> availableGroups;
247 
248  // determine which of the requested groups exist, and early exit
249  // if none are present in the tree
250 
251  for (const auto& groupName : groups) {
252  if (descriptor.hasGroup(groupName)) {
253  availableGroups.push_back(groupName);
254  }
255  }
256 
257  if (availableGroups.empty()) return;
258 
259  std::vector<std::string> empty;
260  std::unique_ptr<MultiGroupFilter> filter;
261  if (invert) {
262  filter.reset(new MultiGroupFilter(groups, empty, leafIter->attributeSet()));
263  }
264  else {
265  filter.reset(new MultiGroupFilter(empty, groups, leafIter->attributeSet()));
266  }
267 
268  { // acquire registry lock to avoid locking when appending attributes in parallel
269 
271 
272  tree::LeafManager<PointDataTreeT> leafManager(pointTree);
274  *filter, &lock);
275  tbb::parallel_for(leafManager.leafRange(), deleteOp);
276  }
277 
278  // remove empty leaf nodes
279 
280  tools::pruneInactive(pointTree);
281 
282  // drop the now-empty groups if requested (unless invert = true)
283 
284  if (drop && !invert) {
285  dropGroups(pointTree, availableGroups);
286  }
287 }
288 
289 template <typename PointDataTreeT>
290 inline void deleteFromGroup(PointDataTreeT& pointTree,
291  const std::string& group,
292  bool invert,
293  bool drop)
294 {
295  std::vector<std::string> groups(1, group);
296 
297  deleteFromGroups(pointTree, groups, invert, drop);
298 }
299 
300 
301 } // namespace points
302 } // namespace OPENVDB_VERSION_NAME
303 } // namespace openvdb
304 
305 #endif // OPENVDB_POINTS_POINT_DELETE_HAS_BEEN_INCLUDED
306 
307 // Copyright (c) DreamWorks Animation LLC
308 // All rights reserved. This software is distributed under the
309 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
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:235
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:290
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...
Definition: IndexFilter.h:164
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
Index targetIndex() const
Definition: PointDelete.h:114
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:385
Index32 Index
Definition: Types.h:61
size_t size() const
Return the number of attributes in this set.
Definition: AttributeSet.h:134
typename LeafNodeT::ValueType ValueType
Definition: PointDelete.h:128
typename PointDataTreeT::LeafNodeType LeafNodeT
Definition: PointDelete.h:127
Defined various multi-threaded utility functions for trees.
Point group manipulation in a VDB Point Grid.
Index filters primarily designed to be used with a FilterIndexIter.
void dropGroups(PointDataTree &tree, const std::vector< Name > &groups)
Drops existing groups from the VDB tree, the tree is compacted after dropping.
Definition: PointGroup.h:579
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:128
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointDelete.h:126
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:381
virtual Index stride() const =0
Definition: Exceptions.h:40
Definition: Exceptions.h:87
void operator()(const LeafRangeT &range) const
Definition: PointDelete.h:135
Index Iterators.
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 sourceIndex() const
Definition: PointDelete.h:113
VectorWrapper(const T &_data)
Definition: PointDelete.h:110
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
std::vector< std::pair< Index, Index >> T
Definition: PointDelete.h:108
Definition: Exceptions.h:88
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:180
A LeafManager manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional au...
Definition: LeafManager.h:126
const AttributeArray * get(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...
DeleteByFilterOp(const FilterT &filter, const AttributeArray::ScopedRegistryLock *lock)
Definition: PointDelete.h:130
Base class for storing attribute data.
Definition: AttributeArray.h:118
bool hasConstantStride() const
Return true if this attribute has a constant stride.
Definition: AttributeArray.h:369
VectorWrapper & operator++()
Definition: PointDelete.h:112
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:341