10 #ifndef OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED    11 #define OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED    22 #include <unordered_map>    23 #include <unordered_set>    45 template <
typename TreeT>
    51     using MaskTreeType = 
typename TreeT::template ValueConverter<ValueMask>::Type;
    57         : mTree(&tree), mSteal(true) { }
    60         : mTreePtr(treePtr), mTree(mTreePtr.get()), mSteal(true) { }
    68         : mTree(&tree), mSteal(false)
    70         if (mTree && 
initialize)     this->initializeMask();
    84     void reset(
typename TreeType::Ptr treePtr, 
Steal);
    96     template<
typename NodeT>
    97     const NodeT* probeConstNode(
const Coord& ijk) 
const;
   103     template <
typename NodeT>
   104     std::unique_ptr<NodeT> stealOrDeepCopyNode(
const Coord& ijk);
   108     template <
typename NodeT>
   109     void addTile(
const Coord& ijk, 
const ValueType& 
value, 
bool active);
   113     void initializeMask();
   116     bool hasMask() 
const;
   126     typename TreeType::Ptr mTreePtr;
   134 template <
typename TreeT>
   137     std::unique_ptr<MaskTreeType> 
ptr;
   144         : ptr(bool(other.ptr) ? 
std::make_unique<
MaskTreeType>(*other.ptr) : nullptr) { }
   147         if (
bool(other.
ptr))    ptr = std::make_unique<MaskTreeType>(*other.
ptr);
   155 template <
typename TreeT>
   159     using RootT = 
typename MaskT::RootNodeType;
   160     using LeafT = 
typename MaskT::LeafNodeType;
   163     bool operator()(
RootT& root, 
size_t) 
const;
   164     template<
typename NodeT>
   165     bool operator()(NodeT& node, 
size_t) 
const;
   181 template<
typename TreeT, 
bool Union>
   184     using ValueT = 
typename TreeT::ValueType;
   185     using RootT = 
typename TreeT::RootNodeType;
   186     using LeafT = 
typename TreeT::LeafNodeType;
   191     template <
typename TagT>
   203     template <
