OpenVDB  5.2.0
ValueTransformer.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 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 template<typename ValueType>
284 struct MultOp {
285  const ValueType val;
286  MultOp(const ValueType& v): val(v) {}
287  inline void operator()(ValueType& v) const { v *= val; }
288 };
289 
290 }
291 
292 
293 template<typename TreeT>
294 inline void
295 setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
296 {
297  tree.modifyValue(xyz, valxform::MinOp<typename TreeT::ValueType>(value));
298 }
299 
300 
301 template<typename TreeT>
302 inline void
303 setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
304 {
305  tree.modifyValue(xyz, valxform::MaxOp<typename TreeT::ValueType>(value));
306 }
307 
308 
309 template<typename TreeT>
310 inline void
311 setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
312 {
313  tree.modifyValue(xyz, valxform::SumOp<typename TreeT::ValueType>(value));
314 }
315 
316 
317 template<typename TreeT>
318 inline void
319 setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
320 {
321  tree.modifyValue(xyz, valxform::MultOp<typename TreeT::ValueType>(value));
322 }
323 
324 
326 
327 
328 namespace valxform {
329 
330 template<typename IterT, typename OpT>
332 {
333 public:
335 
336  SharedOpApplier(const IterT& iter, OpT& op): mIter(iter), mOp(op) {}
337 
338  void process(bool threaded = true)
339  {
340  IterRange range(mIter);
341  if (threaded) {
342  tbb::parallel_for(range, *this);
343  } else {
344  (*this)(range);
345  }
346  }
347 
348  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
349 
350 private:
351  IterT mIter;
352  OpT& mOp;
353 };
354 
355 
356 template<typename IterT, typename OpT>
358 {
359 public:
361 
362  CopyableOpApplier(const IterT& iter, const OpT& op): mIter(iter), mOp(op), mOrigOp(&op) {}
363 
364  // When splitting this task, give the subtask a copy of the original functor,
365  // not of this task's functor, which might have been modified arbitrarily.
367  mIter(other.mIter), mOp(*other.mOrigOp), mOrigOp(other.mOrigOp) {}
368 
369  void process(bool threaded = true)
370  {
371  IterRange range(mIter);
372  if (threaded) {
373  tbb::parallel_for(range, *this);
374  } else {
375  (*this)(range);
376  }
377  }
378 
379  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
380 
381 private:
382  IterT mIter;
383  OpT mOp; // copy of original functor
384  OpT const * const mOrigOp; // pointer to original functor
385 };
386 
387 } // namespace valxform
388 
389 
390 template<typename IterT, typename XformOp>
391 inline void
392 foreach(const IterT& iter, XformOp& op, bool threaded, bool shared)
393 {
394  if (shared) {
395  typename valxform::SharedOpApplier<IterT, XformOp> proc(iter, op);
396  proc.process(threaded);
397  } else {
398  typedef typename valxform::CopyableOpApplier<IterT, XformOp> Processor;
399  Processor proc(iter, op);
400  proc.process(threaded);
401  }
402 }
403 
404 template<typename IterT, typename XformOp>
405 inline void
406 foreach(const IterT& iter, const XformOp& op, bool threaded, bool /*shared*/)
407 {
408  // Const ops are shared across threads, not copied.
409  typename valxform::SharedOpApplier<IterT, const XformOp> proc(iter, op);
410  proc.process(threaded);
411 }
412 
413 
415 
416 
417 namespace valxform {
418 
419 template<typename InIterT, typename OutTreeT, typename OpT>
421 {
422 public:
423  typedef typename InIterT::TreeT InTreeT;
425  typedef typename OutTreeT::ValueType OutValueT;
426 
427  SharedOpTransformer(const InIterT& inIter, OutTreeT& outTree, OpT& op, MergePolicy merge):
428  mIsRoot(true),
429  mInputIter(inIter),
430  mInputTree(inIter.getTree()),
431  mOutputTree(&outTree),
432  mOp(op),
433  mMergePolicy(merge)
434  {
435  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
436  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
437  " to transform a grid in place");
438  }
439  }
440 
443  mIsRoot(false),
444  mInputIter(other.mInputIter),
445  mInputTree(other.mInputTree),
446  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
447  mOp(other.mOp),
448  mMergePolicy(other.mMergePolicy)
449  {}
450 
452  {
453  // Delete the output tree only if it was allocated locally
454  // (the top-level output tree was supplied by the caller).
455  if (!mIsRoot) {
456  delete mOutputTree;
457  mOutputTree = NULL;
458  }
459  }
460 
461  void process(bool threaded = true)
462  {
463  if (!mInputTree || !mOutputTree) return;
464 
465  IterRange range(mInputIter);
466 
467  // Independently transform elements in the iterator range,
468  // either in parallel or serially.
469  if (threaded) {
470  tbb::parallel_reduce(range, *this);
471  } else {
472  (*this)(range);
473  }
474  }
475 
477  void operator()(IterRange& range) const
478  {
479  if (!mOutputTree) return;
480  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
481  for ( ; range; ++range) {
482  mOp(range.iterator(), outAccessor);
483  }
484  }
485 
486  void join(const SharedOpTransformer& other)
487  {
488  if (mOutputTree && other.mOutputTree) {
489  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
490  }
491  }
492 
493 private:
494  bool mIsRoot;
495  InIterT mInputIter;
496  const InTreeT* mInputTree;
497  OutTreeT* mOutputTree;
498  OpT& mOp;
499  MergePolicy mMergePolicy;
500 }; // class SharedOpTransformer
501 
502 
503 template<typename InIterT, typename OutTreeT, typename OpT>
505 {
506 public:
507  typedef typename InIterT::TreeT InTreeT;
509  typedef typename OutTreeT::ValueType OutValueT;
510 
511  CopyableOpTransformer(const InIterT& inIter, OutTreeT& outTree,
512  const OpT& op, MergePolicy merge):
513  mIsRoot(true),
514  mInputIter(inIter),
515  mInputTree(inIter.getTree()),
516  mOutputTree(&outTree),
517  mOp(op),
518  mOrigOp(&op),
519  mMergePolicy(merge)
520  {
521  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
522  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
523  " to transform a grid in place");
524  }
525  }
526 
527  // When splitting this task, give the subtask a copy of the original functor,
528  // not of this task's functor, which might have been modified arbitrarily.
530  mIsRoot(false),
531  mInputIter(other.mInputIter),
532  mInputTree(other.mInputTree),
533  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
534  mOp(*other.mOrigOp),
535  mOrigOp(other.mOrigOp),
536  mMergePolicy(other.mMergePolicy)
537  {}
538 
540  {
541  // Delete the output tree only if it was allocated locally
542  // (the top-level output tree was supplied by the caller).
543  if (!mIsRoot) {
544  delete mOutputTree;
545  mOutputTree = NULL;
546  }
547  }
548 
549  void process(bool threaded = true)
550  {
551  if (!mInputTree || !mOutputTree) return;
552 
553  IterRange range(mInputIter);
554 
555  // Independently transform elements in the iterator range,
556  // either in parallel or serially.
557  if (threaded) {
558  tbb::parallel_reduce(range, *this);
559  } else {
560  (*this)(range);
561  }
562  }
563 
565  void operator()(IterRange& range)
566  {
567  if (!mOutputTree) return;
568  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
569  for ( ; range; ++range) {
570  mOp(range.iterator(), outAccessor);
571  }
572  }
573 
574  void join(const CopyableOpTransformer& other)
575  {
576  if (mOutputTree && other.mOutputTree) {
577  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
578  }
579  }
580 
581 private:
582  bool mIsRoot;
583  InIterT mInputIter;
584  const InTreeT* mInputTree;
585  OutTreeT* mOutputTree;
586  OpT mOp; // copy of original functor
587  OpT const * const mOrigOp; // pointer to original functor
588  MergePolicy mMergePolicy;
589 }; // class CopyableOpTransformer
590 
591 } // namespace valxform
592 
593 
595 
596 
597 template<typename InIterT, typename OutGridT, typename XformOp>
598 inline void
599 transformValues(const InIterT& inIter, OutGridT& outGrid, XformOp& op,
600  bool threaded, bool shared, MergePolicy merge)
601 {
602  typedef TreeAdapter<OutGridT> Adapter;
603  typedef typename Adapter::TreeType OutTreeT;
604  if (shared) {
606  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
607  proc.process(threaded);
608  } else {
610  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
611  proc.process(threaded);
612  }
613 }
614 
615 #ifndef _MSC_VER
616 template<typename InIterT, typename OutGridT, typename XformOp>
617 inline void
618 transformValues(const InIterT& inIter, OutGridT& outGrid, const XformOp& op,
619  bool threaded, bool /*share*/, MergePolicy merge)
620 {
621  typedef TreeAdapter<OutGridT> Adapter;
622  typedef typename Adapter::TreeType OutTreeT;
623  // Const ops are shared across threads, not copied.
625  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
626  proc.process(threaded);
627 }
628 #endif
629 
630 
632 
633 
634 namespace valxform {
635 
636 template<typename IterT, typename OpT>
638 {
639 public:
641 
642  // The root task makes a const copy of the original functor (mOrigOp)
643  // and keeps a pointer to the original functor (mOp), which it then modifies.
644  // Each subtask keeps a const pointer to the root task's mOrigOp
645  // and makes and then modifies a non-const copy (mOp) of it.
646  OpAccumulator(const IterT& iter, OpT& op):
647  mIsRoot(true),
648  mIter(iter),
649  mOp(&op),
650  mOrigOp(new OpT(op))
651  {}
652 
653  // When splitting this task, give the subtask a copy of the original functor,
654  // not of this task's functor, which might have been modified arbitrarily.
655  OpAccumulator(OpAccumulator& other, tbb::split):
656  mIsRoot(false),
657  mIter(other.mIter),
658  mOp(new OpT(*other.mOrigOp)),
659  mOrigOp(other.mOrigOp)
660  {}
661 
662  ~OpAccumulator() { if (mIsRoot) delete mOrigOp; else delete mOp; }
663 
664  void process(bool threaded = true)
665  {
666  IterRange range(mIter);
667  if (threaded) {
668  tbb::parallel_reduce(range, *this);
669  } else {
670  (*this)(range);
671  }
672  }
673 
674  void operator()(IterRange& r) { for ( ; r; ++r) (*mOp)(r.iterator()); }
675 
676  void join(OpAccumulator& other) { mOp->join(*other.mOp); }
677 
678 private:
679  const bool mIsRoot;
680  const IterT mIter;
681  OpT* mOp; // pointer to original functor, which might get modified
682  OpT const * const mOrigOp; // const copy of original functor
683 }; // class OpAccumulator
684 
685 } // namespace valxform
686 
687 
689 
690 
691 template<typename IterT, typename XformOp>
692 inline void
693 accumulate(const IterT& iter, XformOp& op, bool threaded)
694 {
695  typename valxform::OpAccumulator<IterT, XformOp> proc(iter, op);
696  proc.process(threaded);
697 }
698 
699 } // namespace tools
700 } // namespace OPENVDB_VERSION_NAME
701 } // namespace openvdb
702 
703 #endif // OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
704 
705 // Copyright (c) 2012-2018 DreamWorks Animation LLC
706 // All rights reserved. This software is distributed under the
707 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
MaxOp(const ValueType &v)
Definition: ValueTransformer.h:272
void operator()(ValueType &v) const
Definition: ValueTransformer.h:273
~CopyableOpTransformer()
Definition: ValueTransformer.h:539
void operator()(ValueType &v) const
Definition: ValueTransformer.h:266
void join(const SharedOpTransformer &other)
Definition: ValueTransformer.h:486
void operator()(IterRange &r)
Definition: ValueTransformer.h:674
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
InIterT::TreeT InTreeT
Definition: ValueTransformer.h:507
~OpAccumulator()
Definition: ValueTransformer.h:662
MinOp(const ValueType &v)
Definition: ValueTransformer.h:265
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:303
void process(bool threaded=true)
Definition: ValueTransformer.h:549
SharedOpApplier(const IterT &iter, OpT &op)
Definition: ValueTransformer.h:336
Definition: ValueTransformer.h:270
void process(bool threaded=true)
Definition: ValueTransformer.h:338
Definition: ValueTransformer.h:284
OutTreeT::ValueType OutValueT
Definition: ValueTransformer.h:425
void join(const CopyableOpTransformer &other)
Definition: ValueTransformer.h:574
OutTreeT::ValueType OutValueT
Definition: ValueTransformer.h:509
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:319
Definition: ValueTransformer.h:263
void accumulate(const IterT &iter, XformOp &op, bool threaded=true)
Definition: ValueTransformer.h:693
tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:334
tree::IteratorRange< InIterT > IterRange
Definition: ValueTransformer.h:508
Definition: ValueAccessor.h:220
MultOp(const ValueType &v)
Definition: ValueTransformer.h:286
void operator()(IterRange &range) const
Transform each element in the given range.
Definition: ValueTransformer.h:477
void operator()(IterRange &range)
Transform each element in the given range.
Definition: ValueTransformer.h:565
const ValueType val
Definition: ValueTransformer.h:271
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:311
void operator()(IterRange &r) const
Definition: ValueTransformer.h:348
void operator()(IterRange &r) const
Definition: ValueTransformer.h:379
Definition: ValueTransformer.h:357
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
const ValueType val
Definition: ValueTransformer.h:285
~SharedOpTransformer()
Definition: ValueTransformer.h:451
CopyableOpApplier(const CopyableOpApplier &other)
Definition: ValueTransformer.h:366
Definition: ValueTransformer.h:420
CopyableOpTransformer(const InIterT &inIter, OutTreeT &outTree, const OpT &op, MergePolicy merge)
Definition: ValueTransformer.h:511
CopyableOpTransformer(CopyableOpTransformer &other, tbb::split)
Definition: ValueTransformer.h:529
Definition: Exceptions.h:40
const ValueType val
Definition: ValueTransformer.h:278
void operator()(ValueType &v) const
Definition: ValueTransformer.h:287
Definition: ValueTransformer.h:331
void process(bool threaded=true)
Definition: ValueTransformer.h:461
Definition: ValueTransformer.h:637
MergePolicy
Definition: Types.h:328
void transformValues(const InIterT &inIter, OutGridT &outGrid, const XformOp &op, bool threaded=true, bool shareOp=true, MergePolicy merge=MERGE_ACTIVE_STATES)
Definition: ValueTransformer.h:618
void process(bool threaded=true)
Definition: ValueTransformer.h:369
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:86
Definition: TreeIterator.h:1351
OpAccumulator(const IterT &iter, OpT &op)
Definition: ValueTransformer.h:646
tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:360
OpAccumulator(OpAccumulator &other, tbb::split)
Definition: ValueTransformer.h:655
const ValueType val
Definition: ValueTransformer.h:264
tree::IteratorRange< IterT > IterRange
Definition: ValueTransformer.h:640
void operator()(ValueType &v) const
Definition: ValueTransformer.h:280
#define OPENVDB_LOG_INFO(message)
Log an info message of the form &#39;someVar << "some text" << ...&#39;.
Definition: logging.h:278
void process(bool threaded=true)
Definition: ValueTransformer.h:664
Definition: Types.h:329
SharedOpTransformer(SharedOpTransformer &other, tbb::split)
Splitting constructor.
Definition: ValueTransformer.h:442
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
SharedOpTransformer(const InIterT &inIter, OutTreeT &outTree, OpT &op, MergePolicy merge)
Definition: ValueTransformer.h:427
SumOp(const ValueType &v)
Definition: ValueTransformer.h:279
void join(OpAccumulator &other)
Definition: ValueTransformer.h:676
Definition: ValueTransformer.h:277
tree::IteratorRange< InIterT > IterRange
Definition: ValueTransformer.h:424
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:944
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:295
InIterT::TreeT InTreeT
Definition: ValueTransformer.h:423
CopyableOpApplier(const IterT &iter, const OpT &op)
Definition: ValueTransformer.h:362
const IterT & iterator() const
Return a reference to this range&#39;s iterator.
Definition: TreeIterator.h:1372