OpenVDB: TopologyToLevelSet.h Source File

OpenVDB 8.1.0

TopologyToLevelSet.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
11
12 #ifndef OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
13 #define OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
14
15 #include "LevelSetFilter.h"
16 #include "Morphology.h" // for erodeActiveValues and dilateActiveValues
17 #include "SignedFloodFill.h"
18
19 #include <openvdb/Grid.h>
20 #include <openvdb/Types.h>
21 #include <openvdb/math/FiniteDifference.h> // for math::BiasedGradientScheme
22 #include <openvdb/util/NullInterrupter.h>
23 #include <tbb/task_group.h>
24 #include <algorithm> // for std::min(), std::max()
25 #include <vector>
26
27
28 namespace openvdb {
29 OPENVDB_USE_VERSION_NAMESPACE
30 namespace OPENVDB_VERSION_NAME {
31 namespace tools {
32
33
46 template<typename GridT>
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);
50
51
65 template<typename GridT, 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);
69
70
72
73
74 namespace ttls_internal {
75
76
77 template<typename TreeT>
78 struct DilateOp
79 {
80 DilateOp(TreeT& t, int n) : tree(&t), size(n) {}
81 void operator()() const {
82 dilateActiveValues( *tree, size, tools::NN_FACE, tools::IGNORE_TILES);
83 }
84 TreeT* tree;
85 const int size;
86 };
87
88
89 template<typename TreeT>
90 struct ErodeOp
91 {
92 ErodeOp(TreeT& t, int n) : tree(&t), size(n) {}
93 void operator()() const {
94 tools::erodeActiveValues(*tree, /*iterations=*/size, tools::NN_FACE, tools::IGNORE_TILES);
95 tools::pruneInactive(*tree);
96 }
97 TreeT* tree;
98 const int size;
99 };
100
101
102 template<typename TreeType>
103 struct OffsetAndMinComp
104 {
105 using LeafNodeType = typename TreeType::LeafNodeType;
106 using ValueType = typename TreeType::ValueType;
107
108 OffsetAndMinComp(std::vector<LeafNodeType*>& lhsNodes,
109 const TreeType& rhsTree, ValueType offset)
110 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes[0]), mRhsTree(&rhsTree), mOffset(offset)
111 {
112 }
113
114 void operator()(const tbb::blocked_range<size_t>& range) const
115 {
116 using Iterator = typename LeafNodeType::ValueOnIter;
117
118 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
119 const ValueType offset = mOffset;
120
121 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
122
123 LeafNodeType& lhsNode = *mLhsNodes[n];
124 const LeafNodeType * rhsNodePt = rhsAcc.probeConstLeaf(lhsNode.origin());
125 if (!rhsNodePt) continue;
126
127 for (Iterator it = lhsNode.beginValueOn(); it; ++it) {
128 ValueType& val = const_cast<ValueType&>(it.getValue());
129 val = std::min(val, offset + rhsNodePt->getValue(it.pos()));
130 }
131 }
132 }
133
134 private:
135 LeafNodeType * * const mLhsNodes;
136 TreeType const * const mRhsTree;
137 ValueType const mOffset;
138 }; // struct OffsetAndMinComp
139
140
141 template<typename GridType, typename InterrupterType>
142 inline void
143 normalizeLevelSet(GridType& grid, const int halfWidthInVoxels, InterrupterType* interrupt = nullptr)
144 {
145 LevelSetFilter<GridType, GridType, InterrupterType> filter(grid, interrupt);
146 filter.setSpatialScheme(math::FIRST_BIAS);
147 filter.setNormCount(halfWidthInVoxels);
148 filter.normalize();
149 filter.prune();
150 }
151
152
153 template<typename GridType, typename InterrupterType>
154 inline void
155 smoothLevelSet(GridType& grid, int iterations, int halfBandWidthInVoxels,
156 InterrupterType* interrupt = nullptr)
157 {
158 using ValueType = typename GridType::ValueType;
159 using TreeType = typename GridType::TreeType;
160 using LeafNodeType = typename TreeType::LeafNodeType;
161
162 GridType filterGrid(grid);
163
164 LevelSetFilter<GridType, GridType, InterrupterType> filter(filterGrid, interrupt);
165 filter.setSpatialScheme(math::FIRST_BIAS);
166
167 for (int n = 0; n < iterations; ++n) {
168 if (interrupt && interrupt->wasInterrupted()) break;
169 filter.mean(1);
170 }
171
172 std::vector<LeafNodeType*> nodes;
173 grid.tree().getNodes(nodes);
174
175 const ValueType offset = ValueType(double(0.5) * grid.transform().voxelSize()[0]);
176
177 tbb::parallel_for(tbb::blocked_range<size_t>(0, nodes.size()),
178 OffsetAndMinComp<TreeType>(nodes, filterGrid.tree(), -offset));
179
180 // Clean up any damanage that was done by the min operation
181 normalizeLevelSet(grid, halfBandWidthInVoxels, interrupt);
182 }
183
184
185 } // namespace ttls_internal
186
187
188
189 template<typename GridT, typename InterrupterT>
190 inline typename GridT::template ValueConverter<float>::Type::Ptr
191 topologyToLevelSet(const GridT& grid, int halfWidth, int closingSteps, int dilation,
192 int smoothingSteps, InterrupterT* interrupt)
193 {
194 using MaskTreeT = typename GridT::TreeType::template ValueConverter<ValueMask>::Type;
195 using FloatTreeT = typename GridT::TreeType::template ValueConverter<float>::Type;
196 using FloatGridT = Grid<FloatTreeT>;
197
198 // Check inputs
199
200 halfWidth = std::max(halfWidth, 1);
201 closingSteps = std::max(closingSteps, 0);
202 dilation = std::max(dilation, 0);
203
204 if (!grid.hasUniformVoxels()) {
205 OPENVDB_THROW(ValueError, "Non-uniform voxels are not supported!");
206 }
207
208 // Copy the topology into a MaskGrid.
209 MaskTreeT maskTree( grid.tree(), false/*background*/, openvdb::TopologyCopy() );
210
211 // Morphological closing operation.
212 tools::dilateActiveValues(maskTree, closingSteps + dilation, tools::NN_FACE, tools::IGNORE_TILES);
213 tools::erodeActiveValues(maskTree, /*iterations=*/closingSteps, tools::NN_FACE, tools::IGNORE_TILES);
214 tools::pruneInactive(maskTree);
215
216 // Generate a volume with an implicit zero crossing at the boundary
217 // between active and inactive values in the input grid.
218 const float background = float(grid.voxelSize()[0]) * float(halfWidth);
219 typename FloatTreeT::Ptr lsTree(
220 new FloatTreeT( maskTree, /*out=*/background, /*in=*/-background, openvdb::TopologyCopy() ) );
221
222 tbb::task_group pool;
223 pool.run( ttls_internal::ErodeOp< MaskTreeT >( maskTree, halfWidth ) );
224 pool.run( ttls_internal::DilateOp<FloatTreeT>( *lsTree , halfWidth ) );
225 pool.wait();// wait for both tasks to complete
226
227 lsTree->topologyDifference( maskTree );
228 tools::pruneLevelSet( *lsTree, /*threading=*/true);
229
230 // Create a level set grid from the tree
231 typename FloatGridT::Ptr lsGrid = FloatGridT::create( lsTree );
232 lsGrid->setTransform( grid.transform().copy() );
233 lsGrid->setGridClass( openvdb::GRID_LEVEL_SET );
234
235 // Use a PDE based scheme to propagate distance values from the
236 // implicit zero crossing.
237 ttls_internal::normalizeLevelSet(*lsGrid, 3*halfWidth, interrupt);
238
239 // Additional filtering
240 if (smoothingSteps > 0) {
241 ttls_internal::smoothLevelSet(*lsGrid, smoothingSteps, halfWidth, interrupt);
242 }
243
244 return lsGrid;
245 }
246
247
248 template<typename GridT>
249 inline typename GridT::template ValueConverter<float>::Type::Ptr
250 topologyToLevelSet(const GridT& grid, int halfWidth, int closingSteps, int dilation, int smoothingSteps)
251 {
252 util::NullInterrupter interrupt;
253 return topologyToLevelSet(grid, halfWidth, closingSteps, dilation, smoothingSteps, &interrupt);
254 }
255
256
257 } // namespace tools
258 } // namespace OPENVDB_VERSION_NAME
259 } // namespace openvdb
260
261 #endif // OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
262
FiniteDifference.h
Grid.h
LevelSetFilter.h
Performs various types of level set deformations with interface tracking. These unrestricted deformat...
Morphology.h
Implementation of morphological dilation and erosion.
NullInterrupter.h
SignedFloodFill.h
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
openvdb::v8_1::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
openvdb::v8_1::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:560
openvdb::v8_1::ValueError
Definition: openvdb/Exceptions.h:65
openvdb::v8_1::tools::LevelSetFilter
Filtering (e.g. diffusion) of narrow-band level sets. An optional scalar field can be used to produce...
Definition: LevelSetFilter.h:40
openvdb::v8_1::tools::LevelSetFilter::mean
void mean(int width=1, const MaskType *mask=nullptr)
One iteration of mean-value flow of the level set.
Definition: LevelSetFilter.h:140
openvdb::v8_1::tools::LevelSetTracker::prune
void prune()
Set voxels that are outside the narrow band to the background value (if trimming is enabled) and prun...
Definition: LevelSetTracker.h:280
openvdb::v8_1::tools::LevelSetTracker::normalize
void normalize(const MaskType *mask)
Iterative normalization, i.e. solving the Eikonal equation.
openvdb::v8_1::tools::LevelSetTracker::setSpatialScheme
void setSpatialScheme(math::BiasedGradientScheme s)
Set the spatial finite difference scheme.
Definition: LevelSetTracker.h:145
openvdb::v8_1::tools::LevelSetTracker::setNormCount
void setNormCount(int n)
Set the number of normalizations performed per track or normalize call.
Definition: LevelSetTracker.h:159
openvdb::v8_1::tree::ValueAccessor
Definition: ValueAccessor.h:183
openvdb::v8_1::tree::ValueAccessor::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:384
openvdb::v8_1::math::FIRST_BIAS
@ FIRST_BIAS
Definition: FiniteDifference.h:167
openvdb::v8_1::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
openvdb::v8_1::tools::composite::min
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
openvdb::v8_1::tools::ttls_internal::smoothLevelSet
void smoothLevelSet(GridType &grid, int iterations, int halfBandWidthInVoxels, InterrupterType *interrupt=nullptr)
Definition: TopologyToLevelSet.h:155
openvdb::v8_1::tools::ttls_internal::normalizeLevelSet
void normalizeLevelSet(GridType &grid, const int halfWidthInVoxels, InterrupterType *interrupt=nullptr)
Definition: TopologyToLevelSet.h:143
openvdb::v8_1::tools::topologyToLevelSet
GridT::template ValueConverter< float >::Type::Ptr topologyToLevelSet(const GridT &grid, int halfWidth=3, int closingSteps=1, int dilation=0, int smoothingSteps=0, InterrupterT *interrupt=nullptr)
Compute the narrow-band signed distance to the interface between active and inactive voxels in the in...
Definition: TopologyToLevelSet.h:191
openvdb::v8_1::tools::NN_FACE
@ NN_FACE
Definition: Morphology.h:56
openvdb::v8_1::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:389
openvdb::v8_1::tools::erodeActiveValues
void erodeActiveValues(TreeOrLeafManagerT &tree, const int iterations=1, const NearestNeighbors nn=NN_FACE, const TilePolicy mode=PRESERVE_TILES, const bool threaded=true)
Topologically erode all active values (i.e. both voxels and tiles) in a tree using one of three neare...
Definition: Morphology.h:1126
openvdb::v8_1::tools::dilateActiveValues
void dilateActiveValues(TreeOrLeafManagerT &tree, const int iterations=1, const NearestNeighbors nn=NN_FACE, const TilePolicy mode=PRESERVE_TILES, const bool threaded=true)
Topologically dilate all active values (i.e. both voxels and tiles) in a tree using one of three near...
Definition: Morphology.h:1049
openvdb::v8_1::tools::IGNORE_TILES
@ IGNORE_TILES
Definition: Morphology.h:78
openvdb::v8_1::tools::pruneInactive
void pruneInactive(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with background tiles any nodes whose values are a...
Definition: Prune.h:354
openvdb::v8_1::GRID_LEVEL_SET
@ GRID_LEVEL_SET
Definition: openvdb/Types.h:333
openvdb
Definition: openvdb/Exceptions.h:13
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
Types.h
openvdb::v8_1::tools::ttls_internal::DilateOp
Definition: TopologyToLevelSet.h:79
openvdb::v8_1::tools::ttls_internal::DilateOp::DilateOp
DilateOp(TreeT &t, int n)
Definition: TopologyToLevelSet.h:80
openvdb::v8_1::tools::ttls_internal::DilateOp::tree
TreeT * tree
Definition: TopologyToLevelSet.h:84
openvdb::v8_1::tools::ttls_internal::DilateOp::size
const int size
Definition: TopologyToLevelSet.h:85
openvdb::v8_1::tools::ttls_internal::DilateOp::operator()
void operator()() const
Definition: TopologyToLevelSet.h:81
openvdb::v8_1::tools::ttls_internal::ErodeOp
Definition: TopologyToLevelSet.h:91
openvdb::v8_1::tools::ttls_internal::ErodeOp::ErodeOp
ErodeOp(TreeT &t, int n)
Definition: TopologyToLevelSet.h:92
openvdb::v8_1::tools::ttls_internal::ErodeOp::tree
TreeT * tree
Definition: TopologyToLevelSet.h:97
openvdb::v8_1::tools::ttls_internal::ErodeOp::size
const int size
Definition: TopologyToLevelSet.h:98
openvdb::v8_1::tools::ttls_internal::ErodeOp::operator()
void operator()() const
Definition: TopologyToLevelSet.h:93
openvdb::v8_1::tools::ttls_internal::OffsetAndMinComp
Definition: TopologyToLevelSet.h:104
openvdb::v8_1::tools::ttls_internal::OffsetAndMinComp::ValueType
typename TreeType::ValueType ValueType
Definition: TopologyToLevelSet.h:106
openvdb::v8_1::tools::ttls_internal::OffsetAndMinComp::OffsetAndMinComp
OffsetAndMinComp(std::vector< LeafNodeType * > &lhsNodes, const TreeType &rhsTree, ValueType offset)
Definition: TopologyToLevelSet.h:108
openvdb::v8_1::tools::ttls_internal::OffsetAndMinComp::operator()
void operator()(const tbb::blocked_range< size_t > &range) const
Definition: TopologyToLevelSet.h:114
openvdb::v8_1::tools::ttls_internal::OffsetAndMinComp::LeafNodeType
typename TreeType::LeafNodeType LeafNodeType
Definition: TopologyToLevelSet.h:105
openvdb::v8_1::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:26
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:178