12 #ifndef OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
13 #define OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
23 #include <tbb/task_group.h>
46 template<
typename Gr
idT>
47 inline typename GridT::template ValueConverter<float>::Type::Ptr
48 topologyToLevelSet(
const GridT& grid,
int halfWidth = 3,
int closingSteps = 1,
int dilation = 0,
49 int smoothingSteps = 0);
65 template<
typename Gr
idT,
typename InterrupterT>
66 inline typename GridT::template ValueConverter<float>::Type::Ptr
67 topologyToLevelSet(
const GridT& grid,
int halfWidth = 3,
int closingSteps = 1,
int dilation = 0,
68 int smoothingSteps = 0, InterrupterT* interrupt =
nullptr);
75 namespace ttls_internal {
78 template<
typename TreeT>
81 DilateOp(TreeT& t,
int n) : tree(&t), size(n) {}
82 void operator()()
const {
90 template<
typename TreeT>
93 ErodeOp(TreeT& t,
int n) : tree(&t), size(n) {}
94 void operator()()
const {
103 template<
typename TreeType>
104 struct OffsetAndMinComp
106 using LeafNodeType =
typename TreeType::LeafNodeType;
107 using ValueType =
typename TreeType::ValueType;
109 OffsetAndMinComp(std::vector<LeafNodeType*>& lhsNodes,
110 const TreeType& rhsTree, ValueType offset)
111 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes[0]), mRhsTree(&rhsTree), mOffset(offset)
115 void operator()(
const tbb::blocked_range<size_t>& range)
const
117 using Iterator =
typename LeafNodeType::ValueOnIter;
119 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
120 const ValueType offset = mOffset;
122 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
124 LeafNodeType& lhsNode = *mLhsNodes[n];
125 const LeafNodeType * rhsNodePt = rhsAcc.probeConstLeaf(lhsNode.origin());
126 if (!rhsNodePt)
continue;
128 for (Iterator it = lhsNode.beginValueOn(); it; ++it) {
129 ValueType& val =
const_cast<ValueType&
>(it.getValue());
130 val =
std::min(val, offset + rhsNodePt->getValue(it.pos()));
136 LeafNodeType * *
const mLhsNodes;
137 TreeType
const *
const mRhsTree;
138 ValueType
const mOffset;
142 template<
typename Gr
idType,
typename InterrupterType>
144 normalizeLevelSet(GridType& grid,
const int halfWidthInVoxels, InterrupterType* interrupt =
nullptr)
146 LevelSetFilter<GridType, GridType, InterrupterType> filter(grid, interrupt);
148 filter.setNormCount(halfWidthInVoxels);
154 template<
typename Gr
idType,
typename InterrupterType>
156 smoothLevelSet(GridType& grid,
int iterations,
int halfBandWidthInVoxels,
157 InterrupterType* interrupt =
nullptr)
159 using ValueType =
typename GridType::ValueType;
160 using TreeType =
typename GridType::TreeType;
161 using LeafNodeType =
typename TreeType::LeafNodeType;
163 GridType filterGrid(grid);
165 LevelSetFilter<GridType, GridType, InterrupterType> filter(filterGrid, interrupt);
168 for (
int n = 0; n < iterations; ++n) {
169 if (interrupt && interrupt->wasInterrupted())
break;
173 std::vector<LeafNodeType*> nodes;
174 grid.tree().getNodes(nodes);
176 const ValueType offset = ValueType(
double(0.5) * grid.transform().voxelSize()[0]);
178 tbb::parallel_for(tbb::blocked_range<size_t>(0, nodes.size()),
179 OffsetAndMinComp<TreeType>(nodes, filterGrid.tree(), -offset));
182 normalizeLevelSet(grid, halfBandWidthInVoxels, interrupt);
190 template<
typename Gr
idT,
typename InterrupterT>
191 inline typename GridT::template ValueConverter<float>::Type::Ptr
193 int smoothingSteps, InterrupterT* interrupt)
195 using MaskTreeT =
typename GridT::TreeType::template ValueConverter<ValueMask>::Type;
196 using FloatTreeT =
typename GridT::TreeType::template ValueConverter<float>::Type;
202 closingSteps =
std::max(closingSteps, 0);
205 if (!grid.hasUniformVoxels()) {
219 const float background = float(grid.voxelSize()[0]) * float(halfWidth);
220 typename FloatTreeT::Ptr lsTree(
223 tbb::task_group pool;
224 pool.run( ttls_internal::ErodeOp< MaskTreeT >( maskTree, halfWidth ) );
225 pool.run( ttls_internal::DilateOp<FloatTreeT>( *lsTree , halfWidth ) );
228 lsTree->topologyDifference( maskTree );
232 typename FloatGridT::Ptr lsGrid = FloatGridT::create( lsTree );
233 lsGrid->setTransform( grid.transform().copy() );
238 ttls_internal::normalizeLevelSet(*lsGrid, 3*halfWidth, interrupt);
241 if (smoothingSteps > 0) {
242 ttls_internal::smoothLevelSet(*lsGrid, smoothingSteps, halfWidth, interrupt);
249 template<
typename Gr
idT>
250 inline typename GridT::template ValueConverter<float>::Type::Ptr
251 topologyToLevelSet(
const GridT& grid,
int halfWidth,
int closingSteps,
int dilation,
int smoothingSteps)
254 return topologyToLevelSet(grid, halfWidth, closingSteps, dilation, smoothingSteps, &interrupt);
Performs various types of level set deformations with interface tracking. These unrestricted deformat...
Implementation of morphological dilation and erosion.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:564
Definition: Exceptions.h:65
@ FIRST_BIAS
Definition: FiniteDifference.h:167
@ GRID_LEVEL_SET
Definition: Types.h:337
Definition: Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:26
#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:180