38 #ifndef OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED 39 #define OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED 46 #include <boost/mpl/at.hpp> 47 #include <boost/mpl/int.hpp> 48 #include <tbb/blocked_range.h> 49 #include <tbb/parallel_for.h> 50 #include <tbb/parallel_reduce.h> 51 #include <tbb/parallel_sort.h> 71 template<
typename Gr
idType>
72 inline typename GridType::ValueType lsutilGridMax()
77 template<
typename Gr
idType>
78 inline typename GridType::ValueType lsutilGridZero()
80 return zeroVal<typename GridType::ValueType>();
103 template<
class Gr
idType>
107 typename GridType::ValueType cutoffDistance = lsutilGridMax<GridType>());
120 template<
class Gr
idOrTreeType>
121 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
123 const GridOrTreeType& volume,
124 typename GridOrTreeType::ValueType isovalue = lsutilGridZero<GridOrTreeType>());
147 template<
typename Gr
idOrTreeType>
148 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
150 const GridOrTreeType& volume,
151 typename GridOrTreeType::ValueType isovalue = lsutilGridZero<GridOrTreeType>(),
152 const typename TreeAdapter<GridOrTreeType>::TreeType::template ValueConverter<bool>::Type*
161 template<
typename Gr
idOrTreeType>
162 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
171 template<
typename Gr
idOrTreeType>
174 std::vector<
typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr>& masks);
184 template<
typename Gr
idOrTreeType>
187 std::vector<typename GridOrTreeType::Ptr>& segments);
198 template<
typename Gr
idOrTreeType>
200 segmentSDF(
const GridOrTreeType& volume, std::vector<typename GridOrTreeType::Ptr>& segments);
209 namespace level_set_util_internal {
212 template<
typename LeafNodeType>
220 : mNodes(nodes), mMaskNodes(maskNodes), mIsovalue(isovalue)
224 void operator()(
const tbb::blocked_range<size_t>& range)
const {
228 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
230 mMaskNodes[n] =
nullptr;
231 const LeafNodeType& node = *mNodes[n];
239 const ValueType* values = &node.getValue(0);
240 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
241 if (values[i] < mIsovalue) maskNodePt->
setValueOn(i,
true);
245 mMaskNodes[n] = maskNodePt;
246 maskNodePt =
nullptr;
250 if (maskNodePt)
delete maskNodePt;
253 LeafNodeType
const *
const *
const mNodes;
259 template<
typename TreeType,
typename InternalNodeType>
265 : mTree(&tree), mMaskNodes(maskNodes), mIsovalue(isovalue) { }
267 void operator()(
const tbb::blocked_range<size_t>& range)
const {
269 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
270 typename InternalNodeType::ValueAllIter it = mMaskNodes[n]->beginValueAll();
272 if (acc.
getValue(it.getCoord()) < mIsovalue) {
286 template<
typename TreeType>
293 const size_t * nodexIndexMap,
ValueType background)
294 : mNewTree(background)
297 , mNodeIndexMap(nodexIndexMap)
302 : mNewTree(rhs.mNewTree.background())
305 , mNodeIndexMap(rhs.mNodeIndexMap)
314 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
315 for (
size_t i = mNodeIndexMap[n], I = mNodeIndexMap[n + 1]; i < I; ++i) {
316 if (mNodes[i] !=
nullptr) acc.
addLeaf(mNodes[i]);
320 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
330 TreeType *
const mTreePt;
331 LeafNodeType **
const mNodes;
332 size_t const *
const mNodeIndexMap;
337 template<
typename LeafNodeType>
345 : mNodes(nodes), mMaskNodes(maskNodes), mIsovalue(isovalue)
349 void operator()(
const tbb::blocked_range<size_t>& range)
const {
353 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
355 mMaskNodes[n] =
nullptr;
356 const LeafNodeType& node = *mNodes[n];
364 typename LeafNodeType::ValueOnCIter it;
365 for (it = node.cbeginValueOn(); it; ++it) {
366 maskNodePt->
setValueOn(it.pos(), ((*it - mIsovalue) < 0.0) ? 0 : 1);
370 mMaskNodes[n] = maskNodePt;
371 maskNodePt =
nullptr;
375 if (maskNodePt)
delete maskNodePt;
378 LeafNodeType
const *
const *
const mNodes;
384 template<
typename LeafNodeType>
390 void operator()(
const tbb::blocked_range<size_t>& range)
const {
391 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
392 ValueType* values = const_cast<ValueType*>(&mNodes[n]->getValue(0));
393 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
394 values[i] = values[i] < 0 ? 1 : -1;
403 template<
typename LeafNodeType>
421 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
422 const ValueType* data = mNodes[n]->buffer().data();
423 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
424 minValue =
std::min(minValue, data[i]);
433 LeafNodeType
const *
const *
const mNodes;
437 template<
typename InternalNodeType>
455 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
456 typename InternalNodeType::ValueAllCIter it = mNodes[n]->beginValueAll();
467 InternalNodeType
const *
const *
const mNodes;
471 template<
typename LeafNodeType>
477 : mNodes(nodes), mWeight(
ValueType(1.0) / cutoffDistance)
481 void operator()(
const tbb::blocked_range<size_t>& range)
const {
483 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
485 LeafNodeType& node = *mNodes[n];
488 ValueType* values = node.buffer().data();
489 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
491 if (values[i] >
ValueType(0.0)) node.setValueOn(i);
494 if (node.onVoxelCount() == 0) {
506 template<
typename TreeType,
typename InternalNodeType>
510 : mTree(&tree), mNodes(nodes) { }
512 void operator()(
const tbb::blocked_range<size_t>& range)
const {
514 using ValueType =
typename TreeType::ValueType;
517 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
518 typename InternalNodeType::ValueAllIter it = mNodes[n]->beginValueAll();
520 if (acc.
getValue(it.getCoord()) < ValueType(0.0)) {
521 it.setValue(ValueType(1.0));
533 template<
typename TreeType>
538 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
544 , mFillMask(&fillMask)
545 , mFillNodes(fillNodes)
546 , mNewNodes(newNodes)
547 , mIsovalue(isovalue)
551 void operator()(
const tbb::blocked_range<size_t>& range)
const {
556 std::unique_ptr<char[]> valueMask(
new char[BoolLeafNodeType::SIZE]);
558 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
560 mNewNodes[n] =
nullptr;
562 const Coord& origin = node.origin();
564 const bool denseNode = node.isDense();
569 int denseNeighbors = 0;
573 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
576 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
579 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
582 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
585 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
588 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
590 if (denseNeighbors == 6)
continue;
594 memset(valueMask.get(), 0,
sizeof(char) * BoolLeafNodeType::SIZE);
596 const typename TreeType::LeafNodeType* distNode = distAcc.
probeConstLeaf(origin);
600 bool earlyTermination =
false;
604 evalInternalNeighborsP(valueMask.get(), node, *distNode);
605 evalInternalNeighborsN(valueMask.get(), node, *distNode);
606 }
else if (distAcc.
getValue(origin) > mIsovalue) {
607 earlyTermination = evalInternalNeighborsP(valueMask.get(), node);
608 if (!earlyTermination) {
609 earlyTermination = evalInternalNeighborsN(valueMask.get(), node);
616 if (!earlyTermination) {
617 evalExternalNeighborsX<true>(valueMask.get(), node, maskAcc, distAcc);
618 evalExternalNeighborsX<false>(valueMask.get(), node, maskAcc, distAcc);
619 evalExternalNeighborsY<true>(valueMask.get(), node, maskAcc, distAcc);
620 evalExternalNeighborsY<false>(valueMask.get(), node, maskAcc, distAcc);
621 evalExternalNeighborsZ<true>(valueMask.get(), node, maskAcc, distAcc);
622 evalExternalNeighborsZ<false>(valueMask.get(), node, maskAcc, distAcc);
627 int numBoundaryValues = 0;
628 for (
Index i = 0, I = BoolLeafNodeType::SIZE; i < I; ++i) {
629 numBoundaryValues += valueMask[i] == 1;
632 if (numBoundaryValues > 0) {
634 for (
Index i = 0, I = BoolLeafNodeType::SIZE; i < I; ++i) {
635 if (valueMask[i] == 1) mNewNodes[n]->setValueOn(i);
643 void evalInternalNeighborsP(
char* valueMask,
const BoolLeafNodeType& node,
644 const LeafNodeType& distNode)
const 646 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
647 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
648 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
649 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
650 for (
Index z = 0; z < BoolLeafNodeType::DIM - 1; ++z) {
651 const Index pos = yPos + z;
653 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
655 if (!node.isValueOn(pos + 1) && distNode.getValue(pos + 1) > mIsovalue) {
662 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
663 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
664 for (
Index y = 0; y < BoolLeafNodeType::DIM - 1; ++y) {
665 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
666 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
667 const Index pos = yPos + z;
669 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
671 if (!node.isValueOn(pos + BoolLeafNodeType::DIM) &&
672 distNode.getValue(pos + BoolLeafNodeType::DIM) > mIsovalue) {
679 for (
Index x = 0; x < BoolLeafNodeType::DIM - 1; ++x) {
680 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
681 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
682 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
683 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
684 const Index pos = yPos + z;
686 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
688 if (!node.isValueOn(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) &&
689 (distNode.getValue(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)
699 bool evalInternalNeighborsP(
char* valueMask,
const BoolLeafNodeType& node)
const {
701 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
702 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
703 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
704 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
705 for (
Index z = 0; z < BoolLeafNodeType::DIM - 1; ++z) {
706 const Index pos = yPos + z;
708 if (node.isValueOn(pos) && !node.isValueOn(pos + 1)) {
716 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
717 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
718 for (
Index y = 0; y < BoolLeafNodeType::DIM - 1; ++y) {
719 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
720 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
721 const Index pos = yPos + z;
723 if (node.isValueOn(pos) && !node.isValueOn(pos + BoolLeafNodeType::DIM)) {
731 for (
Index x = 0; x < BoolLeafNodeType::DIM - 1; ++x) {
732 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
733 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
734 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
735 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
736 const Index pos = yPos + z;
738 if (node.isValueOn(pos) &&
739 !node.isValueOn(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)) {
752 void evalInternalNeighborsN(
char* valueMask,
const BoolLeafNodeType& node,
753 const LeafNodeType& distNode)
const 755 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
756 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
757 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
758 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
759 for (
Index z = 1; z < BoolLeafNodeType::DIM; ++z) {
760 const Index pos = yPos + z;
762 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
764 if (!node.isValueOn(pos - 1) && distNode.getValue(pos - 1) > mIsovalue) {
771 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
772 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
773 for (
Index y = 1; y < BoolLeafNodeType::DIM; ++y) {
774 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
775 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
776 const Index pos = yPos + z;
778 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
780 if (!node.isValueOn(pos - BoolLeafNodeType::DIM) &&
781 distNode.getValue(pos - BoolLeafNodeType::DIM) > mIsovalue) {
788 for (
Index x = 1; x < BoolLeafNodeType::DIM; ++x) {
789 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
790 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
791 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
792 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
793 const Index pos = yPos + z;
795 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
797 if (!node.isValueOn(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) &&
798 (distNode.getValue(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)
809 bool evalInternalNeighborsN(
char* valueMask,
const BoolLeafNodeType& node)
const {
811 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
812 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
813 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
814 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
815 for (
Index z = 1; z < BoolLeafNodeType::DIM; ++z) {
816 const Index pos = yPos + z;
818 if (node.isValueOn(pos) && !node.isValueOn(pos - 1)) {
826 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
827 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
828 for (
Index y = 1; y < BoolLeafNodeType::DIM; ++y) {
829 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
830 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
831 const Index pos = yPos + z;
833 if (node.isValueOn(pos) && !node.isValueOn(pos - BoolLeafNodeType::DIM)) {
841 for (
Index x = 1; x < BoolLeafNodeType::DIM; ++x) {
842 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
843 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
844 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
845 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
846 const Index pos = yPos + z;
848 if (node.isValueOn(pos) &&
849 !node.isValueOn(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)) {
864 template<
bool UpWind>
865 void evalExternalNeighborsX(
char* valueMask,
const BoolLeafNodeType& node,
866 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
867 const tree::ValueAccessor<const TreeType>& distAcc)
const {
869 const Coord& origin = node.origin();
870 Coord ijk(0, 0, 0), nijk;
875 ijk[0] = int(BoolLeafNodeType::DIM) - 1;
878 const Index xPos = ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM));
880 for (ijk[1] = 0; ijk[1] < int(BoolLeafNodeType::DIM); ++ijk[1]) {
881 const Index yPos = xPos + (ijk[1] << int(BoolLeafNodeType::LOG2DIM));
883 for (ijk[2] = 0; ijk[2] < int(BoolLeafNodeType::DIM); ++ijk[2]) {
884 const Index pos = yPos + ijk[2];
886 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
888 nijk = origin + ijk.offsetBy(step, 0, 0);
890 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
899 template<
bool UpWind>
900 void evalExternalNeighborsY(
char* valueMask,
const BoolLeafNodeType& node,
901 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
902 const tree::ValueAccessor<const TreeType>& distAcc)
const {
904 const Coord& origin = node.origin();
905 Coord ijk(0, 0, 0), nijk;
910 ijk[1] = int(BoolLeafNodeType::DIM) - 1;
913 const Index yPos = ijk[1] << int(BoolLeafNodeType::LOG2DIM);
915 for (ijk[0] = 0; ijk[0] < int(BoolLeafNodeType::DIM); ++ijk[0]) {
916 const Index xPos = yPos + (ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM)));
918 for (ijk[2] = 0; ijk[2] < int(BoolLeafNodeType::DIM); ++ijk[2]) {
919 const Index pos = xPos + ijk[2];
921 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
923 nijk = origin + ijk.offsetBy(0, step, 0);
924 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
933 template<
bool UpWind>
934 void evalExternalNeighborsZ(
char* valueMask,
const BoolLeafNodeType& node,
935 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
936 const tree::ValueAccessor<const TreeType>& distAcc)
const {
938 const Coord& origin = node.origin();
939 Coord ijk(0, 0, 0), nijk;
944 ijk[2] = int(BoolLeafNodeType::DIM) - 1;
947 for (ijk[0] = 0; ijk[0] < int(BoolLeafNodeType::DIM); ++ijk[0]) {
948 const Index xPos = ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM));
950 for (ijk[1] = 0; ijk[1] < int(BoolLeafNodeType::DIM); ++ijk[1]) {
951 const Index pos = ijk[2] + xPos + (ijk[1] << int(BoolLeafNodeType::LOG2DIM));
953 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
955 nijk = origin + ijk.offsetBy(0, 0, step);
956 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
966 TreeType
const *
const mTree;
967 BoolTreeType
const *
const mFillMask;
968 BoolLeafNodeType
const *
const *
const mFillNodes;
969 BoolLeafNodeType **
const mNewNodes;
970 ValueType
const mIsovalue;
976 template <
class TreeType>
977 inline typename TreeType::template ValueConverter<char>::Type::Ptr
979 const typename TreeType::template ValueConverter<bool>::Type* fillMask)
981 using LeafNodeType =
typename TreeType::LeafNodeType;
982 using RootNodeType =
typename TreeType::RootNodeType;
983 using NodeChainType =
typename RootNodeType::NodeChainType;
984 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1>>::type;
986 using CharTreeType =
typename TreeType::template ValueConverter<char>::Type;
987 using CharLeafNodeType =
typename CharTreeType::LeafNodeType;
989 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
990 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
992 const TreeType* treePt = &tree;
994 size_t numLeafNodes = 0, numInternalNodes = 0;
996 std::vector<const LeafNodeType*> nodes;
997 std::vector<size_t> leafnodeCount;
1001 std::vector<const InternalNodeType*> internalNodes;
1002 treePt->getNodes(internalNodes);
1004 numInternalNodes = internalNodes.size();
1006 leafnodeCount.push_back(0);
1007 for (
size_t n = 0; n < numInternalNodes; ++n) {
1008 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
1011 numLeafNodes = leafnodeCount.back();
1014 nodes.reserve(numLeafNodes);
1016 for (
size_t n = 0; n < numInternalNodes; ++n) {
1017 internalNodes[n]->getNodes(nodes);
1022 std::unique_ptr<CharLeafNodeType*[]> maskNodes(
new CharLeafNodeType*[numLeafNodes]);
1024 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1028 typename CharTreeType::Ptr maskTree(
new CharTreeType(1));
1031 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
1035 std::vector<CharLeafNodeType*> extraMaskNodes;
1039 std::vector<const BoolLeafNodeType*> fillMaskNodes;
1040 fillMask->getNodes(fillMaskNodes);
1042 std::unique_ptr<BoolLeafNodeType*[]> boundaryMaskNodes(
1043 new BoolLeafNodeType*[fillMaskNodes.size()]);
1045 tbb::parallel_for(tbb::blocked_range<size_t>(0, fillMaskNodes.size()),
1047 boundaryMaskNodes.get()));
1051 for (
size_t n = 0, N = fillMaskNodes.size(); n < N; ++n) {
1053 if (boundaryMaskNodes[n] ==
nullptr)
continue;
1055 const BoolLeafNodeType& boundaryNode = *boundaryMaskNodes[n];
1056 const Coord& origin = boundaryNode.origin();
1058 CharLeafNodeType* maskNodePt = maskAcc.
probeLeaf(origin);
1062 extraMaskNodes.push_back(maskNodePt);
1065 char* data = maskNodePt->buffer().data();
1067 typename BoolLeafNodeType::ValueOnCIter it = boundaryNode.cbeginValueOn();
1069 if (data[it.pos()] != 0) data[it.pos()] = -1;
1072 delete boundaryMaskNodes[n];
1080 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1083 if (!extraMaskNodes.empty()) {
1084 tbb::parallel_for(tbb::blocked_range<size_t>(0, extraMaskNodes.size()),
1095 template <
class TreeType>
1096 inline typename TreeType::template ValueConverter<bool>::Type::Ptr
1099 using ValueType =
typename TreeType::ValueType;
1100 using LeafNodeType =
typename TreeType::LeafNodeType;
1101 using RootNodeType =
typename TreeType::RootNodeType;
1102 using NodeChainType =
typename RootNodeType::NodeChainType;
1103 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
1105 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1106 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
1107 using BoolRootNodeType =
typename BoolTreeType::RootNodeType;
1108 using BoolNodeChainType =
typename BoolRootNodeType::NodeChainType;
1109 using BoolInternalNodeType =
1110 typename boost::mpl::at<BoolNodeChainType, boost::mpl::int_<1>>::type;
1122 size_t numLeafNodes = 0, numInternalNodes = 0;
1124 std::vector<const LeafNodeType*> nodes;
1125 std::vector<size_t> leafnodeCount;
1129 std::vector<const InternalNodeType*> internalNodes;
1130 tree.getNodes(internalNodes);
1132 numInternalNodes = internalNodes.size();
1134 leafnodeCount.push_back(0);
1135 for (
size_t n = 0; n < numInternalNodes; ++n) {
1136 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
1139 numLeafNodes = leafnodeCount.back();
1142 nodes.reserve(numLeafNodes);
1144 for (
size_t n = 0; n < numInternalNodes; ++n) {
1145 internalNodes[n]->getNodes(nodes);
1150 std::unique_ptr<BoolLeafNodeType*[]> maskNodes(
new BoolLeafNodeType*[numLeafNodes]);
1152 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1157 typename BoolTreeType::Ptr maskTree(
new BoolTreeType(
false));
1160 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
1164 std::vector<BoolInternalNodeType*> internalMaskNodes;
1165 maskTree->getNodes(internalMaskNodes);
1167 tbb::parallel_for(tbb::blocked_range<size_t>(0, internalMaskNodes.size()),
1172 typename BoolTreeType::ValueAllIter it(*maskTree);
1173 it.setMaxDepth(BoolTreeType::ValueAllIter::LEAF_DEPTH - 2);
1176 if (acc.getValue(it.getCoord()) < iso) {
1178 it.setActiveState(
true);
1186 template<
typename InputTreeType>
1191 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
1195 const InputTreeType& inputTree,
1196 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
1199 : mInputAccessor(inputTree)
1200 , mInputNodes(!inputLeafNodes.empty() ? &inputLeafNodes.front() : nullptr)
1202 , mMaskAccessor(maskTree)
1208 : mInputAccessor(rhs.mInputAccessor.tree())
1209 , mInputNodes(rhs.mInputNodes)
1211 , mMaskAccessor(mMaskTree)
1212 , mIsovalue(rhs.mIsovalue)
1223 for (
size_t n = range.begin(); mInputNodes && (n != range.end()); ++n) {
1228 else maskNodePt->setOrigin(node.origin());
1230 bool collectedData =
false;
1232 for (
typename InputLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
1234 bool isUnder = *it < iso;
1236 ijk = it.getCoord();
1239 bool signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1244 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1250 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1256 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1262 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1268 signChange = isUnder != (mInputAccessor.getValue(ijk) < iso);
1273 collectedData =
true;
1274 maskNodePt->setValueOn(it.pos(),
true);
1278 if (collectedData) {
1279 mMaskAccessor.addLeaf(maskNodePt);
1280 maskNodePt =
nullptr;
1284 if (maskNodePt)
delete maskNodePt;
1288 mMaskAccessor.tree().merge(rhs.mMaskAccessor.
tree());
1293 InputLeafNodeType
const *
const *
const mInputNodes;
1295 BoolTreeType mMaskTree;
1298 InputValueType mIsovalue;
1305 template<
typename NodeType>
1320 template<
typename NodeType>
1325 using NodeMaskType =
typename NodeType::NodeMaskType;
1327 using NodeMaskSegmentTypePtr =
typename NodeMaskSegmentType::Ptr;
1329 NodeMaskType nodeMask(node.getValueMask());
1330 std::deque<Index> indexList;
1332 while (!nodeMask.isOff()) {
1334 NodeMaskSegmentTypePtr segment(
new NodeMaskSegmentType());
1335 segment->origin = node.origin();
1337 NodeMaskType& mask = segment->mask;
1339 indexList.push_back(nodeMask.findFirstOn());
1340 nodeMask.setOff(indexList.back());
1343 while (!indexList.empty()) {
1345 const Index pos = indexList.back();
1346 indexList.pop_back();
1348 if (mask.isOn(pos))
continue;
1351 ijk = NodeType::offsetToLocalCoord(pos);
1353 Index npos = pos - 1;
1354 if (ijk[2] != 0 && nodeMask.isOn(npos)) {
1355 nodeMask.setOff(npos);
1356 indexList.push_back(npos);
1360 if (ijk[2] != (NodeType::DIM - 1) && nodeMask.isOn(npos)) {
1361 nodeMask.setOff(npos);
1362 indexList.push_back(npos);
1365 npos = pos - NodeType::DIM;
1366 if (ijk[1] != 0 && nodeMask.isOn(npos)) {
1367 nodeMask.setOff(npos);
1368 indexList.push_back(npos);
1371 npos = pos + NodeType::DIM;
1372 if (ijk[1] != (NodeType::DIM - 1) && nodeMask.isOn(npos)) {
1373 nodeMask.setOff(npos);
1374 indexList.push_back(npos);
1377 npos = pos - NodeType::DIM * NodeType::DIM;
1378 if (ijk[0] != 0 && nodeMask.isOn(npos)) {
1379 nodeMask.setOff(npos);
1380 indexList.push_back(npos);
1383 npos = pos + NodeType::DIM * NodeType::DIM;
1384 if (ijk[0] != (NodeType::DIM - 1) && nodeMask.isOn(npos)) {
1385 nodeMask.setOff(npos);
1386 indexList.push_back(npos);
1391 segments.push_back(segment);
1396 template<
typename NodeType>
1404 : mNodes(!nodes.empty() ? &nodes.front() : nullptr)
1405 , mNodeMaskArray(nodeMaskArray)
1410 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1411 NodeType& node = *mNodes[n];
1415 Coord& origin = const_cast<Coord&>(node.origin());
1416 origin[0] = static_cast<int>(n);
1425 template<
typename TreeType,
typename NodeType>
1435 , mNodeMaskArray(nodeMaskArray)
1443 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1446 if (segments.empty())
continue;
1448 std::vector<std::set<NodeMaskSegmentType*> > connections(segments.size());
1450 Coord ijk = segments[0]->origin;
1452 const NodeType* node = acc.template probeConstNode<NodeType>(ijk);
1453 if (!node)
continue;
1457 ijk[2] += NodeType::DIM;
1458 const NodeType* nodeZUp = acc.template probeConstNode<NodeType>(ijk);
1459 ijk[2] -= (NodeType::DIM + NodeType::DIM);
1460 const NodeType* nodeZDown = acc.template probeConstNode<NodeType>(ijk);
1461 ijk[2] += NodeType::DIM;
1463 ijk[1] += NodeType::DIM;
1464 const NodeType* nodeYUp = acc.template probeConstNode<NodeType>(ijk);
1465 ijk[1] -= (NodeType::DIM + NodeType::DIM);
1466 const NodeType* nodeYDown = acc.template probeConstNode<NodeType>(ijk);
1467 ijk[1] += NodeType::DIM;
1469 ijk[0] += NodeType::DIM;
1470 const NodeType* nodeXUp = acc.template probeConstNode<NodeType>(ijk);
1471 ijk[0] -= (NodeType::DIM + NodeType::DIM);
1472 const NodeType* nodeXDown = acc.template probeConstNode<NodeType>(ijk);
1473 ijk[0] += NodeType::DIM;
1475 const Index startPos = node->getValueMask().findFirstOn();
1476 for (
Index pos = startPos; pos < NodeMaskType::SIZE; ++pos) {
1478 if (!node->isValueOn(pos))
continue;
1480 ijk = NodeType::offsetToLocalCoord(pos);
1482 #ifdef _MSC_FULL_VER 1483 #if _MSC_FULL_VER >= 190000000 && _MSC_FULL_VER < 190024210 1485 volatile Index npos = 0;
1494 npos = pos + (NodeType::DIM - 1);
1495 if (nodeZDown && nodeZDown->isValueOn(npos)) {
1497 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeZDown)], npos);
1498 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1499 connections[idx].insert(nsegment);
1501 }
else if (ijk[2] == (NodeType::DIM - 1)) {
1502 npos = pos - (NodeType::DIM - 1);
1503 if (nodeZUp && nodeZUp->isValueOn(npos)) {
1505 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeZUp)], npos);
1506 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1507 connections[idx].insert(nsegment);
1512 npos = pos + (NodeType::DIM - 1) * NodeType::DIM;
1513 if (nodeYDown && nodeYDown->isValueOn(npos)) {
1515 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeYDown)], npos);
1516 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1517 connections[idx].insert(nsegment);
1519 }
else if (ijk[1] == (NodeType::DIM - 1)) {
1520 npos = pos - (NodeType::DIM - 1) * NodeType::DIM;
1521 if (nodeYUp && nodeYUp->isValueOn(npos)) {
1523 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeYUp)], npos);
1524 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1525 connections[idx].insert(nsegment);
1530 npos = pos + (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1531 if (nodeXDown && nodeXDown->isValueOn(npos)) {
1533 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeXDown)], npos);
1534 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1535 connections[idx].insert(nsegment);
1537 }
else if (ijk[0] == (NodeType::DIM - 1)) {
1538 npos = pos - (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1539 if (nodeXUp && nodeXUp->isValueOn(npos)) {
1541 findNodeMaskSegment(mNodeMaskArray[getNodeOffset(*nodeXUp)], npos);
1542 const Index idx = findNodeMaskSegmentIndex(segments, pos);
1543 connections[idx].insert(nsegment);
1548 for (
size_t i = 0, I = connections.size(); i < I; ++i) {
1550 typename std::set<NodeMaskSegmentType*>::iterator
1551 it = connections[i].begin(), end = connections[i].end();
1553 std::vector<NodeMaskSegmentType*>& segmentConnections = segments[i]->connections;
1554 segmentConnections.reserve(connections.size());
1555 for (; it != end; ++it) {
1556 segmentConnections.push_back(*it);
1564 static inline size_t getNodeOffset(
const NodeType& node) {
1565 return static_cast<size_t>(node.origin()[0]);
1568 static inline NodeMaskSegmentType*
1569 findNodeMaskSegment(NodeMaskSegmentVector& segments,
Index pos)
1571 NodeMaskSegmentType* segment =
nullptr;
1573 for (
size_t n = 0, N = segments.size(); n < N; ++n) {
1574 if (segments[n]->mask.isOn(pos)) {
1575 segment = segments[n].get();
1584 findNodeMaskSegmentIndex(NodeMaskSegmentVector& segments,
Index pos)
1586 for (
Index n = 0, N =
Index(segments.size()); n < N; ++n) {
1587 if (segments[n]->mask.isOn(pos))
return n;
1592 TreeType
const *
const mTree;
1593 NodeMaskSegmentVector *
const mNodeMaskArray;
1597 template<
typename TreeType>
1605 : mSegments(!segments.empty() ? &segments.front() : nullptr)
1606 , mTree(new TreeType(false))
1611 : mSegments(rhs.mSegments)
1612 , mTree(new TreeType(false))
1624 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1627 node->getValueMask() |= segment.
mask;
1632 NodeMaskSegmentType *
const *
const mSegments;
1640 template<
typename TreeType>
1647 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1653 std::vector<BoolLeafNodeType*>& maskNodes)
1654 : mDistTree(&distTree)
1655 , mMaskTree(&maskTree)
1656 , mMaskNodes(!maskNodes.empty() ? &maskNodes.front() : nullptr)
1657 , mNewMaskTree(false)
1662 : mDistTree(rhs.mDistTree)
1663 , mMaskTree(rhs.mMaskTree)
1664 , mMaskNodes(rhs.mMaskNodes)
1665 , mNewMaskTree(false)
1681 NodeMaskType maskZUp, maskZDown, maskYUp, maskYDown, maskXUp, maskXDown;
1683 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1686 if (maskNode.isEmpty())
continue;
1688 Coord ijk = maskNode.origin(), nijk;
1691 if (!distNode)
continue;
1693 const ValueType *dataZUp =
nullptr, *dataZDown =
nullptr,
1694 *dataYUp =
nullptr, *dataYDown =
nullptr,
1695 *dataXUp =
nullptr, *dataXDown =
nullptr;
1697 ijk[2] += NodeType::DIM;
1698 getData(ijk, distAcc, maskAcc, maskZUp, dataZUp);
1699 ijk[2] -= (NodeType::DIM + NodeType::DIM);
1700 getData(ijk, distAcc, maskAcc, maskZDown, dataZDown);
1701 ijk[2] += NodeType::DIM;
1703 ijk[1] += NodeType::DIM;
1704 getData(ijk, distAcc, maskAcc, maskYUp, dataYUp);
1705 ijk[1] -= (NodeType::DIM + NodeType::DIM);
1706 getData(ijk, distAcc, maskAcc, maskYDown, dataYDown);
1707 ijk[1] += NodeType::DIM;
1709 ijk[0] += NodeType::DIM;
1710 getData(ijk, distAcc, maskAcc, maskXUp, dataXUp);
1711 ijk[0] -= (NodeType::DIM + NodeType::DIM);
1712 getData(ijk, distAcc, maskAcc, maskXDown, dataXDown);
1713 ijk[0] += NodeType::DIM;
1715 for (
typename BoolLeafNodeType::ValueOnIter it = maskNode.beginValueOn(); it; ++it) {
1717 const Index pos = it.pos();
1718 const ValueType val = std::abs(distNode->getValue(pos));
1720 ijk = BoolLeafNodeType::offsetToLocalCoord(pos);
1721 nijk = ijk + maskNode.origin();
1723 if (dataZUp && ijk[2] == (BoolLeafNodeType::DIM - 1)) {
1724 const Index npos = pos - (NodeType::DIM - 1);
1725 if (maskZUp.isOn(npos) && std::abs(dataZUp[npos]) > val) {
1726 newMaskAcc.
setValueOn(nijk.offsetBy(0, 0, 1));
1728 }
else if (dataZDown && ijk[2] == 0) {
1729 const Index npos = pos + (NodeType::DIM - 1);
1730 if (maskZDown.isOn(npos) && std::abs(dataZDown[npos]) > val) {
1731 newMaskAcc.
setValueOn(nijk.offsetBy(0, 0, -1));
1735 if (dataYUp && ijk[1] == (BoolLeafNodeType::DIM - 1)) {
1736 const Index npos = pos - (NodeType::DIM - 1) * NodeType::DIM;
1737 if (maskYUp.isOn(npos) && std::abs(dataYUp[npos]) > val) {
1738 newMaskAcc.
setValueOn(nijk.offsetBy(0, 1, 0));
1740 }
else if (dataYDown && ijk[1] == 0) {
1741 const Index npos = pos + (NodeType::DIM - 1) * NodeType::DIM;
1742 if (maskYDown.isOn(npos) && std::abs(dataYDown[npos]) > val) {
1743 newMaskAcc.
setValueOn(nijk.offsetBy(0, -1, 0));
1747 if (dataXUp && ijk[0] == (BoolLeafNodeType::DIM - 1)) {
1748 const Index npos = pos - (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1749 if (maskXUp.isOn(npos) && std::abs(dataXUp[npos]) > val) {
1750 newMaskAcc.
setValueOn(nijk.offsetBy(1, 0, 0));
1752 }
else if (dataXDown && ijk[0] == 0) {
1753 const Index npos = pos + (NodeType::DIM - 1) * NodeType::DIM * NodeType::DIM;
1754 if (maskXDown.isOn(npos) && std::abs(dataXDown[npos]) > val) {
1755 newMaskAcc.
setValueOn(nijk.offsetBy(-1, 0, 0));
1768 const ValueType*& data)
1772 data = node->buffer().data();
1773 mask = node->getValueMask();
1774 const BoolLeafNodeType* maskNodePt = maskAcc.
probeConstLeaf(ijk);
1775 if (maskNodePt) mask -= maskNodePt->getValueMask();
1779 TreeType
const *
const mDistTree;
1780 BoolTreeType *
const mMaskTree;
1781 BoolLeafNodeType **
const mMaskNodes;
1783 BoolTreeType mNewMaskTree;
1787 template<
typename TreeType>
1796 : mTree(&tree), mMaskNodes(!maskNodes.empty() ? &maskNodes.front() : nullptr)
1804 std::vector<Index> indexList;
1805 indexList.reserve(NodeMaskType::SIZE);
1807 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1812 if (!distNode)
continue;
1817 for (
Index pos = narrowbandMask.findFirstOn(); pos < NodeMaskType::SIZE; ++pos) {
1818 if (narrowbandMask.isOn(pos)) indexList.push_back(pos);
1821 mask -= narrowbandMask;
1824 const ValueType* data = distNode->buffer().data();
1827 while (!indexList.empty()) {
1829 const Index pos = indexList.back();
1830 indexList.pop_back();
1832 if (narrowbandMask.isOn(pos))
continue;
1833 narrowbandMask.setOn(pos);
1835 const ValueType dist = std::abs(data[pos]);
1837 ijk = LeafNodeType::offsetToLocalCoord(pos);
1839 Index npos = pos - 1;
1840 if (ijk[2] != 0 && mask.isOn(npos) && std::abs(data[npos]) > dist) {
1842 indexList.push_back(npos);
1846 if ((ijk[2] != (LeafNodeType::DIM - 1)) && mask.isOn(npos)
1847 && std::abs(data[npos]) > dist)
1850 indexList.push_back(npos);
1853 npos = pos - LeafNodeType::DIM;
1854 if (ijk[1] != 0 && mask.isOn(npos) && std::abs(data[npos]) > dist) {
1856 indexList.push_back(npos);
1859 npos = pos + LeafNodeType::DIM;
1860 if ((ijk[1] != (LeafNodeType::DIM - 1)) && mask.isOn(npos)
1861 && std::abs(data[npos]) > dist)
1864 indexList.push_back(npos);
1867 npos = pos - LeafNodeType::DIM * LeafNodeType::DIM;
1868 if (ijk[0] != 0 && mask.isOn(npos) && std::abs(data[npos]) > dist) {
1870 indexList.push_back(npos);
1873 npos = pos + LeafNodeType::DIM * LeafNodeType::DIM;
1874 if ((ijk[0] != (LeafNodeType::DIM - 1)) && mask.isOn(npos)
1875 && std::abs(data[npos]) > dist)
1878 indexList.push_back(npos);
1889 template<
typename TreeType>
1892 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1897 : mTree(&tree), mSegments(!segments.empty() ? &segments.front() : nullptr)
1903 const TreeType& distTree = *mTree;
1904 std::vector<BoolLeafNodeType*> nodes;
1906 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1915 candidateMask.getNodes(nodes);
1916 if (nodes.empty())
break;
1918 const tbb::blocked_range<size_t> nodeRange(0, nodes.size());
1922 narrowBandMask.topologyUnion(candidateMask);
1925 tbb::parallel_reduce(nodeRange, op);
1929 candidateMask.clear();
1940 template<
typename TreeType>
1952 , mSegments(!segments.empty() ? &segments.front() : nullptr)
1958 std::vector<const InternalNodeType*> nodes;
1959 tree.getNodes(nodes);
1961 if (!nodes.empty()) {
1963 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), minOp);
1969 std::vector<const LeafNodeType*> nodes;
1970 tree.getNodes(nodes);
1971 if (!nodes.empty()) {
1973 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), minOp);
1978 mMinValue = minSDFValue;
1982 const ValueType interiorValue = -std::abs(mMinValue);
1983 const ValueType exteriorValue = std::abs(mTree->background());
1984 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
1991 TreeType
const *
const mTree;
1992 TreeTypePtr *
const mSegments;
1993 ValueType mMinValue;
1997 template<
typename TreeType>
2004 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2008 MaskedCopy(
const TreeType& tree, std::vector<TreeTypePtr>& segments,
2009 std::vector<BoolTreeTypePtr>& masks)
2011 , mSegments(!segments.empty() ? &segments.front() : nullptr)
2012 , mMasks(!masks.empty() ? &masks.front() : nullptr)
2018 std::vector<const BoolLeafNodeType*> nodes;
2020 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
2025 mask.getNodes(nodes);
2027 Copy op(*mTree, nodes);
2028 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), op);
2029 mSegments[n] = op.outputTree();
2036 Copy(
const TreeType& inputTree, std::vector<const BoolLeafNodeType*>& maskNodes)
2037 : mInputTree(&inputTree)
2038 , mMaskNodes(!maskNodes.empty() ? &maskNodes.front() : nullptr)
2039 , mOutputTreePtr(new TreeType(inputTree.background()))
2043 Copy(
const Copy& rhs, tbb::split)
2044 : mInputTree(rhs.mInputTree)
2045 , mMaskNodes(rhs.mMaskNodes)
2046 , mOutputTreePtr(new TreeType(mInputTree->background()))
2050 TreeTypePtr& outputTree() {
return mOutputTreePtr; }
2052 void join(Copy& rhs) { mOutputTreePtr->merge(*rhs.mOutputTreePtr); }
2054 void operator()(
const tbb::blocked_range<size_t>& range) {
2056 tree::ValueAccessor<const TreeType> inputAcc(*mInputTree);
2057 tree::ValueAccessor<TreeType> outputAcc(*mOutputTreePtr);
2059 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
2061 const BoolLeafNodeType& maskNode = *mMaskNodes[n];
2062 if (maskNode.isEmpty())
continue;
2064 const Coord& ijk = maskNode.origin();
2066 const LeafNodeType* inputNode = inputAcc.probeConstLeaf(ijk);
2069 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
2071 for (
typename BoolLeafNodeType::ValueOnCIter it = maskNode.cbeginValueOn();
2074 const Index idx = it.pos();
2075 outputNode->setValueOn(idx, inputNode->getValue(idx));
2078 const int valueDepth = inputAcc.getValueDepth(ijk);
2079 if (valueDepth >= 0) {
2080 outputAcc.addTile(TreeType::RootNodeType::LEVEL - valueDepth,
2081 ijk, inputAcc.getValue(ijk),
true);
2088 TreeType
const *
const mInputTree;
2089 BoolLeafNodeType
const *
const *
const mMaskNodes;
2090 TreeTypePtr mOutputTreePtr;
2093 TreeType
const *
const mTree;
2094 TreeTypePtr *
const mSegments;
2095 BoolTreeTypePtr *
const mMasks;
2102 template<
typename VolumePtrType>
2106 : mSegments(!segments.empty() ? &segments.front() : nullptr)
2107 , mCountArray(countArray)
2112 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
2113 mCountArray[n] = mSegments[n]->activeVoxelCount();
2126 inline bool operator() (
const size_t& lhs,
const size_t& rhs)
const 2128 return (mCountArray[lhs] > mCountArray[rhs]);
2137 template<
typename TreeType>
2144 {
return maskTree; }
2149 template<
typename TreeType>
2156 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2170 maskGrid->insertMeta(grid);
2182 template <
class Gr
idType>
2186 using ValueType =
typename GridType::ValueType;
2187 using TreeType =
typename GridType::TreeType;
2188 using LeafNodeType =
typename TreeType::LeafNodeType;
2189 using RootNodeType =
typename TreeType::RootNodeType;
2190 using NodeChainType =
typename RootNodeType::NodeChainType;
2191 using InternalNodeType =
typename boost::mpl::at<NodeChainType, boost::mpl::int_<1>>::type;
2195 TreeType& tree = grid.tree();
2197 size_t numLeafNodes = 0, numInternalNodes = 0;
2199 std::vector<LeafNodeType*> nodes;
2200 std::vector<size_t> leafnodeCount;
2204 std::vector<InternalNodeType*> internalNodes;
2205 tree.getNodes(internalNodes);
2207 numInternalNodes = internalNodes.size();
2209 leafnodeCount.push_back(0);
2210 for (
size_t n = 0; n < numInternalNodes; ++n) {
2211 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
2214 numLeafNodes = leafnodeCount.back();
2217 nodes.reserve(numLeafNodes);
2219 for (
size_t n = 0; n < numInternalNodes; ++n) {
2220 internalNodes[n]->stealNodes(nodes, tree.background(),
false);
2228 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), minOp);
2232 if (minSDFValue > ValueType(0.0)) {
2234 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), minOp);
2238 cutoffDistance = -std::abs(cutoffDistance);
2239 cutoffDistance = minSDFValue > cutoffDistance ? minSDFValue : cutoffDistance;
2245 tbb::parallel_for(tbb::blocked_range<size_t>(0, nodes.size()),
2249 typename TreeType::Ptr newTree(
new TreeType(ValueType(0.0)));
2252 *newTree, &nodes[0], &leafnodeCount[0], 0);
2253 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
2256 std::vector<InternalNodeType*> internalNodes;
2257 newTree->getNodes(internalNodes);
2259 tbb::parallel_for(tbb::blocked_range<size_t>(0, internalNodes.size()),
2261 tree, &internalNodes[0]));
2266 typename TreeType::ValueAllIter it(*newTree);
2267 it.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 2);
2270 if (acc.
getValue(it.getCoord()) < ValueType(0.0)) {
2271 it.setValue(ValueType(1.0));
2272 it.setActiveState(
true);
2280 typename TreeType::ValueAllIter it(tree);
2281 it.setMaxDepth(TreeType::ValueAllIter::ROOT_DEPTH);
2283 if (it.getValue() < ValueType(0.0)) {
2284 newTree->addTile(TreeType::ValueAllIter::ROOT_LEVEL, it.getCoord(),
2285 ValueType(1.0),
true);
2290 grid.setTree(newTree);
2298 template <
class Gr
idOrTreeType>
2299 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
2300 sdfInteriorMask(
const GridOrTreeType& volume,
typename GridOrTreeType::ValueType isovalue)
2305 using BoolTreePtrType =
typename TreeType::template ValueConverter<bool>::Type::Ptr;
2313 template<
typename Gr
idOrTreeType>
2314 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
2316 typename GridOrTreeType::ValueType isovalue,
2323 using CharTreePtrType =
typename TreeType::template ValueConverter<char>::Type::Ptr;
2325 tree, isovalue, fillMask);
2327 using BoolTreePtrType =
typename TreeType::template ValueConverter<bool>::Type::Ptr;
2338 template<
typename Gr
idOrTreeType>
2339 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
2345 std::vector<const typename TreeType::LeafNodeType*> nodes;
2346 tree.getNodes(nodes);
2348 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2349 typename BoolTreeType::Ptr mask(
new BoolTreeType(
false));
2352 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), op);
2362 template<
typename Gr
idOrTreeType>
2365 std::vector<
typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr>& masks)
2368 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2369 using BoolTreePtrType =
typename BoolTreeType::Ptr;
2370 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
2373 using NodeMaskSegmentPtrType =
typename NodeMaskSegmentType::Ptr;
2374 using NodeMaskSegmentPtrVector =
typename std::vector<NodeMaskSegmentPtrType>;
2375 using NodeMaskSegmentRawPtrVector =
typename std::vector<NodeMaskSegmentType*>;
2381 BoolTreeType topologyMask(tree,
false,
TopologyCopy());
2383 if (topologyMask.hasActiveTiles()) {
2384 topologyMask.voxelizeActiveTiles();
2387 std::vector<BoolLeafNodeType*> leafnodes;
2388 topologyMask.getNodes(leafnodes);
2390 if (leafnodes.empty())
return;
2395 std::unique_ptr<NodeMaskSegmentPtrVector[]> nodeSegmentArray(
2396 new NodeMaskSegmentPtrVector[leafnodes.size()]);
2398 tbb::parallel_for(tbb::blocked_range<size_t>(0, leafnodes.size()),
2400 leafnodes, nodeSegmentArray.get()));
2405 tbb::parallel_for(tbb::blocked_range<size_t>(0, leafnodes.size()),
2407 topologyMask, nodeSegmentArray.get()));
2409 topologyMask.clear();
2411 size_t nodeSegmentCount = 0;
2412 for (
size_t n = 0, N = leafnodes.size(); n < N; ++n) {
2413 nodeSegmentCount += nodeSegmentArray[n].size();
2418 std::deque<NodeMaskSegmentRawPtrVector> nodeSegmentGroups;
2420 NodeMaskSegmentType* nextSegment = nodeSegmentArray[0][0].get();
2421 while (nextSegment) {
2423 nodeSegmentGroups.push_back(NodeMaskSegmentRawPtrVector());
2425 std::vector<NodeMaskSegmentType*>& segmentGroup = nodeSegmentGroups.back();
2426 segmentGroup.reserve(nodeSegmentCount);
2428 std::deque<NodeMaskSegmentType*> segmentQueue;
2429 segmentQueue.push_back(nextSegment);
2430 nextSegment =
nullptr;
2432 while (!segmentQueue.empty()) {
2434 NodeMaskSegmentType* segment = segmentQueue.back();
2435 segmentQueue.pop_back();
2437 if (segment->visited)
continue;
2438 segment->visited =
true;
2440 segmentGroup.push_back(segment);
2443 std::vector<NodeMaskSegmentType*>& connections = segment->connections;
2444 for (
size_t n = 0, N = connections.size(); n < N; ++n) {
2445 if (!connections[n]->visited) segmentQueue.push_back(connections[n]);
2450 for (
size_t n = 0, N = leafnodes.size(); n < N; ++n) {
2451 NodeMaskSegmentPtrVector& nodeSegments = nodeSegmentArray[n];
2452 for (
size_t i = 0, I = nodeSegments.size(); i < I; ++i) {
2453 if (!nodeSegments[i]->visited) nextSegment = nodeSegments[i].get();
2460 if (nodeSegmentGroups.size() == 1) {
2462 BoolTreePtrType mask(
new BoolTreeType(tree,
false,
TopologyCopy()));
2464 if (mask->hasActiveTiles()) {
2465 mask->voxelizeActiveTiles();
2472 }
else if (nodeSegmentGroups.size() > 1) {
2474 for (
size_t n = 0, N = nodeSegmentGroups.size(); n < N; ++n) {
2476 NodeMaskSegmentRawPtrVector& segmentGroup = nodeSegmentGroups[n];
2479 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, segmentGroup.size()), op);
2483 volume, op.
mask()));
2489 if (masks.size() > 1) {
2490 const size_t segmentCount = masks.size();
2492 std::unique_ptr<size_t[]> segmentOrderArray(
new size_t[segmentCount]);
2493 std::unique_ptr<size_t[]> voxelCountArray(
new size_t[segmentCount]);
2495 for (
size_t n = 0; n < segmentCount; ++n) {
2496 segmentOrderArray[n] = n;
2499 tbb::parallel_for(tbb::blocked_range<size_t>(0, segmentCount),
2501 masks, voxelCountArray.get()));
2503 size_t *begin = segmentOrderArray.get();
2505 voxelCountArray.get()));
2507 std::vector<BoolTreePtrType> orderedMasks;
2508 orderedMasks.reserve(masks.size());
2510 for (
size_t n = 0; n < segmentCount; ++n) {
2511 orderedMasks.push_back(masks[segmentOrderArray[n]]);
2514 masks.swap(orderedMasks);
2520 template<
typename Gr
idOrTreeType>
2523 std::vector<typename GridOrTreeType::Ptr>& segments)
2526 using TreePtrType =
typename TreeType::Ptr;
2527 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2528 using BoolTreePtrType =
typename BoolTreeType::Ptr;
2533 std::vector<BoolTreePtrType> maskSegmentArray;
2536 const size_t numSegments = maskSegmentArray.size();
2538 if (numSegments < 2) {
2540 TreePtrType segment(
new TreeType(inputTree));
2547 const tbb::blocked_range<size_t> segmentRange(0, numSegments);
2550 std::vector<TreePtrType> outputSegmentArray(numSegments);
2552 tbb::parallel_for(segmentRange,
2556 for (
size_t n = 0, N = numSegments; n < N; ++n) {
2559 volume, outputSegmentArray[n]));
2564 template<
typename Gr
idOrTreeType>
2566 segmentSDF(
const GridOrTreeType& volume, std::vector<typename GridOrTreeType::Ptr>& segments)
2569 using TreePtrType =
typename TreeType::Ptr;
2570 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
2571 using BoolTreePtrType =
typename BoolTreeType::Ptr;
2579 std::vector<BoolTreePtrType> maskSegmentArray;
2582 const size_t numSegments = maskSegmentArray.size();
2584 if (numSegments < 2) {
2586 TreePtrType segment(
new TreeType(inputTree));
2593 const tbb::blocked_range<size_t> segmentRange(0, numSegments);
2597 tbb::parallel_for(segmentRange,
2601 std::vector<TreePtrType> outputSegmentArray(numSegments);
2604 inputTree, outputSegmentArray, maskSegmentArray));
2606 tbb::parallel_for(segmentRange,
2610 for (
size_t n = 0, N = numSegments; n < N; ++n) {
2613 volume, outputSegmentArray[n]));
2621 #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:417
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:944
static TreeType & tree(TreeType &t)
Definition: Grid.h:961
Index32 Index
Definition: Types.h:61
SharedPtr< Grid > Ptr
Definition: Grid.h:502
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:293
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:201
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:518
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:459
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
Index64 onVoxelCount() const
Return the number of voxels marked On.
Definition: LeafNode.h:166
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:889
#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...
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:257
Definition: Exceptions.h:40
_TreeType TreeType
Definition: Grid.h:946
Tolerance for floating-point comparison.
Definition: Math.h:117
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim....
Definition: LeafNode.h:64
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:148
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition: ValueAccessor.h:386
std::shared_ptr< T > SharedPtr
Definition: Types.h:139
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:422
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: LeafNode.h:440
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process....
Definition: ValueAccessor.h:367
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:347
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: LeafNode.h:198
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:118