OpenVDB  7.0.0
ValueTransformer.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
28 
29 #ifndef OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
30 #define OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
31 
32 #include <algorithm> // for std::min(), std::max()
33 #include <tbb/parallel_for.h>
34 #include <tbb/parallel_reduce.h>
35 #include <openvdb/Types.h>
36 #include <openvdb/Grid.h>
37 
38 
39 namespace openvdb {
41 namespace OPENVDB_VERSION_NAME {
42 namespace tools {
43 
87 template<typename IterT, typename XformOp>
88 inline void foreach(const IterT& iter, XformOp& op,
89  bool threaded = true, bool shareOp = true);
90 
91 template<typename IterT, typename XformOp>
92 inline void foreach(const IterT& iter, const XformOp& op,
93  bool threaded = true, bool shareOp = true);
94 
95 
136 template<typename InIterT, typename OutGridT, typename XformOp>
137 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
138  XformOp& op, bool threaded = true, bool shareOp = true,
140 
141 #ifndef _MSC_VER
142 template<typename InIterT, typename OutGridT, typename XformOp>
143 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
144  const XformOp& op, bool threaded = true, bool shareOp = true,
146 #endif
147 
148 
193 template<typename IterT, typename XformOp>
194 inline void accumulate(const IterT& iter, XformOp& op, bool threaded = true);
195 
196 
202 template<typename TreeT>
203 inline void setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
204 
210 template<typename TreeT>
211 inline void setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
212 
218 template<typename TreeT>
219 inline void setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
220 
226 template<typename TreeT>
227 inline void setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
228 
229 
231 
232 
233 namespace valxform {
234 
235 template<typename ValueType>
236 struct MinOp {
237  const ValueType val;
238  MinOp(const ValueType& v): val(v) {}
239  inline void operator()(ValueType& v) const { v = std::min<ValueType>(v, val); }
240 };
241 
242 template<typename ValueType>
243 struct MaxOp {
244  const ValueType val;
245  MaxOp(const ValueType& v): val(v) {}
246  inline void operator()(ValueType& v) const { v = std::max<ValueType>(v, val); }
247 };
248 
249 template<typename ValueType>
250 struct SumOp {
251  const ValueType val;
252  SumOp(const ValueType& v): val(v) {}
253  inline void operator()(ValueType& v) const { v += val; }
254 };
255 
256 
257 template<>
258 struct SumOp<bool> {
259  using ValueType = bool;
260  const ValueType val;
261  SumOp(const ValueType& v): val(v) {}
262  inline void operator()(ValueType& v) const { v = v || val; }
263 };
264 
265 template<typename ValueType>
266 struct MultOp {
267  const ValueType val;
268  MultOp(const ValueType& v): val(v) {}
269  inline void operator()(ValueType& v) const { v *= val; }
270 };
271 
272 }
273 
274 
275 template<typename TreeT>
276 inline void
277 setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
278 {
279  tree.modifyValue(xyz, valxform::MinOp<typename TreeT::ValueType>(value));
280 }
281 
282 
283 template<typename TreeT>
284 inline void
285 setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
286 {
287  tree.modifyValue(xyz, valxform::MaxOp<typename TreeT::ValueType>(value));
288 }
289 
290 
291 template<typename TreeT>
292 inline void
293 setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
294 {
295  tree.modifyValue(xyz, valxform::SumOp<typename TreeT::ValueType>(value));
296 }
297 
298 
299 template<typename TreeT>
300 inline void
301 setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
302 {
303  tree.modifyValue(xyz, valxform::MultOp<typename TreeT::ValueType>(value));
304 }
305 
306 
308 
309 
310 namespace valxform {
311 
312 template<typename IterT, typename OpT>
314 {
315 public:
317 
318  SharedOpApplier(const IterT& iter, OpT& op): mIter(iter), mOp(op) {}
319 
320  void process(bool threaded = true)
321  {
322  IterRange range(mIter);
323  if (threaded) {
324  tbb::parallel_for(range, *this);
325  } else {
326  (*this)(range);
327  }
328  }
329 
330  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
331 
332 private:
333  IterT mIter;
334  OpT& mOp;
335 };
336 
337 
338 template<typename IterT, typename OpT>
340 {
341 public:
343 
344  CopyableOpApplier(const IterT& iter, const OpT& op): mIter(iter), mOp(op), mOrigOp(&op) {}
345 
346  // When splitting this task, give the subtask a copy of the original functor,
347  // not of this task's functor, which might have been modified arbitrarily.
349  mIter(other.mIter), mOp(*other.mOrigOp), mOrigOp(other.mOrigOp) {}
350 
351  void process(bool threaded = true)
352  {
353  IterRange range(mIter);
354  if (threaded) {
355  tbb::parallel_for(range, *this);
356  } else {
357  (*this)(range);
358  }
359  }
360 
361  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
362 
363 private:
364  IterT mIter;
365  OpT mOp; // copy of original functor
366  OpT const * const mOrigOp; // pointer to original functor
367 };
368 
369 } // namespace valxform
370 
371 
372 template<typename IterT, typename XformOp>
373 inline void
374 foreach(const IterT& iter, XformOp& op, bool threaded, bool shared)
375 {
376  if (shared) {
377  typename valxform::SharedOpApplier<IterT, XformOp> proc(iter, op);
378  proc.process(threaded);
379  } else {
380  using Processor = typename valxform::CopyableOpApplier<IterT, XformOp>;
381  Processor proc(iter, op);
382  proc.process(threaded);
383  }
384 }
385 
386 template<typename IterT, typename XformOp>
387 inline void
388 foreach(const IterT& iter, const XformOp& op, bool threaded, bool /*shared*/)
389 {
390  // Const ops are shared across threads, not copied.
391  typename valxform::SharedOpApplier<IterT, const XformOp> proc(iter, op);
392  proc.process(threaded);
393 }
394 
395 
397 
398 
399 namespace valxform {
400 
401 template<typename InIterT, typename OutTreeT, typename OpT>
403 {
404 public:
405  using InTreeT = typename InIterT::TreeT;
407  using OutValueT = typename OutTreeT::ValueType;
408 
409  SharedOpTransformer(const InIterT& inIter, OutTreeT& outTree, OpT& op, MergePolicy merge):
410  mIsRoot(true),
411  mInputIter(inIter),
412  mInputTree(inIter.getTree()),
413  mOutputTree(&outTree),
414  mOp(op),
415  mMergePolicy(merge)
416  {
417  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
418  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
419  " to transform a grid in place");
420  }
421  }
422 
425  mIsRoot(false),
426  mInputIter(other.mInputIter),
427  mInputTree(other.mInputTree),
428  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
429  mOp(other.mOp),
430  mMergePolicy(other.mMergePolicy)
431  {}
432 
434  {
435  // Delete the output tree only if it was allocated locally
436  // (the top-level output tree was supplied by the caller).
437  if (!mIsRoot) {
438  delete mOutputTree;
439  mOutputTree = nullptr;
440  }
441  }
442 
443  void process(bool threaded = true)
444  {
445  if (!mInputTree || !mOutputTree) return;
446 
447  IterRange range(mInputIter);
448 
449  // Independently transform elements in the iterator range,
450  // either in parallel or serially.
451  if (threaded) {
452  tbb::parallel_reduce(range, *this);
453  } else {
454  (*this)(range);
455  }
456  }
457 
459  void operator()(IterRange& range) const
460  {
461  if (!mOutputTree) return;
462  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
463  for ( ; range; ++range) {
464  mOp(range.iterator(), outAccessor);
465  }
466  }
467 
468  void join(const SharedOpTransformer& other)
469  {
470  if (mOutputTree && other.mOutputTree) {
471  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
472  }
473  }
474 
475 private:
476  bool mIsRoot;
477  InIterT mInputIter;
478  const InTreeT* mInputTree;
479  OutTreeT* mOutputTree;
480  OpT& mOp;
481  MergePolicy mMergePolicy;
482 }; // class SharedOpTransformer
483 
484 
485 template<typename InIterT, typename OutTreeT, typename OpT>
487 {
488 public:
489  using InTreeT = typename InIterT::TreeT;
491  using OutValueT = typename OutTreeT::ValueType;
492 
493  CopyableOpTransformer(const InIterT& inIter, OutTreeT& outTree,
494  const OpT& op, MergePolicy merge):
495  mIsRoot(true),
496  mInputIter(inIter),
497  mInputTree(inIter.getTree()),
498  mOutputTree(&outTree),
499  mOp(op),
500  mOrigOp(&op),
501  mMergePolicy(merge)
502  {
503  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
504  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
505  " to transform a grid in place");
506  }
507  }
508 
509  // When splitting this task, give the subtask a copy of the original functor,
510  // not of this task's functor, which might have been modified arbitrarily.
512  mIsRoot(false),
513  mInputIter(other.mInputIter),
514  mInputTree(other.mInputTree),
515  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
516  mOp(*other.mOrigOp),
517  mOrigOp(other.mOrigOp),
518  mMergePolicy(other.mMergePolicy)
519  {}
520 
522  {
523  // Delete the output tree only if it was allocated locally
524  // (the top-level output tree was supplied by the caller).
525  if (!mIsRoot) {
526  delete mOutputTree;
527  mOutputTree = nullptr;
528  }
529  }
530 
531  void process(bool threaded = true)
532  {
533  if (!mInputTree || !mOutputTree) return;
534 
535  IterRange range(mInputIter);
536 
537  // Independently transform elements in the iterator range,
538  // either in parallel or serially.
539  if (threaded) {
540  tbb::parallel_reduce(range, *this);
541  } else {
542  (*this)(range);
543  }
544  }
545 
547  void operator()(IterRange& range)
548  {
549  if (!mOutputTree) return;
550  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
551  for ( ; range; ++range) {
552  mOp(range.iterator(), outAccessor);
553  }
554  }
555 
556  void join(const CopyableOpTransformer& other)
557  {
558  if (mOutputTree && other.mOutputTree) {
559  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
560  }
561  }
562 
563 private:
564  bool mIsRoot;
565  InIterT mInputIter;
566  const InTreeT* mInputTree;
567  OutTreeT* mOutputTree;
568  OpT mOp; // copy of original functor
569  OpT const * const mOrigOp; // pointer to original functor
570  MergePolicy mMergePolicy;
571 }; // class CopyableOpTransformer
572 
573 } // namespace valxform
574 
575 
577 
578 
579 template<typename InIterT, typename OutGridT, typename XformOp>
580 inline void
581 transformValues(const InIterT& inIter, OutGridT& outGrid, XformOp& op,
582  bool threaded, bool shared, MergePolicy merge)
583 {
584  using Adapter = TreeAdapter<OutGridT>;
585  using OutTreeT = typename Adapter::TreeType;
586  if (shared) {
588  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
589  proc.process(threaded);
590  } else {
592  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
593  proc.process(threaded);
594  }
595 }
596 
597 #ifndef _MSC_VER
598 template<typename InIterT, typename OutGridT, typename XformOp>
599 inline void
600 transformValues(const InIterT& inIter, OutGridT& outGrid, const XformOp& op,
601  bool threaded, bool /*share*/, MergePolicy merge)
602 {
603  using Adapter = TreeAdapter<OutGridT>;
604  using OutTreeT = typename Adapter::TreeType;
605  // Const ops are shared across threads, not copied.
607  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
608  proc.process(threaded);
609 }
610 #endif
611 
612 
614 
615 
616 namespace valxform {
617 
618 template<typename IterT, typename OpT>
620 {
621 public:
623 
624  // The root task makes a const copy of the original functor (mOrigOp)
625  // and keeps a pointer to the original functor (mOp), which it then modifies.
626  // Each subtask keeps a const pointer to the root task's mOrigOp
627  // and makes and then modifies a non-const copy (mOp) of it.
628  OpAccumulator(const IterT& iter, OpT& op):
629  mIsRoot(true),
630  mIter(iter),
631  mOp(&op),
632  mOrigOp(new OpT(op))
633  {}
634 
635  // When splitting this task, give the subtask a copy of the original functor,
636  // not of this task's functor, which might have been modified arbitrarily.
637  OpAccumulator(OpAccumulator& other, tbb::split):
638  mIsRoot(false),
639  mIter(other.mIter),
640  mOp(new OpT(*other.mOrigOp)),
641  mOrigOp(other.mOrigOp)
642  {}
643 
644  ~OpAccumulator() { if (mIsRoot) delete mOrigOp; else delete mOp; }
645 
646  void process(bool threaded = true)
647  {
648  IterRange range(mIter);
649  if (threaded) {
650  tbb::parallel_reduce(range, *this);
651  } else {
652  (*this)(range);
653  }
654  }
655 
656  void operator()(IterRange& r) { for ( ; r; ++r) (*mOp)(r.iterator()); }
657 
658  void join(OpAccumulator& other) { mOp->join(*other.mOp); }
659 
660 private:
661  const bool mIsRoot;
662  const IterT mIter;
663  OpT* mOp; // pointer to original functor, which might get modified
664  OpT const * const mOrigOp; // const copy of original functor
665 }; // class OpAccumulator
666 
667 } // namespace valxform
668 
669 
671 
672 
673 template<typename IterT, typename XformOp>
674 inline void
675 accumulate(const IterT& iter, XformOp& op, bool threaded)
676 {
677  typename valxform::OpAccumulator<IterT, XformOp> proc(iter, op);
678  proc.process(threaded);
679 }
680 
681 } // namespace tools
682 } // namespace OPENVDB_VERSION_NAME
683 } // namespace openvdb
684 
685 #endif // OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
const ValueType val
Definition: ValueTransformer.h:237
#define OPENVDB_LOG_INFO(message)
Log an info message of the form &#39;someVar << "some text" << ...&#39;.
Definition: logging.h:251
~OpAccumulator()
Definition: ValueTransformer.h:644
typename tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:316
void accumulate(const IterT &iter, XformOp &op, bool threaded=true)
Definition: ValueTransformer.h:675
void operator()(IterRange &r) const
Definition: ValueTransformer.h:330
typename InIterT::TreeT InTreeT
Definition: ValueTransformer.h:405
CopyableOpTransformer(const InIterT &inIter, OutTreeT &outTree, const OpT &op, MergePolicy merge)
Definition: ValueTransformer.h:493
Definition: ValueAccessor.h:193
void setValueOnMax(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the maximum of its current value and v...
Definition: ValueTransformer.h:285
void join(OpAccumulator &other)
Definition: ValueTransformer.h:658
Definition: Types.h:506
typename tree::IteratorRange< InIterT > IterRange
Definition: ValueTransformer.h:406
SumOp(const ValueType &v)
Definition: ValueTransformer.h:261
SumOp(const ValueType &v)
Definition: ValueTransformer.h:252
const ValueType val
Definition: ValueTransformer.h:260
void operator()(ValueType &v) const
Definition: ValueTransformer.h:253
void operator()(ValueType &v) const
Definition: ValueTransformer.h:262
OpAccumulator(const IterT &iter, OpT &op)
Definition: ValueTransformer.h:628
Definition: ValueTransformer.h:402
~CopyableOpTransformer()
Definition: ValueTransformer.h:521
CopyableOpTransformer(CopyableOpTransformer &other, tbb::split)
Definition: ValueTransformer.h:511
const ValueType val
Definition: ValueTransformer.h:267
const ValueType val
Definition: ValueTransformer.h:251
typename OutTreeT::ValueType OutValueT
Definition: ValueTransformer.h:407
void operator()(IterRange &r)
Definition: ValueTransformer.h:656
void setValueOnSum(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the sum of its current value and value...
Definition: ValueTransformer.h:293
void join(const SharedOpTransformer &other)
Definition: ValueTransformer.h:468
Definition: ValueTransformer.h:619
Definition: ValueTransformer.h:250
typename InIterT::TreeT InTreeT
Definition: ValueTransformer.h:489
void setValueOnMin(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the minimum of its current value and v...
Definition: ValueTransformer.h:277
MaxOp(const ValueType &v)
Definition: ValueTransformer.h:245
void join(const CopyableOpTransformer &other)
Definition: ValueTransformer.h:556
MinOp(const ValueType &v)
Definition: ValueTransformer.h:238
void process(bool threaded=true)
Definition: ValueTransformer.h:443
void process(bool threaded=true)
Definition: ValueTransformer.h:646
MultOp(const ValueType &v)
Definition: ValueTransformer.h:268
CopyableOpApplier(const IterT &iter, const OpT &op)
Definition: ValueTransformer.h:344
void operator()(ValueType &v) const
Definition: ValueTransformer.h:269
SharedOpTransformer(const InIterT &inIter, OutTreeT &outTree, OpT &op, MergePolicy merge)
Definition: ValueTransformer.h:409
void operator()(ValueType &v) const
Definition: ValueTransformer.h:246
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:59
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
Definition: ValueTransformer.h:236
typename tree::IteratorRange< InIterT > IterRange
Definition: ValueTransformer.h:490
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
void operator()(IterRange &r) const
Definition: ValueTransformer.h:361
SharedOpTransformer(SharedOpTransformer &other, tbb::split)
Splitting constructor.
Definition: ValueTransformer.h:424
void operator()(ValueType &v) const
Definition: ValueTransformer.h:239
Definition: Exceptions.h:13
Definition: ValueTransformer.h:243
void operator()(IterRange &range)
Transform each element in the given range.
Definition: ValueTransformer.h:547
MergePolicy
Definition: Types.h:505
typename tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:622
typename OutTreeT::ValueType OutValueT
Definition: ValueTransformer.h:491
OpAccumulator(OpAccumulator &other, tbb::split)
Definition: ValueTransformer.h:637
Definition: TreeIterator.h:1307
void operator()(IterRange &range) const
Transform each element in the given range.
Definition: ValueTransformer.h:459
void setValueOnMult(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the product of its current value and v...
Definition: ValueTransformer.h:301
typename tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:342
const ValueType val
Definition: ValueTransformer.h:244
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
Definition: ValueTransformer.h:313
bool ValueType
Definition: ValueTransformer.h:259
Definition: ValueTransformer.h:339
Definition: ValueTransformer.h:266
~SharedOpTransformer()
Definition: ValueTransformer.h:433
CopyableOpApplier(const CopyableOpApplier &other)
Definition: ValueTransformer.h:348
void process(bool threaded=true)
Definition: ValueTransformer.h:531
void process(bool threaded=true)
Definition: ValueTransformer.h:320
SharedOpApplier(const IterT &iter, OpT &op)
Definition: ValueTransformer.h:318
void transformValues(const InIterT &inIter, OutGridT &outGrid, const XformOp &op, bool threaded=true, bool shareOp=true, MergePolicy merge=MERGE_ACTIVE_STATES)
Definition: ValueTransformer.h:600
void process(bool threaded=true)
Definition: ValueTransformer.h:351