OpenVDB  7.0.0
PointMask.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
9 
10 #ifndef OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
12 
13 #include <openvdb/openvdb.h>
14 #include <openvdb/tools/ValueTransformer.h> // valxform::SumOp
15 
16 #include "PointDataGrid.h"
17 #include "IndexFilter.h"
18 
19 #include <tbb/combinable.h>
20 
21 #include <type_traits>
22 #include <vector>
23 
24 
25 namespace openvdb {
27 namespace OPENVDB_VERSION_NAME {
28 namespace points {
29 
30 
36 template <typename PointDataGridT,
37  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type,
38  typename FilterT = NullFilter>
39 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
40  typename MaskT::Ptr>::type
41 convertPointsToMask(const PointDataGridT& grid,
42  const FilterT& filter = NullFilter(),
43  bool threaded = true);
44 
45 
52 template <typename PointDataGridT,
53  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type,
54  typename FilterT = NullFilter>
55 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
56  typename MaskT::Ptr>::type
57 convertPointsToMask(const PointDataGridT& grid,
58  const openvdb::math::Transform& transform,
59  const FilterT& filter = NullFilter(),
60  bool threaded = true);
61 
62 
65 {
66  template <typename LeafT>
67  void reset(LeafT&, size_t /*idx*/ = 0) { }
68 
69  template <typename IterT>
70  void apply(Vec3d&, IterT&) const { }
71 };
72 
75 template <typename DeformerT>
77 {
78  static const bool IndexSpace = false;
79 };
80 
81 
83 
84 
85 namespace point_mask_internal {
86 
87 template <typename LeafT>
88 void voxelSum(LeafT& leaf, const Index offset, const typename LeafT::ValueType& value)
89 {
90  leaf.modifyValue(offset, tools::valxform::SumOp<typename LeafT::ValueType>(value));
91 }
92 
93 // overload PointDataLeaf access to use setOffsetOn(), as modifyValue()
94 // is intentionally disabled to avoid accidental usage
95 
96 template <typename T, Index Log2Dim>
97 void voxelSum(PointDataLeafNode<T, Log2Dim>& leaf, const Index offset,
98  const typename PointDataLeafNode<T, Log2Dim>::ValueType& value)
99 {
100  leaf.setOffsetOn(offset, leaf.getValue(offset) + value);
101 }
102 
103 
106 template<typename GridT>
108 {
109  using CombinableT = typename tbb::combinable<GridT>;
110 
111  using TreeT = typename GridT::TreeType;
112  using LeafT = typename TreeT::LeafNodeType;
113  using ValueType = typename TreeT::ValueType;
115 
116  GridCombinerOp(GridT& grid)
117  : mTree(grid.tree()) {}
118 
119  void operator()(const GridT& grid)
120  {
121  for (auto leaf = grid.tree().beginLeaf(); leaf; ++leaf) {
122  auto* newLeaf = mTree.probeLeaf(leaf->origin());
123  if (!newLeaf) {
124  // if the leaf doesn't yet exist in the new tree, steal it
125  auto& tree = const_cast<GridT&>(grid).tree();
126  mTree.addLeaf(tree.template stealNode<LeafT>(leaf->origin(),
127  zeroVal<ValueType>(), false));
128  }
129  else {
130  // otherwise increment existing values
131  for (auto iter = leaf->cbeginValueOn(); iter; ++iter) {
132  voxelSum(*newLeaf, iter.offset(), ValueType(*iter));
133  }
134  }
135  }
136  }
137 
138 private:
139  TreeT& mTree;
140 }; // struct GridCombinerOp
141 
142 
144 template <typename GridT, typename PointDataGridT, typename FilterT>
146 {
147  using LeafT = typename GridT::TreeType::LeafNodeType;
148  using ValueT = typename LeafT::ValueType;
149 
150  PointsToScalarOp( const PointDataGridT& grid,
151  const FilterT& filter)
152  : mPointDataAccessor(grid.getConstAccessor())
153  , mFilter(filter) { }
154 
155  void operator()(LeafT& leaf, size_t /*idx*/) const {
156 
157  const auto* const pointLeaf =
158  mPointDataAccessor.probeConstLeaf(leaf.origin());
159 
160  // assumes matching topology
161  assert(pointLeaf);
162 
163  for (auto value = leaf.beginValueOn(); value; ++value) {
164  const Index64 count = points::iterCount(
165  pointLeaf->beginIndexVoxel(value.getCoord(), mFilter));
166  if (count > Index64(0)) {
167  value.setValue(ValueT(count));
168  } else {
169  // disable any empty voxels
170  value.setValueOn(false);
171  }
172  }
173  }
174 
175 private:
176  const typename PointDataGridT::ConstAccessor mPointDataAccessor;
177  const FilterT& mFilter;
178 }; // struct PointsToScalarOp
179 
180 
183 template <typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
185 {
186  using PointDataLeafT = typename PointDataGridT::TreeType::LeafNodeType;
187  using ValueT = typename GridT::TreeType::ValueType;
190 
192  const math::Transform& sourceTransform,
193  const FilterT& filter,
194  const DeformerT& deformer,
195  CombinableT& combinable)
196  : mTargetTransform(targetTransform)
197  , mSourceTransform(sourceTransform)
198  , mFilter(filter)
199  , mDeformer(deformer)
200  , mCombinable(combinable) { }
201 
202  void operator()(const PointDataLeafT& leaf, size_t idx) const
203  {
204  DeformerT deformer(mDeformer);
205 
206  auto& grid = mCombinable.local();
207  auto& countTree = grid.tree();
209 
210  deformer.reset(leaf, idx);
211 
212  auto handle = HandleT::create(leaf.constAttributeArray("P"));
213 
214  for (auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
215 
216  // extract index-space position
217 
218  Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
219 
220  // if deformer is designed to be used in index-space, perform deformation prior
221  // to transforming position to world-space, otherwise perform deformation afterwards
222 
224  deformer.template apply<decltype(iter)>(position, iter);
225  position = mSourceTransform.indexToWorld(position);
226  }
227  else {
228  position = mSourceTransform.indexToWorld(position);
229  deformer.template apply<decltype(iter)>(position, iter);
230  }
231 
232  // determine coord of target grid
233 
234  const Coord ijk = mTargetTransform.worldToIndexCellCentered(position);
235 
236  // increment count in target voxel
237 
238  auto* newLeaf = accessor.touchLeaf(ijk);
239  assert(newLeaf);
240  voxelSum(*newLeaf, newLeaf->coordToOffset(ijk), ValueT(1));
241  }
242  }
243 
244 private:
245  const openvdb::math::Transform& mTargetTransform;
246  const openvdb::math::Transform& mSourceTransform;
247  const FilterT& mFilter;
248  const DeformerT& mDeformer;
249  CombinableT& mCombinable;
250 }; // struct PointsToTransformedScalarOp
251 
252 
253 template<typename GridT, typename PointDataGridT, typename FilterT>
254 inline typename GridT::Ptr convertPointsToScalar(
255  const PointDataGridT& points,
256  const FilterT& filter,
257  bool threaded = true)
258 {
260 
261  using GridTreeT = typename GridT::TreeType;
262  using ValueT = typename GridTreeT::ValueType;
263 
264  // copy the topology from the points grid
265 
266  typename GridTreeT::Ptr tree(new GridTreeT(points.constTree(),
267  false, openvdb::TopologyCopy()));
268  typename GridT::Ptr grid = GridT::create(tree);
269  grid->setTransform(points.transform().copy());
270 
271  // early exit if no leaves
272 
273  if (points.constTree().leafCount() == 0) return grid;
274 
275  // early exit if mask and no group logic
276 
277  if (std::is_same<ValueT, bool>::value && filter.state() == index::ALL) return grid;
278 
279  // evaluate point group filters to produce a subset of the generated mask
280 
281  tree::LeafManager<GridTreeT> leafManager(*tree);
282 
283  if (filter.state() == index::ALL) {
284  NullFilter nullFilter;
286  points, nullFilter);
287  leafManager.foreach(pointsToScalarOp, threaded);
288  } else {
289  // build mask from points in parallel only where filter evaluates to true
291  points, filter);
292  leafManager.foreach(pointsToScalarOp, threaded);
293  }
294 
295  return grid;
296 }
297 
298 
299 template<typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
300 inline typename GridT::Ptr convertPointsToScalar(
301  PointDataGridT& points,
302  const openvdb::math::Transform& transform,
303  const FilterT& filter,
304  const DeformerT& deformer,
305  bool threaded = true)
306 {
309 
310  using CombinerOpT = GridCombinerOp<GridT>;
311  using CombinableT = typename GridCombinerOp<GridT>::CombinableT;
312 
313  // use the simpler method if the requested transform matches the existing one
314 
315  const openvdb::math::Transform& pointsTransform = points.constTransform();
316 
317  if (transform == pointsTransform && std::is_same<NullDeformer, DeformerT>()) {
318  return convertPointsToScalar<GridT>(points, filter, threaded);
319  }
320 
321  typename GridT::Ptr grid = GridT::create();
322  grid->setTransform(transform.copy());
323 
324  // early exit if no leaves
325 
326  if (points.constTree().leafCount() == 0) return grid;
327 
328  // compute mask grids in parallel using new transform
329 
330  CombinableT combiner;
331 
332  tree::LeafManager<typename PointDataGridT::TreeType> leafManager(points.tree());
333 
334  if (filter.state() == index::ALL) {
335  NullFilter nullFilter;
337  transform, pointsTransform, nullFilter, deformer, combiner);
338  leafManager.foreach(pointsToScalarOp, threaded);
339  } else {
341  transform, pointsTransform, filter, deformer, combiner);
342  leafManager.foreach(pointsToScalarOp, threaded);
343  }
344 
345  // combine the mask grids into one
346 
347  CombinerOpT combineOp(*grid);
348  combiner.combine_each(combineOp);
349 
350  return grid;
351 }
352 
353 
354 } // namespace point_mask_internal
355 
356 
358 
359 
360 template<typename PointDataGridT, typename MaskT, typename FilterT>
361 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
362  typename MaskT::Ptr>::type
364  const PointDataGridT& points,
365  const FilterT& filter,
366  bool threaded)
367 {
368  return point_mask_internal::convertPointsToScalar<MaskT>(
369  points, filter, threaded);
370 }
371 
372 
373 template<typename PointDataGridT, typename MaskT, typename FilterT>
374 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
375  typename MaskT::Ptr>::type
377  const PointDataGridT& points,
378  const openvdb::math::Transform& transform,
379  const FilterT& filter,
380  bool threaded)
381 {
382  // This is safe because the PointDataGrid can only be modified by the deformer
384  auto& nonConstPoints = const_cast<typename AdapterT::NonConstGridType&>(points);
385 
386  NullDeformer deformer;
387  return point_mask_internal::convertPointsToScalar<MaskT>(
388  nonConstPoints, transform, filter, deformer, threaded);
389 }
390 
391 
393 
394 
395 // deprecated functions
396 
397 
398 template <typename PointDataGridT,
399  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type>
401 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
402  typename MaskT::Ptr>::type
403 convertPointsToMask(const PointDataGridT& grid,
404  const std::vector<Name>& includeGroups,
405  const std::vector<Name>& excludeGroups)
406 {
407  auto leaf = grid.tree().cbeginLeaf();
408  if (!leaf) return MaskT::create();
409  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
410  return convertPointsToMask(grid, filter);
411 }
412 
413 
414 template <typename PointDataGridT,
415  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type>
417 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
418  typename MaskT::Ptr>::type
419 convertPointsToMask(const PointDataGridT& grid,
420  const openvdb::math::Transform& transform,
421  const std::vector<Name>& includeGroups,
422  const std::vector<Name>& excludeGroups)
423 {
424  auto leaf = grid.tree().cbeginLeaf();
425  if (!leaf) return MaskT::create();
426  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
427  return convertPointsToMask(grid, transform, filter);
428 }
429 
430 
431 } // namespace points
432 } // namespace OPENVDB_VERSION_NAME
433 } // namespace openvdb
434 
435 #endif // OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
PointsToScalarOp(const PointDataGridT &grid, const FilterT &filter)
Definition: PointMask.h:150
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:50
typename TreeT::LeafNodeType LeafT
Definition: PointMask.h:112
OPENVDB_DEPRECATED std::enable_if< std::is_same< typename MaskT::ValueType, bool >::value, typename MaskT::Ptr >::type convertPointsToMask(const PointDataGridT &grid, const openvdb::math::Transform &transform, const std::vector< Name > &includeGroups, const std::vector< Name > &excludeGroups)
Definition: PointMask.h:419
typename GridT::TreeType TreeT
Definition: PointMask.h:111
#define OPENVDB_DEPRECATED
Definition: Platform.h:42
Definition: ValueAccessor.h:193
Vec3< double > Vec3d
Definition: Vec3.h:662
typename LeafT::ValueType ValueT
Definition: PointMask.h:148
void apply(Vec3d &, IterT &) const
Definition: PointMask.h:70
typename PointDataGridT::TreeType::LeafNodeType PointDataLeafT
Definition: PointMask.h:186
Deformer Traits for optionally configuring deformers to be applied in index-space. The default is world-space.
Definition: PointMask.h:76
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1061
Definition: ValueTransformer.h:250
void operator()(LeafT &leaf, size_t) const
Definition: PointMask.h:155
typename TreeT::ValueType ValueType
Definition: PointMask.h:113
Definition: IndexIterator.h:43
void reset(LeafT &, size_t=0)
Definition: PointMask.h:67
No-op deformer (adheres to the deformer interface documented in PointMove.h)
Definition: PointMask.h:64
Index filters primarily designed to be used with a FilterIndexIter.
Definition: PointDataGrid.h:185
PointsToTransformedScalarOp(const math::Transform &targetTransform, const math::Transform &sourceTransform, const FilterT &filter, const DeformerT &deformer, CombinableT &combinable)
Definition: PointMask.h:191
typename GridT::TreeType::ValueType ValueT
Definition: PointMask.h:187
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
typename GridT::TreeType::LeafNodeType LeafT
Definition: PointMask.h:147
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1065
Definition: IndexFilter.h:135
T ValueType
Definition: PointDataGrid.h:243
Definition: Exceptions.h:13
void operator()(const GridT &grid)
Definition: PointMask.h:119
void setOffsetOn(Index offset, const ValueType &val)
Definition: PointDataGrid.h:1114
typename tbb::combinable< GridT > CombinableT
Definition: PointMask.h:109
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:82
void voxelSum(PointDataLeafNode< T, Log2Dim > &leaf, const Index offset, const typename PointDataLeafNode< T, Log2Dim >::ValueType &value)
Definition: PointMask.h:97
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:314
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:681
GridCombinerOp(GridT &grid)
Definition: PointMask.h:116
Definition: Transform.h:39
void operator()(const PointDataLeafT &leaf, size_t idx) const
Definition: PointMask.h:202
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:496
Index32 Index
Definition: Types.h:31
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:359
Definition: AttributeArray.h:849
typename GridCombinerOp< GridT >::CombinableT CombinableT
Definition: PointMask.h:189
GridT::Ptr convertPointsToScalar(PointDataGridT &points, const openvdb::math::Transform &transform, const FilterT &filter, const DeformerT &deformer, bool threaded=true)
Definition: PointMask.h:300
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Combines multiple grids into one by stealing leaf nodes and summing voxel values This class is design...
Definition: PointMask.h:107
uint64_t Index64
Definition: Types.h:30
Compute scalar grid from PointDataGrid using a different transform and while evaluating the point fil...
Definition: PointMask.h:184
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
Compute scalar grid from PointDataGrid while evaluating the point filter.
Definition: PointMask.h:145