10 #ifndef OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
11 #define OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
22 #include <tbb/blocked_range.h>
23 #include <tbb/parallel_for.h>
24 #include <tbb/parallel_reduce.h>
25 #include <tbb/task_group.h>
26 #include <tbb/task_scheduler_init.h>
28 #include <type_traits>
40 inline void csgUnion(GridOrTreeT& a, GridOrTreeT& b,
bool prune =
true);
56 inline typename GridOrTreeT::Ptr
csgUnionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
61 inline typename GridOrTreeT::Ptr
csgIntersectionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
66 inline typename GridOrTreeT::Ptr
csgDifferenceCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
71 inline void compMax(GridOrTreeT& a, GridOrTreeT& b);
75 inline void compMin(GridOrTreeT& a, GridOrTreeT& b);
79 inline void compSum(GridOrTreeT& a, GridOrTreeT& b);
83 inline void compMul(GridOrTreeT& a, GridOrTreeT& b);
87 inline void compDiv(GridOrTreeT& a, GridOrTreeT& b);
91 inline void compReplace(GridOrTreeT& a,
const GridOrTreeT& b);
100 template<
typename T>
inline
101 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
104 template<
typename T>
inline
105 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
110 template<
typename T>
inline
111 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
112 min(
const T& a,
const T& b)
114 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
115 return (aMag < bMag ? a : (bMag < aMag ? b :
std::min(a, b)));
118 template<
typename T>
inline
119 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
120 max(
const T& a,
const T& b)
122 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
123 return (aMag < bMag ? b : (bMag < aMag ? a :
std::max(a, b)));
127 template<
typename T>
inline
128 typename std::enable_if<!std::is_integral<T>::value, T>::type
129 divide(
const T& a,
const T& b) {
return a / b; }
131 template<
typename T>
inline
132 typename std::enable_if<std::is_integral<T>::value, T>::type
136 if (b != zero)
return a / b;
137 if (a == zero)
return 0;
144 inline bool divide(
bool a,
bool ) {
return a; }
149 template<
typename TreeType, CSGOperation Operation>
158 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
161 : mSegment(new TreeType(lhs.background()))
169 std::vector<const LeafNodeType*> leafNodes;
172 std::vector<const InternalNodeType*> internalNodes;
173 mLhsTree->getNodes(internalNodes);
175 ProcessInternalNodes op(internalNodes, *mRhsTree, *mSegment, leafNodes);
176 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
179 ProcessLeafNodes op(leafNodes, *mRhsTree, *mSegment);
180 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
187 struct ProcessInternalNodes {
189 ProcessInternalNodes(std::vector<const InternalNodeType*>& lhsNodes,
190 const TreeType& rhsTree, TreeType& outputTree,
191 std::vector<const LeafNodeType*>& outputLeafNodes)
192 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
194 , mLocalTree(mRhsTree->background())
195 , mOutputTree(&outputTree)
197 , mOutputLeafNodes(&outputLeafNodes)
201 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
202 : mLhsNodes(other.mLhsNodes)
203 , mRhsTree(other.mRhsTree)
204 , mLocalTree(mRhsTree->background())
205 , mOutputTree(&mLocalTree)
207 , mOutputLeafNodes(&mLocalLeafNodes)
211 void join(ProcessInternalNodes& other)
213 mOutputTree->merge(*other.mOutputTree);
214 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
215 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
218 void operator()(
const tbb::blocked_range<size_t>& range)
223 std::vector<const LeafNodeType*> tmpLeafNodes;
225 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
227 const InternalNodeType& lhsNode = *mLhsNodes[n];
228 const Coord& ijk = lhsNode.origin();
229 const InternalNodeType * rhsNode =
230 rhsAcc.template probeConstNode<InternalNodeType>(ijk);
233 lhsNode.getNodes(*mOutputLeafNodes);
236 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
237 tmpLeafNodes.clear();
238 lhsNode.getNodes(tmpLeafNodes);
239 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
240 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
244 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
245 tmpLeafNodes.clear();
246 lhsNode.getNodes(tmpLeafNodes);
247 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
248 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
256 InternalNodeType
const *
const *
const mLhsNodes;
257 TreeType
const *
const mRhsTree;
259 TreeType *
const mOutputTree;
261 std::vector<const LeafNodeType*> mLocalLeafNodes;
262 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
265 struct ProcessLeafNodes {
267 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes,
268 const TreeType& rhsTree, TreeType& output)
269 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
271 , mLocalTree(mRhsTree->background())
272 , mOutputTree(&output)
276 ProcessLeafNodes(ProcessLeafNodes& other, tbb::split)
277 : mLhsNodes(other.mLhsNodes)
278 , mRhsTree(other.mRhsTree)
279 , mLocalTree(mRhsTree->background())
280 , mOutputTree(&mLocalTree)
284 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
286 void operator()(
const tbb::blocked_range<size_t>& range)
288 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
289 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
291 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
293 const LeafNodeType& lhsNode = *mLhsNodes[n];
294 const Coord& ijk = lhsNode.origin();
296 const LeafNodeType* rhsNodePt = rhsAcc.probeConstLeaf(ijk);
300 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
301 ValueType * outputData = outputNode->buffer().
data();
302 NodeMaskType& outputMask = outputNode->getValueMask();
304 const ValueType * lhsData = lhsNode.buffer().data();
305 const NodeMaskType& lhsMask = lhsNode.getValueMask();
307 const ValueType * rhsData = rhsNodePt->buffer().data();
308 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
311 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
312 const bool fromRhs = lhsData[pos] < rhsData[pos];
313 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
314 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
317 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
319 const bool fromRhs = lhsData[pos] < rhsVal;
320 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
321 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
324 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
325 const bool fromRhs = lhsData[pos] > rhsData[pos];
326 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
327 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
333 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
334 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
337 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
338 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
345 LeafNodeType
const *
const *
const mLhsNodes;
346 TreeType
const *
const mRhsTree;
348 TreeType *
const mOutputTree;
351 TreePtrType mSegment;
352 TreeType
const *
const mLhsTree;
353 TreeType
const *
const mRhsTree;
357 template<
typename TreeType, CSGOperation Operation>
366 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
369 : mSegment(new TreeType(lhs.background()))
377 std::vector<const LeafNodeType*> leafNodes;
380 std::vector<const InternalNodeType*> internalNodes;
381 mRhsTree->getNodes(internalNodes);
383 ProcessInternalNodes op(internalNodes, *mLhsTree, *mSegment, leafNodes);
384 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
387 ProcessLeafNodes op(leafNodes, *mLhsTree, *mSegment);
388 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
395 struct ProcessInternalNodes {
397 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes,
398 const TreeType& lhsTree, TreeType& outputTree,
399 std::vector<const LeafNodeType*>& outputLeafNodes)
400 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
402 , mLocalTree(mLhsTree->background())
403 , mOutputTree(&outputTree)
405 , mOutputLeafNodes(&outputLeafNodes)
409 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
410 : mRhsNodes(other.mRhsNodes)
411 , mLhsTree(other.mLhsTree)
412 , mLocalTree(mLhsTree->background())
413 , mOutputTree(&mLocalTree)
415 , mOutputLeafNodes(&mLocalLeafNodes)
419 void join(ProcessInternalNodes& other)
421 mOutputTree->merge(*other.mOutputTree);
422 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
423 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
426 void operator()(
const tbb::blocked_range<size_t>& range)
431 std::vector<const LeafNodeType*> tmpLeafNodes;
433 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
435 const InternalNodeType& rhsNode = *mRhsNodes[n];
436 const Coord& ijk = rhsNode.origin();
437 const InternalNodeType * lhsNode =
438 lhsAcc.template probeConstNode<InternalNodeType>(ijk);
441 rhsNode.getNodes(*mOutputLeafNodes);
444 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
445 tmpLeafNodes.clear();
446 rhsNode.getNodes(tmpLeafNodes);
447 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
448 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
452 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
453 tmpLeafNodes.clear();
454 rhsNode.getNodes(tmpLeafNodes);
455 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
456 LeafNodeType* outputNode =
new LeafNodeType(*tmpLeafNodes[i]);
457 outputNode->negate();
458 outputAcc.addLeaf(outputNode);
462 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
463 tmpLeafNodes.clear();
464 rhsNode.getNodes(tmpLeafNodes);
465 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
466 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
474 InternalNodeType
const *
const *
const mRhsNodes;
475 TreeType
const *
const mLhsTree;
477 TreeType *
const mOutputTree;
479 std::vector<const LeafNodeType*> mLocalLeafNodes;
480 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
483 struct ProcessLeafNodes {
485 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes,
486 const TreeType& lhsTree, TreeType& output)
487 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
489 , mLocalTree(mLhsTree->background())
490 , mOutputTree(&output)
494 ProcessLeafNodes(ProcessLeafNodes& rhs, tbb::split)
495 : mRhsNodes(rhs.mRhsNodes)
496 , mLhsTree(rhs.mLhsTree)
497 , mLocalTree(mLhsTree->background())
498 , mOutputTree(&mLocalTree)
502 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
504 void operator()(
const tbb::blocked_range<size_t>& range)
506 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
507 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
509 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
511 const LeafNodeType& rhsNode = *mRhsNodes[n];
512 const Coord& ijk = rhsNode.origin();
514 const LeafNodeType* lhsNode = lhsAcc.probeConstLeaf(ijk);
518 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
519 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
522 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
523 LeafNodeType* outputNode =
new LeafNodeType(rhsNode);
524 outputNode->negate();
525 outputAcc.addLeaf(outputNode);
528 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
529 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
536 LeafNodeType
const *
const *
const mRhsNodes;
537 TreeType
const *
const mLhsTree;
539 TreeType *
const mOutputTree;
542 TreePtrType mSegment;
543 TreeType
const *
const mLhsTree;
544 TreeType
const *
const mRhsTree;
548 template<CSGOperation Operation,
typename TreeType>
549 inline typename TreeType::Ptr
556 tbb::task_group tasks;
558 tasks.run(secondary);
573 template<
typename TreeType>
581 template<
typename TreeType>
590 maskGrid->setTransform(grid.transform().
copy());
591 maskGrid->insertMeta(grid);
601 template <
typename LeafT>
602 using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
610 template <
typename TreeT>
611 inline void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
612 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
614 using LeafT =
typename TreeT::LeafNodeType;
616 std::vector<LeafT*> srcLeafNodes;
617 srcLeafNodes.reserve(srcTree.leafCount());
618 srcTree.stealNodes(srcLeafNodes);
620 for (LeafT *srcLeaf : srcLeafNodes) {
621 LeafT *dstLeaf = acc.probeLeaf(srcLeaf->origin());
623 overlapping.emplace_back(dstLeaf, srcLeaf);
625 acc.addLeaf(srcLeaf);
633 template <
typename TreeT,
typename OpT>
635 typename std::enable_if<
636 !std::is_same<typename TreeT::ValueType, bool>::value &&
637 !std::is_same<typename TreeT::BuildType, ValueMask>::value &&
638 std::is_same<
typename TreeT::LeafNodeType::Buffer::ValueType,
639 typename TreeT::LeafNodeType::Buffer::StorageType>::value>::type
640 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
642 using LeafT =
typename TreeT::LeafNodeType;
643 LeafPairList<LeafT> overlapping;
644 transferLeafNodes(srcTree, dstTree, overlapping);
646 using RangeT = tbb::blocked_range<size_t>;
647 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
648 for (auto i = r.begin(); i != r.end(); ++i) {
649 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
650 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
651 auto *ptr = dstLeaf->buffer().data();
652 for (auto v = srcLeaf->cbeginValueOn(); v; ++v) op(ptr[v.pos()], *v);
661 template <
typename TreeT,
typename OpT>
663 typename std::enable_if<
664 std::is_same<typename TreeT::BuildType, ValueMask>::value &&
665 std::is_same<typename TreeT::ValueType, bool>::value>::type
666 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT)
668 using LeafT =
typename TreeT::LeafNodeType;
669 LeafPairList<LeafT> overlapping;
670 transferLeafNodes(srcTree, dstTree, overlapping);
672 using RangeT = tbb::blocked_range<size_t>;
673 tbb::parallel_for(RangeT(0, overlapping.size()), [&overlapping](
const RangeT& r) {
674 for (auto i = r.begin(); i != r.end(); ++i) {
675 overlapping[i].first->getValueMask() |= overlapping[i].second->getValueMask();
676 delete overlapping[i].second;
683 template <
typename TreeT,
typename OpT>
685 typename std::enable_if<
686 std::is_same<typename TreeT::ValueType, bool>::value &&
687 !std::is_same<typename TreeT::BuildType, ValueMask>::value>::type
688 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
690 using LeafT =
typename TreeT::LeafNodeType;
691 LeafPairList<LeafT> overlapping;
692 transferLeafNodes(srcTree, dstTree, overlapping);
694 using RangeT = tbb::blocked_range<size_t>;
695 using WordT =
typename LeafT::Buffer::WordType;
696 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
697 for (auto i = r.begin(); i != r.end(); ++i) {
698 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
699 WordT *w1 = dstLeaf->buffer().data();
700 const WordT *w2 = srcLeaf->buffer().data();
701 const WordT *w3 = &(srcLeaf->getValueMask().template getWord<WordT>(0));
702 for (Index32 n = LeafT::Buffer::WORD_COUNT; n--; ++w1) {
703 WordT tmp = *w1, state = *w3++;
705 *w1 = (state & tmp) | (~state & *w1);
707 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
716 template <
typename TreeT>
719 using ValueT =
typename TreeT::ValueType;
721 void operator()(ValueT& dst,
const ValueT& src)
const { dst = src; }
728 template<
typename Gr
idOrTreeT>
730 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
733 using TreeT =
typename Adapter::TreeType;
734 using ValueT =
typename TreeT::ValueType;
740 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
744 template<
typename Gr
idOrTreeT>
746 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
749 using TreeT =
typename Adapter::TreeType;
750 using ValueT =
typename TreeT::ValueType;
756 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
760 template<
typename Gr
idOrTreeT>
762 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
765 using TreeT =
typename Adapter::TreeType;
771 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
775 template<
typename Gr
idOrTreeT>
777 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
780 using TreeT =
typename Adapter::TreeType;
786 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
790 template<
typename Gr
idOrTreeT>
792 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
795 using TreeT =
typename Adapter::TreeType;
801 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
808 template<
typename TreeT>
816 void operator()(
const typename TreeT::ValueOnCIter& iter)
const
819 iter.getBoundingBox(bbox);
820 aTree->fill(bbox, *iter);
823 void operator()(
const typename TreeT::LeafCIter& leafIter)
const
826 for (
typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
827 leafIter->cbeginValueOn(); iter; ++iter)
829 acc.
setValue(iter.getCoord(), *iter);
835 template<
typename Gr
idOrTreeT>
840 using TreeT =
typename Adapter::TreeType;
841 using ValueOnCIterT =
typename TreeT::ValueOnCIter;
844 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
849 ValueOnCIterT iter = bTree.cbeginValueOn();
850 iter.setMaxDepth(iter.getLeafDepth() - 1);
851 foreach(iter, op,
false);
854 foreach(Adapter::tree(bTree).cbeginLeaf(), op);
863 template<
typename TreeType>
868 using ValueT =
typename TreeT::ValueType;
869 using ChildIterT =
typename TreeT::LeafNodeType::ChildAllIter;
874 mAOutside(aTree.background()),
875 mAInside(math::
negative(mAOutside)),
876 mBOutside(bTree.background()),
879 const ValueT zero = zeroVal<ValueT>();
880 if (!(mAOutside > zero)) {
882 "expected grid A outside value > 0, got " << mAOutside);
884 if (!(mAInside < zero)) {
886 "expected grid A inside value < 0, got " << mAInside);
888 if (!(mBOutside > zero)) {
890 "expected grid B outside value > 0, got " << mBOutside);
892 if (!(mBInside < zero)) {
894 "expected grid B outside value < 0, got " << mBOutside);
906 template<
typename TreeType>
910 using ValueT =
typename TreeT::ValueType;
911 using ChildIterT =
typename TreeT::LeafNodeType::ChildAllIter;
918 template<
typename AIterT,
typename BIterT>
922 template<
typename IterT>
925 ValueT aValue = zeroVal<ValueT>();
926 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
927 if (!aChild && aValue < zeroVal<ValueT>()) {
932 ValueT bValue = zeroVal<ValueT>();
933 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
934 if (!bChild && bValue < zeroVal<ValueT>()) {
936 aIter.setValue(this->mAInside);
937 aIter.setValueOn(bIter.isValueOn());
942 if (!aChild && aValue > zeroVal<ValueT>()) {
946 bIter.setValue(this->mBOutside);
948 bChild->resetBackground(this->mBOutside, this->mAOutside);
949 aIter.setChild(bChild);
957 return (aChild && bChild) ? 0 : STOP;
964 aIter.probeValue(aValue);
965 bIter.probeValue(bValue);
966 if (aValue > bValue) {
967 aIter.setValue(bValue);
968 aIter.setValueOn(bIter.isValueOn());
979 template<
typename TreeType>
983 using ValueT =
typename TreeT::ValueType;
984 using ChildIterT =
typename TreeT::LeafNodeType::ChildAllIter;
991 template<
typename AIterT,
typename BIterT>
995 template<
typename IterT>
998 ValueT aValue = zeroVal<ValueT>();
999 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1000 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1005 ValueT bValue = zeroVal<ValueT>();
1006 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1007 if (!bChild && !(bValue < zeroVal<ValueT>())) {
1009 aIter.setValue(this->mAOutside);
1010 aIter.setValueOn(bIter.isValueOn());
1015 if (!aChild && aValue < zeroVal<ValueT>()) {
1019 bIter.setValue(this->mBOutside);
1020 bIter.setValueOff();
1021 bChild->resetBackground(this->mBOutside, this->mAOutside);
1022 aIter.setChild(bChild);
1030 return (aChild && bChild) ? 0 : STOP;
1037 aIter.probeValue(aValue);
1038 bIter.probeValue(bValue);
1039 if (aValue < bValue) {
1040 aIter.setValue(bValue);
1041 aIter.setValueOn(bIter.isValueOn());
1051 template<
typename TreeType>
1063 template<
typename AIterT,
typename BIterT>
1067 template<
typename IterT>
1070 ValueT aValue = zeroVal<ValueT>();
1071 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1072 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1077 ValueT bValue = zeroVal<ValueT>();
1078 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1079 if (!bChild && bValue < zeroVal<ValueT>()) {
1081 aIter.setValue(this->mAOutside);
1082 aIter.setValueOn(bIter.isValueOn());
1087 if (!aChild && aValue < zeroVal<ValueT>()) {
1091 bIter.setValue(this->mBOutside);
1092 bIter.setValueOff();
1093 bChild->resetBackground(this->mBOutside, this->mAOutside);
1094 aIter.setChild(bChild);
1103 return (aChild && bChild) ? 0 : STOP;
1110 aIter.probeValue(aValue);
1111 bIter.probeValue(bValue);
1113 if (aValue < bValue) {
1114 aIter.setValue(bValue);
1115 aIter.setValueOn(bIter.isValueOn());
1125 template<
typename Gr
idOrTreeT>
1130 using TreeT =
typename Adapter::TreeType;
1131 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1133 aTree.visit2(bTree, visitor);
1137 template<
typename Gr
idOrTreeT>
1142 using TreeT =
typename Adapter::TreeType;
1143 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1145 aTree.visit2(bTree, visitor);
1149 template<
typename Gr
idOrTreeT>
1154 using TreeT =
typename Adapter::TreeType;
1155 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1157 aTree.visit2(bTree, visitor);
1162 template<
typename Gr
idOrTreeT>
1167 using TreePtrT =
typename Adapter::TreeType::Ptr;
1169 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
1170 Adapter::tree(a), Adapter::tree(b));
1176 template<
typename Gr
idOrTreeT>
1181 using TreePtrT =
typename Adapter::TreeType::Ptr;
1183 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
1184 Adapter::tree(a), Adapter::tree(b));
1190 template<
typename Gr
idOrTreeT>
1195 using TreePtrT =
typename Adapter::TreeType::Ptr;
1197 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
1198 Adapter::tree(a), Adapter::tree(b));
1226 template<
typename TreeT,
typename OpT = composite::CopyOp<TreeT> >
1230 composite::doCompActiveLeafVoxels<TreeT, OpT>(srcTree, dstTree, op);
1238 #endif // OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED