42 #ifndef OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
43 #define OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
46 #include <boost/type_traits/is_floating_point.hpp>
61 template<
typename GridT,
62 typename MaskT =
typename GridT::template ValueConverter<float>::Type,
63 typename InterruptT = util::NullInterrupter>
74 BOOST_STATIC_ASSERT(boost::is_floating_point<AlphaType>::value);
80 : BaseType(grid, interrupt)
95 , mMinMask(other.mMinMask)
96 , mMaxMask(other.mMaxMask)
97 , mInvertMask(other.mInvertMask)
108 if (mTask) mTask(const_cast<LevelSetFilter*>(
this), range);
114 AlphaType
minMask()
const {
return mMinMask; }
117 AlphaType
maxMask()
const {
return mMaxMask; }
145 void laplacian(
const MaskType* mask = NULL);
153 void gaussian(
int width = 1,
const MaskType* mask = NULL);
158 void offset(ValueType offset,
const MaskType* mask = NULL);
166 void median(
int width = 1,
const MaskType* mask = NULL);
173 void mean(
int width = 1,
const MaskType* mask = NULL);
176 typedef typename TreeType::LeafNodeType LeafT;
177 typedef typename LeafT::ValueOnIter VoxelIterT;
178 typedef typename LeafT::ValueOnCIter VoxelCIterT;
180 typedef typename RangeType::Iterator LeafIterT;
184 typename boost::function<void (LevelSetFilter*, const RangeType&)> mTask;
185 const MaskType* mMask;
186 AlphaType mMinMask, mMaxMask;
192 const int n = BaseType::getGrainSize();
194 tbb::parallel_for(BaseType::leafs().leafRange(n), *
this);
196 (*this)(BaseType::leafs().leafRange());
198 if (swap) BaseType::leafs().swapLeafBuffer(1, n==0);
204 template <
size_t Axis>
206 Avg(
const GridT& grid,
Int32 w) :
207 acc(grid.tree()), width(w), frac(1/ValueType(2*w+1))
210 ValueType operator()(Coord xyz)
212 ValueType sum = zeroVal<ValueType>();
214 for (i -= width; i <= j; ++i) sum += acc.getValue(xyz);
217 typename GridT::ConstAccessor acc;
219 const ValueType frac;
223 template <
typename AvgT>
224 void doBox(
const RangeType& r,
Int32 w);
225 void doBoxX(
const RangeType& r,
Int32 w) { this->doBox<Avg<0> >(r,w); }
226 void doBoxZ(
const RangeType& r,
Int32 w) { this->doBox<Avg<1> >(r,w); }
227 void doBoxY(
const RangeType& r,
Int32 w) { this->doBox<Avg<2> >(r,w); }
228 void doMedian(
const RangeType&,
int);
229 void doMeanCurvature(
const RangeType&);
230 void doLaplacian(
const RangeType&);
231 void doOffset(
const RangeType&, ValueType);
238 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
244 BaseType::startInterrupter(
"Median-value flow of level set");
246 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
248 mTask = boost::bind(&LevelSetFilter::doMedian, _1, _2,
std::max(1, width));
253 BaseType::endInterrupter();
256 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
262 BaseType::startInterrupter(
"Mean-value flow of level set");
266 BaseType::endInterrupter();
269 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
275 BaseType::startInterrupter(
"Gaussian flow of level set");
277 for (
int n=0; n<4; ++n) this->box(width);
279 BaseType::endInterrupter();
282 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
286 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
290 mTask = boost::bind(&LevelSetFilter::doBoxX, _1, _2, width);
293 mTask = boost::bind(&LevelSetFilter::doBoxY, _1, _2, width);
296 mTask = boost::bind(&LevelSetFilter::doBoxZ, _1, _2, width);
302 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
308 BaseType::startInterrupter(
"Mean-curvature flow of level set");
310 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
312 mTask = boost::bind(&LevelSetFilter::doMeanCurvature, _1, _2);
317 BaseType::endInterrupter();
320 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
326 BaseType::startInterrupter(
"Laplacian flow of level set");
328 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
330 mTask = boost::bind(&LevelSetFilter::doLaplacian, _1, _2);
335 BaseType::endInterrupter();
338 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
344 BaseType::startInterrupter(
"Offsetting level set");
346 BaseType::leafs().removeAuxBuffers();
348 const ValueType CFL = ValueType(0.5) * BaseType::voxelSize(), offset =
openvdb::math::Abs(value);
349 ValueType dist = 0.0;
350 while (offset-dist > ValueType(0.001)*CFL && BaseType::checkInterrupter()) {
354 mTask = boost::bind(&LevelSetFilter::doOffset, _1, _2, copysign(delta, value));
360 BaseType::endInterrupter();
367 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
371 BaseType::checkInterrupter();
373 const ValueType dx = BaseType::voxelSize(), dt =
math::Pow2(dx) / ValueType(3.0);
376 typename AlphaMaskT::FloatType a, b;
377 AlphaMaskT alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
378 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
379 BufferT& buffer = leafIter.buffer(1);
380 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
381 if (alpha(iter.getCoord(), a, b)) {
382 stencil.moveTo(iter);
383 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.meanCurvatureNormGrad();
384 buffer.setValue(iter.pos(), b*phi0 + a*phi1);
389 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
390 BufferT& buffer = leafIter.buffer(1);
391 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
392 stencil.moveTo(iter);
393 buffer.setValue(iter.pos(), *iter + dt*stencil.meanCurvatureNormGrad());
406 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
408 LevelSetFilter<GridT, MaskT, InterruptT>::doLaplacian(
const RangeType& range)
410 BaseType::checkInterrupter();
412 const ValueType dx = BaseType::voxelSize(), dt =
math::Pow2(dx) / ValueType(6.0);
413 math::GradStencil<GridType> stencil(BaseType::grid(), dx);
415 typename AlphaMaskT::FloatType a, b;
416 AlphaMaskT alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
417 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
418 BufferT& buffer = leafIter.buffer(1);
419 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
420 if (alpha(iter.getCoord(), a, b)) {
421 stencil.moveTo(iter);
422 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.laplacian();
423 buffer.setValue(iter.pos(), b*phi0 + a*phi1);
428 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
429 BufferT& buffer = leafIter.buffer(1);
430 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
431 stencil.moveTo(iter);
432 buffer.setValue(iter.pos(), *iter + dt*stencil.laplacian());
439 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
441 LevelSetFilter<GridT, MaskT, InterruptT>::doOffset(
const RangeType& range, ValueType offset)
443 BaseType::checkInterrupter();
445 typename AlphaMaskT::FloatType a, b;
446 AlphaMaskT alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
447 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
448 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
449 if (alpha(iter.getCoord(), a, b)) iter.setValue(*iter + a*offset);
453 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
454 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
455 iter.setValue(*iter + offset);
462 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
464 LevelSetFilter<GridT, MaskT, InterruptT>::doMedian(
const RangeType& range,
int width)
466 BaseType::checkInterrupter();
467 typename math::DenseStencil<GridType> stencil(BaseType::grid(), width);
469 typename AlphaMaskT::FloatType a, b;
470 AlphaMaskT alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
471 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
472 BufferT& buffer = leafIter.buffer(1);
473 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
474 if (alpha(iter.getCoord(), a, b)) {
475 stencil.moveTo(iter);
476 buffer.setValue(iter.pos(), b*(*iter) + a*stencil.median());
481 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
482 BufferT& buffer = leafIter.buffer(1);
483 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
484 stencil.moveTo(iter);
485 buffer.setValue(iter.pos(), stencil.median());
492 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
493 template <
typename AvgT>
495 LevelSetFilter<GridT, MaskT, InterruptT>::doBox(
const RangeType& range,
Int32 w)
497 BaseType::checkInterrupter();
498 AvgT avg(BaseType::grid(), w);
500 typename AlphaMaskT::FloatType a, b;
501 AlphaMaskT alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
502 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
503 BufferT& buffer = leafIter.buffer(1);
504 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
505 const Coord xyz = iter.getCoord();
506 if (alpha(xyz, a, b)) buffer.setValue(iter.pos(), b*(*iter)+ a*avg(xyz));
510 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
511 BufferT& buffer = leafIter.buffer(1);
512 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
513 buffer.setValue(iter.pos(), avg(iter.getCoord()));
523 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
Definition: LeafManager.h:126
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:284
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Type Pow2(Type x)
Return .
Definition: Math.h:498
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:606
int32_t Int32
Definition: Types.h:61
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Definition: Exceptions.h:39
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Axis
Definition: Math.h:822
Definition: Exceptions.h:88
Definition: Stencils.h:1454
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:120