OpenVDB  6.2.0
ValueTransformer.h
Go to the documentation of this file.
1 //
3 // Copyright (c) DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
55 
56 #ifndef OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
57 #define OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
58 
59 #include <algorithm> // for std::min(), std::max()
60 #include <tbb/parallel_for.h>
61 #include <tbb/parallel_reduce.h>
62 #include <openvdb/Types.h>
63 #include <openvdb/Grid.h>
64 
65 
66 namespace openvdb {
68 namespace OPENVDB_VERSION_NAME {
69 namespace tools {
70 
114 template<typename IterT, typename XformOp>
115 inline void foreach(const IterT& iter, XformOp& op,
116  bool threaded = true, bool shareOp = true);
117 
118 template<typename IterT, typename XformOp>
119 inline void foreach(const IterT& iter, const XformOp& op,
120  bool threaded = true, bool shareOp = true);
121 
122 
163 template<typename InIterT, typename OutGridT, typename XformOp>
164 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
165  XformOp& op, bool threaded = true, bool shareOp = true,
167 
168 #ifndef _MSC_VER
169 template<typename InIterT, typename OutGridT, typename XformOp>
170 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
171  const XformOp& op, bool threaded = true, bool shareOp = true,
173 #endif
174 
175 
220 template<typename IterT, typename XformOp>
221 inline void accumulate(const IterT& iter, XformOp& op, bool threaded = true);
222 
223 
229 template<typename TreeT>
230 inline void setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
231 
237 template<typename TreeT>
238 inline void setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
239 
245 template<typename TreeT>
246 inline void setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
247 
253 template<typename TreeT>
254 inline void setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
255 
256 
258 
259 
260 namespace valxform {
261 
262 template<typename ValueType>
263 struct MinOp {
264  const ValueType val;
265  MinOp(const ValueType& v): val(v) {}
266  inline void operator()(ValueType& v) const { v = std::min<ValueType>(v, val); }
267 };
268 
269 template<typename ValueType>
270 struct MaxOp {
271  const ValueType val;
272  MaxOp(const ValueType& v): val(v) {}
273  inline void operator()(ValueType& v) const { v = std::max<ValueType>(v, val); }
274 };
275 
276 template<typename ValueType>
277 struct SumOp {
278  const ValueType val;
279  SumOp(const ValueType& v): val(v) {}
280  inline void operator()(ValueType& v) const { v += val; }
281 };
282 
283 
284 template<>
285 struct SumOp<bool> {
286  using ValueType = bool;
287  const ValueType val;
288  SumOp(const ValueType& v): val(v) {}
289  inline void operator()(ValueType& v) const { v = v || val; }
290 };
291 
292 template<typename ValueType>
293 struct MultOp {
294  const ValueType val;
295  MultOp(const ValueType& v): val(v) {}
296  inline void operator()(ValueType& v) const { v *= val; }
297 };
298 
299 }
300 
301 
302 template<typename TreeT>
303 inline void
304 setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
305 {
306  tree.modifyValue(xyz, valxform::MinOp<typename TreeT::ValueType>(value));
307 }
308 
309 
310 template<typename TreeT>
311 inline void
312 setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
313 {
314  tree.modifyValue(xyz, valxform::MaxOp<typename TreeT::ValueType>(value));
315 }
316 
317 
318 template<typename TreeT>
319 inline void
320 setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
321 {
322  tree.modifyValue(xyz, valxform::SumOp<typename TreeT::ValueType>(value));
323 }
324 
325 
326 template<typename TreeT>
327 inline void
328 setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
329 {
330  tree.modifyValue(xyz, valxform::MultOp<typename TreeT::ValueType>(value));
331 }
332 
333 
335 
336 
337 namespace valxform {
338 
339 template<typename IterT, typename OpT>
341 {
342 public:
344 
345  SharedOpApplier(const IterT& iter, OpT& op): mIter(iter), mOp(op) {}
346 
347  void process(bool threaded = true)
348  {
349  IterRange range(mIter);
350  if (threaded) {
351  tbb::parallel_for(range, *this);
352  } else {
353  (*this)(range);
354  }
355  }
356 
357  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
358 
359 private:
360  IterT mIter;
361  OpT& mOp;
362 };
363 
364 
365 template<typename IterT, typename OpT>
367 {
368 public:
370 
371  CopyableOpApplier(const IterT& iter, const OpT& op): mIter(iter), mOp(op), mOrigOp(&op) {}
372 
373  // When splitting this task, give the subtask a copy of the original functor,
374  // not of this task's functor, which might have been modified arbitrarily.
376  mIter(other.mIter), mOp(*other.mOrigOp), mOrigOp(other.mOrigOp) {}
377 
378  void process(bool threaded = true)
379  {
380  IterRange range(mIter);
381  if (threaded) {
382  tbb::parallel_for(range, *this);
383  } else {
384  (*this)(range);
385  }
386  }
387 
388  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
389 
390 private:
391  IterT mIter;
392  OpT mOp; // copy of original functor
393  OpT const * const mOrigOp; // pointer to original functor
394 };
395 
396 } // namespace valxform
397 
398 
399 template<typename IterT, typename XformOp>
400 inline void
401 foreach(const IterT& iter, XformOp& op, bool threaded, bool shared)
402 {
403  if (shared) {
404  typename valxform::SharedOpApplier<IterT, XformOp> proc(iter, op);
405  proc.process(threaded);
406  } else {
407  using Processor = typename valxform::CopyableOpApplier<IterT, XformOp>;
408  Processor proc(iter, op);
409  proc.process(threaded);
410  }
411 }
412 
413 template<typename IterT, typename XformOp>
414 inline void
415 foreach(const IterT& iter, const XformOp& op, bool threaded, bool /*shared*/)
416 {
417  // Const ops are shared across threads, not copied.
418  typename valxform::SharedOpApplier<IterT, const XformOp> proc(iter, op);
419  proc.process(threaded);
420 }
421 
422 
424 
425 
426 namespace valxform {
427 
428 template<typename InIterT, typename OutTreeT, typename OpT>
430 {
431 public:
432  using InTreeT = typename InIterT::TreeT;
434  using OutValueT = typename OutTreeT::ValueType;
435 
436  SharedOpTransformer(const InIterT& inIter, OutTreeT& outTree, OpT& op, MergePolicy merge):
437  mIsRoot(true),
438  mInputIter(inIter),
439  mInputTree(inIter.getTree()),
440  mOutputTree(&outTree),
441  mOp(op),
442  mMergePolicy(merge)
443  {
444  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
445  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
446  " to transform a grid in place");
447  }
448  }
449 
452  mIsRoot(false),
453  mInputIter(other.mInputIter),
454  mInputTree(other.mInputTree),
455  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
456  mOp(other.mOp),
457  mMergePolicy(other.mMergePolicy)
458  {}
459 
461  {
462  // Delete the output tree only if it was allocated locally
463  // (the top-level output tree was supplied by the caller).
464  if (!mIsRoot) {
465  delete mOutputTree;
466  mOutputTree = nullptr;
467  }
468  }
469 
470  void process(bool threaded = true)
471  {
472  if (!mInputTree || !mOutputTree) return;
473 
474  IterRange range(mInputIter);
475 
476  // Independently transform elements in the iterator range,
477  // either in parallel or serially.
478  if (threaded) {
479  tbb::parallel_reduce(range, *this);
480  } else {
481  (*this)(range);
482  }
483  }
484 
486  void operator()(IterRange& range) const
487  {
488  if (!mOutputTree) return;
489  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
490  for ( ; range; ++range) {
491  mOp(range.iterator(), outAccessor);
492  }
493  }
494 
495  void join(const SharedOpTransformer& other)
496  {
497  if (mOutputTree && other.mOutputTree) {
498  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
499  }
500  }
501 
502 private:
503  bool mIsRoot;
504  InIterT mInputIter;
505  const InTreeT* mInputTree;
506  OutTreeT* mOutputTree;
507  OpT& mOp;
508  MergePolicy mMergePolicy;
509 }; // class SharedOpTransformer
510 
511 
512 template<typename InIterT, typename OutTreeT, typename OpT>
514 {
515 public:
516  using InTreeT = typename InIterT::TreeT;
518  using OutValueT = typename OutTreeT::ValueType;
519 
520  CopyableOpTransformer(const InIterT& inIter, OutTreeT& outTree,
521  const OpT& op, MergePolicy merge):
522  mIsRoot(true),
523  mInputIter(inIter),
524  mInputTree(inIter.getTree()),
525  mOutputTree(&outTree),
526  mOp(op),
527  mOrigOp(&op),
528  mMergePolicy(merge)
529  {
530  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
531  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
532  " to transform a grid in place");
533  }
534  }
535 
536  // When splitting this task, give the subtask a copy of the original functor,
537  // not of this task's functor, which might have been modified arbitrarily.
539  mIsRoot(false),
540  mInputIter(other.mInputIter),
541  mInputTree(other.mInputTree),
542  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
543  mOp(*other.mOrigOp),
544  mOrigOp(other.mOrigOp),
545  mMergePolicy(other.mMergePolicy)
546  {}
547 
549  {
550  // Delete the output tree only if it was allocated locally
551  // (the top-level output tree was supplied by the caller).
552  if (!mIsRoot) {
553  delete mOutputTree;
554  mOutputTree = nullptr;
555  }
556  }
557 
558  void process(bool threaded = true)
559  {
560  if (!mInputTree || !mOutputTree) return;
561 
562  IterRange range(mInputIter);
563 
564  // Independently transform elements in the iterator range,
565  // either in parallel or serially.
566  if (threaded) {
567  tbb::parallel_reduce(range, *this);
568  } else {
569  (*this)(range);
570  }
571  }
572 
574  void operator()(IterRange& range)
575  {
576  if (!mOutputTree) return;
577  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
578  for ( ; range; ++range) {
579  mOp(range.iterator(), outAccessor);
580  }
581  }
582 
583  void join(const CopyableOpTransformer& other)
584  {
585  if (mOutputTree && other.mOutputTree) {
586  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
587  }
588  }
589 
590 private:
591  bool mIsRoot;
592  InIterT mInputIter;
593  const InTreeT* mInputTree;
594  OutTreeT* mOutputTree;
595  OpT mOp; // copy of original functor
596  OpT const * const mOrigOp; // pointer to original functor
597  MergePolicy mMergePolicy;
598 }; // class CopyableOpTransformer
599 
600 } // namespace valxform
601 
602 
604 
605 
606 template<typename InIterT, typename OutGridT, typename XformOp>
607 inline void
608 transformValues(const InIterT& inIter, OutGridT& outGrid, XformOp& op,
609  bool threaded, bool shared, MergePolicy merge)
610 {
611  using Adapter = TreeAdapter<OutGridT>;
612  using OutTreeT = typename Adapter::TreeType;
613  if (shared) {
615  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
616  proc.process(threaded);
617  } else {
619  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
620  proc.process(threaded);
621  }
622 }
623 
624 #ifndef _MSC_VER
625 template<typename InIterT, typename OutGridT, typename XformOp>
626 inline void
627 transformValues(const InIterT& inIter, OutGridT& outGrid, const XformOp& op,
628  bool threaded, bool /*share*/, MergePolicy merge)
629 {
630  using Adapter = TreeAdapter<OutGridT>;
631  using OutTreeT = typename Adapter::TreeType;
632  // Const ops are shared across threads, not copied.
634  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
635  proc.process(threaded);
636 }
637 #endif
638 
639 
641 
642 
643 namespace valxform {
644 
645 template<typename IterT, typename OpT>
647 {
648 public:
650 
651  // The root task makes a const copy of the original functor (mOrigOp)
652  // and keeps a pointer to the original functor (mOp), which it then modifies.
653  // Each subtask keeps a const pointer to the root task's mOrigOp
654  // and makes and then modifies a non-const copy (mOp) of it.
655  OpAccumulator(const IterT& iter, OpT& op):
656  mIsRoot(true),
657  mIter(iter),
658  mOp(&op),
659  mOrigOp(new OpT(op))
660  {}
661 
662  // When splitting this task, give the subtask a copy of the original functor,
663  // not of this task's functor, which might have been modified arbitrarily.
664  OpAccumulator(OpAccumulator& other, tbb::split):
665  mIsRoot(false),
666  mIter(other.mIter),
667  mOp(new OpT(*other.mOrigOp)),
668  mOrigOp(other.mOrigOp)
669  {}
670 
671  ~OpAccumulator() { if (mIsRoot) delete mOrigOp; else delete mOp; }
672 
673  void process(bool threaded = true)
674  {
675  IterRange range(mIter);
676  if (threaded) {
677  tbb::parallel_reduce(range, *this);
678  } else {
679  (*this)(range);
680  }
681  }
682 
683  void operator()(IterRange& r) { for ( ; r; ++r) (*mOp)(r.iterator()); }
684 
685  void join(OpAccumulator& other) { mOp->join(*other.mOp); }
686 
687 private:
688  const bool mIsRoot;
689  const IterT mIter;
690  OpT* mOp; // pointer to original functor, which might get modified
691  OpT const * const mOrigOp; // const copy of original functor
692 }; // class OpAccumulator
693 
694 } // namespace valxform
695 
696 
698 
699 
700 template<typename IterT, typename XformOp>
701 inline void
702 accumulate(const IterT& iter, XformOp& op, bool threaded)
703 {
704  typename valxform::OpAccumulator<IterT, XformOp> proc(iter, op);
705  proc.process(threaded);
706 }
707 
708 } // namespace tools
709 } // namespace OPENVDB_VERSION_NAME
710 } // namespace openvdb
711 
712 #endif // OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
713 
714 // Copyright (c) DreamWorks Animation LLC
715 // All rights reserved. This software is distributed under the
716 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
#define OPENVDB_LOG_INFO(message)
Log an info message of the form &#39;someVar << "some text" << ...&#39;.
Definition: logging.h:278
void join(OpAccumulator &other)
Definition: ValueTransformer.h:685
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:304
Definition: ValueTransformer.h:277
typename tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:369
Definition: ValueTransformer.h:263
typename tree::IteratorRange< InIterT > IterRange
Definition: ValueTransformer.h:517
CopyableOpApplier(const CopyableOpApplier &other)
Definition: ValueTransformer.h:375
void operator()(IterRange &r) const
Definition: ValueTransformer.h:388
void operator()(IterRange &r)
Definition: ValueTransformer.h:683
Definition: ValueTransformer.h:340
typename tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:343
void operator()(ValueType &v) const
Definition: ValueTransformer.h:273
void process(bool threaded=true)
Definition: ValueTransformer.h:378
~OpAccumulator()
Definition: ValueTransformer.h:671
Definition: ValueTransformer.h:270
const ValueType val
Definition: ValueTransformer.h:287
MinOp(const ValueType &v)
Definition: ValueTransformer.h:265
MultOp(const ValueType &v)
Definition: ValueTransformer.h:295
void operator()(ValueType &v) const
Definition: ValueTransformer.h:289
void join(const SharedOpTransformer &other)
Definition: ValueTransformer.h:495
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:320
MergePolicy
Definition: Types.h:555
Definition: Types.h:556
typename tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:649
void operator()(IterRange &r) const
Definition: ValueTransformer.h:357
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:128
Definition: ValueTransformer.h:366
typename InIterT::TreeT InTreeT
Definition: ValueTransformer.h:432
const ValueType val
Definition: ValueTransformer.h:294
void transformValues(const InIterT &inIter, OutGridT &outGrid, const XformOp &op, bool threaded=true, bool shareOp=true, MergePolicy merge=MERGE_ACTIVE_STATES)
Definition: ValueTransformer.h:627
CopyableOpApplier(const IterT &iter, const OpT &op)
Definition: ValueTransformer.h:371
~SharedOpTransformer()
Definition: ValueTransformer.h:460
Definition: Exceptions.h:40
typename tree::IteratorRange< InIterT > IterRange
Definition: ValueTransformer.h:433
MaxOp(const ValueType &v)
Definition: ValueTransformer.h:272
Definition: TreeIterator.h:1334
~CopyableOpTransformer()
Definition: ValueTransformer.h:548
SumOp(const ValueType &v)
Definition: ValueTransformer.h:279
void process(bool threaded=true)
Definition: ValueTransformer.h:347
OpAccumulator(const IterT &iter, OpT &op)
Definition: ValueTransformer.h:655
typename OutTreeT::ValueType OutValueT
Definition: ValueTransformer.h:434
void operator()(IterRange &range) const
Transform each element in the given range.
Definition: ValueTransformer.h:486
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:312
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:86
typename InIterT::TreeT InTreeT
Definition: ValueTransformer.h:516
void accumulate(const IterT &iter, XformOp &op, bool threaded=true)
Definition: ValueTransformer.h:702
void operator()(IterRange &range)
Transform each element in the given range.
Definition: ValueTransformer.h:574
Definition: ValueAccessor.h:220
const ValueType val
Definition: ValueTransformer.h:264
Definition: ValueTransformer.h:429
SharedOpTransformer(const InIterT &inIter, OutTreeT &outTree, OpT &op, MergePolicy merge)
Definition: ValueTransformer.h:436
SharedOpApplier(const IterT &iter, OpT &op)
Definition: ValueTransformer.h:345
void process(bool threaded=true)
Definition: ValueTransformer.h:470
void process(bool threaded=true)
Definition: ValueTransformer.h:558
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1076
const ValueType val
Definition: ValueTransformer.h:278
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:180
Definition: ValueTransformer.h:293
typename OutTreeT::ValueType OutValueT
Definition: ValueTransformer.h:518
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:328
Definition: ValueTransformer.h:646
bool ValueType
Definition: ValueTransformer.h:286
OpAccumulator(OpAccumulator &other, tbb::split)
Definition: ValueTransformer.h:664
void operator()(ValueType &v) const
Definition: ValueTransformer.h:296
CopyableOpTransformer(CopyableOpTransformer &other, tbb::split)
Definition: ValueTransformer.h:538
CopyableOpTransformer(const InIterT &inIter, OutTreeT &outTree, const OpT &op, MergePolicy merge)
Definition: ValueTransformer.h:520
void operator()(ValueType &v) const
Definition: ValueTransformer.h:280
const ValueType val
Definition: ValueTransformer.h:271
void operator()(ValueType &v) const
Definition: ValueTransformer.h:266
SharedOpTransformer(SharedOpTransformer &other, tbb::split)
Splitting constructor.
Definition: ValueTransformer.h:451
void process(bool threaded=true)
Definition: ValueTransformer.h:673
void join(const CopyableOpTransformer &other)
Definition: ValueTransformer.h:583
SumOp(const ValueType &v)
Definition: ValueTransformer.h:288