10 #ifndef OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED
11 #define OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED
19 #include <unordered_map>
20 #include <unordered_set>
42 template <
typename TreeT>
48 using MaskTreeType =
typename TreeT::template ValueConverter<ValueMask>::Type;
54 : mTree(&tree), mSteal(true) { }
57 : mTreePtr(treePtr), mTree(mTreePtr.get()), mSteal(true) { }
65 : mTree(&tree), mSteal(false)
67 if (mTree &&
initialize) this->initializeMask();
81 void reset(
typename TreeType::Ptr treePtr,
Steal);
89 const RootNodeType* rootPtr()
const;
93 template<
typename NodeT>
94 const NodeT* probeConstNode(
const Coord& ijk)
const;
100 template <
typename NodeT>
101 std::unique_ptr<NodeT> stealOrDeepCopyNode(
const Coord& ijk);
105 template <
typename NodeT>
106 void addTile(
const Coord& ijk,
const ValueType& value,
bool active);
110 void initializeMask();
113 bool hasMask()
const;
123 typename TreeType::Ptr mTreePtr;
124 const TreeType* mTree;
131 template <
typename TreeT>
134 std::unique_ptr<MaskTreeType>
ptr;
141 : ptr(bool(other.ptr) ?
std::make_unique<
MaskTreeType>(*other.ptr) : nullptr) { }
144 ptr.reset(
bool(other.
ptr) ? std::make_unique<MaskTreeType>(*other.
ptr) :
nullptr);
151 template <
typename TreeT>
155 using RootT =
typename MaskT::RootNodeType;
156 using LeafT =
typename MaskT::LeafNodeType;
159 bool operator()(RootT& root,
size_t)
const;
160 template<
typename NodeT>
161 bool operator()(NodeT& node,
size_t)
const;
177 template<
typename TreeT,
bool Union>
180 using ValueT =
typename TreeT::ValueType;
181 using RootT =
typename TreeT::RootNodeType;
182 using LeafT =
typename TreeT::LeafNodeType;
187 template <
typename TagT>
199 template <
typename TreesT,
typename TagT>
202 for (
auto* tree : trees) {
204 mTreesToMerge.emplace_back(*tree, tag);
213 : mTreesToMerge(trees) { }
219 : mTreesToMerge(trees.cbegin(), trees.cend()) { }
222 bool empty()
const {
return mTreesToMerge.empty(); }
225 size_t size()
const {
return mTreesToMerge.size(); }
228 bool operator()(RootT& root,
size_t idx)
const;
231 template<
typename NodeT>
232 bool operator()(NodeT& node,
size_t idx)
const;
235 bool operator()(LeafT& leaf,
size_t idx)
const;
240 const ValueT& background()
const;
242 mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
243 mutable const ValueT* mBackground =
nullptr;
247 template <
typename TreeT>
250 template <
typename TreeT>
257 template<
typename TreeT>
260 using ValueT =
typename TreeT::ValueType;
261 using RootT =
typename TreeT::RootNodeType;
262 using LeafT =
typename TreeT::LeafNodeType;
267 template <
typename TagT>
279 size_t size()
const {
return 1; }
282 bool operator()(RootT& root,
size_t idx)
const;
285 template<
typename NodeT>
286 bool operator()(NodeT& node,
size_t idx)
const;
289 bool operator()(LeafT& leaf,
size_t idx)
const;
294 const ValueT& background()
const;
295 const ValueT& otherBackground()
const;
300 mutable const ValueT* mBackground =
nullptr;
301 mutable const ValueT* mOtherBackground =
nullptr;
308 template<
typename TreeT>
315 manager.foreachTopDown(op);
318 template<
typename TreeT>
321 return bool(mMaskTree.ptr);
324 template<
typename TreeT>
332 mTree = mTreePtr.get();
335 template<
typename TreeT>
339 return &mTree->root();
342 template<
typename TreeT>
343 template<
typename NodeT>
348 if (!mSteal && !this->mask()->isValueOn(ijk))
return nullptr;
349 return mTree->template probeConstNode<NodeT>(ijk);
352 template<
typename TreeT>
353 template<
typename NodeT>
354 std::unique_ptr<NodeT>
359 return std::unique_ptr<NodeT>(
360 tree->root().template stealNode<NodeT>(ijk, mTree->root().background(),
false)
363 auto* child = this->probeConstNode<NodeT>(ijk);
365 assert(this->hasMask());
366 auto result = std::make_unique<NodeT>(*child);
368 this->mask()->addTile(NodeT::LEVEL, ijk,
false,
false);
372 return std::unique_ptr<NodeT>();
375 template<
typename TreeT>
376 template<
typename NodeT>
381 if (NodeT::LEVEL == 0)
return;
385 auto* node = tree->template probeNode<NodeT>(ijk);
387 const Index pos = NodeT::coordToOffset(ijk);
388 node->addTile(pos, value, active);
391 auto* node = mTree->template probeConstNode<NodeT>(ijk);
394 assert(this->hasMask());
395 this->mask()->addTile(NodeT::LEVEL, ijk,
false,
false);
404 template <
typename TreeT>
407 using ChildT =
typename RootT::ChildNodeType;
409 const Index count = mTree.root().childCount();
411 std::vector<std::unique_ptr<ChildT>> children(count);
416 tbb::blocked_range<Index>(0, count),
417 [&](tbb::blocked_range<Index>& range)
419 for (
Index i = range.begin(); i < range.end(); i++) {
420 children[i] = std::make_unique<ChildT>(Coord::max(), true, true);
428 for (
auto iter = mTree.root().cbeginChildOn(); iter; ++iter) {
429 children[i]->setOrigin(iter->origin());
430 root.addChild(children[i].release());
437 template <
typename TreeT>
438 template <
typename NodeT>
441 using ChildT =
typename NodeT::ChildNodeType;
443 const auto* otherNode = mTree.template probeConstNode<NodeT>(node.origin());
444 if (!otherNode)
return false;
448 if (NodeT::LEVEL == 1) {
449 for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
450 node.addTile(iter.pos(),
true,
true);
453 for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
454 auto* child =
new ChildT(iter->origin(),
true,
true);
455 node.addChild(child);
466 namespace merge_internal {
469 template <
typename BufferT,
typename ValueT>
474 if (!buffer.isOutOfCore() && buffer.empty()) {
476 buffer.fill(background);
482 return !buffer.isOutOfCore() && buffer.empty();
486 template <
typename BufferT>
501 template <
typename TreeT,
bool Union>
504 if (this->empty())
return false;
507 if (!mBackground) mBackground = &root.background();
512 constexpr uint8_t ACTIVE_TILE = 0x1;
513 constexpr uint8_t INSIDE_TILE = 0x2;
514 constexpr uint8_t OUTSIDE_TILE = 0x4;
516 constexpr uint8_t INSIDE_STATE = Union ? INSIDE_TILE : OUTSIDE_TILE;
517 constexpr uint8_t OUTSIDE_STATE = Union ? OUTSIDE_TILE : INSIDE_TILE;
519 const ValueT insideBackground = Union ? -this->background() : this->background();
520 const ValueT outsideBackground = -insideBackground;
522 auto getTileFlag = [&](
auto& valueIter) -> uint8_t
525 const ValueT& value = valueIter.getValue();
526 if (value < zeroVal<ValueT>()) flag |= INSIDE_TILE;
527 else if (value > zeroVal<ValueT>()) flag |= OUTSIDE_TILE;
528 if (valueIter.isValueOn()) flag |= ACTIVE_TILE;
532 std::unordered_map<
Coord, uint8_t> tiles;
534 if (root.getTableSize() > 0) {
535 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
536 const Coord& key = valueIter.getCoord();
537 tiles.insert({key, getTileFlag(valueIter)});
544 const auto* mergeRoot = mergeTree.rootPtr();
545 if (!mergeRoot)
continue;
546 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
547 const Coord& key = valueIter.getCoord();
548 auto it = tiles.find(key);
549 if (it == tiles.end()) {
551 tiles.insert({key, getTileFlag(valueIter)});
554 const uint8_t flag = it->second;
555 if (flag & OUTSIDE_STATE) {
556 const uint8_t newFlag = getTileFlag(valueIter);
557 if (newFlag & INSIDE_STATE) {
558 it->second = newFlag;
567 for (
auto it : tiles) {
568 const uint8_t flag = it.second;
569 if (flag & INSIDE_STATE) {
570 const Coord& key = it.first;
571 const bool state = flag & ACTIVE_TILE;
572 root.addTile(key, insideBackground, state);
576 std::unordered_set<Coord> children;
578 if (root.getTableSize() > 0) {
579 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
580 const Coord& key = childIter.getCoord();
581 children.insert(key);
585 bool continueRecurse =
false;
591 const auto* mergeRoot = mergeTree.rootPtr();
592 if (!mergeRoot)
continue;
593 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
594 const Coord& key = childIter.getCoord();
597 if (children.count(key)) {
598 continueRecurse =
true;
603 auto it = tiles.find(key);
604 if (it != tiles.end() && it->second == INSIDE_STATE)
continue;
606 auto childPtr = mergeTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
607 if (childPtr) root.addChild(childPtr.release());
609 children.insert(key);
615 for (
auto it : tiles) {
616 const uint8_t flag = it.second;
617 if (flag & OUTSIDE_STATE) {
618 const Coord& key = it.first;
619 if (!children.count(key)) {
620 const bool state = flag & ACTIVE_TILE;
621 root.addTile(key, outsideBackground, state);
626 return continueRecurse;
629 template<
typename TreeT,
bool Union>
630 template<
typename NodeT>
633 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
635 if (this->empty())
return false;
637 const ValueT insideBackground = Union ? -this->background() : this->background();
638 const ValueT outsideBackground = -insideBackground;
640 using NodeMaskT =
typename NodeT::NodeMaskType;
644 NodeMaskT invalidTile;
646 auto isValid = [](
const ValueT& value)
648 return Union ? value < zeroVal<ValueT>() : value > zeroVal<ValueT>();
651 auto isInvalid = [](
const ValueT& value)
653 return Union ? value > zeroVal<ValueT>() : value < zeroVal<ValueT>();
656 for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
657 if (isValid(iter.getValue())) {
658 validTile.setOn(iter.pos());
659 }
else if (isInvalid(iter.getValue())) {
660 invalidTile.setOn(iter.pos());
664 bool continueRecurse =
false;
668 auto* mergeNode = mergeTree.template probeConstNode<NonConstNodeT>(node.origin());
670 if (!mergeNode)
continue;
674 for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
675 Index pos = iter.pos();
677 if (validTile.isOn(pos))
continue;
679 if (isValid(iter.getValue())) {
680 node.addTile(pos, insideBackground, iter.isValueOn());
681 validTile.setOn(pos);
687 for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
688 Index pos = iter.pos();
689 const Coord& ijk = iter.getCoord();
691 if (validTile.isOn(pos)) {
692 mergeTree.template addTile<NonConstNodeT>(ijk, outsideBackground,
false);
693 }
else if (invalidTile.isOn(pos)) {
694 auto childPtr = mergeTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
695 if (childPtr) node.addChild(childPtr.release());
696 invalidTile.setOff(pos);
700 continueRecurse =
true;
705 return continueRecurse;
708 template <
typename TreeT,
bool Union>
711 using LeafT =
typename TreeT::LeafNodeType;
712 using ValueT =
typename LeafT::ValueType;
713 using BufferT =
typename LeafT::Buffer;
715 if (this->empty())
return false;
717 const ValueT background = Union ? this->background() : -this->background();
723 leaf.buffer(), background);
726 const LeafT* mergeLeaf = mergeTree.template probeConstNode<LeafT>(leaf.origin());
727 if (!mergeLeaf)
continue;
731 mergeLeaf->buffer())) {
735 for (
Index i = 0 ; i < LeafT::SIZE; i++) {
736 const ValueT& newValue = mergeLeaf->getValue(i);
737 const bool doMerge = Union ? newValue < leaf.getValue(i) : newValue > leaf.getValue(i);
739 leaf.setValueOnly(i, newValue);
740 leaf.setActiveState(i, mergeLeaf->isValueOn(i));
748 template <
typename TreeT,
bool Union>
761 template <
typename TreeT>
765 if (!mBackground) mBackground = &root.background();
766 if (!mOtherBackground) mOtherBackground = &mTree.rootPtr()->background();
771 constexpr uint8_t ACTIVE_TILE = 0x1;
772 constexpr uint8_t INSIDE_TILE = 0x2;
773 constexpr uint8_t CHILD = 0x4;
775 auto getTileFlag = [&](
auto& valueIter) -> uint8_t
778 const ValueT& value = valueIter.getValue();
779 if (value < zeroVal<ValueT>()) flag |= INSIDE_TILE;
780 if (valueIter.isValueOn()) flag |= ACTIVE_TILE;
784 std::unordered_map<
Coord, uint8_t> flags;
786 if (root.getTableSize() > 0) {
787 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
788 const Coord& key = valueIter.getCoord();
789 const uint8_t flag = getTileFlag(valueIter);
790 if (flag & INSIDE_TILE) {
791 flags.insert({key, getTileFlag(valueIter)});
795 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
796 const Coord& key = childIter.getCoord();
797 flags.insert({key, CHILD});
801 bool continueRecurse =
false;
803 const auto* mergeRoot = mTree.rootPtr();
806 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
807 const Coord& key = valueIter.getCoord();
808 const uint8_t flag = getTileFlag(valueIter);
809 if (flag & INSIDE_TILE) {
810 auto it = flags.find(key);
811 if (it != flags.end()) {
812 const bool state = flag & ACTIVE_TILE;
813 root.addTile(key, this->background(), state);
818 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
819 const Coord& key = childIter.getCoord();
820 auto it = flags.find(key);
821 if (it != flags.end()) {
822 const uint8_t otherFlag = it->second;
823 if (otherFlag & CHILD) {
825 continueRecurse =
true;
826 }
else if (otherFlag & INSIDE_TILE) {
827 auto childPtr = mTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
829 childPtr->resetBackground(this->otherBackground(), this->background());
831 root.addChild(childPtr.release());
838 return continueRecurse;
841 template<
typename TreeT>
842 template<
typename NodeT>
845 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
847 using NodeMaskT =
typename NodeT::NodeMaskType;
851 NodeMaskT insideTile;
852 for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
853 if (iter.getValue() < zeroVal<ValueT>()) {
854 insideTile.setOn(iter.pos());
858 bool continueRecurse =
false;
860 auto* mergeNode = mTree.template probeConstNode<NonConstNodeT>(node.origin());
862 if (!mergeNode)
return continueRecurse;
866 for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
867 Index pos = iter.pos();
868 if (iter.getValue() < zeroVal<ValueT>()) {
869 if (insideTile.isOn(pos) || node.isChildMaskOn(pos)) {
870 node.addTile(pos, this->background(), iter.isValueOn());
877 for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
878 Index pos = iter.pos();
879 const Coord& ijk = iter.getCoord();
880 if (insideTile.isOn(pos)) {
881 auto childPtr = mTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
883 childPtr->resetBackground(this->otherBackground(), this->background());
885 node.addChild(childPtr.release());
887 }
else if (node.isChildMaskOn(pos)) {
890 continueRecurse =
true;
894 return continueRecurse;
897 template <
typename TreeT>
900 using LeafT =
typename TreeT::LeafNodeType;
901 using ValueT =
typename LeafT::ValueType;
902 using BufferT =
typename LeafT::Buffer;
908 leaf.buffer(), this->background());
910 const LeafT* mergeLeaf = mTree.template probeConstNode<LeafT>(leaf.origin());
911 if (!mergeLeaf)
return false;
917 mergeLeaf->buffer())) {
921 for (
Index i = 0 ; i < LeafT::SIZE; i++) {
922 const ValueT& aValue = leaf.getValue(i);
924 if (aValue < bValue) {
925 leaf.setValueOnly(i, bValue);
926 leaf.setActiveState(i, mergeLeaf->isValueOn(i));
933 template <
typename TreeT>
942 template <
typename TreeT>
943 const typename CsgDifferenceOp<TreeT>::ValueT&
944 CsgDifferenceOp<TreeT>::otherBackground()
const
947 assert(mOtherBackground);
948 return *mOtherBackground;
956 #endif // OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED