38 #ifndef OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED 39 #define OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED 46 #include <boost/scoped_array.hpp> 47 #include <tbb/blocked_range.h> 48 #include <tbb/parallel_for.h> 49 #include <tbb/parallel_reduce.h> 50 #include <tbb/parallel_sort.h> 62 template<
typename Gr
idType>
63 inline typename GridType::ValueType lsutilGridMax()
68 template<
typename Gr
idType>
69 inline typename GridType::ValueType lsutilGridZero()
71 return zeroVal<typename GridType::ValueType>();
94 template<
class Gr
idType>
98 typename GridType::ValueType cutoffDistance = lsutilGridMax<GridType>());
111 template<
class Gr
idOrTreeType>
112 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
114 const GridOrTreeType& volume,
115 typename GridOrTreeType::ValueType isovalue = lsutilGridZero<GridOrTreeType>());
138 template<
typename Gr
idOrTreeType>
139 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
141 const GridOrTreeType& volume,
142 typename GridOrTreeType::ValueType isovalue = lsutilGridZero<GridOrTreeType>(),
143 const typename TreeAdapter<GridOrTreeType>::TreeType::template ValueConverter<bool>::Type*
152 template<
typename Gr
idOrTreeType>
153 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
162 template<
typename Gr
idOrTreeType>
165 std::vector<
typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr>& masks);
175 template<
typename Gr
idOrTreeType>
178 std::vector<typename GridOrTreeType::Ptr>& segments);
189 template<
typename Gr
idOrTreeType>
191 segmentSDF(
const GridOrTreeType& volume, std::vector<typename GridOrTreeType::Ptr>& segments);
200 namespace level_set_util_internal {
203 template<
typename LeafNodeType>
211 : mNodes(nodes), mMaskNodes(maskNodes), mIsovalue(isovalue)
215 void operator()(
const tbb::blocked_range<size_t>& range)
const {
219 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
221 mMaskNodes[n] =
nullptr;
222 const LeafNodeType& node = *mNodes[n];
230 const ValueType* values = &node.getValue(0);
231 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
232 if (values[i] < mIsovalue) maskNodePt->
setValueOn(i,
true);
236 mMaskNodes[n] = maskNodePt;
237 maskNodePt =
nullptr;
241 if (maskNodePt)
delete maskNodePt;
244 LeafNodeType
const *
const *
const mNodes;
250 template<
typename TreeType,
typename InternalNodeType>
256 : mTree(&tree), mMaskNodes(maskNodes), mIsovalue(isovalue) { }
258 void operator()(
const tbb::blocked_range<size_t>& range)
const {
260 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
261 typename InternalNodeType::ValueAllIter it = mMaskNodes[n]->beginValueAll();
263 if (acc.
getValue(it.getCoord()) < mIsovalue) {
277 template<
typename TreeType>
284 const size_t * nodexIndexMap,
ValueType background)
285 : mNewTree(background)
288 , mNodeIndexMap(nodexIndexMap)
293 : mNewTree(rhs.mNewTree.background())
296 , mNodeIndexMap(rhs.mNodeIndexMap)
305 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
306 for (
size_t i = mNodeIndexMap[n], I = mNodeIndexMap[n + 1]; i < I; ++i) {
307 if (mNodes[i] !=
nullptr) acc.
addLeaf(mNodes[i]);
311 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
321 TreeType *
const mTreePt;
322 LeafNodeType **
const mNodes;
323 size_t const *
const mNodeIndexMap;
328 template<
typename LeafNodeType>
336 : mNodes(nodes), mMaskNodes(maskNodes), mIsovalue(isovalue)
340 void operator()(
const tbb::blocked_range<size_t>& range)
const {
344 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
346 mMaskNodes[n] =
nullptr;
347 const LeafNodeType& node = *mNodes[n];
355 typename LeafNodeType::ValueOnCIter it;
356 for (it = node.cbeginValueOn(); it; ++it) {
357 maskNodePt->
setValueOn(it.pos(), ((*it - mIsovalue) < 0.0) ? 0 : 1);
361 mMaskNodes[n] = maskNodePt;
362 maskNodePt =
nullptr;
366 if (maskNodePt)
delete maskNodePt;
369 LeafNodeType
const *
const *
const mNodes;
375 template<
typename LeafNodeType>
381 void operator()(
const tbb::blocked_range<size_t>& range)
const {
382 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
384 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
385 values[i] = values[i] < 0 ? 1 : -1;
394 template<
typename LeafNodeType>
412 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
413 const ValueType* data = mNodes[n]->buffer().data();
414 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
415 minValue =
std::min(minValue, data[i]);
424 LeafNodeType
const *
const *
const mNodes;
428 template<
typename InternalNodeType>
446 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
447 typename InternalNodeType::ValueAllCIter it = mNodes[n]->beginValueAll();
458 InternalNodeType
const *
const *
const mNodes;
462 template<
typename LeafNodeType>
468 : mNodes(nodes), mWeight(
ValueType(1.0) / cutoffDistance)
472 void operator()(
const tbb::blocked_range<size_t>& range)
const {
474 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
476 LeafNodeType& node = *mNodes[n];
479 ValueType* values = node.buffer().data();
480 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
482 if (values[i] >
ValueType(0.0)) node.setValueOn(i);
485 if (node.onVoxelCount() == 0) {
497 template<
typename TreeType,
typename InternalNodeType>
501 : mTree(&tree), mNodes(nodes) { }
503 void operator()(
const tbb::blocked_range<size_t>& range)
const {
505 using ValueType =
typename TreeType::ValueType;
508 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
509 typename InternalNodeType::ValueAllIter it = mNodes[n]->beginValueAll();
511 if (acc.
getValue(it.getCoord()) < ValueType(0.0)) {
512 it.setValue(ValueType(1.0));
524 template<
typename TreeType>
529 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
535 , mFillMask(&fillMask)
536 , mFillNodes(fillNodes)
537 , mNewNodes(newNodes)
538 , mIsovalue(isovalue)
542 void operator()(
const tbb::blocked_range<size_t>& range)
const {
547 boost::scoped_array<char> valueMask(
new char[BoolLeafNodeType::SIZE]);
549 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
551 mNewNodes[n] =
nullptr;
553 const Coord& origin = node.origin();
555 const bool denseNode = node.isDense();
560 int denseNeighbors = 0;
564 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
567 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
570 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
573 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
576 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
579 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
581 if (denseNeighbors == 6)
continue;
585 memset(valueMask.get(), 0,
sizeof(char) * BoolLeafNodeType::SIZE);
587 const typename TreeType::LeafNodeType* distNode = distAcc.
probeConstLeaf(origin);
591 bool earlyTermination =
false;
595 evalInternalNeighborsP(valueMask.get(), node, *distNode);
596 evalInternalNeighborsN(valueMask.get(), node, *distNode);
597 }
else if (distAcc.
getValue(origin) > mIsovalue) {
598 earlyTermination = evalInternalNeighborsP(valueMask.get(), node);
599 if (!earlyTermination) {
600 earlyTermination = evalInternalNeighborsN(valueMask.get(), node);
607 if (!earlyTermination) {
608 evalExternalNeighborsX<true>(valueMask.get(), node, maskAcc, distAcc);
609 evalExternalNeighborsX<false>(valueMask.get(), node, maskAcc, distAcc);
610 evalExternalNeighborsY<true>(valueMask.get(), node, maskAcc, distAcc);
611 evalExternalNeighborsY<false>(valueMask.get(), node, maskAcc, distAcc);
612 evalExternalNeighborsZ<true>(valueMask.get(), node, maskAcc, distAcc);
613 evalExternalNeighborsZ<false>(valueMask.get(), node, maskAcc, distAcc);
618 int numBoundaryValues = 0;
619 for (
Index i = 0, I = BoolLeafNodeType::SIZE; i < I; ++i) {
620 numBoundaryValues += valueMask[i] == 1;
623 if (numBoundaryValues > 0) {
625 for (
Index i = 0, I = BoolLeafNodeType::SIZE; i < I; ++i) {
626 if (valueMask[i] == 1) mNewNodes[n]->setValueOn(i);
634 void evalInternalNeighborsP(
char* valueMask,
const BoolLeafNodeType& node,
635 const LeafNodeType& distNode)
const 637 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
638 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
639 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
640 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
641 for (
Index z = 0; z < BoolLeafNodeType::DIM - 1; ++z) {
642 const Index pos = yPos + z;
644 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
646 if (!node.isValueOn(pos + 1) && distNode.getValue(pos + 1) > mIsovalue) {
653 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
654 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
655 for (
Index y = 0; y < BoolLeafNodeType::DIM - 1; ++y) {
656 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
657 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
658 const Index pos = yPos + z;
660 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
662 if (!node.isValueOn(pos + BoolLeafNodeType::DIM) &&
663 distNode.getValue(pos + BoolLeafNodeType::DIM) > mIsovalue) {
670 for (
Index x = 0; x < BoolLeafNodeType::DIM - 1; ++x) {
671 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
672 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
673 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
674 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
675 const Index pos = yPos + z;
677 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
679 if (!node.isValueOn(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) &&
680 (distNode.getValue(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)
690 bool evalInternalNeighborsP(
char* valueMask,
const BoolLeafNodeType& node)
const {
692 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
693 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
694 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
695 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
696 for (
Index z = 0; z < BoolLeafNodeType::DIM - 1; ++z) {
697 const Index pos = yPos + z;
699 if (node.isValueOn(pos) && !node.isValueOn(pos + 1)) {
707 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
708 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
709 for (
Index y = 0; y < BoolLeafNodeType::DIM - 1; ++y) {
710 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
711 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
712 const Index pos = yPos + z;
714 if (node.isValueOn(pos) && !node.isValueOn(pos + BoolLeafNodeType::DIM)) {
722 for (
Index x = 0; x < BoolLeafNodeType::DIM - 1; ++x) {
723 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
724 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
725 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
726 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
727 const Index pos = yPos + z;
729 if (node.isValueOn(pos) &&
730 !node.isValueOn(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)) {
743 void evalInternalNeighborsN(
char* valueMask,
const BoolLeafNodeType& node,
744 const LeafNodeType& distNode)
const 746 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
747 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
748 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
749 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
750 for (
Index z = 1; z < BoolLeafNodeType::DIM; ++z) {
751 const Index pos = yPos + z;
753 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
755 if (!node.isValueOn(pos - 1) && distNode.getValue(pos - 1) > mIsovalue) {
762 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
763 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
764 for (
Index y = 1; y < BoolLeafNodeType::DIM; ++y) {
765 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
766 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
767 const Index pos = yPos + z;
769 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
771 if (!node.isValueOn(pos - BoolLeafNodeType::DIM) &&
772 distNode.getValue(pos - BoolLeafNodeType::DIM) > mIsovalue) {
779 for (
Index x = 1; x < BoolLeafNodeType::DIM; ++x) {
780 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
781 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
782 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
783 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
784 const Index pos = yPos + z;
786 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
788 if (!node.isValueOn(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) &&
789 (distNode.getValue(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)
800 bool evalInternalNeighborsN(
char* valueMask,
const BoolLeafNodeType& node)
const {
802 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
803 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
804 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
805 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
806 for (
Index z = 1; z < BoolLeafNodeType::DIM; ++z) {
807 const Index pos = yPos + z;
809 if (node.isValueOn(pos) && !node.isValueOn(pos - 1)) {
817 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
818 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
819 for (
Index y = 1; y < BoolLeafNodeType::DIM; ++y) {
820 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
821 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
822 const Index pos = yPos + z;
824 if (node.isValueOn(pos) && !node.isValueOn(pos - BoolLeafNodeType::DIM)) {
832 for (
Index x = 1; x < BoolLeafNodeType::DIM; ++x) {
833 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
834 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
835 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
836 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
837 const Index pos = yPos + z;
839 if (node.isValueOn(pos) &&
840 !node.isValueOn(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)) {
855 template<
bool UpWind>
856 void evalExternalNeighborsX(
char* valueMask,
const BoolLeafNodeType& node,
857 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
858 const tree::ValueAccessor<const TreeType>& distAcc)
const {
860 const Coord& origin = node.origin();
861 Coord ijk(0, 0, 0), nijk;
866 ijk[0] = int(BoolLeafNodeType::DIM) - 1;
869 const Index xPos = ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM));
871 for (ijk[1] = 0; ijk[1] < int(BoolLeafNodeType::DIM); ++ijk[1]) {
872 const Index yPos = xPos + (ijk[1] << int(BoolLeafNodeType::LOG2DIM));
874 for (ijk[2] = 0; ijk[2] < int(BoolLeafNodeType::DIM); ++ijk[2]) {
875 const Index pos = yPos + ijk[2];
877 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
879 nijk = origin + ijk.offsetBy(step, 0, 0);
881 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
890 template<
bool UpWind>
891 void evalExternalNeighborsY(
char* valueMask,
const BoolLeafNodeType& node,
892 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
893 const tree::ValueAccessor<const TreeType>& distAcc)
const {
895 const Coord& origin = node.origin();
896 Coord ijk(0, 0, 0), nijk;
901 ijk[1] = int(BoolLeafNodeType::DIM) - 1;
904 const Index yPos = ijk[1] << int(BoolLeafNodeType::LOG2DIM);
906 for (ijk[0] = 0; ijk[0] < int(BoolLeafNodeType::DIM); ++ijk[0]) {
907 const Index xPos = yPos + (ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM)));
909 for (ijk[2] = 0; ijk[2] < int(BoolLeafNodeType::DIM); ++ijk[2]) {
910 const Index pos = xPos + ijk[2];
912 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
914 nijk = origin + ijk.offsetBy(0, step, 0);
915 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
924 template<
bool UpWind>
925 void evalExternalNeighborsZ(
char* valueMask,
const BoolLeafNodeType& node,
926 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
927 const tree::ValueAccessor<const TreeType>& distAcc)
const {
929 const Coord& origin = node.origin();
930 Coord ijk(0, 0, 0), nijk;
935 ijk[2] = int(BoolLeafNodeType::DIM) - 1;
938 for (ijk[0] = 0; ijk[0] < int(BoolLeafNodeType::DIM); ++ijk[0]) {
939 const Index xPos = ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM));
941 for (ijk[1] = 0; ijk[1] < int(BoolLeafNodeType::DIM); ++ijk[1]) {
942 const Index pos = ijk[2] + xPos + (ijk[1] << int(BoolLeafNodeType::LOG2DIM));
944 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
946 nijk = origin + ijk.offsetBy(0, 0, step);
947 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
957 TreeType
const *
const mTree;
958 BoolTreeType
const *
const mFillMask;
959 BoolLeafNodeType
const *
const *
const mFillNodes;
960 BoolLeafNodeType **
const mNewNodes;
961 ValueType
const mIsovalue;
967 template <
class TreeType>
968 inline typename TreeType::template ValueConverter<char>::Type::Ptr
970 const typename TreeType::template ValueConverter<bool>::Type* fillMask)
972 using LeafNodeType =
typename TreeType::LeafNodeType;
973 using RootNodeType =
typename TreeType::RootNodeType;
974 using NodeChainType =
typename RootNodeType::NodeChainType;
975 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1>>::type;
977 using CharTreeType =
typename TreeType::template ValueConverter<char>::Type;
978 using CharLeafNodeType =
typename CharTreeType::LeafNodeType;
980 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
981 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
983 const TreeType* treePt = &tree;
985 size_t numLeafNodes = 0, numInternalNodes = 0;
987 std::vector<const LeafNodeType*> nodes;
988 std::vector<size_t> leafnodeCount;
992 std::vector<const InternalNodeType*> internalNodes;
993 treePt->getNodes(internalNodes);
995 numInternalNodes = internalNodes.size();
997 leafnodeCount.push_back(0);
998 for (
size_t n = 0; n < numInternalNodes; ++n) {
999 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
1002 numLeafNodes = leafnodeCount.back();
1005 nodes.reserve(numLeafNodes);
1007 for (
size_t n = 0; n < numInternalNodes; ++n) {
1008 internalNodes[n]->getNodes(nodes);
1013 boost::scoped_array<CharLeafNodeType*> maskNodes(
new CharLeafNodeType*[numLeafNodes]);
1015 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1019 typename CharTreeType::Ptr maskTree(
new CharTreeType(1));
1022 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
1026 std::vector<CharLeafNodeType*> extraMaskNodes;
1030 std::vector<const BoolLeafNodeType*> fillMaskNodes;
1031 fillMask->getNodes(fillMaskNodes);
1033 boost::scoped_array<BoolLeafNodeType*> boundaryMaskNodes(
1034 new BoolLeafNodeType*[fillMaskNodes.size()]);
1036 tbb::parallel_for(tbb::blocked_range<size_t>(0, fillMaskNodes.size()),
1038 boundaryMaskNodes.get()));
1042 for (
size_t n = 0, N = fillMaskNodes.size(); n < N; ++n) {
1044 if (boundaryMaskNodes[n] ==
nullptr)
continue;
1046 const BoolLeafNodeType& boundaryNode = *boundaryMaskNodes[n];
1047 const Coord& origin = boundaryNode.origin();
1049 CharLeafNodeType* maskNodePt = maskAcc.
probeLeaf(origin);
1053 extraMaskNodes.push_back(maskNodePt);
1056 char* data = maskNodePt->buffer().data();
1058 typename BoolLeafNodeType::ValueOnCIter it = boundaryNode.cbeginValueOn();
1060 if (data[it.pos()] != 0) data[it.pos()] = -1;
1063 delete boundaryMaskNodes[n];
1071 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1074 if (!extraMaskNodes.empty()) {
1075 tbb::parallel_for(tbb::blocked_range<size_t>(0, extraMaskNodes.size()),
1086 template <
class TreeType>
1087 inline typename TreeType::template ValueConverter<bool>::Type::Ptr
1090 using ValueType =
typename TreeType::ValueType;
1091 using LeafNodeType =
typename TreeType::LeafNodeType;
1092 using RootNodeType =
typename TreeType::RootNodeType;
1093 using NodeChainType =
typename RootNodeType::NodeChainType;
1094 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
1096 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1097 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
1098 using BoolRootNodeType =
typename BoolTreeType::RootNodeType;
1099 using BoolNodeChainType =
typename BoolRootNodeType::NodeChainType;
1100 using BoolInternalNodeType =
1101 typename boost::mpl::at<BoolNodeChainType, boost::mpl::int_<1>>::type;
1113 size_t numLeafNodes = 0, numInternalNodes = 0;
1115 std::vector<const LeafNodeType*> nodes;
1116 std::vector<size_t> leafnodeCount;
1120 std::vector<const InternalNodeType*> internalNodes;
1121 tree.getNodes(internalNodes);
1123 numInternalNodes = internalNodes.size();
1125 leafnodeCount.push_back(0);
1126 for (
size_t n = 0; n < numInternalNodes; ++n) {
1127 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
1130 numLeafNodes = leafnodeCount.back();
1133 nodes.reserve(numLeafNodes);
1135 for (
size_t n = 0; n < numInternalNodes; ++n) {
1136 internalNodes[n]->getNodes(nodes);
1141 boost::scoped_array<BoolLeafNodeType*> maskNodes(
new BoolLeafNodeType*[numLeafNodes]);
1143 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1148 typename BoolTreeType::Ptr maskTree(
new BoolTreeType(
false));
1151 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
1155 std::vector<BoolInternalNodeType*> internalMaskNodes;
1156 maskTree->getNodes(internalMaskNodes);
1158 tbb::parallel_for(tbb::blocked_range<size_t>(0, internalMaskNodes.size()),
1163 typename BoolTreeType::ValueAllIter it(*maskTree);
1164 it.setMaxDepth(BoolTreeType::ValueAllIter::LEAF_DEPTH - 2);
1167 if (acc.getValue(it.getCoord()) < iso) {
1169 it.setActiveState(
true);
1177 template<
typename InputTreeType>
1182 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
1186 const InputTreeType& inputTree,
1187 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
1190 : mInputAccessor(inputTree)
1191 , mInputNodes(!inputLeafNodes.empty() ? &inputLeafNodes.front() : nullptr)
1193 , mMaskAccessor(maskTree)
1199 : mInputAccessor(rhs.mInputAccessor.tree())
1200 , mInputNodes(rhs.mInputNodes)
1202 , mMaskAccessor(mMaskTree)
1203 , mIsovalue(rhs.mIsovalue)
1214 for (
size_t n = range.begin(); mInputNodes && (n != range.end()); ++n) {
1219 else maskNodePt->setOrigin(node.origin());
1221 bool collectedData =
false;
1223 for (
typename InputLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
1225 bool isUnder = *it < iso;
1227 ijk = it.getCoord();
1230 bool signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1235 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1241 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1247 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1253 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1259 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1264 collectedData =
true;
1265 maskNodePt->setValueOn(it.pos(),
true);
1269 if (collectedData) {
1270 mMaskAccessor.addLeaf(maskNodePt);
1271 maskNodePt =
nullptr;
1275 if (maskNodePt)
delete maskNodePt;
1279 mMaskAccessor.tree().merge(rhs.mMaskAccessor.
tree());
1284 InputLeafNodeType
const *
const *
const mInputNodes;
1286 BoolTreeType mMaskTree;
1289 InputValueType mIsovalue;
1296 template<
typename NodeType>
1311 template<
typename NodeType>
1316 using NodeMaskType =
typename NodeType::NodeMaskType;
1318 using NodeMaskSegmentTypePtr =
typename NodeMaskSegmentType::Ptr;
1320 NodeMaskType nodeMask(node.getValueMask());
1321 std::deque<Index> indexList;
1323 while (!nodeMask.isOff()) {
1325 NodeMaskSegmentTypePtr segment(
new NodeMaskSegmentType());
1326 segment->origin = node.origin();
1328 NodeMaskType& mask = segment->mask;
1330 indexList.push_back(nodeMask.findFirstOn());
1331 nodeMask.setOff(indexList.back());
1334 while (!indexList.empty()) {
1336 const Index pos = indexList.back();
1337 indexList.pop_back();
1339 if (mask.isOn(pos))
continue;
1342 ijk = NodeType::offsetToLocalCoord(pos);
1344 Index npos = pos - 1;
1345 if (ijk[2] != 0 && nodeMask.isOn(npos)) {
1346 nodeMask.setOff(npos);
1347 indexList.push_back(npos);
1351 if (ijk[2] != (NodeType::DIM - 1) && nodeMask.isOn(npos)) {
1352 nodeMask.setOff(npos);
1353 indexList.push_back(npos);
1356 npos = pos - NodeType::DIM;
1357 if (ijk[1] != 0 && nodeMask.isOn(npos)) {
1358 nodeMask.setOff(npos);
1359 indexList.push_back(npos);
1362 npos = pos + NodeType::DIM;
1363 if (ijk[1] != (NodeType::DIM - 1) && nodeMask.isOn(npos)) {
1364 nodeMask.setOff(npos);
1365 indexList.push_back(npos);
1368 npos = pos - NodeType::DIM * NodeType::DIM;
1369 if (ijk[0] != 0 && nodeMask.isOn(npos)) {
1370 nodeMask.setOff(npos);
1371 indexList.push_back(npos);
1374 npos = pos + NodeType::DIM * NodeType::DIM;
1375 if (ijk[0] != (NodeType::DIM - 1) && nodeMask.isOn(npos)) {
1376 nodeMask.setOff(npos);
1377 indexList.push_back(npos);
1382 segments.push_back(segment);
1387 template<
typename NodeType>
1395 : mNodes(!nodes.empty() ? &nodes.front() : nullptr)
1396 , mNodeMaskArray(nodeMaskArray)
1401 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1402 NodeType& node = *mNodes[n];
1406 Coord& origin =
const_cast<Coord&
>(node.origin());
1407 origin[0] =
static_cast<int>(n);
1416 template<
typename TreeType,
typename NodeType>
1426 , mNodeMaskArray(nodeMaskArray)
1434 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1437 if (segments.empty())
continue;
1439 std::vector<std::set<NodeMaskSegmentType*> > connections(segments.size());
1441 Coord ijk = segments[0]->origin;
1443 const NodeType* node = acc.template probeConstNode<NodeType>(ijk);
1444 if (!node)
continue;
1448 ijk[2] += NodeType::DIM;
1449 const NodeType* nodeZUp = acc.template probeConstNode<NodeType>(ijk);
1450 ijk[2] -= (NodeType::DIM + NodeType::DIM);
1451 const NodeType* nodeZDown = acc.template probeConstNode<NodeType>(ijk);
1452 ijk[2] += NodeType::DIM;
1454 ijk[1] += NodeType::DIM;
1455 const NodeType* nodeYUp = acc.template probeConstNode<NodeType>(ijk);
1456 ijk[1] -= (NodeType::DIM + NodeType::DIM);
1457 const NodeType* nodeYDown = acc.template probeConstNode<NodeType>(ijk);
1458 ijk[1] += NodeType::DIM;
1460 ijk[0] += NodeType::DIM;
1461 const NodeType* nodeXUp = acc.template probeConstNode<NodeType>(ijk);
1462 ijk[0] -= (NodeType::DIM + NodeType::DIM);
1463 const NodeType* nodeXDown = acc.template probeConstNode<NodeType>(ijk);
1464 ijk[0] += NodeType::DIM;
1466 const Index startPos = node->getValueMask().findFirstOn();
1467 for (
Index pos = startPos; pos < NodeMaskType::SIZE; ++pos) {
1469 if (!node->isValueOn(pos))
continue;
1471 ijk = NodeType::offsetToLocalCoord(pos);
1473 #ifdef _MSC_FULL_VER 1474 #if _MSC_FULL_VER >= 190000000 && _MSC_FULL_VER < 190024210 1476 volatile Index npos = 0;
1485 npos = pos + (NodeType::DIM - 1);
1486 if (nodeZDown && nodeZDown->isValueOn(npos)) {
1488 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeZDown)], npos);
1489 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1490 connections[idx].insert(nsegment);
1492 }
else if (ijk[2] == (NodeType::DIM - 1)) {
1493 npos = pos - (NodeType::DIM - 1);
1494 if (nodeZUp && nodeZUp->isValueOn(npos)) {
1496 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeZUp)], npos);
1497 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1498 connections[idx].insert(nsegment);
1503 npos = pos + (NodeType::DIM - 1) * NodeType::DIM;
1504 if (nodeYDown && nodeYDown->isValueOn(npos)) {
1506 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeYDown)], npos);
1507 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1508 connections[idx].insert(nsegment);
1510 }
else if (ijk[1] == (NodeType::DIM - 1)) {
1511 npos = pos - (NodeType::DIM - 1) * NodeType::DIM;
1512 if (nodeYUp && nodeYUp->isValueOn(npos)) {
1514 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeYUp)], npos);
1515 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1516 connections[idx].insert(nsegment);
1521 npos = pos + (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1522 if (nodeXDown && nodeXDown->isValueOn(npos)) {
1524 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeXDown)], npos);
1525 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1526 connections[idx].insert(nsegment);
1528 }
else if (ijk[0] == (NodeType::DIM - 1)) {
1529 npos = pos - (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1530 if (nodeXUp && nodeXUp->isValueOn(npos)) {
1532 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeXUp)], npos);
1533 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1534 connections[idx].insert(nsegment);
1539 for (
size_t i = 0, I = connections.size(); i < I; ++i) {
1541 typename std::set<NodeMaskSegmentType*>::iterator
1542 it = connections[i].begin(), end = connections[i].end();
1544 std::vector<NodeMaskSegmentType*>& segmentConnections = segments[i]->connections;
1545 segmentConnections.reserve(connections.size());
1546 for (; it != end; ++it) {
1547 segmentConnections.push_back(*it);
1555 static inline size_t getNodeOffset(
const NodeType& node) {
1556 return static_cast<size_t>(node.origin()[0]);
1559 static inline NodeMaskSegmentType*
1560 findNodeMaskSegment(NodeMaskSegmentVector& segments,
Index pos)
1562 NodeMaskSegmentType* segment =
nullptr;
1564 for (
size_t n = 0, N = segments.size(); n < N; ++n) {
1565 if (segments[n]->mask.isOn(pos)) {
1566 segment = segments[n].get();
1575 findNodeMaskSegmentIndex(NodeMaskSegmentVector& segments,
Index pos)
1577 for (
Index n = 0, N =
Index(segments.size()); n < N; ++n) {
1578 if (segments[n]->mask.isOn(pos))
return n;
1583 TreeType
const *
const mTree;
1584 NodeMaskSegmentVector *
const mNodeMaskArray;
1588 template<
typename TreeType>
1596 : mSegments(!segments.empty() ? &segments.front() : nullptr)
1597 , mTree(new TreeType(false))
1602 : mSegments(rhs.mSegments)
1603 , mTree(new TreeType(false))
1615 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1618 node->getValueMask() |= segment.
mask;
1623 NodeMaskSegmentType *
const *
const mSegments;
1631 template<
typename TreeType>
1638 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1644 std::vector<BoolLeafNodeType*>& maskNodes)
1645 : mDistTree(&distTree)
1646 , mMaskTree(&maskTree)
1647 , mMaskNodes(!maskNodes.empty() ? &maskNodes.front() : nullptr)
1648 , mNewMaskTree(false)
1653 : mDistTree(rhs.mDistTree)
1654 , mMaskTree(rhs.mMaskTree)
1655 , mMaskNodes(rhs.mMaskNodes)
1656 , mNewMaskTree(false)
1672 NodeMaskType maskZUp, maskZDown, maskYUp, maskYDown, maskXUp, maskXDown;
1674 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1677 if (maskNode.isEmpty())
continue;
1679 Coord ijk = maskNode.origin(), nijk;
1682 if (!distNode)
continue;
1684 const ValueType *dataZUp =
nullptr, *dataZDown =
nullptr,
1685 *dataYUp =
nullptr, *dataYDown =
nullptr,
1686 *dataXUp =
nullptr, *dataXDown =
nullptr;
1688 ijk[2] += NodeType::DIM;
1689 getData(ijk, distAcc, maskAcc, maskZUp, dataZUp);
1690 ijk[2] -= (NodeType::DIM + NodeType::DIM);
1691 getData(ijk, distAcc, maskAcc, maskZDown, dataZDown);
1692 ijk[2] += NodeType::DIM;
1694 ijk[1] += NodeType::DIM;
1695 getData(ijk, distAcc, maskAcc, maskYUp, dataYUp);
1696 ijk[1] -= (NodeType::DIM + NodeType::DIM);
1697 getData(ijk, distAcc, maskAcc, maskYDown, dataYDown);
1698 ijk[1] += NodeType::DIM;
1700 ijk[0] += NodeType::DIM;
1701 getData(ijk, distAcc, maskAcc, maskXUp, dataXUp);
1702 ijk[0] -= (NodeType::DIM + NodeType::DIM);
1703 getData(ijk, distAcc, maskAcc, maskXDown, dataXDown);
1704 ijk[0] += NodeType::DIM;
1706 for (
typename BoolLeafNodeType::ValueOnIter it = maskNode.beginValueOn(); it; ++it) {
1708 const Index pos = it.pos();
1709 const ValueType val = std::abs(distNode->getValue(pos));
1711 ijk = BoolLeafNodeType::offsetToLocalCoord(pos);
1712 nijk = ijk + maskNode.origin();
1714 if (dataZUp && ijk[2] == (BoolLeafNodeType::DIM - 1)) {
1715 const Index npos = pos - (NodeType::DIM - 1);
1716 if (maskZUp.isOn(npos) && std::abs(dataZUp[npos]) > val) {
1717 newMaskAcc.
setValueOn(nijk.offsetBy(0, 0, 1));
1719 }
else if (dataZDown && ijk[2] == 0) {
1720 const Index npos = pos + (NodeType::DIM - 1);
1721 if (maskZDown.isOn(npos) && std::abs(dataZDown[npos]) > val) {
1722 newMaskAcc.
setValueOn(nijk.offsetBy(0, 0, -1));
1726 if (dataYUp && ijk[1] == (BoolLeafNodeType::DIM - 1)) {
1727 const Index npos = pos - (NodeType::DIM - 1) * NodeType::DIM;
1728 if (maskYUp.isOn(npos) && std::abs(dataYUp[npos]) > val) {
1729 newMaskAcc.
setValueOn(nijk.offsetBy(0, 1, 0));
1731 }
else if (dataYDown && ijk[1] == 0) {
1732 const Index npos = pos + (NodeType::DIM - 1) * NodeType::DIM;
1733 if (maskYDown.isOn(npos) && std::abs(dataYDown[npos]) > val) {
1734 newMaskAcc.
setValueOn(nijk.offsetBy(0, -1, 0));
1738 if (dataXUp && ijk[0] == (BoolLeafNodeType::DIM - 1)) {
1739 const Index npos = pos - (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1740 if (maskXUp.isOn(npos) && std::abs(dataXUp[npos]) > val) {
1741 newMaskAcc.
setValueOn(nijk.offsetBy(1, 0, 0));
1743 }
else if (dataXDown && ijk[0] == 0) {
1744 const Index npos = pos + (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1745 if (maskXDown.isOn(npos) && std::abs(dataXDown[npos]) > val) {
1746 newMaskAcc.
setValueOn(nijk.offsetBy(-1, 0, 0));
1759 const ValueType*& data)
1763 data = node->buffer().data();
1764 mask = node->getValueMask();
1765 const BoolLeafNodeType* maskNodePt = maskAcc.
probeConstLeaf(ijk);
1766 if (maskNodePt) mask -= maskNodePt->getValueMask();
1770 TreeType
const *
const mDistTree;
1771 BoolTreeType *
const mMaskTree;
1772 BoolLeafNodeType **
const mMaskNodes;
1774 BoolTreeType mNewMaskTree;
1778 template<
typename TreeType>
1787 : mTree(&tree), mMaskNodes(!maskNodes.empty() ? &maskNodes.front() : nullptr)
1795 std::vector<Index> indexList;
1796 indexList.reserve(NodeMaskType::SIZE);
1798 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1803 if (!distNode)
continue;
1808 for (
Index pos = narrowbandMask.findFirstOn(); pos < NodeMaskType::SIZE; ++pos) {
1809 if (narrowbandMask.isOn(pos)) indexList.push_back(pos);
1812 mask -= narrowbandMask;
1815 const ValueType* data = distNode->buffer().data();
1818 while (!indexList.empty()) {
1820 const Index pos = indexList.back();
1821 indexList.pop_back();
1823 if (narrowbandMask.isOn(pos))
continue;
1824 narrowbandMask.setOn(pos);
1826 const ValueType dist = std::abs(data[pos]);
1828 ijk = LeafNodeType::offsetToLocalCoord(pos);
1830 Index npos = pos - 1;
1831 if (ijk[2] != 0 && mask.isOn(npos) && std::abs(data[npos]) > dist) {
1833 indexList.push_back(npos);
1837 if ((ijk[2] != (LeafNodeType::DIM - 1)) && mask.isOn(npos)
1838 && std::abs(data[npos]) > dist)
1841 indexList.push_back(npos);
1844 npos = pos - LeafNodeType::DIM;
1845 if (ijk[1] != 0 && mask.isOn(npos) && std::abs(data[npos]) > dist) {
1847 indexList.push_back(npos);
1850 npos = pos + LeafNodeType::DIM;
1851 if ((ijk[1] != (LeafNodeType::DIM - 1)) && mask.isOn(npos)
1852 && std::abs(data[npos]) > dist)
1855 indexList.push_back(npos);
1858 npos = pos - LeafNodeType::DIM * LeafNodeType::DIM;
1859 if (ijk[0] != 0 && mask.isOn(npos) && std::abs(data[npos]) > dist) {
1861 indexList.push_back(npos);
1864 npos = pos + LeafNodeType::DIM * LeafNodeType::DIM;
1865 if ((ijk[0] != (LeafNodeType::DIM - 1)) && mask.isOn(npos)
1866 && std::abs(data[npos]) > dist)
1869 indexList.push_back(npos);
1880 template<
typename TreeType>
1883 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1888 : mTree(&tree), mSegments(!segments.empty() ? &segments.front() : nullptr)
1894 const TreeType& distTree = *mTree;
1895 std::vector<BoolLeafNodeType*> nodes;
1897 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1906 candidateMask.getNodes(nodes);
1907 if (nodes.empty())
break;
1909 const tbb::blocked_range<size_t> nodeRange(0, nodes.size());
1913 narrowBandMask.topologyUnion(candidateMask);
1916 tbb::parallel_reduce(nodeRange, op);
1920 candidateMask.clear();
1931 template<
typename TreeType>
1943 , mSegments(!segments.empty() ? &segments.front() : nullptr)
1949 std::vector<const InternalNodeType*> nodes;
1950 tree.getNodes(nodes);
1952 if (!nodes.empty()) {
1954 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), minOp);
1960 std::vector<const LeafNodeType*> nodes;
1961 tree.getNodes(nodes);
1962 if (!nodes.empty()) {
1964 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), minOp);
1969 mMinValue = minSDFValue;
1973 const ValueType interiorValue = -std::abs(mMinValue);
1974 const ValueType exteriorValue = std::abs(mTree->background());
1975 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1982 TreeType
const *
const mTree;
1983 TreeTypePtr *
const mSegments;
1984 ValueType mMinValue;
1988 template<
typename TreeType>
1995 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1999 MaskedCopy(
const TreeType& tree, std::vector<TreeTypePtr>& segments,
2000 std::vector<BoolTreeTypePtr>& masks)
2002 , mSegments(!segments.empty() ? &segments.front() : nullptr)
2003 , mMasks(!masks.empty() ? &masks.front() : nullptr)
2009 std::vector<const BoolLeafNodeType*> nodes;
2011 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
2016 mask.getNodes(nodes);
2018 Copy op(*mTree, nodes);
2019 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), op);
2020 mSegments[n] = op.outputTree();
2027 Copy(
const TreeType& inputTree, std::vector<const BoolLeafNodeType*>& maskNodes)
2028 : mInputTree(&inputTree)
2029 , mMaskNodes(!maskNodes.empty() ? &maskNodes.front() : nullptr)
2030 , mOutputTreePtr(new TreeType(inputTree.background()))
2034 Copy(
const Copy& rhs, tbb::split)
2035 : mInputTree(rhs.mInputTree)
2036 , mMaskNodes(rhs.mMaskNodes)
2037 , mOutputTreePtr(new TreeType(mInputTree->background()))
2041 TreeTypePtr& outputTree() {
return mOutputTreePtr; }
2043 void join(Copy& rhs) { mOutputTreePtr->merge(*rhs.mOutputTreePtr); }
2045 void operator()(
const tbb::blocked_range<size_t>& range) {
2047 tree::ValueAccessor<const TreeType> inputAcc(*mInputTree);
2048 tree::ValueAccessor<TreeType> outputAcc(*mOutputTreePtr);
2050 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
2052 const BoolLeafNodeType& maskNode = *mMaskNodes[n];
2053 if (maskNode.isEmpty())
continue;
2055 const Coord& ijk = maskNode.origin();
2057 const LeafNodeType* inputNode = inputAcc.probeConstLeaf(ijk);
2060 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
2062 for (
typename BoolLeafNodeType::ValueOnCIter it = maskNode.cbeginValueOn();
2065 const Index idx = it.pos();
2066 outputNode->setValueOn(idx, inputNode->getValue(idx));
2069 const int valueDepth = inputAcc.getValueDepth(ijk);
2070 if (valueDepth >= 0) {
2071 outputAcc.addTile(TreeType::RootNodeType::LEVEL - valueDepth,
2072 ijk, inputAcc.getValue(ijk),
true);
2079 TreeType
const *
const mInputTree;
2080 BoolLeafNodeType
const *
const *
const mMaskNodes;
2081 TreeTypePtr mOutputTreePtr;
2084 TreeType
const *
const mTree;
2085 TreeTypePtr *
const mSegments;
2086 BoolTreeTypePtr *
const mMasks;
2093 template<
typename VolumePtrType>
2097 : mSegments(!segments.empty() ? &segments.front() : nullptr)
2098 , mCountArray(countArray)
2103 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
2104 mCountArray[n] = mSegments[n]->activeVoxelCount();
2117 inline bool operator() (
const size_t& lhs,
const size_t& rhs)
const 2119 return (mCountArray[lhs] > mCountArray[rhs]);
2128 template<
typename TreeType>
2135 {
return maskTree; }
2140 template<
typename TreeType>
2147 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2161 maskGrid->insertMeta(grid);
2173 template <
class Gr
idType>
2177 using ValueType =
typename GridType::ValueType;
2178 using TreeType =
typename GridType::TreeType;
2179 using LeafNodeType =
typename TreeType::LeafNodeType;
2180 using RootNodeType =
typename TreeType::RootNodeType;
2181 using NodeChainType =
typename RootNodeType::NodeChainType;
2182 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1>>::type;
2186 TreeType& tree = grid.tree();
2188 size_t numLeafNodes = 0, numInternalNodes = 0;
2190 std::vector<LeafNodeType*> nodes;
2191 std::vector<size_t> leafnodeCount;
2195 std::vector<InternalNodeType*> internalNodes;
2196 tree.getNodes(internalNodes);
2198 numInternalNodes = internalNodes.size();
2200 leafnodeCount.push_back(0);
2201 for (
size_t n = 0; n < numInternalNodes; ++n) {
2202 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
2205 numLeafNodes = leafnodeCount.back();
2208 nodes.reserve(numLeafNodes);
2210 for (
size_t n = 0; n < numInternalNodes; ++n) {
2211 internalNodes[n]->stealNodes(nodes, tree.background(),
false);
2219 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), minOp);
2223 if (minSDFValue > ValueType(0.0)) {
2225 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), minOp);
2229 cutoffDistance = -std::abs(cutoffDistance);
2230 cutoffDistance = minSDFValue > cutoffDistance ? minSDFValue : cutoffDistance;
2236 tbb::parallel_for(tbb::blocked_range<size_t>(0, nodes.size()),
2240 typename TreeType::Ptr newTree(
new TreeType(ValueType(0.0)));
2243 *newTree, &nodes[0], &leafnodeCount[0], 0);
2244 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
2247 std::vector<InternalNodeType*> internalNodes;
2248 newTree->getNodes(internalNodes);
2250 tbb::parallel_for(tbb::blocked_range<size_t>(0, internalNodes.size()),
2252 tree, &internalNodes[0]));
2257 typename TreeType::ValueAllIter it(*newTree);
2258 it.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 2);
2261 if (acc.
getValue(it.getCoord()) < ValueType(0.0)) {
2262 it.setValue(ValueType(1.0));
2263 it.setActiveState(
true);
2271 typename TreeType::ValueAllIter it(tree);
2272 it.setMaxDepth(TreeType::ValueAllIter::ROOT_DEPTH);
2274 if (it.getValue() < ValueType(0.0)) {
2275 newTree->addTile(TreeType::ValueAllIter::ROOT_LEVEL, it.getCoord(),
2276 ValueType(1.0),
true);
2281 grid.setTree(newTree);
2289 template <
class Gr
idOrTreeType>
2290 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
2291 sdfInteriorMask(
const GridOrTreeType& volume,
typename GridOrTreeType::ValueType isovalue)
2296 using BoolTreePtrType =
typename TreeType::template ValueConverter<bool>::Type::Ptr;
2304 template<
typename Gr
idOrTreeType>
2305 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
2307 typename GridOrTreeType::ValueType isovalue,
2314 using CharTreePtrType =
typename TreeType::template ValueConverter<char>::Type::Ptr;
2316 tree, isovalue, fillMask);
2318 using BoolTreePtrType =
typename TreeType::template ValueConverter<bool>::Type::Ptr;
2329 template<
typename Gr
idOrTreeType>
2330 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
2336 std::vector<const typename TreeType::LeafNodeType*> nodes;
2337 tree.getNodes(nodes);
2339 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2340 typename BoolTreeType::Ptr mask(
new BoolTreeType(
false));
2343 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), op);
2353 template<
typename Gr
idOrTreeType>
2356 std::vector<
typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr>& masks)
2359 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2360 using BoolTreePtrType =
typename BoolTreeType::Ptr;
2361 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
2364 using NodeMaskSegmentPtrType =
typename NodeMaskSegmentType::Ptr;
2365 using NodeMaskSegmentPtrVector =
typename std::vector<NodeMaskSegmentPtrType>;
2366 using NodeMaskSegmentRawPtrVector =
typename std::vector<NodeMaskSegmentType*>;
2372 BoolTreeType topologyMask(tree,
false,
TopologyCopy());
2374 if (topologyMask.hasActiveTiles()) {
2375 topologyMask.voxelizeActiveTiles();
2378 std::vector<BoolLeafNodeType*> leafnodes;
2379 topologyMask.getNodes(leafnodes);
2381 if (leafnodes.empty())
return;
2386 boost::scoped_array<NodeMaskSegmentPtrVector> nodeSegmentArray(
2387 new NodeMaskSegmentPtrVector[leafnodes.size()]);
2389 tbb::parallel_for(tbb::blocked_range<size_t>(0, leafnodes.size()),
2391 leafnodes, nodeSegmentArray.get()));
2396 tbb::parallel_for(tbb::blocked_range<size_t>(0, leafnodes.size()),
2398 topologyMask, nodeSegmentArray.get()));
2400 topologyMask.clear();
2402 size_t nodeSegmentCount = 0;
2403 for (
size_t n = 0, N = leafnodes.size(); n < N; ++n) {
2404 nodeSegmentCount += nodeSegmentArray[n].size();
2409 std::deque<NodeMaskSegmentRawPtrVector> nodeSegmentGroups;
2411 NodeMaskSegmentType* nextSegment = nodeSegmentArray[0][0].get();
2412 while (nextSegment) {
2414 nodeSegmentGroups.push_back(NodeMaskSegmentRawPtrVector());
2416 std::vector<NodeMaskSegmentType*>& segmentGroup = nodeSegmentGroups.back();
2417 segmentGroup.reserve(nodeSegmentCount);
2419 std::deque<NodeMaskSegmentType*> segmentQueue;
2420 segmentQueue.push_back(nextSegment);
2421 nextSegment =
nullptr;
2423 while (!segmentQueue.empty()) {
2425 NodeMaskSegmentType* segment = segmentQueue.back();
2426 segmentQueue.pop_back();
2428 if (segment->visited)
continue;
2429 segment->visited =
true;
2431 segmentGroup.push_back(segment);
2434 std::vector<NodeMaskSegmentType*>& connections = segment->connections;
2435 for (
size_t n = 0, N = connections.size(); n < N; ++n) {
2436 if (!connections[n]->visited) segmentQueue.push_back(connections[n]);
2441 for (
size_t n = 0, N = leafnodes.size(); n < N; ++n) {
2442 NodeMaskSegmentPtrVector& nodeSegments = nodeSegmentArray[n];
2443 for (
size_t i = 0, I = nodeSegments.size(); i < I; ++i) {
2444 if (!nodeSegments[i]->visited) nextSegment = nodeSegments[i].get();
2451 if (nodeSegmentGroups.size() == 1) {
2453 BoolTreePtrType mask(
new BoolTreeType(tree,
false,
TopologyCopy()));
2455 if (mask->hasActiveTiles()) {
2456 mask->voxelizeActiveTiles();
2463 }
else if (nodeSegmentGroups.size() > 1) {
2465 for (
size_t n = 0, N = nodeSegmentGroups.size(); n < N; ++n) {
2467 NodeMaskSegmentRawPtrVector& segmentGroup = nodeSegmentGroups[n];
2470 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, segmentGroup.size()), op);
2474 volume, op.
mask()));
2480 if (masks.size() > 1) {
2481 const size_t segmentCount = masks.size();
2483 boost::scoped_array<size_t> segmentOrderArray(
new size_t[segmentCount]);
2484 boost::scoped_array<size_t> voxelCountArray(
new size_t[segmentCount]);
2486 for (
size_t n = 0; n < segmentCount; ++n) {
2487 segmentOrderArray[n] = n;
2490 tbb::parallel_for(tbb::blocked_range<size_t>(0, segmentCount),
2492 masks, voxelCountArray.get()));
2494 size_t *begin = segmentOrderArray.get();
2496 voxelCountArray.get()));
2498 std::vector<BoolTreePtrType> orderedMasks;
2499 orderedMasks.reserve(masks.size());
2501 for (
size_t n = 0; n < segmentCount; ++n) {
2502 orderedMasks.push_back(masks[segmentOrderArray[n]]);
2505 masks.swap(orderedMasks);
2511 template<
typename Gr
idOrTreeType>
2514 std::vector<typename GridOrTreeType::Ptr>& segments)
2517 using TreePtrType =
typename TreeType::Ptr;
2518 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2519 using BoolTreePtrType =
typename BoolTreeType::Ptr;
2524 std::vector<BoolTreePtrType> maskSegmentArray;
2527 const size_t numSegments = maskSegmentArray.size();
2529 if (numSegments < 2) {
2531 TreePtrType segment(
new TreeType(inputTree));
2538 const tbb::blocked_range<size_t> segmentRange(0, numSegments);
2541 std::vector<TreePtrType> outputSegmentArray(numSegments);
2543 tbb::parallel_for(segmentRange,
2547 for (
size_t n = 0, N = numSegments; n < N; ++n) {
2550 volume, outputSegmentArray[n]));
2555 template<
typename Gr
idOrTreeType>
2557 segmentSDF(
const GridOrTreeType& volume, std::vector<typename GridOrTreeType::Ptr>& segments)
2560 using TreePtrType =
typename TreeType::Ptr;
2561 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2562 using BoolTreePtrType =
typename BoolTreeType::Ptr;
2570 std::vector<BoolTreePtrType> maskSegmentArray;
2573 const size_t numSegments = maskSegmentArray.size();
2575 if (numSegments < 2) {
2577 TreePtrType segment(
new TreeType(inputTree));
2584 const tbb::blocked_range<size_t> segmentRange(0, numSegments);
2588 tbb::parallel_for(segmentRange,
2592 std::vector<TreePtrType> outputSegmentArray(numSegments);
2595 inputTree, outputSegmentArray, maskSegmentArray));
2597 tbb::parallel_for(segmentRange,
2601 for (
size_t n = 0, N = numSegments; n < N; ++n) {
2604 volume, outputSegmentArray[n]));
2612 #endif // OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:424
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:943
_TreeType TreeType
Definition: Grid.h:945
void setValueOn(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:292
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: LeafNode.h:198
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:459
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:147
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:201
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:347
Tolerance for floating-point comparison.
Definition: Math.h:117
Index32 Index
Definition: Types.h:60
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:889
Convert polygonal meshes that consist of quads and/or triangles into signed or unsigned distance fiel...
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
static TreeType & tree(TreeType &t)
Definition: Grid.h:960
Definition: Exceptions.h:39
Index64 onVoxelCount() const
Return the number of voxels marked On.
Definition: LeafNode.h:166
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:118
std::shared_ptr< T > SharedPtr
Definition: Types.h:134
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:393
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:508
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:429
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: LeafNode.h:440
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:374
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:64
SharedPtr< Grid > Ptr
Definition: Grid.h:502