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);
95 , mMinMask(other.mMinMask)
96 , mMaxMask(other.mMaxMask)
97 , mInvertMask(other.mInvertMask)
108 if (mTask) mTask(const_cast<LevelSetFilter*>(
this), range);
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;
183 typename boost::function<void (LevelSetFilter*, const RangeType&)> mTask;
184 const MaskType*
mMask;
185 AlphaType mMinMask, mMaxMask;
191 const int n = BaseType::getGrainSize();
193 tbb::parallel_for(BaseType::leafs().leafRange(n), *
this);
195 (*this)(BaseType::leafs().leafRange());
197 if (swap) BaseType::leafs().swapLeafBuffer(1, n==0);
203 AlphaMask(
const GridType& grid,
const MaskType& mask,
204 AlphaType
min, AlphaType
max,
bool invert)
205 : mSampler(mask, grid), mMin(min), mInvNorm(1/(max-min)), mInvert(invert)
209 inline bool operator()(
const Coord& xyz, AlphaType& a, AlphaType& b)
const
212 const AlphaType t = (a-mMin)*mInvNorm;
213 a = t > 0 ? t < 1 ? (3-2*t)*t*t : 1 : 0;
215 if (mInvert) std::swap(a,b);
218 tools::DualGridSampler<MaskType, GridType, tools::BoxSampler> mSampler;
219 const AlphaType mMin, mInvNorm;
226 template <
size_t Axis>
228 Avg(
const GridT& grid,
Int32 w) :
229 acc(grid.tree()), width(w), frac(1/ValueType(2*w+1)) {}
230 ValueType operator()(Coord xyz) {
231 ValueType sum = zeroVal<ValueType>();
233 for (i -= width; i <= j; ++i) sum += acc.getValue(xyz);
236 typename GridT::ConstAccessor acc;
238 const ValueType frac;
242 template <
typename AvgT>
243 void doBox(
const RangeType& r,
Int32 w);
244 void doBoxX(
const RangeType& r,
Int32 w) { this->doBox<Avg<0> >(r,w); }
245 void doBoxZ(
const RangeType& r,
Int32 w) { this->doBox<Avg<1> >(r,w); }
246 void doBoxY(
const RangeType& r,
Int32 w) { this->doBox<Avg<2> >(r,w); }
247 void doMedian(
const RangeType&,
int);
248 void doMeanCurvature(
const RangeType&);
249 void doLaplacian(
const RangeType&);
250 void doOffset(
const RangeType&, ValueType);
257 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
263 BaseType::startInterrupter(
"Median-value flow of level set");
265 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
267 mTask = boost::bind(&LevelSetFilter::doMedian, _1, _2,
std::max(1, width));
272 BaseType::endInterrupter();
275 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
281 BaseType::startInterrupter(
"Mean-value flow of level set");
285 BaseType::endInterrupter();
288 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
294 BaseType::startInterrupter(
"Gaussian flow of level set");
296 for (
int n=0; n<4; ++n) this->box(width);
298 BaseType::endInterrupter();
301 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
305 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
309 mTask = boost::bind(&LevelSetFilter::doBoxX, _1, _2, width);
312 mTask = boost::bind(&LevelSetFilter::doBoxY, _1, _2, width);
315 mTask = boost::bind(&LevelSetFilter::doBoxZ, _1, _2, width);
321 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
327 BaseType::startInterrupter(
"Mean-curvature flow of level set");
329 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
331 mTask = boost::bind(&LevelSetFilter::doMeanCurvature, _1, _2);
336 BaseType::endInterrupter();
339 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
345 BaseType::startInterrupter(
"Laplacian flow of level set");
347 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
349 mTask = boost::bind(&LevelSetFilter::doLaplacian, _1, _2);
354 BaseType::endInterrupter();
357 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
363 BaseType::startInterrupter(
"Offsetting level set");
365 BaseType::leafs().removeAuxBuffers();
369 while (offset-dist >
ValueType(0.001)*CFL && BaseType::checkInterrupter()) {
373 mTask = boost::bind(&LevelSetFilter::doOffset, _1, _2, copysign(delta, value));
379 BaseType::endInterrupter();
386 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
390 BaseType::checkInterrupter();
392 const ValueType dx = BaseType::voxelSize(), dt =
math::Pow2(dx) / ValueType(3.0);
396 AlphaMask alpha(BaseType::grid(), *
mMask, mMinMask, mMaxMask, mInvertMask);
397 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
398 BufferT& buffer = leafIter.buffer(1);
399 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
400 if (alpha(iter.getCoord(), a, b)) {
401 stencil.moveTo(iter);
402 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.meanCurvatureNormGrad();
403 buffer.setValue(iter.pos(), b*phi0 + a*phi1);
408 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
409 BufferT& buffer = leafIter.buffer(1);
410 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
411 stencil.moveTo(iter);
412 buffer.setValue(iter.pos(), *iter + dt*stencil.meanCurvatureNormGrad());
425 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
427 LevelSetFilter<GridT, MaskT, InterruptT>::doLaplacian(
const RangeType& range)
429 BaseType::checkInterrupter();
431 const ValueType dx = BaseType::voxelSize(), dt =
math::Pow2(dx) / ValueType(6.0);
432 math::GradStencil<GridType> stencil(BaseType::grid(), dx);
435 AlphaMask alpha(BaseType::grid(), *
mMask, mMinMask, mMaxMask, mInvertMask);
436 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
437 BufferT& buffer = leafIter.buffer(1);
438 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
439 if (alpha(iter.getCoord(), a, b)) {
440 stencil.moveTo(iter);
441 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.laplacian();
442 buffer.setValue(iter.pos(), b*phi0 + a*phi1);
447 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
448 BufferT& buffer = leafIter.buffer(1);
449 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
450 stencil.moveTo(iter);
451 buffer.setValue(iter.pos(), *iter + dt*stencil.laplacian());
458 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
460 LevelSetFilter<GridT, MaskT, InterruptT>::doOffset(
const RangeType& range, ValueType offset)
462 BaseType::checkInterrupter();
465 AlphaMask alpha(BaseType::grid(), *
mMask, mMinMask, mMaxMask, mInvertMask);
466 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
467 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
468 if (alpha(iter.getCoord(), a, b)) iter.setValue(*iter + a*offset);
472 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
473 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
474 iter.setValue(*iter + offset);
481 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
483 LevelSetFilter<GridT, MaskT, InterruptT>::doMedian(
const RangeType& range,
int width)
485 BaseType::checkInterrupter();
486 typename math::DenseStencil<GridType> stencil(BaseType::grid(), width);
489 AlphaMask alpha(BaseType::grid(), *
mMask, mMinMask, mMaxMask, mInvertMask);
490 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
491 BufferT& buffer = leafIter.buffer(1);
492 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
493 if (alpha(iter.getCoord(), a, b)) {
494 stencil.moveTo(iter);
495 buffer.setValue(iter.pos(), b*(*iter) + a*stencil.median());
500 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
501 BufferT& buffer = leafIter.buffer(1);
502 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
503 stencil.moveTo(iter);
504 buffer.setValue(iter.pos(), stencil.median());
511 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
512 template <
typename AvgT>
514 LevelSetFilter<GridT, MaskT, InterruptT>::doBox(
const RangeType& range,
Int32 w)
516 BaseType::checkInterrupter();
517 AvgT avg(BaseType::grid(), w);
520 AlphaMask alpha(BaseType::grid(), *
mMask, mMinMask, mMaxMask, mInvertMask);
521 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
522 BufferT& buffer = leafIter.buffer(1);
523 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
524 const Coord xyz = iter.getCoord();
525 if (alpha(xyz, a, b)) buffer.setValue(iter.pos(), b*(*iter)+ a*avg(xyz));
529 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
530 BufferT& buffer = leafIter.buffer(1);
531 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
532 buffer.setValue(iter.pos(), avg(iter.getCoord()));
542 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Definition: Exceptions.h:88
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:253
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:117
Type Pow2(Type x)
Return .
Definition: Math.h:467
#define OPENVDB_VERSION_NAME
Definition: version.h:45
Definition: Stencils.h:1452
const MaskGridType * mMask
Definition: GridOperators.h:386
int32_t Int32
Definition: Types.h:58
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:575
Definition: LeafManager.h:122
Axis
Definition: Math.h:769
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67