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 : mAcc(mask.tree()), mSampler(mAcc, mask.transform(), grid.transform()),
206 mMin(min), mInvNorm(1/(max-min)), mInvert(invert)
210 inline bool operator()(
const Coord& xyz, AlphaType& a, AlphaType& b)
const
213 const AlphaType t = (a-mMin)*mInvNorm;
214 a = t > 0 ? t < 1 ? (3-2*t)*t*t : 1 : 0;
216 if (mInvert) std::swap(a,b);
219 typedef typename MaskType::ConstAccessor AccType;
221 tools::DualGridSampler<AccType, tools::BoxSampler> mSampler;
222 const AlphaType mMin, mInvNorm;
229 template <
size_t Axis>
231 Avg(
const GridT& grid,
Int32 w) :
232 acc(grid.tree()), width(w), frac(1/ValueType(2*w+1)) {}
233 ValueType operator()(Coord xyz) {
234 ValueType sum = zeroVal<ValueType>();
236 for (i -= width; i <= j; ++i) sum += acc.getValue(xyz);
239 typename GridT::ConstAccessor acc;
241 const ValueType frac;
245 template <
typename AvgT>
246 void doBox(
const RangeType& r,
Int32 w);
247 void doBoxX(
const RangeType& r,
Int32 w) { this->doBox<Avg<0> >(r,w); }
248 void doBoxZ(
const RangeType& r,
Int32 w) { this->doBox<Avg<1> >(r,w); }
249 void doBoxY(
const RangeType& r,
Int32 w) { this->doBox<Avg<2> >(r,w); }
250 void doMedian(
const RangeType&,
int);
251 void doMeanCurvature(
const RangeType&);
252 void doLaplacian(
const RangeType&);
253 void doOffset(
const RangeType&, ValueType);
260 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
266 BaseType::startInterrupter(
"Median-value flow of level set");
268 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
270 mTask = boost::bind(&LevelSetFilter::doMedian, _1, _2,
std::max(1, width));
275 BaseType::endInterrupter();
278 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
284 BaseType::startInterrupter(
"Mean-value flow of level set");
288 BaseType::endInterrupter();
291 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
297 BaseType::startInterrupter(
"Gaussian flow of level set");
299 for (
int n=0; n<4; ++n) this->box(width);
301 BaseType::endInterrupter();
304 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
308 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
312 mTask = boost::bind(&LevelSetFilter::doBoxX, _1, _2, width);
315 mTask = boost::bind(&LevelSetFilter::doBoxY, _1, _2, width);
318 mTask = boost::bind(&LevelSetFilter::doBoxZ, _1, _2, width);
324 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
330 BaseType::startInterrupter(
"Mean-curvature flow of level set");
332 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
334 mTask = boost::bind(&LevelSetFilter::doMeanCurvature, _1, _2);
339 BaseType::endInterrupter();
342 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
348 BaseType::startInterrupter(
"Laplacian flow of level set");
350 BaseType::leafs().rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
352 mTask = boost::bind(&LevelSetFilter::doLaplacian, _1, _2);
357 BaseType::endInterrupter();
360 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
366 BaseType::startInterrupter(
"Offsetting level set");
368 BaseType::leafs().removeAuxBuffers();
372 while (offset-dist >
ValueType(0.001)*CFL && BaseType::checkInterrupter()) {
376 mTask = boost::bind(&LevelSetFilter::doOffset, _1, _2, copysign(delta, value));
382 BaseType::endInterrupter();
389 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
393 BaseType::checkInterrupter();
395 const ValueType dx = BaseType::voxelSize(), dt =
math::Pow2(dx) / ValueType(3.0);
399 AlphaMask alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
400 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
401 BufferT& buffer = leafIter.buffer(1);
402 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
403 if (alpha(iter.getCoord(), a, b)) {
404 stencil.moveTo(iter);
405 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.meanCurvatureNormGrad();
406 buffer.setValue(iter.pos(), b*phi0 + a*phi1);
411 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
412 BufferT& buffer = leafIter.buffer(1);
413 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
414 stencil.moveTo(iter);
415 buffer.setValue(iter.pos(), *iter + dt*stencil.meanCurvatureNormGrad());
428 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
430 LevelSetFilter<GridT, MaskT, InterruptT>::doLaplacian(
const RangeType& range)
432 BaseType::checkInterrupter();
434 const ValueType dx = BaseType::voxelSize(), dt =
math::Pow2(dx) / ValueType(6.0);
435 math::GradStencil<GridType> stencil(BaseType::grid(), dx);
438 AlphaMask alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
439 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
440 BufferT& buffer = leafIter.buffer(1);
441 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
442 if (alpha(iter.getCoord(), a, b)) {
443 stencil.moveTo(iter);
444 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.laplacian();
445 buffer.setValue(iter.pos(), b*phi0 + a*phi1);
450 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
451 BufferT& buffer = leafIter.buffer(1);
452 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
453 stencil.moveTo(iter);
454 buffer.setValue(iter.pos(), *iter + dt*stencil.laplacian());
461 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
463 LevelSetFilter<GridT, MaskT, InterruptT>::doOffset(
const RangeType& range, ValueType offset)
465 BaseType::checkInterrupter();
468 AlphaMask alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
469 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
470 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
471 if (alpha(iter.getCoord(), a, b)) iter.setValue(*iter + a*offset);
475 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
476 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
477 iter.setValue(*iter + offset);
484 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
486 LevelSetFilter<GridT, MaskT, InterruptT>::doMedian(
const RangeType& range,
int width)
488 BaseType::checkInterrupter();
489 typename math::DenseStencil<GridType> stencil(BaseType::grid(), width);
492 AlphaMask alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
493 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
494 BufferT& buffer = leafIter.buffer(1);
495 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
496 if (alpha(iter.getCoord(), a, b)) {
497 stencil.moveTo(iter);
498 buffer.setValue(iter.pos(), b*(*iter) + a*stencil.median());
503 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
504 BufferT& buffer = leafIter.buffer(1);
505 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
506 stencil.moveTo(iter);
507 buffer.setValue(iter.pos(), stencil.median());
514 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
515 template <
typename AvgT>
517 LevelSetFilter<GridT, MaskT, InterruptT>::doBox(
const RangeType& range,
Int32 w)
519 BaseType::checkInterrupter();
520 AvgT avg(BaseType::grid(), w);
523 AlphaMask alpha(BaseType::grid(), *mMask, mMinMask, mMaxMask, mInvertMask);
524 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
525 BufferT& buffer = leafIter.buffer(1);
526 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
527 const Coord xyz = iter.getCoord();
528 if (alpha(xyz, a, b)) buffer.setValue(iter.pos(), b*(*iter)+ a*avg(xyz));
532 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
533 BufferT& buffer = leafIter.buffer(1);
534 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
535 buffer.setValue(iter.pos(), avg(iter.getCoord()));
545 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
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
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:244
Type Pow2(Type x)
Return .
Definition: Math.h:458
Definition: Exceptions.h:88
Definition: Stencils.h:1452
Definition: LeafManager.h:122
#define OPENVDB_VERSION_NAME
Definition: version.h:45
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
int32_t Int32
Definition: Types.h:59
Axis
Definition: Math.h:767
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:117
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:566