37 #ifndef OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED 38 #define OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED 49 #include <tbb/blocked_range.h> 50 #include <tbb/parallel_for.h> 51 #include <tbb/parallel_reduce.h> 52 #include <tbb/task_group.h> 53 #include <tbb/task_scheduler_init.h> 55 #include <type_traits> 67 inline void csgUnion(GridOrTreeT& a, GridOrTreeT& b,
bool prune =
true);
83 inline typename GridOrTreeT::Ptr
csgUnionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
88 inline typename GridOrTreeT::Ptr
csgIntersectionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
93 inline typename GridOrTreeT::Ptr
csgDifferenceCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
98 inline void compMax(GridOrTreeT& a, GridOrTreeT& b);
102 inline void compMin(GridOrTreeT& a, GridOrTreeT& b);
106 inline void compSum(GridOrTreeT& a, GridOrTreeT& b);
110 inline void compMul(GridOrTreeT& a, GridOrTreeT& b);
114 inline void compDiv(GridOrTreeT& a, GridOrTreeT& b);
118 inline void compReplace(GridOrTreeT& a,
const GridOrTreeT& b);
124 namespace composite {
127 template<
typename T>
inline 128 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
131 template<
typename T>
inline 132 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
137 template<
typename T>
inline 138 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
139 min(
const T& a,
const T& b)
141 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
142 return (aMag < bMag ? a : (bMag < aMag ? b :
std::min(a, b)));
145 template<
typename T>
inline 146 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
147 max(
const T& a,
const T& b)
149 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
150 return (aMag < bMag ? b : (bMag < aMag ? a :
std::max(a, b)));
154 template<
typename T>
inline 155 typename std::enable_if<!std::is_integral<T>::value, T>::type
156 divide(
const T& a,
const T& b) {
return a / b; }
158 template<
typename T>
inline 159 typename std::enable_if<std::is_integral<T>::value, T>::type
163 if (b != zero)
return a / b;
164 if (a == zero)
return 0;
171 inline bool divide(
bool a,
bool ) {
return a; }
176 template<
typename TreeType, CSGOperation Operation>
185 typedef typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type
InternalNodeType;
188 : mSegment(new TreeType(lhs.background()))
196 std::vector<const LeafNodeType*> leafNodes;
199 std::vector<const InternalNodeType*> internalNodes;
200 mLhsTree->getNodes(internalNodes);
202 ProcessInternalNodes op(internalNodes, *mRhsTree, *mSegment, leafNodes);
203 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
206 ProcessLeafNodes op(leafNodes, *mRhsTree, *mSegment);
207 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
214 struct ProcessInternalNodes {
216 ProcessInternalNodes(std::vector<const InternalNodeType*>& lhsNodes,
const TreeType& rhsTree,
217 TreeType& outputTree, std::vector<const LeafNodeType*>& outputLeafNodes)
218 : mLhsNodes(lhsNodes.empty() ? NULL : &lhsNodes.front())
220 , mLocalTree(mRhsTree->background())
221 , mOutputTree(&outputTree)
223 , mOutputLeafNodes(&outputLeafNodes)
227 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
228 : mLhsNodes(other.mLhsNodes)
229 , mRhsTree(other.mRhsTree)
230 , mLocalTree(mRhsTree->background())
231 , mOutputTree(&mLocalTree)
233 , mOutputLeafNodes(&mLocalLeafNodes)
237 void join(ProcessInternalNodes& other)
239 mOutputTree->merge(*other.mOutputTree);
240 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
241 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
244 void operator()(
const tbb::blocked_range<size_t>& range)
249 std::vector<const LeafNodeType*> tmpLeafNodes;
251 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
253 const InternalNodeType& lhsNode = *mLhsNodes[n];
254 const Coord& ijk = lhsNode.origin();
255 const InternalNodeType * rhsNode = rhsAcc.template probeConstNode<InternalNodeType>(ijk);
258 lhsNode.getNodes(*mOutputLeafNodes);
261 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
262 tmpLeafNodes.clear();
263 lhsNode.getNodes(tmpLeafNodes);
264 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
265 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
269 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
270 tmpLeafNodes.clear();
271 lhsNode.getNodes(tmpLeafNodes);
272 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
273 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
281 InternalNodeType
const *
const *
const mLhsNodes;
282 TreeType
const *
const mRhsTree;
284 TreeType *
const mOutputTree;
286 std::vector<const LeafNodeType*> mLocalLeafNodes;
287 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
290 struct ProcessLeafNodes {
292 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes,
const TreeType& rhsTree, TreeType& output)
293 : mLhsNodes(lhsNodes.empty() ? NULL : &lhsNodes.front())
295 , mLocalTree(mRhsTree->background())
296 , mOutputTree(&output)
300 ProcessLeafNodes(ProcessLeafNodes& other, tbb::split)
301 : mLhsNodes(other.mLhsNodes)
302 , mRhsTree(other.mRhsTree)
303 , mLocalTree(mRhsTree->background())
304 , mOutputTree(&mLocalTree)
308 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
310 void operator()(
const tbb::blocked_range<size_t>& range)
312 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
313 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
315 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
317 const LeafNodeType& lhsNode = *mLhsNodes[n];
318 const Coord& ijk = lhsNode.origin();
320 const LeafNodeType* rhsNodePt = rhsAcc.probeConstLeaf(ijk);
324 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
325 ValueType * outputData = outputNode->buffer().
data();
326 NodeMaskType& outputMask = outputNode->getValueMask();
328 const ValueType * lhsData = lhsNode.buffer().data();
329 const NodeMaskType& lhsMask = lhsNode.getValueMask();
331 const ValueType * rhsData = rhsNodePt->buffer().data();
332 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
335 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
336 const bool fromRhs = lhsData[pos] < rhsData[pos];
337 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
338 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
341 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
343 const bool fromRhs = lhsData[pos] < rhsVal;
344 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
345 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
348 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
349 const bool fromRhs = lhsData[pos] > rhsData[pos];
350 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
351 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
357 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
358 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
361 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
362 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
369 LeafNodeType
const *
const *
const mLhsNodes;
370 TreeType
const *
const mRhsTree;
372 TreeType *
const mOutputTree;
375 TreePtrType mSegment;
376 TreeType
const *
const mLhsTree;
377 TreeType
const *
const mRhsTree;
381 template<
typename TreeType, CSGOperation Operation>
390 typedef typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type
InternalNodeType;
393 : mSegment(new TreeType(lhs.background()))
401 std::vector<const LeafNodeType*> leafNodes;
404 std::vector<const InternalNodeType*> internalNodes;
405 mRhsTree->getNodes(internalNodes);
407 ProcessInternalNodes op(internalNodes, *mLhsTree, *mSegment, leafNodes);
408 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
411 ProcessLeafNodes op(leafNodes, *mLhsTree, *mSegment);
412 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
419 struct ProcessInternalNodes {
421 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes,
const TreeType& lhsTree,
422 TreeType& outputTree, std::vector<const LeafNodeType*>& outputLeafNodes)
423 : mRhsNodes(rhsNodes.empty() ? NULL : &rhsNodes.front())
425 , mLocalTree(mLhsTree->background())
426 , mOutputTree(&outputTree)
428 , mOutputLeafNodes(&outputLeafNodes)
432 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
433 : mRhsNodes(other.mRhsNodes)
434 , mLhsTree(other.mLhsTree)
435 , mLocalTree(mLhsTree->background())
436 , mOutputTree(&mLocalTree)
438 , mOutputLeafNodes(&mLocalLeafNodes)
442 void join(ProcessInternalNodes& other)
444 mOutputTree->merge(*other.mOutputTree);
445 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
446 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
449 void operator()(
const tbb::blocked_range<size_t>& range)
454 std::vector<const LeafNodeType*> tmpLeafNodes;
456 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
458 const InternalNodeType& rhsNode = *mRhsNodes[n];
459 const Coord& ijk = rhsNode.origin();
460 const InternalNodeType * lhsNode = lhsAcc.template probeConstNode<InternalNodeType>(ijk);
463 rhsNode.getNodes(*mOutputLeafNodes);
466 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
467 tmpLeafNodes.clear();
468 rhsNode.getNodes(tmpLeafNodes);
469 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
470 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
474 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
475 tmpLeafNodes.clear();
476 rhsNode.getNodes(tmpLeafNodes);
477 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
478 LeafNodeType* outputNode =
new LeafNodeType(*tmpLeafNodes[i]);
479 outputNode->negate();
480 outputAcc.addLeaf(outputNode);
484 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
485 tmpLeafNodes.clear();
486 rhsNode.getNodes(tmpLeafNodes);
487 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
488 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
496 InternalNodeType
const *
const *
const mRhsNodes;
497 TreeType
const *
const mLhsTree;
499 TreeType *
const mOutputTree;
501 std::vector<const LeafNodeType*> mLocalLeafNodes;
502 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
505 struct ProcessLeafNodes {
507 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes,
const TreeType& lhsTree, TreeType& output)
508 : mRhsNodes(rhsNodes.empty() ? NULL : &rhsNodes.front())
510 , mLocalTree(mLhsTree->background())
511 , mOutputTree(&output)
515 ProcessLeafNodes(ProcessLeafNodes& rhs, tbb::split)
516 : mRhsNodes(rhs.mRhsNodes)
517 , mLhsTree(rhs.mLhsTree)
518 , mLocalTree(mLhsTree->background())
519 , mOutputTree(&mLocalTree)
523 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
525 void operator()(
const tbb::blocked_range<size_t>& range)
527 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
528 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
530 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
532 const LeafNodeType& rhsNode = *mRhsNodes[n];
533 const Coord& ijk = rhsNode.origin();
535 const LeafNodeType* lhsNode = lhsAcc.probeConstLeaf(ijk);
539 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
540 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
543 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
544 LeafNodeType* outputNode =
new LeafNodeType(rhsNode);
545 outputNode->negate();
546 outputAcc.addLeaf(outputNode);
549 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
550 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
557 LeafNodeType
const *
const *
const mRhsNodes;
558 TreeType
const *
const mLhsTree;
560 TreeType *
const mOutputTree;
563 TreePtrType mSegment;
564 TreeType
const *
const mLhsTree;
565 TreeType
const *
const mRhsTree;
569 template<CSGOperation Operation,
typename TreeType>
570 inline typename TreeType::Ptr
577 tbb::task_group tasks;
579 tasks.run(secondary);
594 template<
typename TreeType>
602 template<
typename TreeType>
612 maskGrid->insertMeta(grid);
622 template <
typename LeafT>
623 using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
631 template <
typename TreeT>
632 inline void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
633 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
635 using LeafT =
typename TreeT::LeafNodeType;
637 std::vector<LeafT*> srcLeafNodes;
638 srcLeafNodes.reserve(srcTree.leafCount());
639 srcTree.stealNodes(srcLeafNodes);
641 for (LeafT *srcLeaf : srcLeafNodes) {
642 LeafT *dstLeaf = acc.probeLeaf(srcLeaf->origin());
644 overlapping.emplace_back(dstLeaf, srcLeaf);
646 acc.addLeaf(srcLeaf);
654 template <
typename TreeT,
typename OpT>
656 typename std::enable_if<!std::is_same<typename TreeT::ValueType, bool>::value &&
657 !std::is_same<typename TreeT::BuildType, ValueMask>::value &&
658 std::is_same<
typename TreeT::LeafNodeType::Buffer::ValueType,
659 typename TreeT::LeafNodeType::Buffer::StorageType>::value>::type
660 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
662 using LeafT =
typename TreeT::LeafNodeType;
663 LeafPairList<LeafT> overlapping;
664 transferLeafNodes(srcTree, dstTree, overlapping);
666 using RangeT = tbb::blocked_range<size_t>;
667 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
668 for (
auto i = r.begin(); i != r.end(); ++i) {
669 auto *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
670 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
671 auto *ptr = dstLeaf->buffer().data();
672 for (
auto v = srcLeaf->cbeginValueOn(); v; ++v) op(ptr[v.pos()], *v);
681 template <
typename TreeT,
typename OpT>
683 typename std::enable_if<std::is_same<typename TreeT::BuildType, ValueMask>::value &&
684 std::is_same<typename TreeT::ValueType, bool>::value>::type
685 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT)
687 using LeafT =
typename TreeT::LeafNodeType;
688 LeafPairList<LeafT> overlapping;
689 transferLeafNodes(srcTree, dstTree, overlapping);
691 using RangeT = tbb::blocked_range<size_t>;
692 tbb::parallel_for(RangeT(0, overlapping.size()), [&overlapping](
const RangeT& r) {
693 for (
auto i = r.begin(); i != r.end(); ++i) {
694 overlapping[i].first->getValueMask() |= overlapping[i].second->getValueMask();
695 delete overlapping[i].second;
702 template <
typename TreeT,
typename OpT>
704 typename std::enable_if<std::is_same<typename TreeT::ValueType, bool>::value &&
705 !std::is_same<typename TreeT::BuildType, ValueMask>::value>::type
706 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
708 using LeafT =
typename TreeT::LeafNodeType;
709 LeafPairList<LeafT> overlapping;
710 transferLeafNodes(srcTree, dstTree, overlapping);
712 using RangeT = tbb::blocked_range<size_t>;
713 using WordT =
typename LeafT::Buffer::WordType;
714 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
715 for (
auto i = r.begin(); i != r.end(); ++i) {
716 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
717 WordT *w1 = dstLeaf->buffer().data();
718 const WordT *w2 = srcLeaf->buffer().data();
719 const WordT *w3 = &(srcLeaf->getValueMask().template getWord<WordT>(0));
720 for (
Index32 n = LeafT::Buffer::WORD_COUNT; n--; ++w1) {
721 WordT tmp = *w1, state = *w3++;
723 *w1 = (state & tmp) | (~state & *w1);
725 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
734 template <
typename TreeT>
737 using ValueT =
typename TreeT::ValueType;
739 void operator()(ValueT& dst,
const ValueT& src)
const { dst = src; }
746 template<
typename Gr
idOrTreeT>
748 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
751 typedef typename Adapter::TreeType TreeT;
752 typedef typename TreeT::ValueType ValueT;
758 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
762 template<
typename Gr
idOrTreeT>
764 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
767 typedef typename Adapter::TreeType TreeT;
768 typedef typename TreeT::ValueType ValueT;
774 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
778 template<
typename Gr
idOrTreeT>
780 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
783 typedef typename Adapter::TreeType TreeT;
789 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
793 template<
typename Gr
idOrTreeT>
795 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
798 typedef typename Adapter::TreeType TreeT;
804 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
808 template<
typename Gr
idOrTreeT>
810 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
813 typedef typename Adapter::TreeType TreeT;
819 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
826 template<
typename TreeT>
834 void operator()(
const typename TreeT::ValueOnCIter& iter)
const 837 iter.getBoundingBox(bbox);
838 aTree->fill(bbox, *iter);
841 void operator()(
const typename TreeT::LeafCIter& leafIter)
const 844 for (
typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
845 leafIter->cbeginValueOn(); iter; ++iter)
847 acc.
setValue(iter.getCoord(), *iter);
853 template<
typename Gr
idOrTreeT>
858 typedef typename Adapter::TreeType TreeT;
859 typedef typename TreeT::ValueOnCIter ValueOnCIterT;
862 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
867 ValueOnCIterT iter = bTree.cbeginValueOn();
868 iter.setMaxDepth(iter.getLeafDepth() - 1);
869 foreach(iter, op,
false);
872 foreach(Adapter::tree(bTree).cbeginLeaf(), op);
881 template<
typename TreeType>
886 typedef typename TreeT::ValueType
ValueT;
887 typedef typename TreeT::LeafNodeType::ChildAllIter
ChildIterT;
892 mAOutside(aTree.background()),
893 mAInside(math::
negative(mAOutside)),
894 mBOutside(bTree.background()),
897 const ValueT zero = zeroVal<ValueT>();
898 if (!(mAOutside > zero)) {
900 "expected grid A outside value > 0, got " << mAOutside);
902 if (!(mAInside < zero)) {
904 "expected grid A inside value < 0, got " << mAInside);
906 if (!(mBOutside > zero)) {
908 "expected grid B outside value > 0, got " << mBOutside);
910 if (!(mBInside < zero)) {
912 "expected grid B outside value < 0, got " << mBOutside);
924 template<
typename TreeType>
928 typedef typename TreeT::ValueType
ValueT;
929 typedef typename TreeT::LeafNodeType::ChildAllIter
ChildIterT;
936 template<
typename AIterT,
typename BIterT>
940 template<
typename IterT>
943 ValueT aValue = zeroVal<ValueT>();
944 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
945 if (!aChild && aValue < zeroVal<ValueT>()) {
950 ValueT bValue = zeroVal<ValueT>();
951 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
952 if (!bChild && bValue < zeroVal<ValueT>()) {
954 aIter.setValue(this->mAInside);
955 aIter.setValueOn(bIter.isValueOn());
960 if (!aChild && aValue > zeroVal<ValueT>()) {
964 bIter.setValue(this->mBOutside);
966 bChild->resetBackground(this->mBOutside, this->mAOutside);
967 aIter.setChild(bChild);
975 return (aChild && bChild) ? 0 : STOP;
982 aIter.probeValue(aValue);
983 bIter.probeValue(bValue);
984 if (aValue > bValue) {
985 aIter.setValue(bValue);
986 aIter.setValueOn(bIter.isValueOn());
997 template<
typename TreeType>
1009 template<
typename AIterT,
typename BIterT>
1013 template<
typename IterT>
1016 ValueT aValue = zeroVal<ValueT>();
1017 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1018 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1023 ValueT bValue = zeroVal<ValueT>();
1024 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1025 if (!bChild && !(bValue < zeroVal<ValueT>())) {
1027 aIter.setValue(this->mAOutside);
1028 aIter.setValueOn(bIter.isValueOn());
1033 if (!aChild && aValue < zeroVal<ValueT>()) {
1037 bIter.setValue(this->mBOutside);
1038 bIter.setValueOff();
1039 bChild->resetBackground(this->mBOutside, this->mAOutside);
1040 aIter.setChild(bChild);
1048 return (aChild && bChild) ? 0 : STOP;
1055 aIter.probeValue(aValue);
1056 bIter.probeValue(bValue);
1057 if (aValue < bValue) {
1058 aIter.setValue(bValue);
1059 aIter.setValueOn(bIter.isValueOn());
1069 template<
typename TreeType>
1081 template<
typename AIterT,
typename BIterT>
1085 template<
typename IterT>
1088 ValueT aValue = zeroVal<ValueT>();
1089 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1090 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1095 ValueT bValue = zeroVal<ValueT>();
1096 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1097 if (!bChild && bValue < zeroVal<ValueT>()) {
1099 aIter.setValue(this->mAOutside);
1100 aIter.setValueOn(bIter.isValueOn());
1105 if (!aChild && aValue < zeroVal<ValueT>()) {
1109 bIter.setValue(this->mBOutside);
1110 bIter.setValueOff();
1111 bChild->resetBackground(this->mBOutside, this->mAOutside);
1112 aIter.setChild(bChild);
1121 return (aChild && bChild) ? 0 : STOP;
1128 aIter.probeValue(aValue);
1129 bIter.probeValue(bValue);
1131 if (aValue < bValue) {
1132 aIter.setValue(bValue);
1133 aIter.setValueOn(bIter.isValueOn());
1143 template<
typename Gr
idOrTreeT>
1148 typedef typename Adapter::TreeType TreeT;
1149 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1151 aTree.visit2(bTree, visitor);
1155 template<
typename Gr
idOrTreeT>
1160 typedef typename Adapter::TreeType TreeT;
1161 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1163 aTree.visit2(bTree, visitor);
1167 template<
typename Gr
idOrTreeT>
1172 typedef typename Adapter::TreeType TreeT;
1173 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1175 aTree.visit2(bTree, visitor);
1180 template<
typename Gr
idOrTreeT>
1185 typedef typename Adapter::TreeType::Ptr TreePtrT;
1187 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
1188 Adapter::tree(a), Adapter::tree(b));
1194 template<
typename Gr
idOrTreeT>
1199 typedef typename Adapter::TreeType::Ptr TreePtrT;
1201 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
1202 Adapter::tree(a), Adapter::tree(b));
1208 template<
typename Gr
idOrTreeT>
1213 typedef typename Adapter::TreeType::Ptr TreePtrT;
1215 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
1216 Adapter::tree(a), Adapter::tree(b));
1244 template <
typename TreeT,
typename OpT = composite::CopyOp<TreeT> >
1247 composite::doCompActiveLeafVoxels<TreeT, OpT>(srcTree, dstTree, op);
1255 #endif // OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED 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
Index32 Index
Definition: Types.h:61
SharedPtr< Grid > Ptr
Definition: Grid.h:502
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
Defined various multi-threaded utility functions for trees.
uint32_t Index32
Definition: Types.h:59
const Int32 * data() const
Definition: Coord.h:166
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition: ValueAccessor.h:288
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:108
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
Definition: Exceptions.h:40
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
const AValueType & a() const
Get the A input value.
Definition: Types.h:426
const BValueType & b() const
Get the B input value.
Definition: Types.h:428
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:386
Definition: Exceptions.h:92
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:347
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: Types.h:436