OpenVDB: openvdb/points/PointDelete.h Source File

OpenVDB 9.1.0

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>
19#include <openvdb/tree/LeafManager.h>
20
21#include <memory>
22#include <string>
23#include <vector>
24
25
26namespace openvdb {
27 OPENVDB_USE_VERSION_NAMESPACE
28namespace OPENVDB_VERSION_NAME {
29namespace 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
46template <typename PointDataTreeT>
47inline 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
66template <typename PointDataTreeT>
67inline 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
77namespace point_delete_internal {
78
79
80struct 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
90private:
91 const T& data;
92 T::size_type index = 0;
93}; // struct VectorWrapper
94
95
96template <typename PointDataTreeT, typename FilterT>
97struct 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()) {
142 OPENVDB_THROW(openvdb::NotImplementedError,
143 "Transfer of attribute values for dynamic arrays not currently supported.");
144 }
145
146 if (newArray->stride() != existingArray->stride()) {
147 OPENVDB_THROW(openvdb::LookupError,
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
183private:
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
195template <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
231 AttributeArray::ScopedRegistryLock lock;
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
250template <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
IndexFilter.h
Index filters primarily designed to be used with a FilterIndexIter.
IndexIterator.h
Index Iterators.
LeafManager.h
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
PointGroup.h
Point group manipulation in a VDB Point Grid.
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v9_1::LookupError
Definition: Exceptions.h:60
openvdb::v9_1::NotImplementedError
Definition: Exceptions.h:61
openvdb::v9_1::points::AttributeArray::ScopedRegistryLock
Definition: AttributeArray.h:119
openvdb::v9_1::points::MultiGroupFilter
Definition: IndexFilter.h:138
openvdb::v9_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:85
openvdb::v9_1::tree::LeafManager::leafRange
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
nanovdb::GridBlindDataClass::AttributeArray
@ AttributeArray
openvdb::v9_1::points::dropGroups
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
openvdb::v9_1::points::deleteFromGroups
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
openvdb::v9_1::points::iterCount
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:314
openvdb::v9_1::points::deleteFromGroup
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
openvdb::v9_1::tools::pruneInactive
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
openvdb::v9_1::Index
Index32 Index
Definition: Types.h:54
openvdb
Definition: Exceptions.h:13
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202