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 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
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,
217 const TreeType& rhsTree, TreeType& outputTree,
218 std::vector<const LeafNodeType*>& outputLeafNodes)
219 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
221 , mLocalTree(mRhsTree->background())
222 , mOutputTree(&outputTree)
224 , mOutputLeafNodes(&outputLeafNodes)
228 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
229 : mLhsNodes(other.mLhsNodes)
230 , mRhsTree(other.mRhsTree)
231 , mLocalTree(mRhsTree->background())
232 , mOutputTree(&mLocalTree)
234 , mOutputLeafNodes(&mLocalLeafNodes)
238 void join(ProcessInternalNodes& other)
240 mOutputTree->merge(*other.mOutputTree);
241 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
242 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
245 void operator()(
const tbb::blocked_range<size_t>& range)
250 std::vector<const LeafNodeType*> tmpLeafNodes;
252 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
254 const InternalNodeType& lhsNode = *mLhsNodes[n];
255 const Coord& ijk = lhsNode.origin();
256 const InternalNodeType * rhsNode =
257 rhsAcc.template probeConstNode<InternalNodeType>(ijk);
260 lhsNode.getNodes(*mOutputLeafNodes);
263 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
264 tmpLeafNodes.clear();
265 lhsNode.getNodes(tmpLeafNodes);
266 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
267 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
271 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
272 tmpLeafNodes.clear();
273 lhsNode.getNodes(tmpLeafNodes);
274 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
275 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
283 InternalNodeType
const *
const *
const mLhsNodes;
284 TreeType
const *
const mRhsTree;
286 TreeType *
const mOutputTree;
288 std::vector<const LeafNodeType*> mLocalLeafNodes;
289 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
292 struct ProcessLeafNodes {
294 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes,
295 const TreeType& rhsTree, TreeType& output)
296 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
298 , mLocalTree(mRhsTree->background())
299 , mOutputTree(&output)
303 ProcessLeafNodes(ProcessLeafNodes& other, tbb::split)
304 : mLhsNodes(other.mLhsNodes)
305 , mRhsTree(other.mRhsTree)
306 , mLocalTree(mRhsTree->background())
307 , mOutputTree(&mLocalTree)
311 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
313 void operator()(
const tbb::blocked_range<size_t>& range)
315 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
316 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
318 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
320 const LeafNodeType& lhsNode = *mLhsNodes[n];
321 const Coord& ijk = lhsNode.origin();
323 const LeafNodeType* rhsNodePt = rhsAcc.probeConstLeaf(ijk);
327 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
328 ValueType * outputData = outputNode->buffer().
data();
329 NodeMaskType& outputMask = outputNode->getValueMask();
331 const ValueType * lhsData = lhsNode.buffer().data();
332 const NodeMaskType& lhsMask = lhsNode.getValueMask();
334 const ValueType * rhsData = rhsNodePt->buffer().data();
335 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
338 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
339 const bool fromRhs = lhsData[pos] < rhsData[pos];
340 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
341 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
344 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
346 const bool fromRhs = lhsData[pos] < rhsVal;
347 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
348 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
351 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
352 const bool fromRhs = lhsData[pos] > rhsData[pos];
353 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
354 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
360 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
361 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
364 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
365 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
372 LeafNodeType
const *
const *
const mLhsNodes;
373 TreeType
const *
const mRhsTree;
375 TreeType *
const mOutputTree;
378 TreePtrType mSegment;
379 TreeType
const *
const mLhsTree;
380 TreeType
const *
const mRhsTree;
384 template<
typename TreeType, CSGOperation Operation>
393 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
396 : mSegment(new TreeType(lhs.background()))
404 std::vector<const LeafNodeType*> leafNodes;
407 std::vector<const InternalNodeType*> internalNodes;
408 mRhsTree->getNodes(internalNodes);
410 ProcessInternalNodes op(internalNodes, *mLhsTree, *mSegment, leafNodes);
411 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
414 ProcessLeafNodes op(leafNodes, *mLhsTree, *mSegment);
415 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
422 struct ProcessInternalNodes {
424 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes,
425 const TreeType& lhsTree, TreeType& outputTree,
426 std::vector<const LeafNodeType*>& outputLeafNodes)
427 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
429 , mLocalTree(mLhsTree->background())
430 , mOutputTree(&outputTree)
432 , mOutputLeafNodes(&outputLeafNodes)
436 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
437 : mRhsNodes(other.mRhsNodes)
438 , mLhsTree(other.mLhsTree)
439 , mLocalTree(mLhsTree->background())
440 , mOutputTree(&mLocalTree)
442 , mOutputLeafNodes(&mLocalLeafNodes)
446 void join(ProcessInternalNodes& other)
448 mOutputTree->merge(*other.mOutputTree);
449 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
450 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
453 void operator()(
const tbb::blocked_range<size_t>& range)
458 std::vector<const LeafNodeType*> tmpLeafNodes;
460 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
462 const InternalNodeType& rhsNode = *mRhsNodes[n];
463 const Coord& ijk = rhsNode.origin();
464 const InternalNodeType * lhsNode =
465 lhsAcc.template probeConstNode<InternalNodeType>(ijk);
468 rhsNode.getNodes(*mOutputLeafNodes);
471 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
472 tmpLeafNodes.clear();
473 rhsNode.getNodes(tmpLeafNodes);
474 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
475 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
479 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
480 tmpLeafNodes.clear();
481 rhsNode.getNodes(tmpLeafNodes);
482 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
483 LeafNodeType* outputNode =
new LeafNodeType(*tmpLeafNodes[i]);
484 outputNode->negate();
485 outputAcc.addLeaf(outputNode);
489 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
490 tmpLeafNodes.clear();
491 rhsNode.getNodes(tmpLeafNodes);
492 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
493 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
501 InternalNodeType
const *
const *
const mRhsNodes;
502 TreeType
const *
const mLhsTree;
504 TreeType *
const mOutputTree;
506 std::vector<const LeafNodeType*> mLocalLeafNodes;
507 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
510 struct ProcessLeafNodes {
512 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes,
513 const TreeType& lhsTree, TreeType& output)
514 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
516 , mLocalTree(mLhsTree->background())
517 , mOutputTree(&output)
521 ProcessLeafNodes(ProcessLeafNodes& rhs, tbb::split)
522 : mRhsNodes(rhs.mRhsNodes)
523 , mLhsTree(rhs.mLhsTree)
524 , mLocalTree(mLhsTree->background())
525 , mOutputTree(&mLocalTree)
529 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
531 void operator()(
const tbb::blocked_range<size_t>& range)
533 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
534 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
536 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
538 const LeafNodeType& rhsNode = *mRhsNodes[n];
539 const Coord& ijk = rhsNode.origin();
541 const LeafNodeType* lhsNode = lhsAcc.probeConstLeaf(ijk);
545 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
546 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
549 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
550 LeafNodeType* outputNode =
new LeafNodeType(rhsNode);
551 outputNode->negate();
552 outputAcc.addLeaf(outputNode);
555 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
556 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
563 LeafNodeType
const *
const *
const mRhsNodes;
564 TreeType
const *
const mLhsTree;
566 TreeType *
const mOutputTree;
569 TreePtrType mSegment;
570 TreeType
const *
const mLhsTree;
571 TreeType
const *
const mRhsTree;
575 template<CSGOperation Operation,
typename TreeType>
576 inline typename TreeType::Ptr
583 tbb::task_group tasks;
585 tasks.run(secondary);
600 template<
typename TreeType>
608 template<
typename TreeType>
618 maskGrid->insertMeta(grid);
628 template <
typename LeafT>
629 using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
637 template <
typename TreeT>
638 inline void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
639 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
641 using LeafT =
typename TreeT::LeafNodeType;
643 std::vector<LeafT*> srcLeafNodes;
644 srcLeafNodes.reserve(srcTree.leafCount());
645 srcTree.stealNodes(srcLeafNodes);
647 for (LeafT *srcLeaf : srcLeafNodes) {
648 LeafT *dstLeaf = acc.probeLeaf(srcLeaf->origin());
650 overlapping.emplace_back(dstLeaf, srcLeaf);
652 acc.addLeaf(srcLeaf);
660 template <
typename TreeT,
typename OpT>
662 typename std::enable_if<
663 !std::is_same<typename TreeT::ValueType, bool>::value &&
664 !std::is_same<typename TreeT::BuildType, ValueMask>::value &&
665 std::is_same<
typename TreeT::LeafNodeType::Buffer::ValueType,
666 typename TreeT::LeafNodeType::Buffer::StorageType>::value>::type
667 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
669 using LeafT =
typename TreeT::LeafNodeType;
670 LeafPairList<LeafT> overlapping;
671 transferLeafNodes(srcTree, dstTree, overlapping);
673 using RangeT = tbb::blocked_range<size_t>;
674 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
675 for (
auto i = r.begin(); i != r.end(); ++i) {
676 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
677 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
678 auto *ptr = dstLeaf->buffer().data();
679 for (
auto v = srcLeaf->cbeginValueOn(); v; ++v) op(ptr[v.pos()], *v);
688 template <
typename TreeT,
typename OpT>
690 typename std::enable_if<
691 std::is_same<typename TreeT::BuildType, ValueMask>::value &&
692 std::is_same<typename TreeT::ValueType, bool>::value>::type
693 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT)
695 using LeafT =
typename TreeT::LeafNodeType;
696 LeafPairList<LeafT> overlapping;
697 transferLeafNodes(srcTree, dstTree, overlapping);
699 using RangeT = tbb::blocked_range<size_t>;
700 tbb::parallel_for(RangeT(0, overlapping.size()), [&overlapping](
const RangeT& r) {
701 for (
auto i = r.begin(); i != r.end(); ++i) {
702 overlapping[i].first->getValueMask() |= overlapping[i].second->getValueMask();
703 delete overlapping[i].second;
710 template <
typename TreeT,
typename OpT>
712 typename std::enable_if<
713 std::is_same<typename TreeT::ValueType, bool>::value &&
714 !std::is_same<typename TreeT::BuildType, ValueMask>::value>::type
715 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
717 using LeafT =
typename TreeT::LeafNodeType;
718 LeafPairList<LeafT> overlapping;
719 transferLeafNodes(srcTree, dstTree, overlapping);
721 using RangeT = tbb::blocked_range<size_t>;
722 using WordT =
typename LeafT::Buffer::WordType;
723 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
724 for (
auto i = r.begin(); i != r.end(); ++i) {
725 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
726 WordT *w1 = dstLeaf->buffer().data();
727 const WordT *w2 = srcLeaf->buffer().data();
728 const WordT *w3 = &(srcLeaf->getValueMask().template getWord<WordT>(0));
729 for (
Index32 n = LeafT::Buffer::WORD_COUNT; n--; ++w1) {
730 WordT tmp = *w1, state = *w3++;
732 *w1 = (state & tmp) | (~state & *w1);
734 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
743 template <
typename TreeT>
746 using ValueT =
typename TreeT::ValueType;
748 void operator()(ValueT& dst,
const ValueT& src)
const { dst = src; }
755 template<
typename Gr
idOrTreeT>
757 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
760 using TreeT =
typename Adapter::TreeType;
761 using ValueT =
typename TreeT::ValueType;
767 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
771 template<
typename Gr
idOrTreeT>
773 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
776 using TreeT =
typename Adapter::TreeType;
777 using ValueT =
typename TreeT::ValueType;
783 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
787 template<
typename Gr
idOrTreeT>
789 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
792 using TreeT =
typename Adapter::TreeType;
798 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
802 template<
typename Gr
idOrTreeT>
804 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
807 using TreeT =
typename Adapter::TreeType;
813 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
817 template<
typename Gr
idOrTreeT>
819 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
822 using TreeT =
typename Adapter::TreeType;
828 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
835 template<
typename TreeT>
843 void operator()(
const typename TreeT::ValueOnCIter& iter)
const 846 iter.getBoundingBox(bbox);
847 aTree->fill(bbox, *iter);
850 void operator()(
const typename TreeT::LeafCIter& leafIter)
const 853 for (
typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
854 leafIter->cbeginValueOn(); iter; ++iter)
856 acc.
setValue(iter.getCoord(), *iter);
862 template<
typename Gr
idOrTreeT>
867 using TreeT =
typename Adapter::TreeType;
868 using ValueOnCIterT =
typename TreeT::ValueOnCIter;
871 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
876 ValueOnCIterT iter = bTree.cbeginValueOn();
877 iter.setMaxDepth(iter.getLeafDepth() - 1);
878 foreach(iter, op,
false);
881 foreach(Adapter::tree(bTree).cbeginLeaf(), op);
890 template<
typename TreeType>
895 using ValueT =
typename TreeT::ValueType;
896 using ChildIterT =
typename TreeT::LeafNodeType::ChildAllIter;
901 mAOutside(aTree.background()),
902 mAInside(math::
negative(mAOutside)),
903 mBOutside(bTree.background()),
906 const ValueT zero = zeroVal<ValueT>();
907 if (!(mAOutside > zero)) {
909 "expected grid A outside value > 0, got " << mAOutside);
911 if (!(mAInside < zero)) {
913 "expected grid A inside value < 0, got " << mAInside);
915 if (!(mBOutside > zero)) {
917 "expected grid B outside value > 0, got " << mBOutside);
919 if (!(mBInside < zero)) {
921 "expected grid B outside value < 0, got " << mBOutside);
933 template<
typename TreeType>
937 using ValueT =
typename TreeT::ValueType;
938 using ChildIterT =
typename TreeT::LeafNodeType::ChildAllIter;
945 template<
typename AIterT,
typename BIterT>
949 template<
typename IterT>
952 ValueT aValue = zeroVal<ValueT>();
953 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
954 if (!aChild && aValue < zeroVal<ValueT>()) {
959 ValueT bValue = zeroVal<ValueT>();
960 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
961 if (!bChild && bValue < zeroVal<ValueT>()) {
963 aIter.setValue(this->mAInside);
964 aIter.setValueOn(bIter.isValueOn());
969 if (!aChild && aValue > zeroVal<ValueT>()) {
973 bIter.setValue(this->mBOutside);
975 bChild->resetBackground(this->mBOutside, this->mAOutside);
976 aIter.setChild(bChild);
984 return (aChild && bChild) ? 0 : STOP;
991 aIter.probeValue(aValue);
992 bIter.probeValue(bValue);
993 if (aValue > bValue) {
994 aIter.setValue(bValue);
995 aIter.setValueOn(bIter.isValueOn());
1006 template<
typename TreeType>
1018 template<
typename AIterT,
typename BIterT>
1022 template<
typename IterT>
1025 ValueT aValue = zeroVal<ValueT>();
1026 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1027 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1032 ValueT bValue = zeroVal<ValueT>();
1033 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1034 if (!bChild && !(bValue < zeroVal<ValueT>())) {
1036 aIter.setValue(this->mAOutside);
1037 aIter.setValueOn(bIter.isValueOn());
1042 if (!aChild && aValue < zeroVal<ValueT>()) {
1046 bIter.setValue(this->mBOutside);
1047 bIter.setValueOff();
1048 bChild->resetBackground(this->mBOutside, this->mAOutside);
1049 aIter.setChild(bChild);
1057 return (aChild && bChild) ? 0 : STOP;
1064 aIter.probeValue(aValue);
1065 bIter.probeValue(bValue);
1066 if (aValue < bValue) {
1067 aIter.setValue(bValue);
1068 aIter.setValueOn(bIter.isValueOn());
1078 template<
typename TreeType>
1090 template<
typename AIterT,
typename BIterT>
1094 template<
typename IterT>
1097 ValueT aValue = zeroVal<ValueT>();
1098 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1099 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1104 ValueT bValue = zeroVal<ValueT>();
1105 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1106 if (!bChild && bValue < zeroVal<ValueT>()) {
1108 aIter.setValue(this->mAOutside);
1109 aIter.setValueOn(bIter.isValueOn());
1114 if (!aChild && aValue < zeroVal<ValueT>()) {
1118 bIter.setValue(this->mBOutside);
1119 bIter.setValueOff();
1120 bChild->resetBackground(this->mBOutside, this->mAOutside);
1121 aIter.setChild(bChild);
1130 return (aChild && bChild) ? 0 : STOP;
1137 aIter.probeValue(aValue);
1138 bIter.probeValue(bValue);
1140 if (aValue < bValue) {
1141 aIter.setValue(bValue);
1142 aIter.setValueOn(bIter.isValueOn());
1152 template<
typename Gr
idOrTreeT>
1157 using TreeT =
typename Adapter::TreeType;
1158 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1160 aTree.visit2(bTree, visitor);
1164 template<
typename Gr
idOrTreeT>
1169 using TreeT =
typename Adapter::TreeType;
1170 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1172 aTree.visit2(bTree, visitor);
1176 template<
typename Gr
idOrTreeT>
1181 using TreeT =
typename Adapter::TreeType;
1182 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1184 aTree.visit2(bTree, visitor);
1189 template<
typename Gr
idOrTreeT>
1194 using TreePtrT =
typename Adapter::TreeType::Ptr;
1196 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
1197 Adapter::tree(a), Adapter::tree(b));
1203 template<
typename Gr
idOrTreeT>
1208 using TreePtrT =
typename Adapter::TreeType::Ptr;
1210 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
1211 Adapter::tree(a), Adapter::tree(b));
1217 template<
typename Gr
idOrTreeT>
1222 using TreePtrT =
typename Adapter::TreeType::Ptr;
1224 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
1225 Adapter::tree(a), Adapter::tree(b));
1253 template<
typename TreeT,
typename OpT = composite::CopyOp<TreeT> >
1257 composite::doCompActiveLeafVoxels<TreeT, OpT>(srcTree, dstTree, op);
1265 #endif // OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
Defined various multi-threaded utility functions for trees.
const Int32 * data() const
Definition: Coord.h:167
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
const BValueType & b() const
Get the B input value.
Definition: Types.h:659
const AValueType & a() const
Get the A input value.
Definition: Types.h:657
Index32 Index
Definition: Types.h:61
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:271
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:617
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:426
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:52
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:108
Definition: Exceptions.h:92
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
SharedPtr< Grid > Ptr
Definition: Grid.h:592
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
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: Types.h:667
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1036
uint32_t Index32
Definition: Types.h:59