typename TreesT, 
typename TagT>
   206         for (
auto* tree : trees) {
   208                 mTreesToMerge.emplace_back(*tree, tag);
   217         : mTreesToMerge(trees) { }
   223         : mTreesToMerge(trees.cbegin(), trees.cend()) { }
   226     bool empty()
 const { 
return mTreesToMerge.empty(); }
   229     size_t size()
 const { 
return mTreesToMerge.size(); }
   232     bool operator()(
RootT& root, 
size_t idx) 
const;
   235     template<
typename NodeT>
   236     bool operator()(NodeT& node, 
size_t idx) 
const;
   239     bool operator()(
LeafT& leaf, 
size_t idx) 
const;
   244     const ValueT& background() 
const;
   246     mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
   247     mutable const ValueT* mBackground = 
nullptr;
   251 template <
typename TreeT>
   254 template <
typename TreeT>
   261 template<
typename TreeT>
   264     using ValueT = 
typename TreeT::ValueType;
   265     using RootT = 
typename TreeT::RootNodeType;
   266     using LeafT = 
typename TreeT::LeafNodeType;
   271     template <
typename TagT>
   283     size_t size()
 const { 
return 1; }
   286     bool operator()(
RootT& root, 
size_t idx) 
const;
   289     template<
typename NodeT>
   290     bool operator()(NodeT& node, 
size_t idx) 
const;
   293     bool operator()(
LeafT& leaf, 
size_t idx) 
const;
   298     const ValueT& background() 
const;
   299     const ValueT& otherBackground() 
const;
   304     mutable const ValueT* mBackground = 
nullptr;
   305     mutable const ValueT* mOtherBackground = 
nullptr;
   312 template<
typename TreeT>
   315     using ValueT = 
typename TreeT::ValueType;
   316     using RootT = 
typename TreeT::RootNodeType;
   317     using LeafT = 
typename TreeT::LeafNodeType;
   321     template <
typename TagT>
   322     SumMergeOp(TreeT& tree, TagT tag) { mTreesToMerge.emplace_back(tree, tag); }
   331     template <
typename TreesT, 
typename TagT>
   334         for (
auto* tree : trees) {
   336                 mTreesToMerge.emplace_back(*tree, tag);
   345         : mTreesToMerge(trees) { }
   351         : mTreesToMerge(trees.cbegin(), trees.cend()) { }
   354     bool empty()
 const { 
return mTreesToMerge.empty(); }
   357     size_t size()
 const { 
return mTreesToMerge.size(); }
   360     bool operator()(
RootT& root, 
size_t idx) 
const;
   363     template<
typename NodeT>
   364     bool operator()(NodeT& node, 
size_t idx) 
const;
   367     bool operator()(
LeafT& leaf, 
size_t idx) 
const;
   372     const ValueT& background() 
const;
   374     mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
   375     mutable const ValueT* mBackground = 
nullptr;
   382 template<
typename TreeT>
   389     manager.foreachTopDown(op);
   392 template<
typename TreeT>
   395     return bool(mMaskTree.ptr);
   398 template<
typename TreeT>
   406     mTree = mTreePtr.get();
   409 template<
typename TreeT>
   413     return &mTree->root();
   416 template<
typename TreeT>
   417 template<
typename NodeT>
   422     if (!mSteal && !this->mask()->isValueOn(ijk))    
return nullptr;
   423     return mTree->template probeConstNode<NodeT>(ijk);
   426 template<
typename TreeT>
   427 template<
typename NodeT>
   428 std::unique_ptr<NodeT>
   433         return std::unique_ptr<NodeT>(
   434             tree->root().template stealNode<NodeT>(ijk, mTree->root().background(), 
false)
   437         auto* 
child = this->probeConstNode<NodeT>(ijk);
   439             assert(this->hasMask());
   440             auto result = std::make_unique<NodeT>(*child);
   442             this->mask()->addTile(NodeT::LEVEL, ijk, 
false, 
false);
   446     return std::unique_ptr<NodeT>();
   449 template<
typename TreeT>
   450 template<
typename NodeT>
   455     if (NodeT::LEVEL == 0)  
return;
   459         auto* node = tree->template probeNode<NodeT>(ijk);
   461             const Index pos = NodeT::coordToOffset(ijk);
   462             node->addTile(pos, value, active);
   465         auto* node = mTree->template probeConstNode<NodeT>(ijk);
   468             assert(this->hasMask());
   469             this->mask()->addTile(NodeT::LEVEL, ijk, 
false, 
false);
   478 template <
typename TreeT>
   481     using ChildT = 
typename RootT::ChildNodeType;
   483     const Index count = mTree.root().childCount();
   485     std::vector<std::unique_ptr<ChildT>> children(count);
   490         tbb::blocked_range<Index>(0, count),
   491         [&](tbb::blocked_range<Index>& range)
   493             for (
Index i = range.begin(); i < range.end(); i++) {
   494                 children[i] = std::make_unique<ChildT>(
Coord::max(), 
true, 
true);
   502     for (
auto iter = mTree.root().cbeginChildOn(); iter; ++iter) {
   503         children[i]->setOrigin(iter->origin());
   504         root.addChild(children[i].release());
   511 template <
typename TreeT>
   512 template <
typename NodeT>
   515     using ChildT = 
typename NodeT::ChildNodeType;
   517     const auto* otherNode = mTree.template probeConstNode<NodeT>(node.origin());
   518     if (!otherNode) 
return false;
   522     if (NodeT::LEVEL == 1) {
   523         for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
   524             node.
addTile(iter.pos(), 
true, 
true);
   527         for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
   528             auto* 
child = 
new ChildT(iter->origin(), 
true, 
true);
   529             node.addChild(
child);
   541 namespace merge_internal {
   544 template <
typename BufferT, 
typename ValueT>
   545 struct UnallocatedBuffer
   547     static void allocateAndFill(BufferT& buffer, 
const ValueT& background)
   549         if (buffer.empty()) {
   550             if (!buffer.isOutOfCore()) {
   552                 buffer.fill(background);
   557     static bool isPartiallyConstructed(
const BufferT& buffer)
   559         return !buffer.isOutOfCore() && buffer.empty();
   563 template <
typename BufferT>
   564 struct UnallocatedBuffer<BufferT, bool>
   567     static void allocateAndFill(BufferT&, 
const bool&) { }
   568     static bool isPartiallyConstructed(
const BufferT&) { 
return false; }
   574 template <Index LEVEL>
   577     template <
typename NodeT, 
typename OpT>
   578     static void run(NodeT& node, OpT& op)
   580         using ChildT = 
typename NodeT::ChildNodeType;
   584         Index32 childCount = node.childCount();
   585         if (childCount > 0) {
   589             std::vector<ChildT*> children;
   590             children.reserve(childCount);
   591             for (
auto iter = node.beginChildOn(); iter; ++iter) {
   592                 children.push_back(&(*iter));
   597                 tbb::blocked_range<Index32>(0, childCount),
   598                 [&](tbb::blocked_range<Index32>& range) {
   599                     for (
Index32 n = range.begin(); n < range.end(); n++) {
   614     template <
typename NodeT, 
typename OpT>
   615     static void run(NodeT& node, OpT& op)
   624 template <
typename TreeT>
   625 struct ApplyTileToNodeOp
   627     using LeafT = 
typename TreeT::LeafNodeType;
   628     using ValueT = 
typename TreeT::ValueType;
   630     ApplyTileToNodeOp(
const ValueT& 
value, 
const bool active):
   631         mValue(value), mActive(active) { }
   633     template <
typename NodeT>
   634     void operator()(NodeT& node, 
size_t)
 const   640         for (
auto iter = node.beginValueAll(); iter; ++iter) {
   641             iter.setValue(mValue + *iter);
   643         if (mActive)     node.setValuesOn();
   646     void operator()(
LeafT& leaf, 
size_t)
 const   648         auto* data = leaf.buffer().data();
   650         if (mValue != zeroVal<ValueT>()) {
   651             for (
Index i = 0; i < LeafT::SIZE; ++i) {
   655         if (mActive)    leaf.setValuesOn();
   658     template <
typename NodeT>
   659     void run(NodeT& node)
   678 template <
typename TreeT, 
bool Union>
   681     const bool Intersect = !Union;
   683     if (this->empty())     
return false;
   686     if (!mBackground)   mBackground = &root.background();
   689     auto keyExistsInRoot = [&](
const Coord& key) -> 
bool   691         return root.getValueDepth(key) > -1;
   695     auto keyExistsInAllTrees = [&](
const Coord& key) -> 
bool   698             const auto* mergeRoot = mergeTree.rootPtr();
   699             if (!mergeRoot)                             
return false;
   700             if (mergeRoot->getValueDepth(key) == -1)    
return false;
   706     root.eraseBackgroundTiles();
   711         std::vector<Coord> toDelete;
   712         for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
   713             const Coord& key = valueIter.getCoord();
   714             if (!keyExistsInAllTrees(key))   toDelete.push_back(key);
   717         for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
   718             const Coord& key = childIter.getCoord();
   719             if (!keyExistsInAllTrees(key))   toDelete.push_back(key);
   723         for (Coord& key : toDelete)     root.addTile(key, *mBackground, 
false);
   724         root.eraseBackgroundTiles();
   730     constexpr uint8_t ACTIVE_TILE = 0x1;
   731     constexpr uint8_t INSIDE_TILE = 0x2;
   732     constexpr uint8_t OUTSIDE_TILE = 0x4;
   734     constexpr uint8_t INSIDE_STATE = Union ? INSIDE_TILE : OUTSIDE_TILE;
   735     constexpr uint8_t OUTSIDE_STATE = Union ? OUTSIDE_TILE : INSIDE_TILE;
   737     const ValueT insideBackground = Union ? -this->background() : this->background();
   738     const ValueT outsideBackground = -insideBackground;
   740     auto getTileFlag = [&](
auto& valueIter) -> uint8_t
   744         if (value < zeroVal<ValueT>())          flag |= INSIDE_TILE;
   745         else if (value > zeroVal<ValueT>())     flag |= OUTSIDE_TILE;
   746         if (valueIter.isValueOn())              flag |= ACTIVE_TILE;
   750     std::unordered_map<Coord, uint8_t> tiles;
   752     if (root.getTableSize() > 0) {
   753         for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
   754             const Coord& key = valueIter.getCoord();
   755             tiles.insert({key, getTileFlag(valueIter)});
   762         const auto* mergeRoot = mergeTree.rootPtr();
   763         if (!mergeRoot)     
continue;
   764         for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
   765             const Coord& key = valueIter.getCoord();
   766             auto it = tiles.find(key);
   767             if (it == tiles.end()) {
   769                 tiles.insert({key, getTileFlag(valueIter)});
   772                 const uint8_t flag = it->second;
   773                 if (flag & OUTSIDE_STATE) {
   774                     const uint8_t newFlag = getTileFlag(valueIter);
   775                     if (newFlag & INSIDE_STATE) {
   776                         it->second = newFlag;
   785     for (
auto it : tiles) {
   786         const uint8_t flag = it.second;
   787         if (flag & INSIDE_STATE) {
   788             const Coord& key = it.first;
   789             const bool state = flag & ACTIVE_TILE;
   791             if (Union || keyExistsInRoot(key)) {
   792                 root.addTile(key, insideBackground, state);
   797     std::unordered_set<Coord> children;
   799     if (root.getTableSize() > 0) {
   800         for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
   801             const Coord& key = childIter.getCoord();
   802             children.insert(key);
   806     bool continueRecurse = 
false;
   812         const auto* mergeRoot = mergeTree.rootPtr();
   813         if (!mergeRoot)     
continue;
   814         for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
   815             const Coord& key = childIter.getCoord();
   818             if (Intersect && !keyExistsInRoot(key))        
continue;
   821             if (children.count(key)) {
   822                 continueRecurse = 
true;
   827             auto it = tiles.find(key);
   828             if (it != tiles.end() && it->second == INSIDE_STATE)     
continue;
   830             auto childPtr = mergeTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
   831             childPtr->resetBackground(mergeRoot->background(), root.background());
   832             if (childPtr)   root.addChild(childPtr.release());
   834             children.insert(key);
   840     for (
auto it : tiles) {
   841         const uint8_t flag = it.second;
   842         if (flag & OUTSIDE_STATE) {
   843             const Coord& key = it.first;
   844             if (!children.count(key)) {
   845                 const bool state = flag & ACTIVE_TILE;
   847                 if (Union || keyExistsInRoot(key)) {
   848                     root.addTile(key, outsideBackground, state);
   855     root.eraseBackgroundTiles();
   857     return continueRecurse;
   860 template<
typename TreeT, 
bool Union>
   861 template<
typename NodeT>
   864     using NonConstNodeT = 
typename std::remove_const<NodeT>::type;
   866     if (this->empty())     
return false;
   868     const ValueT insideBackground = Union ? -this->background() : this->background();
   869     const ValueT outsideBackground = -insideBackground;
   871     using NodeMaskT = 
typename NodeT::NodeMaskType;
   875     NodeMaskT invalidTile;
   879         return Union ? value < zeroVal<ValueT>() : 
value > zeroVal<ValueT>();
   884         return Union ? 
value > zeroVal<ValueT>() : 
value < zeroVal<ValueT>();
   887     for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
   888         if (
isValid(iter.getValue())) {
   889             validTile.setOn(iter.pos());
   890         } 
else if (isInvalid(iter.getValue())) {
   891             invalidTile.setOn(iter.pos());
   895     bool continueRecurse = 
false;
   899         auto* mergeNode = mergeTree.template probeConstNode<NonConstNodeT>(node.origin());
   901         if (!mergeNode)     
continue;
   905         for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
   906             Index pos = iter.pos();
   908             if (validTile.isOn(pos))   
continue;
   910             if (
isValid(iter.getValue())) {
   911                 node.addTile(pos, insideBackground, iter.isValueOn());
   912                 validTile.setOn(pos);
   918         for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
   919             Index pos = iter.pos();
   920             const Coord& ijk = iter.getCoord();
   922             if (validTile.isOn(pos)) {
   923                 mergeTree.template addTile<NonConstNodeT>(ijk, outsideBackground, 
false);
   924             } 
else if (invalidTile.isOn(pos)) {
   925                 auto childPtr = mergeTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
   927                     childPtr->resetBackground(mergeTree.rootPtr()->background(), this->background());
   928                     node.addChild(childPtr.release());
   930                 invalidTile.setOff(pos);
   934                 continueRecurse = 
true;
   939     return continueRecurse;
   942 template <
typename TreeT, 
bool Union>
   945     using LeafT = 
typename TreeT::LeafNodeType;
   946     using ValueT = 
typename LeafT::ValueType;
   947     using BufferT = 
typename LeafT::Buffer;
   949     if (this->empty())      
return false;
   951     const ValueT background = Union ? this->background() : -this->background();
   956     merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
   957         leaf.buffer(), background);
   960         const LeafT* mergeLeaf = mergeTree.template probeConstNode<LeafT>(leaf.origin());
   961         if (!mergeLeaf)     
continue;
   964         if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
   965             mergeLeaf->buffer())) {
   969         for (
Index i = 0 ; i < LeafT::SIZE; i++) {
   970             const ValueT& newValue = mergeLeaf->getValue(i);
   971             const bool doMerge = Union ? newValue < leaf.getValue(i) : newValue > leaf.getValue(i);
   973                 leaf.setValueOnly(i, newValue);
   974                 leaf.setActiveState(i, mergeLeaf->isValueOn(i));
   982 template <
typename TreeT, 
bool Union>
   995 template <
typename TreeT>
   999     if (!mBackground)       mBackground = &root.background();
  1000     if (!mOtherBackground)  mOtherBackground = &mTree.rootPtr()->background();
  1005     constexpr uint8_t ACTIVE_TILE = 0x1;
  1006     constexpr uint8_t INSIDE_TILE = 0x2;
  1007     constexpr uint8_t CHILD = 0x4;
  1009     auto getTileFlag = [&](
auto& valueIter) -> uint8_t
  1013         if (value < zeroVal<ValueT>())          flag |= INSIDE_TILE;
  1014         if (valueIter.isValueOn())              flag |= ACTIVE_TILE;
  1019     root.eraseBackgroundTiles();
  1021     std::unordered_map<Coord, uint8_t> flags;
  1023     if (root.getTableSize() > 0) {
  1024         for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
  1025             const Coord& key = valueIter.getCoord();
  1026             const uint8_t flag = getTileFlag(valueIter);
  1027             if (flag & INSIDE_TILE) {
  1028                 flags.insert({key, getTileFlag(valueIter)});
  1032         for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
  1033             const Coord& key = childIter.getCoord();
  1034             flags.insert({key, CHILD});
  1038     bool continueRecurse = 
false;
  1040     const auto* mergeRoot = mTree.rootPtr();
  1043         for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
  1044             const Coord& key = valueIter.getCoord();
  1045             const uint8_t flag = getTileFlag(valueIter);
  1046             if (flag & INSIDE_TILE) {
  1047                 auto it = flags.find(key);
  1048                 if (it != flags.end()) {
  1049                     const bool state = flag & ACTIVE_TILE;
  1050                     root.addTile(key, this->background(), state);
  1055         for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
  1056             const Coord& key = childIter.getCoord();
  1057             auto it = flags.find(key);
  1058             if (it != flags.end()) {
  1059                 const uint8_t otherFlag = it->second;
  1060                 if (otherFlag & CHILD) {
  1062                     continueRecurse = 
true;
  1063                 } 
else if (otherFlag & INSIDE_TILE) {
  1064                     auto childPtr = mTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
  1066                         childPtr->resetBackground(this->otherBackground(), this->background());
  1068                         root.addChild(childPtr.release());
  1076     root.eraseBackgroundTiles();
  1078     return continueRecurse;
  1081 template<
typename TreeT>
  1082 template<
typename NodeT>
  1085     using NonConstNodeT = 
typename std::remove_const<NodeT>::type;
  1087     using NodeMaskT = 
typename NodeT::NodeMaskType;
  1091     NodeMaskT insideTile;
  1092     for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
  1093         if (iter.getValue() < zeroVal<ValueT>()) {
  1094             insideTile.setOn(iter.pos());
  1098     bool continueRecurse = 
false;
  1100     auto* mergeNode = mTree.template probeConstNode<NonConstNodeT>(node.origin());
  1102     if (!mergeNode)     
return continueRecurse;
  1106     for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
  1107         Index pos = iter.pos();
  1108         if (iter.getValue() < zeroVal<ValueT>()) {
  1109             if (insideTile.isOn(pos) || node.isChildMaskOn(pos))   {
  1110                 node.addTile(pos, this->background(), iter.isValueOn());
  1117     for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
  1118         Index pos = iter.pos();
  1119         const Coord& ijk = iter.getCoord();
  1120         if (insideTile.isOn(pos)) {
  1121             auto childPtr = mTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
  1123                 childPtr->resetBackground(this->otherBackground(), this->background());
  1125                 node.addChild(childPtr.release());
  1127         } 
else if (node.isChildMaskOn(pos)) {
  1130             continueRecurse = 
true;
  1134     return continueRecurse;
  1137 template <
typename TreeT>
  1140     using LeafT = 
typename TreeT::LeafNodeType;
  1141     using ValueT = 
typename LeafT::ValueType;
  1142     using BufferT = 
typename LeafT::Buffer;
  1147     merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
  1148         leaf.buffer(), this->background());
  1150     const LeafT* mergeLeaf = mTree.template probeConstNode<LeafT>(leaf.origin());
  1151     if (!mergeLeaf)                 
return false;
  1156     if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
  1157         mergeLeaf->buffer())) {
  1161     for (
Index i = 0 ; i < LeafT::SIZE; i++) {
  1162         const ValueT& aValue = leaf.getValue(i);
  1164         if (aValue < bValue) { 
  1165             leaf.setValueOnly(i, bValue);
  1166             leaf.setActiveState(i, mergeLeaf->isValueOn(i));
  1173 template <
typename TreeT>
  1178     assert(mBackground);
  1179     return *mBackground;
  1182 template <
typename TreeT>
  1187     assert(mOtherBackground);
  1188     return *mOtherBackground;
  1195 template <
typename TreeT>
  1198     using ValueT = 
typename RootT::ValueType;
  1199     using ChildT = 
typename RootT::ChildNodeType;
  1200     using NonConstChildT = 
typename std::remove_const<ChildT>::type;
  1202     if (this->empty())     
return false;
  1205     if (!mBackground)   mBackground = &root.background();
  1208     auto keyExistsInRoot = [](
const auto& rootToTest, 
const Coord& key) -> 
bool  1210         return rootToTest.getValueDepth(key) > -1;
  1213     constexpr uint8_t TILE = 0x1;
  1214     constexpr uint8_t CHILD = 0x2;
  1215     constexpr uint8_t TARGET_CHILD = 0x4; 
  1217     std::unordered_map<Coord, uint8_t> children;
  1221     if (root.getTableSize() > 0) {
  1222         for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
  1223             const Coord& key = valueIter.getCoord();
  1224             children.insert({key, TILE});
  1227         for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
  1228             const Coord& key = childIter.getCoord();
  1229             children.insert({key, CHILD | TARGET_CHILD});
  1236         const auto* mergeRoot = mergeTree.rootPtr();
  1237         if (!mergeRoot)     
continue;
  1239         for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
  1240             const Coord& key = valueIter.getCoord();
  1241             auto it = children.find(key);
  1242             if (it == children.end()) {
  1244                 children.insert({key, TILE});
  1251         for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
  1252             const Coord& key = childIter.getCoord();
  1253             auto it = children.find(key);
  1254             if (it == children.end()) {
  1256                 children.insert({key, CHILD});
  1259                 it->second |= CHILD;
  1266     for (
const auto& it : children) {
  1267         if (!keyExistsInRoot(root, it.first)) {
  1268             root.addTile(it.first, root.background(), 
false);
  1274     for (
const auto& it : children) {
  1276         const Coord& key = it.first;
  1280         if (it.second & TARGET_CHILD)    
continue;
  1283         const bool active = root.probeValue(key, value);
  1286             const auto* mergeRoot = mergeTree.rootPtr();
  1287             if (!mergeRoot)                            
continue;
  1288             if (!keyExistsInRoot(*mergeRoot, key))     
continue;
  1294             const auto* mergeNode = mergeRoot->template probeConstNode<ChildT>(key);
  1296                 auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(key);
  1297                 childPtr->resetBackground(mergeRoot->background(), root.background());
  1300                     merge_internal::ApplyTileToNodeOp<TreeT> applyOp(value, active);
  1301                     applyOp.run(*childPtr);
  1302                     root.addChild(childPtr.release());
  1308             const bool mergeActive = mergeRoot->probeValue(key, mergeValue);
  1310             if (active || mergeActive) {
  1311                 value += mergeValue;
  1312                 root.addTile(key, value, 
true);
  1314                 value += mergeValue;
  1315                 root.addTile(key, value, 
false);
  1319             mergeTree.template addTile<NonConstChildT>(key, zeroVal<ValueT>(), 
false);
  1326 template<
typename TreeT>
  1327 template<
typename NodeT>
  1330     using ChildT = 
typename NodeT::ChildNodeType;
  1331     using NonConstNodeT = 
typename std::remove_const<NodeT>::type;
  1333     if (this->empty())     
return false;
  1336         const auto* mergeRoot = mergeTree.rootPtr();
  1337         if (!mergeRoot)     
continue;
  1339         const auto* mergeNode = mergeRoot->template probeConstNode<NonConstNodeT>(node.origin());
  1343             for (
auto iter = node.beginValueAll(); iter; ++iter) {
  1344                 if (mergeNode->isChildMaskOn(iter.pos())) {
  1346                     auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(iter.getCoord());
  1347                     childPtr->resetBackground(mergeRoot->background(), this->background());
  1350                         merge_internal::ApplyTileToNodeOp<TreeT> applyOp(*iter, iter.isValueOn());
  1351                         applyOp.run(*childPtr);
  1352                         node.addChild(childPtr.release());
  1356                     const bool mergeActive = mergeNode->probeValue(iter.getCoord(), mergeValue);
  1357                     iter.setValue(*iter + mergeValue);
  1358                     if (mergeActive && !iter.isValueOn())   iter.setValueOn();
  1366             const bool mergeActive = mergeRoot->probeValue(node.origin(), mergeValue);
  1367             for (
auto iter = node.beginValueAll(); iter; ++iter) {
  1368                 iter.setValue(*iter + mergeValue);
  1369                 if (mergeActive && !iter.isValueOn())   iter.setValueOn();
  1377 template <
typename TreeT>
  1380     using RootT = 
typename TreeT::RootNodeType;
  1381     using RootChildT = 
typename RootT::ChildNodeType;
  1382     using NonConstRootChildT = 
typename std::remove_const<RootChildT>::type;
  1383     using LeafT = 
typename TreeT::LeafNodeType;
  1384     using ValueT = 
typename LeafT::ValueType;
  1385     using BufferT = 
typename LeafT::Buffer;
  1386     using NonConstLeafT = 
typename std::remove_const<LeafT>::type;
  1388     if (this->empty())      
return false;
  1390     const Coord& ijk = leaf.origin();
  1395     merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
  1396         leaf.buffer(), this->background());
  1398     auto* data = leaf.buffer().data();
  1401         const RootT* mergeRoot = mergeTree.rootPtr();
  1402         if (!mergeRoot)     
continue;
  1404         const RootChildT* mergeRootChild = mergeRoot->template probeConstNode<NonConstRootChildT>(ijk);
  1405         const LeafT* mergeLeaf = mergeRootChild ?
  1406             mergeRootChild->template probeConstNode<NonConstLeafT>(ijk) : 
nullptr;
  1413             if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
  1414                 mergeLeaf->buffer())) {
  1418             for (
Index i = 0; i < LeafT::SIZE; ++i) {
  1419                 data[i] += mergeLeaf->getValue(i);
  1422             leaf.getValueMask() |= mergeLeaf->getValueMask();
  1427             bool mergeActive = mergeRootChild ?
  1428                 mergeRootChild->probeValue(ijk, mergeValue) : mergeRoot->probeValue(ijk, mergeValue);
  1430             if (mergeValue != zeroVal<ValueT>()) {
  1431                 for (
Index i = 0; i < LeafT::SIZE; ++i) {
  1432                     data[i] += mergeValue;
  1436             if (mergeActive)    leaf.setValuesOn();
  1443 template <
typename TreeT>
  1448     assert(mBackground);
  1449     return *mBackground;
  1458 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION  1460 #ifdef OPENVDB_INSTANTIATE_MERGE  1493 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION  1500 #endif // OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED 
ChildT * child
Definition: GridBuilder.h:1286
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
#define OPENVDB_INSTANTIATE_STRUCT
Definition: version.h.in:144
Tag dispatch class that distinguishes constructors that steal. 
Definition: Types.h:648
Implementation of a depth-first node visitor. 
OPENVDB_IMPORT void initialize()
Global registration of basic types. 
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
Definition: Exceptions.h:63
Index32 Index
Definition: Types.h:54
T negative(const T &val)
Return the unary negation of the given value. 
Definition: Math.h:127
bool isValid(GridType gridType, GridClass gridClass)
return true if the combination of GridType and GridClass is valid. 
Definition: NanoVDB.h:520
Tag dispatch class that distinguishes constructors that deep copy. 
Definition: Types.h:646
void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid. 
uint32_t Index32
Definition: Types.h:52
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version. 
Definition: version.h.in:116
Definition: NodeManager.h:36
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202