10#ifndef OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED 
   11#define OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED 
   24#include <unordered_map> 
   25#include <unordered_set> 
   47template <
typename TreeT>
 
   53    using MaskTreeType = 
typename TreeT::template ValueConverter<ValueMask>::Type;
 
   59        : mTree(&
tree), mSteal(true) { }
 
 
   62        : mTreePtr(treePtr), mTree(mTreePtr.get()), mSteal(true) { }
 
 
   70        : mTree(&
tree), mSteal(false)
 
 
   98    template<
typename NodeT>
 
  107    template <
typename NodeT>
 
  114    template <
typename NodeT>
 
  119    template <
typename NodeT>
 
  137    typename TreeType::Ptr mTreePtr;
 
  138    const TreeType* mTree;
 
  145template <
typename TreeT>
 
  148    std::unique_ptr<MaskTreeType> 
ptr;
 
  158        if (
bool(other.
ptr))    
ptr = std::make_unique<MaskTreeType>(*other.
ptr);
 
 
 
  166template <
typename TreeT>
 
  170    using RootT = 
typename MaskT::RootNodeType;
 
  171    using LeafT = 
typename MaskT::LeafNodeType;
 
  174    bool operator()(RootT& root, 
size_t) 
const;
 
  175    template<
typename NodeT>
 
  176    bool operator()(NodeT& node, 
size_t) 
const;
 
 
  192template<
typename TreeT, 
bool Union>
 
  195    using ValueT = 
typename TreeT::ValueType;
 
  196    using RootT = 
typename TreeT::RootNodeType;
 
  197    using LeafT = 
typename TreeT::LeafNodeType;
 
  202    template <
typename TagT>
 
  214    template <
