HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LevelSetFilter.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2017 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 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 <assert.h>
46 #include <hboost/type_traits/is_floating_point.hpp>
47 #include "LevelSetTracker.h"
48 #include "Interpolation.h"
49 
50 namespace openvdb {
52 namespace OPENVDB_VERSION_NAME {
53 namespace tools {
54 
55 /// @brief Filtering (e.g. diffusion) of narrow-band level sets. An
56 /// optional scalar field can be used to produce a (smooth) alpha mask
57 /// for the filtering.
58 ///
59 /// @note This class performs proper interface tracking which allows
60 /// for unrestricted surface deformations
61 template<typename GridT,
62  typename MaskT = typename GridT::template ValueConverter<float>::Type,
63  typename InterruptT = util::NullInterrupter>
64 class LevelSetFilter : public LevelSetTracker<GridT, InterruptT>
65 {
66 public:
68  typedef GridT GridType;
69  typedef MaskT MaskType;
70  typedef typename GridType::TreeType TreeType;
71  typedef typename TreeType::ValueType ValueType;
72  typedef typename MaskType::ValueType AlphaType;
74 
75  /// @brief Main constructor from a grid
76  /// @param grid The level set to be filtered.
77  /// @param interrupt Optional interrupter.
78  LevelSetFilter(GridType& grid, InterruptT* interrupt = nullptr)
79  : BaseType(grid, interrupt)
80  , mMinMask(0)
81  , mMaxMask(1)
82  , mInvertMask(false)
83  {
84  }
85  /// @brief Default destructor
86  virtual ~LevelSetFilter() {}
87 
88  /// @brief Return the minimum value of the mask to be used for the
89  /// derivation of a smooth alpha value.
90  AlphaType minMask() const { return mMinMask; }
91  /// @brief Return the maximum value of the mask to be used for the
92  /// derivation of a smooth alpha value.
93  AlphaType maxMask() const { return mMaxMask; }
94  /// @brief Define the range for the (optional) scalar mask.
95  /// @param min Minimum value of the range.
96  /// @param max Maximum value of the range.
97  /// @details Mask values outside the range maps to alpha values of
98  /// respectfully zero and one, and values inside the range maps
99  /// smoothly to 0->1 (unless of course the mask is inverted).
100  /// @throw ValueError if @a min is not smaller than @a max.
102  {
103  if (!(min < max)) OPENVDB_THROW(ValueError, "Invalid mask range (expects min < max)");
104  mMinMask = min;
105  mMaxMask = max;
106  }
107 
108  /// @brief Return true if the mask is inverted, i.e. min->max in the
109  /// original mask maps to 1->0 in the inverted alpha mask.
110  bool isMaskInverted() const { return mInvertMask; }
111  /// @brief Invert the optional mask, i.e. min->max in the original
112  /// mask maps to 1->0 in the inverted alpha mask.
113  void invertMask(bool invert=true) { mInvertMask = invert; }
114 
115  /// @brief One iteration of mean-curvature flow of the level set.
116  /// @param mask Optional alpha mask.
117  void meanCurvature(const MaskType* mask = nullptr)
118  {
119  Filter f(this, mask); f.meanCurvature();
120  }
121 
122  /// @brief One iteration of Laplacian flow of the level set.
123  /// @param mask Optional alpha mask.
124  void laplacian(const MaskType* mask = nullptr)
125  {
126  Filter f(this, mask); f.laplacian();
127  }
128 
129  /// @brief One iteration of a fast separable Gaussian filter.
130  /// @param width Width of the Gaussian kernel in voxel units.
131  /// @param mask Optional alpha mask.
132  ///
133  /// @note This is approximated as 4 iterations of a separable mean filter
134  /// which typically leads an approximation that's better than 95%!
135  void gaussian(int width = 1, const MaskType* mask = nullptr)
136  {
137  Filter f(this, mask); f.gaussian(width);
138  }
139 
140  /// @brief Offset the level set by the specified (world) distance.
141  /// @param offset Value of the offset.
142  /// @param mask Optional alpha mask.
143  void offset(ValueType offset, const MaskType* mask = nullptr)
144  {
145  Filter f(this, mask); f.offset(offset);
146  }
147 
148  /// @brief One iteration of median-value flow of the level set.
149  /// @param width Width of the median-value kernel in voxel units.
150  /// @param mask Optional alpha mask.
151  ///
152  /// @warning This filter is not separable and is hence relatively
153  /// slow!
154  void median(int width = 1, const MaskType* mask = nullptr)
155  {
156  Filter f(this, mask); f.median(width);
157  }
158 
159  /// @brief One iteration of mean-value flow of the level set.
160  /// @param width Width of the mean-value kernel in voxel units.
161  /// @param mask Optional alpha mask.
162  ///
163  /// @note This filter is separable so it's fast!
164  void mean(int width = 1, const MaskType* mask = nullptr)
165  {
166  Filter f(this, mask); f.mean(width);
167  }
168 
169 private:
170  // disallow copy construction and copy by assignment!
171  LevelSetFilter(const LevelSetFilter&);// not implemented
172  LevelSetFilter& operator=(const LevelSetFilter&);// not implemented
173 
174  // Private struct that implements all the filtering.
175  struct Filter
176  {
177  typedef typename TreeType::LeafNodeType LeafT;
178  typedef typename LeafT::ValueOnIter VoxelIterT;
179  typedef typename LeafT::ValueOnCIter VoxelCIterT;
180  typedef typename tree::LeafManager<TreeType>::BufferType BufferT;
182  typedef typename LeafRange::Iterator LeafIterT;
183  typedef tools::AlphaMask<GridT, MaskT> AlphaMaskT;
184 
185  Filter(LevelSetFilter* parent, const MaskType* mask) : mParent(parent), mMask(mask) {}
186  Filter(const Filter&) = default;
187  virtual ~Filter() {}
188 
189  void box(int width);
190  void median(int width);
191  void mean(int width);
192  void gaussian(int width);
193  void laplacian();
194  void meanCurvature();
195  void offset(ValueType value);
196  void operator()(const LeafRange& r) const
197  {
198  if (mTask) mTask(const_cast<Filter*>(this), r);
199  else OPENVDB_THROW(ValueError, "task is undefined - don\'t call this method directly");
200  }
201  void cook(bool swap)
202  {
203  const int n = mParent->getGrainSize();
204  if (n>0) {
205  tbb::parallel_for(mParent->leafs().leafRange(n), *this);
206  } else {
207  (*this)(mParent->leafs().leafRange());
208  }
209  if (swap) mParent->leafs().swapLeafBuffer(1, n==0);
210  }
211 
212  template <size_t Axis>
213  struct Avg {
214  Avg(const GridT& grid, Int32 w) :
215  acc(grid.tree()), width(w), frac(1/ValueType(2*w+1)) {}
216  inline ValueType operator()(Coord xyz)
217  {
218  ValueType sum = zeroVal<ValueType>();
219  Int32& i = xyz[Axis], j = i + width;
220  for (i -= width; i <= j; ++i) sum += acc.getValue(xyz);
221  return sum*frac;
222  }
223  typename GridT::ConstAccessor acc;
224  const Int32 width;
226  };
227 
228  template <typename AvgT>
229  void box( const LeafRange& r, Int32 w);
230 
231  void boxX(const LeafRange& r, Int32 w) { this->box<Avg<0> >(r,w); }
232  void boxZ(const LeafRange& r, Int32 w) { this->box<Avg<1> >(r,w); }
233  void boxY(const LeafRange& r, Int32 w) { this->box<Avg<2> >(r,w); }
234 
235  void median(const LeafRange&, int);
236  void meanCurvature(const LeafRange&);
237  void laplacian(const LeafRange&);
238  void offset(const LeafRange&, ValueType);
239 
240  LevelSetFilter* mParent;
241  const MaskType* mMask;
242  typename hboost::function<void (Filter*, const LeafRange&)> mTask;
243  }; // end of private Filter struct
244 
245  AlphaType mMinMask, mMaxMask;
246  bool mInvertMask;
247 
248 }; // end of LevelSetFilter class
249 
250 
251 ////////////////////////////////////////
252 
253 template<typename GridT, typename MaskT, typename InterruptT>
254 inline void
255 LevelSetFilter<GridT, MaskT, InterruptT>::
256 Filter::median(int width)
257 {
258  mParent->startInterrupter("Median-value flow of level set");
259 
260  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
261 
262  mTask = hboost::bind(&Filter::median, hboost::placeholders::_1, hboost::placeholders::_2, std::max(1, width));
263  this->cook(true);
264 
265  mParent->track();
266 
267  mParent->endInterrupter();
268 }
269 
270 template<typename GridT, typename MaskT, typename InterruptT>
271 inline void
272 LevelSetFilter<GridT, MaskT, InterruptT>::
273 Filter::mean(int width)
274 {
275  mParent->startInterrupter("Mean-value flow of level set");
276 
277  this->box(width);
278 
279  mParent->endInterrupter();
280 }
281 
282 template<typename GridT, typename MaskT, typename InterruptT>
283 inline void
284 LevelSetFilter<GridT, MaskT, InterruptT>::
285 Filter::gaussian(int width)
286 {
287  mParent->startInterrupter("Gaussian flow of level set");
288 
289  for (int n=0; n<4; ++n) this->box(width);
290 
291  mParent->endInterrupter();
292 }
293 
294 template<typename GridT, typename MaskT, typename InterruptT>
295 inline void
296 LevelSetFilter<GridT, MaskT, InterruptT>::
297 Filter::box(int width)
298 {
299  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
300 
301  width = std::max(1, width);
302 
303  mTask = hboost::bind(&Filter::boxX, hboost::placeholders::_1, hboost::placeholders::_2, width);
304  this->cook(true);
305 
306  mTask = hboost::bind(&Filter::boxY, hboost::placeholders::_1, hboost::placeholders::_2, width);
307  this->cook(true);
308 
309  mTask = hboost::bind(&Filter::boxZ, hboost::placeholders::_1, hboost::placeholders::_2, width);
310  this->cook(true);
311 
312  mParent->track();
313 }
314 
315 template<typename GridT, typename MaskT, typename InterruptT>
316 inline void
319 {
320  mParent->startInterrupter("Mean-curvature flow of level set");
321 
322  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
323 
324  mTask = hboost::bind(&Filter::meanCurvature, hboost::placeholders::_1, hboost::placeholders::_2);
325  this->cook(true);
326 
327  mParent->track();
328 
329  mParent->endInterrupter();
330 }
331 
332 template<typename GridT, typename MaskT, typename InterruptT>
333 inline void
336 {
337  mParent->startInterrupter("Laplacian flow of level set");
338 
339  mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
340 
341  mTask = hboost::bind(&Filter::laplacian, hboost::placeholders::_1, hboost::placeholders::_2);
342  this->cook(true);
343 
344  mParent->track();
345 
346  mParent->endInterrupter();
347 }
348 
349 template<typename GridT, typename MaskT, typename InterruptT>
350 inline void
352 Filter::offset(ValueType value)
353 {
354  mParent->startInterrupter("Offsetting level set");
355 
356  mParent->leafs().removeAuxBuffers();// no auxiliary buffers required
357 
358  const ValueType CFL = ValueType(0.5) * mParent->voxelSize(), offset = openvdb::math::Abs(value);
359  ValueType dist = 0.0;
360  while (offset-dist > ValueType(0.001)*CFL && mParent->checkInterrupter()) {
361  const ValueType delta = openvdb::math::Min(offset-dist, CFL);
362  dist += delta;
363 
364  mTask = hboost::bind(&Filter::offset, hboost::placeholders::_1, hboost::placeholders::_2, copysign(delta, value));
365  this->cook(false);
366 
367  mParent->track();
368  }
369 
370  mParent->endInterrupter();
371 }
372 
373 
374 ///////////////////////// PRIVATE METHODS //////////////////////
375 
376 /// Performs parabolic mean-curvature diffusion
377 template<typename GridT, typename MaskT, typename InterruptT>
378 inline void
380 Filter::meanCurvature(const LeafRange& range)
381 {
382  mParent->checkInterrupter();
383  //const float CFL = 0.9f, dt = CFL * mDx * mDx / 6.0f;
384  const ValueType dx = mParent->voxelSize(), dt = math::Pow2(dx) / ValueType(3.0);
385  math::CurvatureStencil<GridType> stencil(mParent->grid(), dx);
386  if (mMask) {
387  typename AlphaMaskT::FloatType a, b;
388  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
389  mParent->maxMask(), mParent->isMaskInverted());
390  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
391  ValueType* buffer = leafIter.buffer(1).data();
392  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
393  if (alpha(iter.getCoord(), a, b)) {
394  stencil.moveTo(iter);
395  const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.meanCurvatureNormGrad();
396  buffer[iter.pos()] = b * phi0 + a * phi1;
397  }
398  }
399  }
400  } else {
401  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
402  ValueType* buffer = leafIter.buffer(1).data();
403  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
404  stencil.moveTo(iter);
405  buffer[iter.pos()] = *iter + dt*stencil.meanCurvatureNormGrad();
406  }
407  }
408  }
409 }
410 
411 /// Performs Laplacian diffusion. Note if the grids contains a true
412 /// signed distance field (e.g. a solution to the Eikonal equation)
413 /// Laplacian diffusions (e.g. geometric heat equation) is actually
414 /// identical to mean curvature diffusion, yet less computationally
415 /// expensive! In other words if you're performing renormalization
416 /// anyway (e.g. rebuilding the narrow-band) you should consider
417 /// performing Laplacian diffusion over mean curvature flow!
418 template<typename GridT, typename MaskT, typename InterruptT>
419 inline void
421 Filter::laplacian(const LeafRange& range)
422 {
423  mParent->checkInterrupter();
424  //const float CFL = 0.9f, half_dt = CFL * mDx * mDx / 12.0f;
425  const ValueType dx = mParent->voxelSize(), dt = math::Pow2(dx) / ValueType(6.0);
426  math::GradStencil<GridType> stencil(mParent->grid(), dx);
427  if (mMask) {
428  typename AlphaMaskT::FloatType a, b;
429  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
430  mParent->maxMask(), mParent->isMaskInverted());
431  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
432  ValueType* buffer = leafIter.buffer(1).data();
433  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
434  if (alpha(iter.getCoord(), a, b)) {
435  stencil.moveTo(iter);
436  const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.laplacian();
437  buffer[iter.pos()] = b * phi0 + a * phi1;
438  }
439  }
440  }
441  } else {
442  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
443  ValueType* buffer = leafIter.buffer(1).data();
444  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
445  stencil.moveTo(iter);
446  buffer[iter.pos()] = *iter + dt*stencil.laplacian();
447  }
448  }
449  }
450 }
451 
452 /// Offsets the values by a constant
453 template<typename GridT, typename MaskT, typename InterruptT>
454 inline void
456 Filter::offset(const LeafRange& range, ValueType offset)
457 {
458  mParent->checkInterrupter();
459  if (mMask) {
460  typename AlphaMaskT::FloatType a, b;
461  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
462  mParent->maxMask(), mParent->isMaskInverted());
463  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
464  for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
465  if (alpha(iter.getCoord(), a, b)) iter.setValue(*iter + a*offset);
466  }
467  }
468  } else {
469  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
470  for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
471  iter.setValue(*iter + offset);
472  }
473  }
474  }
475 }
476 
477 /// Performs simple but slow median-value diffusion
478 template<typename GridT, typename MaskT, typename InterruptT>
479 inline void
480 LevelSetFilter<GridT, MaskT, InterruptT>::
481 Filter::median(const LeafRange& range, int width)
482 {
483  mParent->checkInterrupter();
484  typename math::DenseStencil<GridType> stencil(mParent->grid(), width);//creates local cache!
485  if (mMask) {
486  typename AlphaMaskT::FloatType a, b;
487  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
488  mParent->maxMask(), mParent->isMaskInverted());
489  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
490  ValueType* buffer = leafIter.buffer(1).data();
491  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
492  if (alpha(iter.getCoord(), a, b)) {
493  stencil.moveTo(iter);
494  buffer[iter.pos()] = b * (*iter) + a * stencil.median();
495  }
496  }
497  }
498  } else {
499  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
500  ValueType* buffer = leafIter.buffer(1).data();
501  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
502  stencil.moveTo(iter);
503  buffer[iter.pos()] = stencil.median();
504  }
505  }
506  }
507 }
508 
509 /// One dimensional convolution of a separable box filter
510 template<typename GridT, typename MaskT, typename InterruptT>
511 template <typename AvgT>
512 inline void
513 LevelSetFilter<GridT, MaskT, InterruptT>::
514 Filter::box(const LeafRange& range, Int32 w)
515 {
516  mParent->checkInterrupter();
517  AvgT avg(mParent->grid(), w);
518  if (mMask) {
519  typename AlphaMaskT::FloatType a, b;
520  AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
521  mParent->maxMask(), mParent->isMaskInverted());
522  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
523  ValueType* buffer = leafIter.buffer(1).data();
524  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
525  const Coord xyz = iter.getCoord();
526  if (alpha(xyz, a, b)) buffer[iter.pos()] = b * (*iter)+ a * avg(xyz);
527  }
528  }
529  } else {
530  for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
531  ValueType* buffer = leafIter.buffer(1).data();
532  for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
533  buffer[iter.pos()] = avg(iter.getCoord());
534  }
535  }
536  }
537 }
538 
539 } // namespace tools
540 } // namespace OPENVDB_VERSION_NAME
541 } // namespace openvdb
542 
543 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
544 
545 // Copyright (c) 2012-2017 DreamWorks Animation LLC
546 // All rights reserved. This software is distributed under the
547 // 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:66
Filtering (e.g. diffusion) of narrow-band level sets. An optional scalar field can be used to produce...
Type Pow2(Type x)
Return .
Definition: Math.h:514
const hboost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:128
GLboolean invert
Definition: glcorearb.h:548
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1561
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
void median(int width=1, int iterations=1, const MaskType *mask=NULL)
One iteration of a median-value filter.
Definition: Filter.h:304
GLint GLuint mask
Definition: glcorearb.h:123
HBOOST_STATIC_ASSERT(hboost::is_floating_point< AlphaType >::value)
void offset(ValueType offset, const MaskType *mask=NULL)
Definition: Filter.h:321
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
const hboost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:132
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:254
#define OPENVDB_VERSION_NAME
Definition: version.h:43
void offset(ValueType offset, const MaskType *mask=nullptr)
Offset the level set by the specified (world) distance.
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
LevelSetTracker< GridT, InterruptT > BaseType
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:622
LevelSetFilter(GridType &grid, InterruptT *interrupt=nullptr)
Main constructor from a grid.
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
GLboolean r
Definition: glcorearb.h:1221
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
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...
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:126
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.
void setMaskRange(AlphaType min, AlphaType max)
Define the range for the (optional) scalar mask.
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
void gaussian(int width=1, const MaskType *mask=nullptr)
One iteration of a fast separable Gaussian filter.