HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LevelSetFilter.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
29 ///////////////////////////////////////////////////////////////////////////
30 //
31 /// @author Ken Museth
32 ///
33 /// @file tools/LevelSetFilter.h
34 ///
35 /// @brief Performs various types of level set deformations with
36 /// interface tracking. These unrestricted deformations include
37 /// surface smoothing (e.g., Laplacian flow), filtering (e.g., mean
38 /// value) and morphological operations (e.g., morphological opening).
39 /// All these operations can optionally be masked with another grid that
40 /// acts as an alpha-mask.
41 
42 #ifndef OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
43 #define OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
44 
45 #include "LevelSetTracker.h"
46 #include "Interpolation.h"
47 #include <algorithm> // for std::max()
48 #include <functional>
49 #include <type_traits>
50 
51 
52 namespace openvdb {
54 namespace OPENVDB_VERSION_NAME {
55 namespace tools {
56 
57 /// @brief Filtering (e.g. diffusion) of narrow-band level sets. An
58 /// optional scalar field can be used to produce a (smooth) alpha mask
59 /// for the filtering.
60 ///
61 /// @note This class performs proper interface tracking which allows
62 /// for unrestricted surface deformations
63 template<typename GridT,
64  typename MaskT = typename GridT::template ValueConverter<float>::Type,
65  typename InterruptT = util::NullInterrupter>
66 class LevelSetFilter : public LevelSetTracker<GridT, InterruptT>
67 {
68 public:
70  using GridType = GridT;
71  using MaskType = MaskT;
72  using TreeType = typename GridType::TreeType;
73  using ValueType = typename TreeType::ValueType;
74  using AlphaType = typename MaskType::ValueType;
76  "LevelSetFilter requires a mask grid with floating-point values");
77 
78  /// @brief Main constructor from a grid
79  /// @param grid The level set to be filtered.
80  /// @param interrupt Optional interrupter.
81  LevelSetFilter(GridType& grid, InterruptT* interrupt = nullptr)
82  : BaseType(grid, interrupt)
83  , mMinMask(0)
84  , mMaxMask(1)
85  , mInvertMask(false)
86  {
87  }
88  /// @brief Default destructor
89  ~LevelSetFilter() override {}
90 
91  /// @brief Return the minimum value of the mask to be used for the
92  /// derivation of a smooth alpha value.
93  AlphaType minMask() const { return mMinMask; }
94  /// @brief Return the maximum value of the mask to be used for the
95  /// derivation of a smooth alpha value.
96  AlphaType maxMask() const { return mMaxMask; }
97  /// @brief Define the range for the (optional) scalar mask.
98  /// @param min Minimum value of the range.
99  /// @param max Maximum value of the range.
100  /// @details Mask values outside the range maps to alpha values of
101  /// respectfully zero and one, and values inside the range maps
102  /// smoothly to 0->1 (unless of course the mask is inverted).
103  /// @throw ValueError if @a min is not smaller than @a max.
105  {
106  if (!(min < max)) OPENVDB_THROW(ValueError, "Invalid mask range (expects min < max)");
107  mMinMask = min;
108  mMaxMask = max;
109  }
110 
111  /// @brief Return true if the mask is inverted, i.e. min->max in the
112  /// original mask maps to 1->0 in the inverted alpha mask.
113  bool isMaskInverted() const { return mInvertMask; }
114  /// @brief Invert the optional mask, i.e. min->max in the original
115  /// mask maps to 1->0 in the inverted alpha mask.
116  void invertMask(bool invert=true) { mInvertMask = invert; }
117 
118  /// @brief One iteration of mean-curvature flow of the level set.
119  /// @param mask Optional alpha mask.
120  void meanCurvature(const MaskType* mask = nullptr)
121  {
122  Filter f(this, mask); f.meanCurvature();
123  }
124 
125  /// @brief One iteration of Laplacian flow of the level set.
126  /// @param mask Optional alpha mask.
127  void laplacian(const MaskType* mask = nullptr)
128  {
129  Filter f(this, mask); f.laplacian();
130  }
131 
132  /// @brief One iteration of a fast separable Gaussian filter.
133  /// @param width Width of the Gaussian kernel in voxel units.
134  /// @param mask Optional alpha mask.
135  ///
136  /// @note This is approximated as 4 iterations of a separable mean filter
137  /// which typically leads an approximation that's better than 95%!
138  void gaussian(int width = 1, const MaskType* mask = nullptr)
139  {
140  Filter f(this, mask); f.gaussian(width);
141  }
142 
143  /// @brief Offset the level set by the specified (world) distance.
144  /// @param offset Value of the offset.
145  /// @param mask Optional alpha mask.
146  void offset(ValueType offset, const MaskType* mask = nullptr)
147  {
148  Filter f(this, mask); f.offset(offset);
149  }
150 
151  /// @brief One iteration of median-value flow of the level set.
152  /// @param width Width of the median-value kernel in voxel units.
153  /// @param mask Optional alpha mask.
154  ///
155  /// @warning This filter is not separable and is hence relatively
156  /// slow!
157  void median(int width = 1, const MaskType* mask = nullptr)
158  {
159  Filter f(this, mask); f.median(width);
160  }
161 
162  /// @brief One iteration of mean-value flow of the level set.
163  /// @param width Width of the mean-value kernel in voxel units.
164  /// @param mask Optional alpha mask.
165  ///
166  /// @note This filter is separable so it's fast!
167  void mean(int width = 1, const MaskType* mask = nullptr)
168  {
169  Filter f(this, mask); f.mean(width);
170  }
171 
172 private:
173  // disallow copy construction and copy by assignment!
174  LevelSetFilter(const LevelSetFilter&);// not implemented
175  LevelSetFilter& operator=(const LevelSetFilter&);// not implemented
176 
177  // Private struct that implements all the filtering.
178  struct Filter
179  {
180  using LeafT = typename TreeType::LeafNodeType;
181  using VoxelIterT = typename LeafT::ValueOnIter;
182  using VoxelCIterT = typename LeafT::ValueOnCIter;
183  using BufferT = typename tree::LeafManager<TreeType>::BufferType;
185  using LeafIterT = typename LeafRange::Iterator;
186  using AlphaMaskT = tools::AlphaMask<GridT, MaskT>;
187 
188  Filter(LevelSetFilter* parent, const MaskType* mask) : mParent(parent), mMask(mask) {}
189  Filter(const Filter&) = default;
190  virtual ~Filter() {}
191 
192  void box(int width);
193  void median(int width);
194  void mean(int width);
195  void gaussian(int width);
196  void laplacian();
197  void meanCurvature();
198  void offset(ValueType value);
199  void operator()(const LeafRange& r) const
200  {
201  if (mTask) mTask(const_cast<Filter*>(this), r);
202  else OPENVDB_THROW(ValueError, "task is undefined - don\'t call this method directly");
203  }
204  void cook(bool swap)
205  {
206  const int n = mParent->getGrainSize();
207  if (n>0) {
208  tbb::parallel_for(mParent->leafs().leafRange(n), *this);
209  } else {
210  (*this)(mParent->leafs().leafRange());
211  }
212  if (swap) mParent->leafs().swapLeafBuffer(1, n==0);
213  }
214 
215  template <size_t Axis>
216  struct Avg {
217  Avg(const GridT& grid, Int32 w) :
218  acc(grid.tree()), width(w), frac(1/ValueType(2*w+1)) {}
219  inline ValueType operator()(Coord xyz)
220  {
221  ValueType sum = zeroVal<ValueType>();
222  Int32& i = xyz[Axis], j = i + width;
223  for (i -= width; i <= j; ++i) sum += acc.getValue(xyz);
224  return sum*frac;
225  }
226  typename GridT::ConstAccessor acc;
227  const Int32 width;
229  };
230 
231  template<typename AvgT>
232  void boxImpl(const LeafRange& r, Int32 w);
233 
234  void boxXImpl(const LeafRange& r, Int32 w) { this->boxImpl<Avg<0> >(r,w); }
235  void boxZImpl(const LeafRange& r, Int32 w) { this->boxImpl<Avg<1> >(r,w); }
236  void boxYImpl(const LeafRange& r, Int32 w) { this->boxImpl<Avg<2> >(r,w); }
237 
238  void medianImpl(const LeafRange&, int);
239  void meanCurvatureImpl(const LeafRange&);
240  void laplacianImpl(const LeafRange&);
241  void offsetImpl(const LeafRange&, ValueType);
242 
243  LevelSetFilter* mParent;
244  const MaskType* mMask;
245  typename std::function<void (Filter*, const LeafRange&)> mTask;
246  }; // end of private Filter struct
247 
248  AlphaType mMinMask, mMaxMask;
249  bool mInvertMask;
250 
251 }; // end of LevelSetFilter class
252 
253 
254 ////////////////////////////////////////
255 
256 template<typename GridT, typename MaskT, typename InterruptT>
257 inline void
258 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::median(int width)
259 {
260  mParent->startInterrupter("Median-value flow of level set");
261 
262  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
263 
264  mTask = std::bind(&Filter::medianImpl,
265  std::placeholders::_1, std::placeholders::_2, std::max(1, width));
266  this->cook(true);
267 
268  mParent->track();
269 
270  mParent->endInterrupter();
271 }
272 
273 template<typename GridT, typename MaskT, typename InterruptT>
274 inline void
275 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::mean(int width)
276 {
277  mParent->startInterrupter("Mean-value flow of level set");
278 
279  this->box(width);
280 
281  mParent->endInterrupter();
282 }
283 
284 template<typename GridT, typename MaskT, typename InterruptT>
285 inline void
286 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::gaussian(int width)
287 {
288  mParent->startInterrupter("Gaussian flow of level set");
289 
290  for (int n=0; n<4; ++n) this->box(width);
291 
292  mParent->endInterrupter();
293 }
294 
295 template<typename GridT, typename MaskT, typename InterruptT>
296 inline void
297 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::box(int width)
298 {
299  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
300 
301  width = std::max(1, width);
302 
303  mTask = std::bind(&Filter::boxXImpl, std::placeholders::_1, std::placeholders::_2, width);
304  this->cook(true);
305 
306  mTask = std::bind(&Filter::boxYImpl, std::placeholders::_1, std::placeholders::_2, width);
307  this->cook(true);
308 
309  mTask = std::bind(&Filter::boxZImpl, std::placeholders::_1, std::placeholders::_2, width);
310  this->cook(true);
311 
312  mParent->track();
313 }
314 
315 template<typename GridT, typename MaskT, typename InterruptT>
316 inline void
318 {
319  mParent->startInterrupter("Mean-curvature flow of level set");
320 
321  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
322 
323  mTask = std::bind(&Filter::meanCurvatureImpl, std::placeholders::_1, std::placeholders::_2);
324  this->cook(true);
325 
326  mParent->track();
327 
328  mParent->endInterrupter();
329 }
330 
331 template<typename GridT, typename MaskT, typename InterruptT>
332 inline void
334 {
335  mParent->startInterrupter("Laplacian flow of level set");
336 
337  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
338 
339  mTask = std::bind(&Filter::laplacianImpl, std::placeholders::_1, std::placeholders::_2);
340  this->cook(true);
341 
342  mParent->track();
343 
344  mParent->endInterrupter();
345 }
346 
347 template<typename GridT, typename MaskT, typename InterruptT>
348 inline void
350 {
351  mParent->startInterrupter("Offsetting level set");
352 
353  mParent->leafs().removeAuxBuffers();// no auxiliary buffers required
354 
355  const ValueType CFL = ValueType(0.5) * mParent->voxelSize(), offset = openvdb::math::Abs(value);
356  ValueType dist = 0.0;
357  while (offset-dist > ValueType(0.001)*CFL && mParent->checkInterrupter()) {
358  const ValueType delta = openvdb::math::Min(offset-dist, CFL);
359  dist += delta;
360 
361  mTask = std::bind(&Filter::offsetImpl,
362  std::placeholders::_1, std::placeholders::_2, copysign(delta, value));
363  this->cook(false);
364 
365  mParent->track();
366  }
367 
368  mParent->endInterrupter();
369 }
370 
371 
372 ///////////////////////// PRIVATE METHODS //////////////////////
373 
374 /// Performs parabolic mean-curvature diffusion
375 template<typename GridT, typename MaskT, typename InterruptT>
376 inline void
377 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::meanCurvatureImpl(const LeafRange& range)
378 {
379  mParent->checkInterrupter();
380  //const float CFL = 0.9f, dt = CFL * mDx * mDx / 6.0f;
381  const ValueType dx = mParent->voxelSize(), dt = math::Pow2(dx) / ValueType(3.0);
382  math::CurvatureStencil<GridType> stencil(mParent->grid(), dx);
383  if (mMask) {
384  typename AlphaMaskT::FloatType a, b;
385  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
386  mParent->maxMask(), mParent->isMaskInverted());
387  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
388  ValueType* buffer = leafIter.buffer(1).data();
389  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
390  if (alpha(iter.getCoord(), a, b)) {
391  stencil.moveTo(iter);
392  const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.meanCurvatureNormGrad();
393  buffer[iter.pos()] = b * phi0 + a * phi1;
394  }
395  }
396  }
397  } else {
398  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
399  ValueType* buffer = leafIter.buffer(1).data();
400  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
401  stencil.moveTo(iter);
402  buffer[iter.pos()] = *iter + dt*stencil.meanCurvatureNormGrad();
403  }
404  }
405  }
406 }
407 
408 /// Performs Laplacian diffusion. Note if the grids contains a true
409 /// signed distance field (e.g. a solution to the Eikonal equation)
410 /// Laplacian diffusions (e.g. geometric heat equation) is actually
411 /// identical to mean curvature diffusion, yet less computationally
412 /// expensive! In other words if you're performing renormalization
413 /// anyway (e.g. rebuilding the narrow-band) you should consider
414 /// performing Laplacian diffusion over mean curvature flow!
415 template<typename GridT, typename MaskT, typename InterruptT>
416 inline void
417 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::laplacianImpl(const LeafRange& range)
418 {
419  mParent->checkInterrupter();
420  //const float CFL = 0.9f, half_dt = CFL * mDx * mDx / 12.0f;
421  const ValueType dx = mParent->voxelSize(), dt = math::Pow2(dx) / ValueType(6.0);
422  math::GradStencil<GridType> stencil(mParent->grid(), dx);
423  if (mMask) {
424  typename AlphaMaskT::FloatType a, b;
425  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
426  mParent->maxMask(), mParent->isMaskInverted());
427  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
428  ValueType* buffer = leafIter.buffer(1).data();
429  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
430  if (alpha(iter.getCoord(), a, b)) {
431  stencil.moveTo(iter);
432  const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.laplacian();
433  buffer[iter.pos()] = b * phi0 + a * phi1;
434  }
435  }
436  }
437  } else {
438  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
439  ValueType* buffer = leafIter.buffer(1).data();
440  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
441  stencil.moveTo(iter);
442  buffer[iter.pos()] = *iter + dt*stencil.laplacian();
443  }
444  }
445  }
446 }
447 
448 /// Offsets the values by a constant
449 template<typename GridT, typename MaskT, typename InterruptT>
450 inline void
451 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::offsetImpl(
452  const LeafRange& range, ValueType offset)
453 {
454  mParent->checkInterrupter();
455  if (mMask) {
456  typename AlphaMaskT::FloatType a, b;
457  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
458  mParent->maxMask(), mParent->isMaskInverted());
459  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
460  for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
461  if (alpha(iter.getCoord(), a, b)) iter.setValue(*iter + a*offset);
462  }
463  }
464  } else {
465  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
466  for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
467  iter.setValue(*iter + offset);
468  }
469  }
470  }
471 }
472 
473 /// Performs simple but slow median-value diffusion
474 template<typename GridT, typename MaskT, typename InterruptT>
475 inline void
476 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::medianImpl(const LeafRange& range, int width)
477 {
478  mParent->checkInterrupter();
479  typename math::DenseStencil<GridType> stencil(mParent->grid(), width);//creates local cache!
480  if (mMask) {
481  typename AlphaMaskT::FloatType a, b;
482  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
483  mParent->maxMask(), mParent->isMaskInverted());
484  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
485  ValueType* buffer = leafIter.buffer(1).data();
486  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
487  if (alpha(iter.getCoord(), a, b)) {
488  stencil.moveTo(iter);
489  buffer[iter.pos()] = b * (*iter) + a * stencil.median();
490  }
491  }
492  }
493  } else {
494  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
495  ValueType* buffer = leafIter.buffer(1).data();
496  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
497  stencil.moveTo(iter);
498  buffer[iter.pos()] = stencil.median();
499  }
500  }
501  }
502 }
503 
504 /// One dimensional convolution of a separable box filter
505 template<typename GridT, typename MaskT, typename InterruptT>
506 template <typename AvgT>
507 inline void
508 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::boxImpl(const LeafRange& range, Int32 w)
509 {
510  mParent->checkInterrupter();
511  AvgT avg(mParent->grid(), w);
512  if (mMask) {
513  typename AlphaMaskT::FloatType a, b;
514  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
515  mParent->maxMask(), mParent->isMaskInverted());
516  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
517  ValueType* buffer = leafIter.buffer(1).data();
518  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
519  const Coord xyz = iter.getCoord();
520  if (alpha(xyz, a, b)) buffer[iter.pos()] = b * (*iter)+ a * avg(xyz);
521  }
522  }
523  } else {
524  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
525  ValueType* buffer = leafIter.buffer(1).data();
526  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
527  buffer[iter.pos()] = avg(iter.getCoord());
528  }
529  }
530  }
531 }
532 
533 } // namespace tools
534 } // namespace OPENVDB_VERSION_NAME
535 } // namespace openvdb
536 
537 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
538 
539 // Copyright (c) 2012-2018 DreamWorks Animation LLC
540 // All rights reserved. This software is distributed under the
541 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
GA_API const UT_StringHolder dist
GLenum GLint * range
Definition: glcorearb.h:1924
Volume filtering (e.g., diffusion) with optional alpha masking.
Definition: Filter.h:67
Filtering (e.g. diffusion) of narrow-band level sets. An optional scalar field can be used to produce...
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:121
Type Pow2(Type x)
Return x2.
Definition: Math.h:502
GLboolean invert
Definition: glcorearb.h:548
void mean(int width=1, const MaskType *mask=nullptr)
One iteration of mean-value flow of the level set.
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
GLint GLuint mask
Definition: glcorearb.h:123
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
void laplacian(const MaskType *mask=nullptr)
One iteration of Laplacian flow of the level set.
Performs multi-threaded interface tracking of narrow band level sets.
GLuint buffer
Definition: glcorearb.h:659
png_uint_32 i
Definition: png.h:2877
GLint GLsizei width
Definition: glcorearb.h:102
GLdouble n
Definition: glcorearb.h:2007
GLfloat f
Definition: glcorearb.h:1925
void invertMask(bool invert=true)
Invert the optional mask, i.e. min->max in the original mask maps to 1->0 in the inverted alpha mask...
Coord Abs(const Coord &xyz)
Definition: Coord.h:513
void offset(ValueType offset, const MaskType *mask=nullptr)
Offset the level set by the specified (world) distance.
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
GLintptr offset
Definition: glcorearb.h:664
bool isMaskInverted() const
Return true if the mask is inverted, i.e. min->max in the original mask maps to 1->0 in the inverted ...
GLfloat GLfloat GLfloat alpha
Definition: glcorearb.h:111
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
GLint GLfloat GLint stencil
Definition: glcorearb.h:1277
GridType::Ptr laplacian(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the Laplacian of the given scalar grid.
GLsizei const GLfloat * value
Definition: glcorearb.h:823
void median(int width=1, const MaskType *mask=nullptr)
One iteration of median-value flow of the level set.
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:610
void swap(TfErrorTransport &l, TfErrorTransport &r)
LevelSetFilter(GridType &grid, InterruptT *interrupt=nullptr)
Main constructor from a grid.
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
typename LeafManagerType::LeafRange LeafRange
GLboolean r
Definition: glcorearb.h:1221
AlphaType minMask() const
Return the minimum value of the mask to be used for the derivation of a smooth alpha value...
AlphaType maxMask() const
Return the maximum value of the mask to be used for the derivation of a smooth alpha value...
GridType::Ptr meanCurvature(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the mean curvature of the given grid.
void meanCurvature(const MaskType *mask=nullptr)
One iteration of mean-curvature flow of the level set.
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:129
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
void setMaskRange(AlphaType min, AlphaType max)
Define the range for the (optional) scalar mask.
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
void gaussian(int width=1, const MaskType *mask=nullptr)
One iteration of a fast separable Gaussian filter.