12 #ifndef OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED 13 #define OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED 25 #include <tbb/task_group.h> 48 template<
typename Gr
idT>
49 typename GridT::template ValueConverter<float>::Type::Ptr
50 topologyToLevelSet(
const GridT& grid,
int halfWidth = 3,
int closingSteps = 1,
int dilation = 0,
51 int smoothingSteps = 0);
67 template<
typename Gr
idT,
typename InterrupterT>
68 typename GridT::template ValueConverter<float>::Type::Ptr
69 topologyToLevelSet(
const GridT& grid,
int halfWidth = 3,
int closingSteps = 1,
int dilation = 0,
70 int smoothingSteps = 0, InterrupterT* interrupt =
nullptr);
77 namespace ttls_internal {
80 template<
typename TreeT>
83 DilateOp(TreeT& t,
int n) : tree(&t), size(n) {}
84 void operator()()
const {
92 template<
typename TreeT>
95 ErodeOp(TreeT& t,
int n) : tree(&t), size(n) {}
96 void operator()()
const {
105 template<
typename TreeType>
106 struct OffsetAndMinComp
108 using LeafNodeType =
typename TreeType::LeafNodeType;
109 using ValueType =
typename TreeType::ValueType;
111 OffsetAndMinComp(std::vector<LeafNodeType*>& lhsNodes,
112 const TreeType& rhsTree, ValueType offset)
113 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes[0]), mRhsTree(&rhsTree), mOffset(offset)
117 void operator()(
const tbb::blocked_range<size_t>& range)
const 119 using Iterator =
typename LeafNodeType::ValueOnIter;
121 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
122 const ValueType offset = mOffset;
124 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
126 LeafNodeType& lhsNode = *mLhsNodes[n];
127 const LeafNodeType * rhsNodePt = rhsAcc.probeConstLeaf(lhsNode.origin());
128 if (!rhsNodePt)
continue;
130 for (Iterator it = lhsNode.beginValueOn(); it; ++it) {
131 ValueType& val =
const_cast<ValueType&
>(it.getValue());
132 val =
std::min(val, offset + rhsNodePt->getValue(it.pos()));
138 LeafNodeType * *
const mLhsNodes;
139 TreeType
const *
const mRhsTree;
140 ValueType
const mOffset;
144 template<
typename Gr
idType,
typename InterrupterType>
146 normalizeLevelSet(
GridType& grid,
const int halfWidthInVoxels, InterrupterType* interrupt =
nullptr)
148 LevelSetFilter<GridType, GridType, InterrupterType> filter(grid, interrupt);
150 filter.setNormCount(halfWidthInVoxels);
156 template<
typename Gr
idType,
typename InterrupterType>
158 smoothLevelSet(
GridType& grid,
int iterations,
int halfBandWidthInVoxels,
159 InterrupterType* interrupt =
nullptr)
161 using ValueType =
typename GridType::ValueType;
162 using TreeType =
typename GridType::TreeType;
163 using LeafNodeType =
typename TreeType::LeafNodeType;
167 LevelSetFilter<GridType, GridType, InterrupterType> filter(filterGrid, interrupt);
170 for (
int n = 0; n < iterations; ++n) {
171 if (interrupt && interrupt->wasInterrupted())
break;
175 std::vector<LeafNodeType*> nodes;
176 grid.tree().getNodes(nodes);
178 const ValueType offset = ValueType(
double(0.5) * grid.transform().voxelSize()[0]);
180 tbb::parallel_for(tbb::blocked_range<size_t>(0, nodes.size()),
181 OffsetAndMinComp<TreeType>(nodes, filterGrid.tree(), -offset));
184 normalizeLevelSet(grid, halfBandWidthInVoxels, interrupt);
192 template<
typename Gr
idT,
typename InterrupterT>
193 typename GridT::template ValueConverter<float>::Type::Ptr
195 int smoothingSteps, InterrupterT* interrupt)
197 using MaskTreeT =
typename GridT::TreeType::template ValueConverter<ValueMask>::Type;
198 using FloatTreeT =
typename GridT::TreeType::template ValueConverter<float>::Type;
204 closingSteps =
std::max(closingSteps, 0);
207 if (!grid.hasUniformVoxels()) {
221 const float background = float(grid.voxelSize()[0]) *
float(halfWidth);
222 typename FloatTreeT::Ptr lsTree(
225 tbb::task_group pool;
226 pool.run( ttls_internal::ErodeOp< MaskTreeT >( maskTree, halfWidth ) );
227 pool.run( ttls_internal::DilateOp<FloatTreeT>( *lsTree , halfWidth ) );
230 lsTree->topologyDifference( maskTree );
234 typename FloatGridT::Ptr lsGrid = FloatGridT::create( lsTree );
235 lsGrid->setTransform( grid.transform().copy() );
240 ttls_internal::normalizeLevelSet(*lsGrid, 3*halfWidth, interrupt);
243 if (smoothingSteps > 0) {
244 ttls_internal::smoothLevelSet(*lsGrid, smoothingSteps, halfWidth, interrupt);
251 template<
typename Gr
idT>
252 typename GridT::template ValueConverter<float>::Type::Ptr
253 topologyToLevelSet(
const GridT& grid,
int halfWidth,
int closingSteps,
int dilation,
int smoothingSteps)
256 return topologyToLevelSet(grid, halfWidth, closingSteps, dilation, smoothingSteps, &interrupt);
265 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 267 #ifdef OPENVDB_INSTANTIATE_TOPOLOGYTOLEVELSET 271 #define _FUNCTION(TreeT) \ 272 Grid<TreeT>::ValueConverter<float>::Type::Ptr topologyToLevelSet(const Grid<TreeT>&, int, int, int, int, \ 273 util::NullInterrupter*) 277 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 284 #endif // OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Base class for interrupters.
Definition: NullInterrupter.h:25
Definition: FiniteDifference.h:167
Definition: Exceptions.h:65
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:644
Performs various types of level set deformations with interface tracking. These unrestricted deformat...
#define OPENVDB_ALL_TREE_INSTANTIATE(Function)
Definition: version.h.in:151
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
Implementation of morphological dilation and erosion.
Definition: Exceptions.h:13
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
GridType
List of types that are currently supported by NanoVDB.
Definition: NanoVDB.h:216
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202