typename TreesT, 
typename TagT>
 
  217        for (
auto* 
tree : trees) {
 
  219                mTreesToMerge.emplace_back(*
tree, tag);
 
 
  228        : mTreesToMerge(trees) { }
 
 
  234        : mTreesToMerge(trees.cbegin(), trees.cend()) { }
 
 
  237    bool empty()
 const { 
return mTreesToMerge.empty(); }
 
  240    size_t size()
 const { 
return mTreesToMerge.size(); }
 
  249    template<
typename NodeT>
 
  258    const ValueT& background() 
const;
 
  260    mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
 
  261    mutable const ValueT* mBackground = 
nullptr;
 
  262    bool mPruneCancelledTiles = 
false;
 
 
  266template <
typename TreeT>
 
  269template <
typename TreeT>
 
  279template<
typename TreeT>
 
  282    using ValueT = 
typename TreeT::ValueType;
 
  283    using RootT = 
typename TreeT::RootNodeType;
 
  284    using LeafT = 
typename TreeT::LeafNodeType;
 
  289    template <
typename TagT>
 
  304    size_t size()
 const { 
return 1; }
 
  307    bool operator()(RootT& root, 
size_t idx) 
const;
 
  310    template<
typename NodeT>
 
  311    bool operator()(NodeT& node, 
size_t idx) 
const;
 
  314    bool operator()(LeafT& leaf, 
size_t idx) 
const;
 
  319    const ValueT& background() 
const;
 
  320    const ValueT& otherBackground() 
const;
 
  325    mutable const ValueT* mBackground = 
nullptr;
 
  326    mutable const ValueT* mOtherBackground = 
nullptr;
 
  327    bool mPruneCancelledTiles = 
false;
 
 
  334template<
typename TreeT>
 
  337    using ValueT = 
typename TreeT::ValueType;
 
  338    using RootT = 
typename TreeT::RootNodeType;
 
  339    using LeafT = 
typename TreeT::LeafNodeType;
 
  343    template <
typename TagT>
 
  353    template <
typename TreesT, 
typename TagT>
 
  356        for (
auto* 
tree : trees) {
 
  358                mTreesToMerge.emplace_back(*
tree, tag);
 
 
  367        : mTreesToMerge(trees) { }
 
 
  373        : mTreesToMerge(trees.cbegin(), trees.cend()) { }
 
 
  376    bool empty()
 const { 
return mTreesToMerge.empty(); }
 
  379    size_t size()
 const { 
return mTreesToMerge.size(); }
 
  382    bool operator()(RootT& root, 
size_t idx) 
const;
 
  385    template<
typename NodeT>
 
  386    bool operator()(NodeT& node, 
size_t idx) 
const;
 
  389    bool operator()(LeafT& leaf, 
size_t idx) 
const;
 
  394    const ValueT& background() 
const;
 
  396    mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
 
  397    mutable const ValueT* mBackground = 
nullptr;
 
 
  404template<
typename TreeT>
 
  411    manager.foreachTopDown(
op);
 
 
  414template<
typename TreeT>
 
  417    return bool(mMaskTree.ptr);
 
 
 
  420template<
typename TreeT>
 
  428    mTree = mTreePtr.get();
 
 
  431template<
typename TreeT>
 
  435    return &mTree->root();
 
 
  438template<
typename TreeT>
 
  439template<
typename NodeT>
 
  444    if (!mSteal && !this->
mask()->isValueOn(ijk))    
return nullptr;
 
 
  448template<
typename TreeT>
 
  454        this->
mask()->addTile(level, ijk, 
false, 
false);
 
 
  458template<
typename TreeT>
 
  459template<
typename NodeT>
 
  460std::unique_ptr<NodeT>
 
  465        return std::unique_ptr<NodeT>(
 
  466            tree->root().template stealNode<NodeT>(ijk, value, 
false)
 
  471            auto result = std::make_unique<NodeT>(*child);
 
  476    return std::unique_ptr<NodeT>();
 
 
  479template<
typename TreeT>
 
  480template<
typename NodeT>
 
  481std::unique_ptr<NodeT>
 
  487template<
typename TreeT>
 
  488template<
typename NodeT>
 
  493    if (NodeT::LEVEL == 0)  
return;
 
  497        auto* node = 
tree->template probeNode<NodeT>(ijk);
 
  499            const Index pos = NodeT::coordToOffset(ijk);
 
  500            node->addTile(pos, value, active);
 
  504        if (node)   this->
pruneMask(NodeT::LEVEL, ijk);
 
 
  512template <
typename TreeT>
 
  515    using ChildT = 
typename RootT::ChildNodeType;
 
  517    const Index count = mTree.root().childCount();
 
  519    std::vector<std::unique_ptr<ChildT>> children(count);
 
  524        tbb::blocked_range<Index>(0, count),
 
  525        [&](tbb::blocked_range<Index>& range)
 
  527            for (
Index i = range.begin(); i < range.end(); i++) {
 
  528                children[i] = std::make_unique<ChildT>(
Coord::max(), 
true, 
true);
 
  536    for (
auto iter = mTree.root().cbeginChildOn(); iter; ++iter) {
 
  537        children[i]->setOrigin(iter->origin());
 
  538        root.addChild(children[i].release());
 
 
  545template <
typename TreeT>
 
  546template <
typename NodeT>
 
  549    using ChildT = 
typename NodeT::ChildNodeType;
 
  552    if (!otherNode) 
return false;
 
  556    if (NodeT::LEVEL == 1) {
 
  557        for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
 
  558            node.addTile(iter.pos(), 
true, 
true);
 
  561        for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
 
  562            auto* child = 
new ChildT(iter->origin(), 
true, 
true);
 
  563            node.addChild(child);
 
 
  575namespace merge_internal {
 
  578template <
typename BufferT, 
typename ValueT>
 
  579struct UnallocatedBuffer
 
  581    static void allocateAndFill(BufferT& buffer, 
const ValueT& background)
 
  583        if (buffer.empty()) {
 
  584            if (!buffer.isOutOfCore()) {
 
  586                buffer.fill(background);
 
  591    static bool isPartiallyConstructed(
const BufferT& buffer)
 
  593        return !buffer.isOutOfCore() && buffer.empty();
 
  597template <
typename BufferT>
 
  598struct UnallocatedBuffer<BufferT, 
bool>
 
  601    static void allocateAndFill(BufferT&, 
const bool&) { }
 
  602    static bool isPartiallyConstructed(
const BufferT&) { 
return false; }
 
  608template <Index LEVEL>
 
  611    template <
typename NodeT, 
typename OpT>
 
  612    static void run(NodeT& node, OpT& op)
 
  614        using NonConstChildT = 
typename NodeT::ChildNodeType;
 
  615        using ChildT = 
typename CopyConstness<NodeT, NonConstChildT>::Type;
 
  619        Index32 childCount = node.childCount();
 
  620        if (childCount > 0) {
 
  624            std::vector<ChildT*> children;
 
  625            children.reserve(childCount);
 
  626            for (
auto iter = node.beginChildOn(); iter; ++iter) {
 
  627                children.push_back(&(*iter));
 
  632                tbb::blocked_range<Index32>(0, childCount),
 
  633                [&](tbb::blocked_range<Index32>& range) {
 
  634                    for (Index32 n = range.begin(); n < range.end(); n++) {
 
  635                        DepthFirstNodeVisitor<ChildT>::visit(*children[n], op);
 
  640            DepthFirstNodeVisitor<NodeT>::visit(node, op);
 
  649    template <
typename NodeT, 
typename OpT>
 
  650    static void run(NodeT& node, OpT& op)
 
  652        DepthFirstNodeVisitor<NodeT>::visit(node, op);
 
  659template <
typename TreeT>
 
  660struct ApplyTileSumToNodeOp
 
  662    using LeafT = 
typename TreeT::LeafNodeType;
 
  663    using ValueT = 
typename TreeT::ValueType;
 
  665    ApplyTileSumToNodeOp(
const ValueT& value, 
const bool active):
 
  666        mValue(value), mActive(active) { }
 
  668    template <
typename NodeT>
 
  669    void operator()(NodeT& node, 
size_t)
 const 
  675        for (
auto iter = node.beginValueAll(); iter; ++iter) {
 
  676            iter.setValue(mValue + *iter);
 
  678        if (mActive)     node.setValuesOn();
 
  681    void operator()(LeafT& leaf, 
size_t)
 const 
  683        auto* data = leaf.buffer().data();
 
  685        if (mValue != zeroVal<ValueT>()) {
 
  686            for (Index i = 0; i < LeafT::SIZE; ++i) {
 
  690        if (mActive)    leaf.setValuesOn();
 
  693    template <
typename NodeT>
 
  694    void run(NodeT& node)
 
  696        Dispatch<NodeT::LEVEL>::run(node, *
this);
 
  714template <
typename TreeT, 
bool Union>
 
  717    const bool Intersect = !Union;
 
  719    if (this->
empty())     
return false;
 
  722    if (!mBackground)   mBackground = &root.background();
 
  725    auto keyExistsInRoot = [&](
const Coord& key) -> 
bool 
  727        return root.getValueDepth(key) > -1;
 
  731    auto keyExistsInAllTrees = [&](
const Coord& key) -> 
bool 
  734            const auto* mergeRoot = mergeTree.rootPtr();
 
  735            if (!mergeRoot)                             
return false;
 
  736            if (mergeRoot->getValueDepth(key) == -1)    
return false;
 
  742    root.eraseBackgroundTiles();
 
  747        std::vector<Coord> toDelete;
 
  748        for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
 
  749            const Coord& key = valueIter.getCoord();
 
  750            if (!keyExistsInAllTrees(key))   toDelete.push_back(key);
 
  753        for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
 
  754            const Coord& key = childIter.getCoord();
 
  755            if (!keyExistsInAllTrees(key))   toDelete.push_back(key);
 
  759        for (
Coord& key : toDelete)     root.addTile(key, *mBackground, 
false);
 
  760        root.eraseBackgroundTiles();
 
  766    constexpr uint8_t ACTIVE_TILE = 0x1;
 
  767    constexpr uint8_t INSIDE_TILE = 0x2;
 
  768    constexpr uint8_t OUTSIDE_TILE = 0x4;
 
  770    constexpr uint8_t INSIDE_STATE = Union ? INSIDE_TILE : OUTSIDE_TILE;
 
  771    constexpr uint8_t OUTSIDE_STATE = Union ? OUTSIDE_TILE : INSIDE_TILE;
 
  773    const ValueT insideBackground = Union ? -this->background() : this->background();
 
  774    const ValueT outsideBackground = -insideBackground;
 
  776    auto getTileFlag = [&](
auto& valueIter) -> uint8_t
 
  779        const ValueT& value = valueIter.getValue();
 
  782        if (valueIter.isValueOn())              flag |= ACTIVE_TILE;
 
  786    std::unordered_map<
Coord, uint8_t> tiles;
 
  788    if (root.getTableSize() > 0) {
 
  789        for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
 
  790            const Coord& key = valueIter.getCoord();
 
  791            tiles.insert({key, getTileFlag(valueIter)});
 
  798        const auto* mergeRoot = mergeTree.rootPtr();
 
  799        if (!mergeRoot)     
continue;
 
  800        for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
 
  801            const Coord& key = valueIter.getCoord();
 
  802            auto it = tiles.find(key);
 
  803            if (it == tiles.end()) {
 
  805                tiles.insert({key, getTileFlag(valueIter)});
 
  808                const uint8_t flag = it->second;
 
  809                if (flag & OUTSIDE_STATE) {
 
  810                    const uint8_t newFlag = getTileFlag(valueIter);
 
  811                    if (newFlag & INSIDE_STATE) {
 
  812                        it->second = newFlag;
 
  821    for (
auto it : tiles) {
 
  822        const uint8_t flag = it.second;
 
  823        if (flag & INSIDE_STATE) {
 
  824            const Coord& key = it.first;
 
  825            const bool state = flag & ACTIVE_TILE;
 
  827            if (Union || keyExistsInRoot(key)) {
 
  828                root.addTile(key, insideBackground, state);
 
  833    std::unordered_set<Coord> children;
 
  835    if (root.getTableSize() > 0) {
 
  836        for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
 
  837            const Coord& key = childIter.getCoord();
 
  838            children.insert(key);
 
  842    bool continueRecurse = 
false;
 
  848        const auto* mergeRoot = mergeTree.rootPtr();
 
  849        if (!mergeRoot)     
continue;
 
  850        for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
 
  851            const Coord& key = childIter.getCoord();
 
  854            if (Intersect && !keyExistsInRoot(key))        
continue;
 
  857            if (children.count(key)) {
 
  858                continueRecurse = 
true;
 
  863            auto it = tiles.find(key);
 
  864            if (it != tiles.end() && it->second == INSIDE_STATE)     
continue;
 
  866            auto childPtr = mergeTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
 
  867            childPtr->resetBackground(mergeRoot->background(), root.background());
 
  868            if (childPtr)   root.addChild(childPtr.release());
 
  870            children.insert(key);
 
  876    for (
auto it : tiles) {
 
  877        const uint8_t flag = it.second;
 
  878        if (flag & OUTSIDE_STATE) {
 
  879            const Coord& key = it.first;
 
  880            if (!children.count(key)) {
 
  881                const bool state = flag & ACTIVE_TILE;
 
  883                if (Union || keyExistsInRoot(key)) {
 
  884                    root.addTile(key, outsideBackground, state);
 
  891    root.eraseBackgroundTiles();
 
  893    return continueRecurse;
 
 
  896template<
typename TreeT, 
bool Union>
 
  897template<
typename NodeT>
 
  900    using NonConstNodeT = 
typename std::remove_const<NodeT>::type;
 
  902    if (this->
empty())     
return false;
 
  904    const ValueT insideBackground = Union ? -this->background() : this->background();
 
  905    const ValueT outsideBackground = -insideBackground;
 
  907    using NodeMaskT = 
typename NodeT::NodeMaskType;
 
  911    NodeMaskT invalidTile;
 
  913    auto isValid = [](
const ValueT& value)
 
  918    auto isInvalid = [](
const ValueT& value)
 
  923    for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
 
  924        if (isValid(iter.getValue())) {
 
  925            validTile.setOn(iter.pos());
 
  926        } 
else if (isInvalid(iter.getValue())) {
 
  927            invalidTile.setOn(iter.pos());
 
  931    bool continueRecurse = 
false;
 
  935        auto* mergeNode = mergeTree.template probeConstNode<NonConstNodeT>(node.origin());
 
  937        if (!mergeNode)     
continue;
 
  941        for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
 
  942            Index pos = iter.pos();
 
  944            if (validTile.isOn(pos))   
continue;
 
  946            if (isValid(iter.getValue())) {
 
  947                node.addTile(pos, insideBackground, iter.isValueOn());
 
  948                validTile.setOn(pos);
 
  954        for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
 
  955            Index pos = iter.pos();
 
  956            const Coord& ijk = iter.getCoord();
 
  958            if (validTile.isOn(pos)) {
 
  959                mergeTree.template addTile<NonConstNodeT>(ijk, outsideBackground, 
false);
 
  960            } 
else if (invalidTile.isOn(pos)) {
 
  961                auto childPtr = mergeTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
 
  963                    childPtr->resetBackground(mergeTree.rootPtr()->background(), this->background());
 
  964                    node.addChild(childPtr.release());
 
  966                invalidTile.setOff(pos);
 
  970                continueRecurse = 
true;
 
  975    return continueRecurse;
 
 
  978template <
typename TreeT, 
bool Union>
 
  981    using LeafT = 
typename TreeT::LeafNodeType;
 
  982    using ValueT = 
typename LeafT::ValueType;
 
  983    using BufferT = 
typename LeafT::Buffer;
 
  985    if (this->
empty())      
return false;
 
  987    const ValueT background = Union ? this->background() : -this->background();
 
  992    merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
 
  993        leaf.buffer(), background);
 
  996        const LeafT* mergeLeaf = mergeTree.template probeConstNode<LeafT>(leaf.origin());
 
  997        if (!mergeLeaf)     
continue;
 
 1000        if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
 
 1001            mergeLeaf->buffer())) {
 
 1005        if (mPruneCancelledTiles) {
 
 1006            bool allnegequal = 
true;
 
 1007            for (
Index i = 0 ; i < LeafT::SIZE; i++) {
 
 1008                const ValueT& newValue = mergeLeaf->getValue(i);
 
 1009                const ValueT& oldValue = leaf.getValue(i);
 
 1011                const bool doMerge = Union ? newValue < oldValue : newValue > oldValue;
 
 1013                    leaf.setValueOnly(i, newValue);
 
 1014                    leaf.setActiveState(i, mergeLeaf->isValueOn(i));
 
 1021                if (Union) { leaf.fill(
math::negative(this->background()), 
false); }
 
 1022                else { leaf.fill(this->background(), 
false); }
 
 1026            for (
Index i = 0 ; i < LeafT::SIZE; i++) {
 
 1027                const ValueT& newValue = mergeLeaf->getValue(i);
 
 1028                const ValueT& oldValue = leaf.getValue(i);
 
 1029                const bool doMerge = Union ? newValue < oldValue : newValue > oldValue;
 
 1031                    leaf.setValueOnly(i, newValue);
 
 1032                    leaf.setActiveState(i, mergeLeaf->isValueOn(i));
 
 
 1041template <
typename TreeT, 
bool Union>
 
 1043CsgUnionOrIntersectionOp<TreeT, Union>::background()
 const 
 1047    return *mBackground;
 
 1054template <
typename TreeT>
 
 1058    if (!mBackground)       mBackground = &root.background();
 
 1059    if (!mOtherBackground)  mOtherBackground = &mTree.rootPtr()->background();
 
 1064    constexpr uint8_t ACTIVE_TILE = 0x1;
 
 1065    constexpr uint8_t INSIDE_TILE = 0x2;
 
 1066    constexpr uint8_t CHILD = 0x4;
 
 1068    auto getTileFlag = [&](
auto& valueIter) -> uint8_t
 
 1071        const ValueT& value = valueIter.getValue();
 
 1073        if (valueIter.isValueOn())              flag |= ACTIVE_TILE;
 
 1078    root.eraseBackgroundTiles();
 
 1080    std::unordered_map<
Coord, uint8_t> flags;
 
 1082    if (root.getTableSize() > 0) {
 
 1083        for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
 
 1084            const Coord& key = valueIter.getCoord();
 
 1085            const uint8_t flag = getTileFlag(valueIter);
 
 1086            if (flag & INSIDE_TILE) {
 
 1087                flags.insert({key, getTileFlag(valueIter)});
 
 1091        for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
 
 1092            const Coord& key = childIter.getCoord();
 
 1093            flags.insert({key, CHILD});
 
 1097    bool continueRecurse = 
false;
 
 1099    const auto* mergeRoot = mTree.rootPtr();
 
 1102        for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
 
 1103            const Coord& key = valueIter.getCoord();
 
 1104            const uint8_t flag = getTileFlag(valueIter);
 
 1105            if (flag & INSIDE_TILE) {
 
 1106                auto it = flags.find(key);
 
 1107                if (it != flags.end()) {
 
 1108                    const bool state = flag & ACTIVE_TILE;
 
 1109                    root.addTile(key, this->background(), state);
 
 1114        for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
 
 1115            const Coord& key = childIter.getCoord();
 
 1116            auto it = flags.find(key);
 
 1117            if (it != flags.end()) {
 
 1118                const uint8_t otherFlag = it->second;
 
 1119                if (otherFlag & CHILD) {
 
 1121                    continueRecurse = 
true;
 
 1122                } 
else if (otherFlag & INSIDE_TILE) {
 
 1123                    auto childPtr = mTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
 
 1125                        childPtr->resetBackground(this->otherBackground(), this->background());
 
 1127                        root.addChild(childPtr.release());
 
 1135    root.eraseBackgroundTiles();
 
 1137    return continueRecurse;
 
 
 1140template<
typename TreeT>
 
 1141template<
typename NodeT>
 
 1144    using NonConstNodeT = 
typename std::remove_const<NodeT>::type;
 
 1146    using NodeMaskT = 
typename NodeT::NodeMaskType;
 
 1150    NodeMaskT insideTile;
 
 1151    for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
 
 1153            insideTile.setOn(iter.pos());
 
 1157    bool continueRecurse = 
false;
 
 1159    auto* mergeNode = mTree.template probeConstNode<NonConstNodeT>(node.origin());
 
 1161    if (!mergeNode)     
return continueRecurse;
 
 1165    for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
 
 1166        Index pos = iter.pos();
 
 1168            if (insideTile.isOn(pos) || node.isChildMaskOn(pos))   {
 
 1169                node.addTile(pos, this->background(), iter.isValueOn());
 
 1176    for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
 
 1177        Index pos = iter.pos();
 
 1178        const Coord& ijk = iter.getCoord();
 
 1179        if (insideTile.isOn(pos)) {
 
 1180            auto childPtr = mTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
 
 1182                childPtr->resetBackground(this->otherBackground(), this->background());
 
 1184                node.addChild(childPtr.release());
 
 1186        } 
else if (node.isChildMaskOn(pos)) {
 
 1189            continueRecurse = 
true;
 
 1193    return continueRecurse;
 
 
 1196template <
typename TreeT>
 
 1199    using LeafT = 
typename TreeT::LeafNodeType;
 
 1200    using ValueT = 
typename LeafT::ValueType;
 
 1201    using BufferT = 
typename LeafT::Buffer;
 
 1206    merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
 
 1207        leaf.buffer(), this->background());
 
 1209    const LeafT* mergeLeaf = mTree.template probeConstNode<LeafT>(leaf.origin());
 
 1210    if (!mergeLeaf)                 
return false;
 
 1215    if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
 
 1216        mergeLeaf->buffer())) {
 
 1220    if (mPruneCancelledTiles) {
 
 1221        bool allequal = 
true;
 
 1222        for (
Index i = 0 ; i < LeafT::SIZE; i++) {
 
 1223            const ValueT& aValue = leaf.getValue(i);
 
 1224            ValueT bValue = mergeLeaf->getValue(i);
 
 1225            allequal &= aValue == bValue;
 
 1227            if (aValue < bValue) { 
 
 1228                leaf.setValueOnly(i, bValue);
 
 1229                leaf.setActiveState(i, mergeLeaf->isValueOn(i));
 
 1236            leaf.fill(background(), 
false);
 
 1239        for (
Index i = 0 ; i < LeafT::SIZE; i++) {
 
 1240            const ValueT& aValue = leaf.getValue(i);
 
 1241            ValueT bValue = mergeLeaf->getValue(i);
 
 1243            if (aValue < bValue) { 
 
 1244                leaf.setValueOnly(i, bValue);
 
 1245                leaf.setActiveState(i, mergeLeaf->isValueOn(i));
 
 
 1253template <
typename TreeT>
 
 1255CsgDifferenceOp<TreeT>::background()
 const 
 1259    return *mBackground;
 
 1262template <
typename TreeT>
 
 1263const typename CsgDifferenceOp<TreeT>::ValueT&
 
 1264CsgDifferenceOp<TreeT>::otherBackground()
 const 
 1268    return *mOtherBackground;
 
 1275template <
typename TreeT>
 
 1278    using ValueT = 
typename RootT::ValueType;
 
 1279    using ChildT = 
typename RootT::ChildNodeType;
 
 1280    using NonConstChildT = 
typename std::remove_const<ChildT>::type;
 
 1282    if (this->
empty())     
return false;
 
 1285    if (!mBackground)   mBackground = &root.background();
 
 1288    auto keyExistsInRoot = [](
const auto& rootToTest, 
const Coord& key) -> 
bool 
 1290        return rootToTest.getValueDepth(key) > -1;
 
 1293    constexpr uint8_t TILE = 0x1;
 
 1294    constexpr uint8_t CHILD = 0x2;
 
 1295    constexpr uint8_t TARGET_CHILD = 0x4; 
 
 1297    std::unordered_map<
Coord, uint8_t> children;
 
 1301    if (root.getTableSize() > 0) {
 
 1302        for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
 
 1303            const Coord& key = valueIter.getCoord();
 
 1304            children.insert({key, TILE});
 
 1307        for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
 
 1308            const Coord& key = childIter.getCoord();
 
 1309            children.insert({key, CHILD | TARGET_CHILD});
 
 1316        const auto* mergeRoot = mergeTree.rootPtr();
 
 1317        if (!mergeRoot)     
continue;
 
 1319        for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
 
 1320            const Coord& key = valueIter.getCoord();
 
 1321            auto it = children.find(key);
 
 1322            if (it == children.end()) {
 
 1324                children.insert({key, TILE});
 
 1331        for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
 
 1332            const Coord& key = childIter.getCoord();
 
 1333            auto it = children.find(key);
 
 1334            if (it == children.end()) {
 
 1336                children.insert({key, CHILD});
 
 1339                it->second |= CHILD;
 
 1346    for (
const auto& it : children) {
 
 1347        if (!keyExistsInRoot(root, it.first)) {
 
 1348            root.addTile(it.first, root.background(), 
false);
 
 1354    for (
const auto& it : children) {
 
 1356        const Coord& key = it.first;
 
 1360        if (it.second & TARGET_CHILD)    
continue;
 
 1363        const bool active = root.probeValue(key, value);
 
 1366            const auto* mergeRoot = mergeTree.rootPtr();
 
 1367            if (!mergeRoot)                            
continue;
 
 1373            const auto* mergeNode = mergeRoot->template probeConstNode<ChildT>(key);
 
 1375                auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(key);
 
 1378                    merge_internal::ApplyTileSumToNodeOp<TreeT> applyOp(value, active);
 
 1379                    applyOp.run(*childPtr);
 
 1380                    root.addChild(childPtr.release());
 
 1386            const bool mergeActive = mergeRoot->probeValue(key, mergeValue);
 
 1388            if (active || mergeActive) {
 
 1389                value += mergeValue;
 
 1390                root.addTile(key, value, 
true);
 
 1392                value += mergeValue;
 
 1393                root.addTile(key, value, 
false);
 
 1397            mergeTree.template addTile<NonConstChildT>(key, 
zeroVal<ValueT>(), 
false);
 
 1403    ValueT background = root.background();
 
 1406        const auto* mergeRoot = mergeTree.rootPtr();
 
 1407        if (!mergeRoot)     
continue;
 
 1408        background += mergeRoot->background();
 
 1411    root.setBackground(background, 
false);
 
 
 1416template<
typename TreeT>
 
 1417template<
typename NodeT>
 
 1420    using ChildT = 
typename NodeT::ChildNodeType;
 
 1421    using NonConstNodeT = 
typename std::remove_const<NodeT>::type;
 
 1423    if (this->
empty())     
return false;
 
 1426        const auto* mergeRoot = mergeTree.rootPtr();
 
 1427        if (!mergeRoot)     
continue;
 
 1429        const auto* mergeNode = mergeTree.template probeConstNode<NonConstNodeT>(node.origin());
 
 1433            for (
auto iter = node.beginValueAll(); iter; ++iter) {
 
 1434                if (mergeNode->isChildMaskOn(iter.pos())) {
 
 1436                    auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(iter.getCoord());
 
 1439                        merge_internal::ApplyTileSumToNodeOp<TreeT> applyOp(*iter, iter.isValueOn());
 
 1440                        applyOp.run(*childPtr);
 
 1441                        node.addChild(childPtr.release());
 
 1445                    const bool mergeActive = mergeNode->probeValue(iter.getCoord(), mergeValue);
 
 1446                    iter.setValue(*iter + mergeValue);
 
 1447                    if (mergeActive && !iter.isValueOn())   iter.setValueOn();
 
 1454            if (mergeTree.hasMask()) {
 
 1457                const ChildT* originalMergeNode = mergeRoot->template probeConstNode<ChildT>(node.origin());
 
 1458                if (originalMergeNode)  
continue;
 
 1462            const bool mergeActive = mergeRoot->probeValue(node.origin(), mergeValue);
 
 1463            for (
auto iter = node.beginValueAll(); iter; ++iter) {
 
 1464                iter.setValue(*iter + mergeValue);
 
 1465                if (mergeActive && !iter.isValueOn())   iter.setValueOn();
 
 
 1473template <
typename TreeT>
 
 1476    using RootT = 
typename TreeT::RootNodeType;
 
 1477    using RootChildT = 
typename RootT::ChildNodeType;
 
 1478    using NonConstRootChildT = 
typename std::remove_const<RootChildT>::type;
 
 1479    using LeafT = 
typename TreeT::LeafNodeType;
 
 1480    using ValueT = 
typename LeafT::ValueType;
 
 1481    using BufferT = 
typename LeafT::Buffer;
 
 1482    using NonConstLeafT = 
typename std::remove_const<LeafT>::type;
 
 1484    if (this->
empty())      
return false;
 
 1486    const Coord& ijk = leaf.origin();
 
 1491    merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
 
 1492        leaf.buffer(), this->background());
 
 1494    auto* data = leaf.buffer().data();
 
 1497        const RootT* mergeRoot = mergeTree.rootPtr();
 
 1498        if (!mergeRoot)     
continue;
 
 1500        const LeafT* mergeLeaf = mergeTree.template probeConstNode<NonConstLeafT>(ijk);
 
 1507            if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
 
 1508                mergeLeaf->buffer())) {
 
 1512            for (
Index i = 0; i < LeafT::SIZE; ++i) {
 
 1513                data[i] += mergeLeaf->getValue(i);
 
 1516            leaf.getValueMask() |= mergeLeaf->getValueMask();
 
 1520            if (mergeTree.hasMask()) {
 
 1523                const LeafT* originalMergeLeaf = mergeRoot->template probeConstNode<NonConstLeafT>(ijk);
 
 1524                if (originalMergeLeaf)  
continue;
 
 1527            const RootChildT* mergeRootChild = mergeRoot->template probeConstNode<NonConstRootChildT>(ijk);
 
 1530            bool mergeActive = mergeRootChild ?
 
 1531                mergeRootChild->probeValue(ijk, mergeValue) : mergeRoot->probeValue(ijk, mergeValue);
 
 1534                for (
Index i = 0; i < LeafT::SIZE; ++i) {
 
 1535                    data[i] += mergeValue;
 
 1539            if (mergeActive)    leaf.setValuesOn();
 
 
 1546template <
typename TreeT>
 
 1548SumMergeOp<TreeT>::background()
 const 
 1552    return *mBackground;
 
 1560#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
 1562#ifdef OPENVDB_INSTANTIATE_MERGE 
 
 
 
 
 
 
 
 
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Implementation of a depth-first node visitor.
static Coord max()
Return the largest possible coordinate.
Definition Coord.h:47
Tag dispatch class that distinguishes constructors that deep copy.
Definition Types.h:685
Definition Exceptions.h:63
Tag dispatch class that distinguishes constructors that steal.
Definition Types.h:687
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Definition NodeManager.h:891
OPENVDB_AX_API 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.
T negative(const T &val)
Return the unary negation of the given value.
Definition Math.h:128
Definition PointDataGrid.h:170
Index32 Index
Definition Types.h:54
OPENVDB_IMPORT void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types....
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
uint32_t Index32
Definition Types.h:52
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
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:121
#define OPENVDB_INSTANTIATE_STRUCT
Definition version.h.in:159
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218