HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GridOperators.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /// @file tools/GridOperators.h
5 ///
6 /// @brief Apply an operator to an input grid to produce an output grid
7 /// with the same active voxel topology but a potentially different value type.
8 
9 #ifndef OPENVDB_TOOLS_GRID_OPERATORS_HAS_BEEN_INCLUDED
10 #define OPENVDB_TOOLS_GRID_OPERATORS_HAS_BEEN_INCLUDED
11 
12 #include "openvdb/Grid.h"
13 #include "openvdb/math/Operators.h"
18 #include "ValueTransformer.h" // for tools::foreach()
19 
20 #include <tbb/parallel_for.h>
21 
22 namespace openvdb {
24 namespace OPENVDB_VERSION_NAME {
25 namespace tools {
26 
27 /// @brief VectorToScalarConverter<VectorGridType>::Type is the type of a grid
28 /// having the same tree configuration as VectorGridType but a scalar value type, T,
29 /// where T is the type of the original vector components.
30 /// @details For example, VectorToScalarConverter<Vec3DGrid>::Type is equivalent to DoubleGrid.
31 template<typename VectorGridType> struct VectorToScalarConverter {
33  typedef typename VectorGridType::template ValueConverter<VecComponentValueT>::Type Type;
34 };
35 
36 /// @brief ScalarToVectorConverter<ScalarGridType>::Type is the type of a grid
37 /// having the same tree configuration as ScalarGridType but value type Vec3<T>
38 /// where T is ScalarGridType::ValueType.
39 /// @details For example, ScalarToVectorConverter<DoubleGrid>::Type is equivalent to Vec3DGrid.
40 template<typename ScalarGridType> struct ScalarToVectorConverter {
42  typedef typename ScalarGridType::template ValueConverter<VectorValueT>::Type Type;
43 };
44 
45 
46 /// @brief Compute the Closest-Point Transform (CPT) from a distance field.
47 /// @return a new vector-valued grid with the same numerical precision as the input grid
48 /// (for example, if the input grid is a DoubleGrid, the output grid will be a Vec3DGrid)
49 /// @details When a mask grid is specified, the solution is calculated only in
50 /// the intersection of the mask active topology and the input active topology
51 /// independent of the transforms associated with either grid.
52 template<typename GridType, typename InterruptT> inline
54 cpt(const GridType& grid, bool threaded, InterruptT* interrupt);
55 
56 template<typename GridType, typename MaskT, typename InterruptT> inline
58 cpt(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
59 
60 template<typename GridType> inline
62 cpt(const GridType& grid, bool threaded = true)
63 {
64  return cpt<GridType, util::NullInterrupter>(grid, threaded, nullptr);
65 }
66 
67 template<typename GridType, typename MaskT> inline
68 typename ScalarToVectorConverter<GridType>::Type::Ptr
69 cpt(const GridType& grid, const MaskT& mask, bool threaded = true)
70 {
71  return cpt<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
72 }
73 
74 
75 /// @brief Compute the curl of the given vector-valued grid.
76 /// @return a new vector-valued grid
77 /// @details When a mask grid is specified, the solution is calculated only in
78 /// the intersection of the mask active topology and the input active topology
79 /// independent of the transforms associated with either grid.
80 template<typename GridType, typename InterruptT> inline
81 typename GridType::Ptr
82 curl(const GridType& grid, bool threaded, InterruptT* interrupt);
83 
84 template<typename GridType, typename MaskT, typename InterruptT> inline
85 typename GridType::Ptr
86 curl(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
87 
88 template<typename GridType> inline
89 typename GridType::Ptr
90 curl(const GridType& grid, bool threaded = true)
91 {
92  return curl<GridType, util::NullInterrupter>(grid, threaded, nullptr);
93 }
94 
95 template<typename GridType, typename MaskT> inline
96 typename GridType::Ptr
97 curl(const GridType& grid, const MaskT& mask, bool threaded = true)
98 {
99  return curl<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
100 }
101 
102 
103 /// @brief Compute the divergence of the given vector-valued grid.
104 /// @return a new scalar-valued grid with the same numerical precision as the input grid
105 /// (for example, if the input grid is a Vec3DGrid, the output grid will be a DoubleGrid)
106 /// @details When a mask grid is specified, the solution is calculated only in
107 /// the intersection of the mask active topology and the input active topology
108 /// independent of the transforms associated with either grid.
109 template<typename GridType, typename InterruptT> inline
110 typename VectorToScalarConverter<GridType>::Type::Ptr
111 divergence(const GridType& grid, bool threaded, InterruptT* interrupt);
112 
113 template<typename GridType, typename MaskT, typename InterruptT> inline
114 typename VectorToScalarConverter<GridType>::Type::Ptr
115 divergence(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
116 
117 template<typename GridType> inline
118 typename VectorToScalarConverter<GridType>::Type::Ptr
119 divergence(const GridType& grid, bool threaded = true)
120 {
121  return divergence<GridType, util::NullInterrupter>(grid, threaded, nullptr);
122 }
123 
124 template<typename GridType, typename MaskT> inline
125 typename VectorToScalarConverter<GridType>::Type::Ptr
126 divergence(const GridType& grid, const MaskT& mask, bool threaded = true)
127 {
128  return divergence<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
129 }
130 
131 
132 /// @brief Compute the gradient of the given scalar grid.
133 /// @return a new vector-valued grid with the same numerical precision as the input grid
134 /// (for example, if the input grid is a DoubleGrid, the output grid will be a Vec3DGrid)
135 /// @details When a mask grid is specified, the solution is calculated only in
136 /// the intersection of the mask active topology and the input active topology
137 /// independent of the transforms associated with either grid.
138 template<typename GridType, typename InterruptT> inline
139 typename ScalarToVectorConverter<GridType>::Type::Ptr
140 gradient(const GridType& grid, bool threaded, InterruptT* interrupt);
141 
142 template<typename GridType, typename MaskT, typename InterruptT> inline
143 typename ScalarToVectorConverter<GridType>::Type::Ptr
144 gradient(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
145 
146 template<typename GridType> inline
147 typename ScalarToVectorConverter<GridType>::Type::Ptr
148 gradient(const GridType& grid, bool threaded = true)
149 {
150  return gradient<GridType, util::NullInterrupter>(grid, threaded, nullptr);
151 }
152 
153 template<typename GridType, typename MaskT> inline
154 typename ScalarToVectorConverter<GridType>::Type::Ptr
155 gradient(const GridType& grid, const MaskT& mask, bool threaded = true)
156 {
157  return gradient<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
158 }
159 
160 
161 /// @brief Compute the Laplacian of the given scalar grid.
162 /// @return a new scalar grid
163 /// @details When a mask grid is specified, the solution is calculated only in
164 /// the intersection of the mask active topology and the input active topology
165 /// independent of the transforms associated with either grid.
166 template<typename GridType, typename InterruptT> inline
167 typename GridType::Ptr
168 laplacian(const GridType& grid, bool threaded, InterruptT* interrupt);
169 
170 template<typename GridType, typename MaskT, typename InterruptT> inline
171 typename GridType::Ptr
172 laplacian(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
173 
174 template<typename GridType> inline
175 typename GridType::Ptr
176 laplacian(const GridType& grid, bool threaded = true)
177 {
178  return laplacian<GridType, util::NullInterrupter>(grid, threaded, nullptr);
179 }
180 
181 template<typename GridType, typename MaskT> inline
182 typename GridType::Ptr
183 laplacian(const GridType& grid, const MaskT mask, bool threaded = true)
184 {
185  return laplacian<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
186 }
187 
188 
189 /// @brief Compute the mean curvature of the given grid.
190 /// @return a new grid
191 /// @details When a mask grid is specified, the solution is calculated only in
192 /// the intersection of the mask active topology and the input active topology
193 /// independent of the transforms associated with either grid.
194 template<typename GridType, typename InterruptT> inline
195 typename GridType::Ptr
196 meanCurvature(const GridType& grid, bool threaded, InterruptT* interrupt);
197 
198 template<typename GridType, typename MaskT, typename InterruptT> inline
199 typename GridType::Ptr
200 meanCurvature(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
201 
202 template<typename GridType> inline
203 typename GridType::Ptr
204 meanCurvature(const GridType& grid, bool threaded = true)
205 {
206  return meanCurvature<GridType, util::NullInterrupter>(grid, threaded, nullptr);
207 }
208 
209 template<typename GridType, typename MaskT> inline
210 typename GridType::Ptr
211 meanCurvature(const GridType& grid, const MaskT& mask, bool threaded = true)
212 {
213  return meanCurvature<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
214 }
215 
216 
217 /// @brief Compute the magnitudes of the vectors of the given vector-valued grid.
218 /// @return a new scalar-valued grid with the same numerical precision as the input grid
219 /// (for example, if the input grid is a Vec3DGrid, the output grid will be a DoubleGrid)
220 /// @details When a mask grid is specified, the solution is calculated only in
221 /// the intersection of the mask active topology and the input active topology
222 /// independent of the transforms associated with either grid.
223 template<typename GridType, typename InterruptT> inline
224 typename VectorToScalarConverter<GridType>::Type::Ptr
225 magnitude(const GridType& grid, bool threaded, InterruptT* interrupt);
226 
227 template<typename GridType, typename MaskT, typename InterruptT> inline
228 typename VectorToScalarConverter<GridType>::Type::Ptr
229 magnitude(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
230 
231 template<typename GridType> inline
232 typename VectorToScalarConverter<GridType>::Type::Ptr
233 magnitude(const GridType& grid, bool threaded = true)
234 {
235  return magnitude<GridType, util::NullInterrupter>(grid, threaded, nullptr);
236 }
237 
238 template<typename GridType, typename MaskT> inline
239 typename VectorToScalarConverter<GridType>::Type::Ptr
240 magnitude(const GridType& grid, const MaskT& mask, bool threaded = true)
241 {
242  return magnitude<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
243 }
244 
245 
246 /// @brief Normalize the vectors of the given vector-valued grid.
247 /// @return a new vector-valued grid
248 /// @details When a mask grid is specified, the solution is calculated only in
249 /// the intersection of the mask active topology and the input active topology
250 /// independent of the transforms associated with either grid.
251 template<typename GridType, typename InterruptT> inline
252 typename GridType::Ptr
253 normalize(const GridType& grid, bool threaded, InterruptT* interrupt);
254 
255 template<typename GridType, typename MaskT, typename InterruptT> inline
256 typename GridType::Ptr
257 normalize(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
258 
259 template<typename GridType> inline
260 typename GridType::Ptr
261 normalize(const GridType& grid, bool threaded = true)
262 {
263  return normalize<GridType, util::NullInterrupter>(grid, threaded, nullptr);
264 }
265 
266 template<typename GridType, typename MaskT> inline
267 typename GridType::Ptr
268 normalize(const GridType& grid, const MaskT& mask, bool threaded = true)
269 {
270  return normalize<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
271 }
272 
273 
274 ////////////////////////////////////////
275 
276 
277 namespace gridop {
278 
279 /// @brief ToMaskGrid<T>::Type is the type of a grid having the same
280 /// tree hierarchy as grid type T but a value equal to its active state.
281 /// @details For example, ToMaskGrid<FloatGrid>::Type is equivalent to MaskGrid.
282 template<typename GridType>
283 struct ToMaskGrid {
285 };
286 
287 
288 /// @brief Apply an operator to an input grid to produce an output grid
289 /// with the same active voxel topology but a potentially different value type.
290 /// @details To facilitate inlining, this class is also templated on a Map type.
291 ///
292 /// @note This is a helper class and should never be used directly.
293 template<
294  typename InGridT,
295  typename MaskGridType,
296  typename OutGridT,
297  typename MapT,
298  typename OperatorT,
299  typename InterruptT = util::NullInterrupter>
301 {
302 public:
303  typedef typename OutGridT::TreeType OutTreeT;
304  typedef typename OutTreeT::LeafNodeType OutLeafT;
306 
307  GridOperator(const InGridT& grid, const MaskGridType* mask, const MapT& map,
308  InterruptT* interrupt = nullptr, bool densify = true)
309  : mAcc(grid.getConstAccessor())
310  , mMap(map)
311  , mInterrupt(interrupt)
312  , mMask(mask)
313  , mDensify(densify) ///< @todo consider adding a "NeedsDensification" operator trait
314  {
315  }
316  GridOperator(const GridOperator&) = default;
317  GridOperator& operator=(const GridOperator&) = default;
318  virtual ~GridOperator() = default;
319 
320  typename OutGridT::Ptr process(bool threaded = true)
321  {
322  if (mInterrupt) mInterrupt->start("Processing grid");
323 
324  // Derive background value of the output grid
325  typename InGridT::TreeType tmp(mAcc.tree().background());
326  typename OutGridT::ValueType backg = OperatorT::result(mMap, tmp, math::Coord(0));
327 
328  // The output tree is topology copy, optionally densified, of the input tree.
329  // (Densification is necessary for some operators because applying the operator to
330  // a constant tile produces distinct output values, particularly along tile borders.)
331  /// @todo Can tiles be handled correctly without densification, or by densifying
332  /// only to the width of the operator stencil?
333  typename OutTreeT::Ptr tree(new OutTreeT(mAcc.tree(), backg, TopologyCopy()));
334  if (mDensify) tree->voxelizeActiveTiles();
335 
336  // create grid with output tree and unit transform
337  typename OutGridT::Ptr result(new OutGridT(tree));
338 
339  // Modify the solution area if a mask was supplied.
340  if (mMask) {
341  result->topologyIntersection(*mMask);
342  }
343 
344  // transform of output grid = transform of input grid
345  result->setTransform(math::Transform::Ptr(new math::Transform( mMap.copy() )));
346 
347  LeafManagerT leafManager(*tree);
348 
349  if (threaded) {
350  tbb::parallel_for(leafManager.leafRange(), *this);
351  } else {
352  (*this)(leafManager.leafRange());
353  }
354 
355  // If the tree wasn't densified, it might have active tiles that need to be processed.
356  if (!mDensify) {
357  using TileIter = typename OutTreeT::ValueOnIter;
358 
359  TileIter tileIter = tree->beginValueOn();
360  tileIter.setMaxDepth(tileIter.getLeafDepth() - 1); // skip leaf values (i.e., voxels)
361 
362  AccessorT inAcc = mAcc; // each thread needs its own accessor, captured by value
363  auto tileOp = [this, inAcc](const TileIter& it) {
364  // Apply the operator to the input grid's tile value at the iterator's
365  // current coordinates, and set the output tile's value to the result.
366  it.setValue(OperatorT::result(this->mMap, inAcc, it.getCoord()));
367  };
368 
369  // Apply the operator to tile values, optionally in parallel.
370  // (But don't share the functor; each thread needs its own accessor.)
371  tools::foreach(tileIter, tileOp, threaded, /*shareFunctor=*/false);
372  }
373 
374  if (mDensify) tree->prune();
375 
376  if (mInterrupt) mInterrupt->end();
377  return result;
378  }
379 
380  /// @brief Iterate sequentially over LeafNodes and voxels in the output
381  /// grid and apply the operator using a value accessor for the input grid.
382  ///
383  /// @note Never call this public method directly - it is called by
384  /// TBB threads only!
385  void operator()(const typename LeafManagerT::LeafRange& range) const
386  {
389  }
390 
391  for (typename LeafManagerT::LeafRange::Iterator leaf=range.begin(); leaf; ++leaf) {
392  for (typename OutLeafT::ValueOnIter value=leaf->beginValueOn(); value; ++value) {
393  value.setValue(OperatorT::result(mMap, mAcc, value.getCoord()));
394  }
395  }
396  }
397 
398 protected:
399  typedef typename InGridT::ConstAccessor AccessorT;
400  mutable AccessorT mAcc;
401  const MapT& mMap;
402  InterruptT* mInterrupt;
403  const MaskGridType* mMask;
404  const bool mDensify;
405 }; // end of GridOperator class
406 
407 } // namespace gridop
408 
409 
410 ////////////////////////////////////////
411 
412 
413 /// @brief Compute the closest-point transform of a scalar grid.
414 template<
415  typename InGridT,
416  typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
417  typename InterruptT = util::NullInterrupter>
418 class Cpt
419 {
420 public:
421  typedef InGridT InGridType;
423 
424  Cpt(const InGridType& grid, InterruptT* interrupt = nullptr):
425  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
426  {
427  }
428 
429  Cpt(const InGridType& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
430  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
431  {
432  }
433 
434  typename OutGridType::Ptr process(bool threaded = true, bool useWorldTransform = true)
435  {
436  Functor functor(mInputGrid, mMask, threaded, useWorldTransform, mInterrupt);
437  processTypedMap(mInputGrid.transform(), functor);
438  if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_CONTRAVARIANT_ABSOLUTE);
439  return functor.mOutputGrid;
440  }
441 
442 private:
443  struct IsOpT
444  {
445  template<typename MapT, typename AccT>
446  static typename OutGridType::ValueType
447  result(const MapT& map, const AccT& acc, const Coord& xyz)
448  {
449  return math::CPT<MapT, math::CD_2ND>::result(map, acc, xyz);
450  }
451  };
452  struct WsOpT
453  {
454  template<typename MapT, typename AccT>
455  static typename OutGridType::ValueType
456  result(const MapT& map, const AccT& acc, const Coord& xyz)
457  {
458  return math::CPT_RANGE<MapT, math::CD_2ND>::result(map, acc, xyz);
459  }
460  };
461  struct Functor
462  {
463  Functor(const InGridType& grid, const MaskGridType* mask,
464  bool threaded, bool worldspace, InterruptT* interrupt)
465  : mThreaded(threaded)
466  , mWorldSpace(worldspace)
467  , mInputGrid(grid)
468  , mInterrupt(interrupt)
469  , mMask(mask)
470  {}
471 
472  template<typename MapT>
473  void operator()(const MapT& map)
474  {
475  if (mWorldSpace) {
476  gridop::GridOperator<InGridType, MaskGridType, OutGridType, MapT, WsOpT, InterruptT>
477  op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
478  mOutputGrid = op.process(mThreaded); // cache the result
479  } else {
480  gridop::GridOperator<InGridType, MaskGridType, OutGridType, MapT, IsOpT, InterruptT>
481  op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
482  mOutputGrid = op.process(mThreaded); // cache the result
483  }
484  }
485  const bool mThreaded;
486  const bool mWorldSpace;
487  const InGridType& mInputGrid;
488  typename OutGridType::Ptr mOutputGrid;
489  InterruptT* mInterrupt;
490  const MaskGridType* mMask;
491  };
492  const InGridType& mInputGrid;
493  InterruptT* mInterrupt;
494  const MaskGridType* mMask;
495 }; // end of Cpt class
496 
497 
498 ////////////////////////////////////////
499 
500 
501 /// @brief Compute the curl of a vector grid.
502 template<
503  typename GridT,
504  typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
505  typename InterruptT = util::NullInterrupter>
506 class Curl
507 {
508 public:
509  typedef GridT InGridType;
510  typedef GridT OutGridType;
511 
512  Curl(const GridT& grid, InterruptT* interrupt = nullptr):
513  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
514  {
515  }
516 
517  Curl(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
518  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
519  {
520  }
521 
522  typename GridT::Ptr process(bool threaded = true)
523  {
524  Functor functor(mInputGrid, mMask, threaded, mInterrupt);
525  processTypedMap(mInputGrid.transform(), functor);
526  if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
527  return functor.mOutputGrid;
528  }
529 
530 private:
531  struct Functor
532  {
533  Functor(const GridT& grid, const MaskGridType* mask,
534  bool threaded, InterruptT* interrupt):
535  mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
536 
537  template<typename MapT>
538  void operator()(const MapT& map)
539  {
540  typedef math::Curl<MapT, math::CD_2ND> OpT;
541  gridop::GridOperator<GridT, MaskGridType, GridT, MapT, OpT, InterruptT>
542  op(mInputGrid, mMask, map, mInterrupt);
543  mOutputGrid = op.process(mThreaded); // cache the result
544  }
545 
546  const bool mThreaded;
547  const GridT& mInputGrid;
548  typename GridT::Ptr mOutputGrid;
549  InterruptT* mInterrupt;
550  const MaskGridType* mMask;
551  }; // Private Functor
552 
553  const GridT& mInputGrid;
554  InterruptT* mInterrupt;
555  const MaskGridType* mMask;
556 }; // end of Curl class
557 
558 
559 ////////////////////////////////////////
560 
561 
562 /// @brief Compute the divergence of a vector grid.
563 template<
564  typename InGridT,
565  typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
566  typename InterruptT = util::NullInterrupter>
568 {
569 public:
570  typedef InGridT InGridType;
572 
573  Divergence(const InGridT& grid, InterruptT* interrupt = nullptr):
574  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
575  {
576  }
577 
578  Divergence(const InGridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
579  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
580  {
581  }
582 
583  typename OutGridType::Ptr process(bool threaded = true)
584  {
585  if (mInputGrid.getGridClass() == GRID_STAGGERED) {
586  Functor<math::FD_1ST> functor(mInputGrid, mMask, threaded, mInterrupt);
587  processTypedMap(mInputGrid.transform(), functor);
588  return functor.mOutputGrid;
589  } else {
590  Functor<math::CD_2ND> functor(mInputGrid, mMask, threaded, mInterrupt);
591  processTypedMap(mInputGrid.transform(), functor);
592  return functor.mOutputGrid;
593  }
594  }
595 
596 protected:
597  template<math::DScheme DiffScheme>
598  struct Functor
599  {
600  Functor(const InGridT& grid, const MaskGridType* mask,
601  bool threaded, InterruptT* interrupt):
602  mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
603 
604  template<typename MapT>
605  void operator()(const MapT& map)
606  {
609  op(mInputGrid, mMask, map, mInterrupt);
610  mOutputGrid = op.process(mThreaded); // cache the result
611  }
612 
613  const bool mThreaded;
615  typename OutGridType::Ptr mOutputGrid;
616  InterruptT* mInterrupt;
617  const MaskGridType* mMask;
618  }; // Private Functor
619 
621  InterruptT* mInterrupt;
622  const MaskGridType* mMask;
623 }; // end of Divergence class
624 
625 
626 ////////////////////////////////////////
627 
628 
629 /// @brief Compute the gradient of a scalar grid.
630 template<
631  typename InGridT,
632  typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
633  typename InterruptT = util::NullInterrupter>
634 class Gradient
635 {
636 public:
637  typedef InGridT InGridType;
639 
640  Gradient(const InGridT& grid, InterruptT* interrupt = nullptr):
641  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
642  {
643  }
644 
645  Gradient(const InGridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
646  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
647  {
648  }
649 
650  typename OutGridType::Ptr process(bool threaded = true)
651  {
652  Functor functor(mInputGrid, mMask, threaded, mInterrupt);
653  processTypedMap(mInputGrid.transform(), functor);
654  if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
655  return functor.mOutputGrid;
656  }
657 
658 protected:
659  struct Functor
660  {
661  Functor(const InGridT& grid, const MaskGridType* mask,
662  bool threaded, InterruptT* interrupt):
663  mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
664 
665  template<typename MapT>
666  void operator()(const MapT& map)
667  {
670  op(mInputGrid, mMask, map, mInterrupt);
671  mOutputGrid = op.process(mThreaded); // cache the result
672  }
673 
674  const bool mThreaded;
675  const InGridT& mInputGrid;
676  typename OutGridType::Ptr mOutputGrid;
677  InterruptT* mInterrupt;
678  const MaskGridType* mMask;
679  }; // Private Functor
680 
681  const InGridT& mInputGrid;
682  InterruptT* mInterrupt;
683  const MaskGridType* mMask;
684 }; // end of Gradient class
685 
686 
687 ////////////////////////////////////////
688 
689 
690 template<
691  typename GridT,
692  typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
693  typename InterruptT = util::NullInterrupter>
695 {
696 public:
697  typedef GridT InGridType;
698  typedef GridT OutGridType;
699 
700  Laplacian(const GridT& grid, InterruptT* interrupt = nullptr):
701  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
702  {
703  }
704 
705  Laplacian(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
706  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
707  {
708  }
709 
710  typename GridT::Ptr process(bool threaded = true)
711  {
712  Functor functor(mInputGrid, mMask, threaded, mInterrupt);
713  processTypedMap(mInputGrid.transform(), functor);
714  if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
715  return functor.mOutputGrid;
716  }
717 
718 protected:
719  struct Functor
720  {
721  Functor(const GridT& grid, const MaskGridType* mask, bool threaded, InterruptT* interrupt):
722  mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
723 
724  template<typename MapT>
725  void operator()(const MapT& map)
726  {
729  op(mInputGrid, mMask, map, mInterrupt);
730  mOutputGrid = op.process(mThreaded); // cache the result
731  }
732 
733  const bool mThreaded;
734  const GridT& mInputGrid;
735  typename GridT::Ptr mOutputGrid;
736  InterruptT* mInterrupt;
737  const MaskGridType* mMask;
738  }; // Private Functor
739 
740  const GridT& mInputGrid;
741  InterruptT* mInterrupt;
742  const MaskGridType* mMask;
743 }; // end of Laplacian class
744 
745 
746 ////////////////////////////////////////
747 
748 
749 template<
750  typename GridT,
751  typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
752  typename InterruptT = util::NullInterrupter>
754 {
755 public:
756  typedef GridT InGridType;
757  typedef GridT OutGridType;
758 
759  MeanCurvature(const GridT& grid, InterruptT* interrupt = nullptr):
760  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
761  {
762  }
763 
764  MeanCurvature(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
765  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
766  {
767  }
768 
769  typename GridT::Ptr process(bool threaded = true)
770  {
771  Functor functor(mInputGrid, mMask, threaded, mInterrupt);
772  processTypedMap(mInputGrid.transform(), functor);
773  if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
774  return functor.mOutputGrid;
775  }
776 
777 protected:
778  struct Functor
779  {
780  Functor(const GridT& grid, const MaskGridType* mask, bool threaded, InterruptT* interrupt):
781  mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
782 
783  template<typename MapT>
784  void operator()(const MapT& map)
785  {
788  op(mInputGrid, mMask, map, mInterrupt);
789  mOutputGrid = op.process(mThreaded); // cache the result
790  }
791 
792  const bool mThreaded;
793  const GridT& mInputGrid;
794  typename GridT::Ptr mOutputGrid;
795  InterruptT* mInterrupt;
796  const MaskGridType* mMask;
797  }; // Private Functor
798 
799  const GridT& mInputGrid;
800  InterruptT* mInterrupt;
801  const MaskGridType* mMask;
802 }; // end of MeanCurvature class
803 
804 
805 ////////////////////////////////////////
806 
807 
808 template<
809  typename InGridT,
810  typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
811  typename InterruptT = util::NullInterrupter>
813 {
814 public:
815  typedef InGridT InGridType;
817 
818  Magnitude(const InGridType& grid, InterruptT* interrupt = nullptr):
819  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
820  {
821  }
822 
823  Magnitude(const InGridType& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
824  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
825  {
826  }
827 
828  typename OutGridType::Ptr process(bool threaded = true)
829  {
830  Functor functor(mInputGrid, mMask, threaded, mInterrupt);
831  processTypedMap(mInputGrid.transform(), functor);
832  return functor.mOutputGrid;
833  }
834 
835 protected:
836  struct OpT
837  {
838  template<typename MapT, typename AccT>
839  static typename OutGridType::ValueType
840  result(const MapT&, const AccT& acc, const Coord& xyz) { return acc.getValue(xyz).length();}
841  };
842  struct Functor
843  {
844  Functor(const InGridT& grid, const MaskGridType* mask,
845  bool threaded, InterruptT* interrupt):
846  mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
847 
848  template<typename MapT>
849  void operator()(const MapT& map)
850  {
852  op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
853  mOutputGrid = op.process(mThreaded); // cache the result
854  }
855 
856  const bool mThreaded;
858  typename OutGridType::Ptr mOutputGrid;
859  InterruptT* mInterrupt;
860  const MaskGridType* mMask;
861  }; // Private Functor
862 
864  InterruptT* mInterrupt;
865  const MaskGridType* mMask;
866 }; // end of Magnitude class
867 
868 
869 ////////////////////////////////////////
870 
871 
872 template<
873  typename GridT,
874  typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
875  typename InterruptT = util::NullInterrupter>
877 {
878 public:
879  typedef GridT InGridType;
880  typedef GridT OutGridType;
881 
882  Normalize(const GridT& grid, InterruptT* interrupt = nullptr):
883  mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
884  {
885  }
886 
887  Normalize(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
888  mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
889  {
890  }
891 
892  typename GridT::Ptr process(bool threaded = true)
893  {
894  Functor functor(mInputGrid, mMask, threaded, mInterrupt);
895  processTypedMap(mInputGrid.transform(), functor);
896  if (typename GridT::Ptr outGrid = functor.mOutputGrid) {
897  const VecType vecType = mInputGrid.getVectorType();
898  if (vecType == VEC_COVARIANT) {
899  outGrid->setVectorType(VEC_COVARIANT_NORMALIZE);
900  } else {
901  outGrid->setVectorType(vecType);
902  }
903  }
904  return functor.mOutputGrid;
905  }
906 
907 protected:
908  struct OpT
909  {
910  template<typename MapT, typename AccT>
911  static typename OutGridType::ValueType
912  result(const MapT&, const AccT& acc, const Coord& xyz)
913  {
914  typename OutGridType::ValueType vec = acc.getValue(xyz);
915  if ( !vec.normalize() ) vec.setZero();
916  return vec;
917  }
918  };
919  struct Functor
920  {
921  Functor(const GridT& grid, const MaskGridType* mask, bool threaded, InterruptT* interrupt):
922  mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
923 
924  template<typename MapT>
925  void operator()(const MapT& map)
926  {
928  op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
929  mOutputGrid = op.process(mThreaded); // cache the result
930  }
931 
932  const bool mThreaded;
933  const GridT& mInputGrid;
934  typename GridT::Ptr mOutputGrid;
935  InterruptT* mInterrupt;
936  const MaskGridType* mMask;
937  }; // Private Functor
938 
939  const GridT& mInputGrid;
940  InterruptT* mInterrupt;
941  const MaskGridType* mMask;
942 }; // end of Normalize class
943 
944 
945 ////////////////////////////////////////
946 
947 
948 template<typename GridType, typename InterruptT> inline
950 cpt(const GridType& grid, bool threaded, InterruptT* interrupt)
951 {
952  Cpt<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT> op(grid, interrupt);
953  return op.process(threaded);
954 }
955 
956 template<typename GridType, typename MaskT, typename InterruptT> inline
957 typename ScalarToVectorConverter<GridType>::Type::Ptr
958 cpt(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
959 {
960  Cpt<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
961  return op.process(threaded);
962 }
963 
964 template<typename GridType, typename InterruptT> inline
965 typename GridType::Ptr
966 curl(const GridType& grid, bool threaded, InterruptT* interrupt)
967 {
968  Curl<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT> op(grid, interrupt);
969  return op.process(threaded);
970 }
971 
972 template<typename GridType, typename MaskT, typename InterruptT> inline
973 typename GridType::Ptr
974 curl(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
975 {
976  Curl<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
977  return op.process(threaded);
978 }
979 
980 template<typename GridType, typename InterruptT> inline
981 typename VectorToScalarConverter<GridType>::Type::Ptr
982 divergence(const GridType& grid, bool threaded, InterruptT* interrupt)
983 {
985  op(grid, interrupt);
986  return op.process(threaded);
987 }
988 
989 template<typename GridType, typename MaskT, typename InterruptT> inline
990 typename VectorToScalarConverter<GridType>::Type::Ptr
991 divergence(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
992 {
993  Divergence<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
994  return op.process(threaded);
995 }
996 
997 template<typename GridType, typename InterruptT> inline
998 typename ScalarToVectorConverter<GridType>::Type::Ptr
999 gradient(const GridType& grid, bool threaded, InterruptT* interrupt)
1000 {
1002  op(grid, interrupt);
1003  return op.process(threaded);
1004 }
1005 
1006 template<typename GridType, typename MaskT, typename InterruptT> inline
1007 typename ScalarToVectorConverter<GridType>::Type::Ptr
1008 gradient(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1009 {
1010  Gradient<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1011  return op.process(threaded);
1012 }
1013 
1014 template<typename GridType, typename InterruptT> inline
1015 typename GridType::Ptr
1016 laplacian(const GridType& grid, bool threaded, InterruptT* interrupt)
1017 {
1019  op(grid, interrupt);
1020  return op.process(threaded);
1021 }
1022 
1023 template<typename GridType, typename MaskT, typename InterruptT> inline
1024 typename GridType::Ptr
1025 laplacian(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1026 {
1027  Laplacian<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1028  return op.process(threaded);
1029 }
1030 
1031 template<typename GridType, typename InterruptT> inline
1032 typename GridType::Ptr
1033 meanCurvature(const GridType& grid, bool threaded, InterruptT* interrupt)
1034 {
1036  op(grid, interrupt);
1037  return op.process(threaded);
1038 }
1039 
1040 template<typename GridType, typename MaskT, typename InterruptT> inline
1041 typename GridType::Ptr
1042 meanCurvature(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1043 {
1044  MeanCurvature<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1045  return op.process(threaded);
1046 }
1047 
1048 template<typename GridType, typename InterruptT> inline
1049 typename VectorToScalarConverter<GridType>::Type::Ptr
1050 magnitude(const GridType& grid, bool threaded, InterruptT* interrupt)
1051 {
1053  op(grid, interrupt);
1054  return op.process(threaded);
1055 }
1056 
1057 template<typename GridType, typename MaskT, typename InterruptT> inline
1058 typename VectorToScalarConverter<GridType>::Type::Ptr
1059 magnitude(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1060 {
1061  Magnitude<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1062  return op.process(threaded);
1063 }
1064 
1065 template<typename GridType, typename InterruptT> inline
1066 typename GridType::Ptr
1067 normalize(const GridType& grid, bool threaded, InterruptT* interrupt)
1068 {
1070  op(grid, interrupt);
1071  return op.process(threaded);
1072 }
1073 
1074 template<typename GridType, typename MaskT, typename InterruptT> inline
1075 typename GridType::Ptr
1076 normalize(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1077 {
1078  Normalize<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1079  return op.process(threaded);
1080 }
1081 
1082 } // namespace tools
1083 } // namespace OPENVDB_VERSION_NAME
1084 } // namespace openvdb
1085 
1086 #endif // OPENVDB_TOOLS_GRID_OPERATORS_HAS_BEEN_INCLUDED
Compute the closest-point transform of a scalar grid.
Compute the gradient of a scalar grid.
Functor(const InGridT &grid, const MaskGridType *mask, bool threaded, InterruptT *interrupt)
OutGridType::Ptr process(bool threaded=true)
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
Definition: parallel.h:127
OutGridType::Ptr process(bool threaded=true, bool useWorldTransform=true)
Normalize(const GridT &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
OutGridType::Ptr process(bool threaded=true)
static OutGridType::ValueType result(const MapT &, const AccT &acc, const Coord &xyz)
VectorGridType::template ValueConverter< VecComponentValueT >::Type Type
Definition: GridOperators.h:33
VectorToScalarConverter<VectorGridType>::Type is the type of a grid having the same tree configuratio...
Definition: GridOperators.h:31
GridOperator(const InGridT &grid, const MaskGridType *mask, const MapT &map, InterruptT *interrupt=nullptr, bool densify=true)
MeanCurvature(const GridT &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
Compute the divergence of a vector grid.
GridT::Ptr process(bool threaded=true)
Cpt(const InGridType &grid, InterruptT *interrupt=nullptr)
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:178
MeanCurvature(const GridT &grid, InterruptT *interrupt=nullptr)
ToMaskGrid<T>::Type is the type of a grid having the same tree hierarchy as grid type T but a value e...
ScalarToVectorConverter< InGridT >::Type OutGridType
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:24
Gradient(const InGridT &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
Dummy NOOP interrupter class defining interface.
ScalarToVectorConverter< InGridT >::Type OutGridType
uint64 value_type
Definition: GA_PrimCompat.h:29
Laplacian(const GridT &grid, InterruptT *interrupt=nullptr)
GridOperator & operator=(const GridOperator &)=default
VectorToScalarConverter< GridType >::Type::Ptr magnitude(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the magnitudes of the vectors of the given vector-valued grid.
Grid< typename GridType::TreeType::template ValueConverter< ValueMask >::Type > Type
void foreach(const IterT &iter, XformOp &op, bool threaded=true, bool shareOp=true)
Cpt(const InGridType &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
Curl(const GridT &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
ScalarToVectorConverter<ScalarGridType>::Type is the type of a grid having the same tree configuratio...
Definition: GridOperators.h:40
Functor(const InGridT &grid, const MaskGridType *mask, bool threaded, InterruptT *interrupt)
Divergence(const InGridT &grid, InterruptT *interrupt=nullptr)
Compute the Laplacian at a given location in a grid using finite differencing of various orders...
Definition: Operators.h:1419
Apply an operator to an input grid to produce an output grid with the same active voxel topology but ...
Functor(const InGridT &grid, const MaskGridType *mask, bool threaded, InterruptT *interrupt)
GridT::Ptr process(bool threaded=true)
static math::Vec3< typename Accessor::ValueType > result(const MapType &map, const Accessor &grid, const Coord &ijk)
Definition: Operators.h:1669
GLint GLuint mask
Definition: glcorearb.h:123
Functor(const GridT &grid, const MaskGridType *mask, bool threaded, InterruptT *interrupt)
ScalarGridType::template ValueConverter< VectorValueT >::Type Type
Definition: GridOperators.h:42
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
Curl(const GridT &grid, InterruptT *interrupt=nullptr)
VectorToScalarConverter< InGridT >::Type OutGridType
void operator()(const typename LeafManagerT::LeafRange &range) const
Iterate sequentially over LeafNodes and voxels in the output grid and apply the operator using a valu...
GridType::Ptr normalize(const GridType &grid, bool threaded, InterruptT *interrupt)
Normalize the vectors of the given vector-valued grid.
Center difference gradient operators, defined with respect to the range-space of the map...
Definition: Operators.h:619
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
VectorToScalarConverter< InGridT >::Type OutGridType
Compute the curl of a vector-valued grid using differencing of various orders in the space defined by...
Definition: Operators.h:1274
static Vec3< typename Accessor::ValueType > result(const MapType &map, const Accessor &grid, const Coord &ijk)
Definition: Operators.h:1722
GridType::Ptr laplacian(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the Laplacian of the given scalar grid.
Magnitude(const InGridType &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
OutGridType::Ptr process(bool threaded=true)
VectorGridType::ValueType::value_type VecComponentValueT
Definition: GridOperators.h:32
ScalarToVectorConverter< GridType >::Type::Ptr gradient(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the gradient of the given scalar grid.
Gradient(const InGridT &grid, InterruptT *interrupt=nullptr)
GLsizei const GLfloat * value
Definition: glcorearb.h:823
Divergence(const InGridT &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
Magnitude(const InGridType &grid, InterruptT *interrupt=nullptr)
Compute the curl of a vector grid.
Functor(const GridT &grid, const MaskGridType *mask, bool threaded, InterruptT *interrupt)
math::Vec3< typename ScalarGridType::ValueType > VectorValueT
Definition: GridOperators.h:41
GLenum GLint * range
Definition: glcorearb.h:1924
Laplacian(const GridT &grid, const MaskGridType &mask, InterruptT *interrupt=nullptr)
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:560
VectorToScalarConverter< GridType >::Type::Ptr divergence(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the divergence of the given vector-valued grid.
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Compute the divergence of a vector-valued grid using differencing of various orders, the result defined with respect to the range-space of the map.
Definition: Operators.h:949
GridType::Ptr meanCurvature(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the mean curvature of the given grid.
Normalize(const GridT &grid, InterruptT *interrupt=nullptr)
GridType::Ptr curl(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the curl of the given vector-valued grid.
bool wasInterrupted(T *i, int percent=-1)
ScalarToVectorConverter< GridType >::Type::Ptr cpt(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the Closest-Point Transform (CPT) from a distance field.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:114
GridT::Ptr process(bool threaded=true)
static OutGridType::ValueType result(const MapT &, const AccT &acc, const Coord &xyz)
bool processTypedMap(TransformType &transform, OpType &op)
Utility function that, given a generic map pointer, calls a functor on the fully-resoved map...
Definition: Transform.h:233
Functor(const GridT &grid, const MaskGridType *mask, bool threaded, InterruptT *interrupt)