15#ifndef OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED 
   16#define OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED 
   36template<
typename GridT,
 
   37         typename MaskT = 
typename GridT::template ValueConverter<float>::Type,
 
   38         typename InterruptT = util::NullInterrupter>
 
   48    static_assert(std::is_floating_point<AlphaType>::value,
 
   49        "LevelSetFilter requires a mask grid with floating-point values");
 
   89    void invertMask(
bool invert=
true) { mInvertMask = invert; }
 
   95        Filter f(
this, mask); f.meanCurvature();
 
 
  112        Filter f(
this, mask); f.fillet();
 
 
  119        Filter f(
this, mask); f.laplacian();
 
 
  130        Filter f(
this, mask); f.gaussian(width);
 
 
  138        Filter f(
this, mask); f.offset(
offset);
 
 
  149        Filter f(
this, mask); f.median(width);
 
 
  159        Filter f(
this, mask); f.mean(width);
 
 
  170        using LeafT = 
typename TreeType::LeafNodeType;
 
  171        using VoxelIterT = 
typename LeafT::ValueOnIter;
 
  172        using VoxelCIterT = 
typename LeafT::ValueOnCIter;
 
  175        using LeafIterT = 
typename LeafRange::Iterator;
 
  179        Filter(
const Filter&) = 
default;
 
  183        void median(
int width);
 
  184        void mean(
int width);
 
  185        void gaussian(
int width);
 
  187        void meanCurvature();
 
  189        void offset(ValueType value);
 
  190        void operator()(
const LeafRange& r)
 const 
  192            if (mTask) mTask(
const_cast<Filter*
>(
this), r);
 
  197            const int n = mParent->getGrainSize();
 
  199                tbb::parallel_for(mParent->leafs().leafRange(n), *
this);
 
  201                (*this)(mParent->leafs().leafRange());
 
  203            if (swap) mParent->leafs().swapLeafBuffer(1, n==0);
 
  206        template <
size_t Axis>
 
  214                for (i -= 
width; i <= j; ++i) sum += 
acc.getValue(xyz);
 
 
  217            typename GridT::ConstAccessor 
acc;
 
 
  222        template<
typename AvgT>
 
  223        void boxImpl(
const LeafRange& r, 
Int32 w);
 
  225        void boxXImpl(
const LeafRange& r, 
Int32 w) { this->boxImpl<Avg<0> >(r,w); }
 
  226        void boxZImpl(
const LeafRange& r, 
Int32 w) { this->boxImpl<Avg<1> >(r,w); }
 
  227        void boxYImpl(
const LeafRange& r, 
Int32 w) { this->boxImpl<Avg<2> >(r,w); }
 
  229        void medianImpl(
const LeafRange&, 
int);
 
  230        void meanCurvatureImpl(
const LeafRange&);
 
  231        void filletImpl(
const LeafRange&);
 
  232        void laplacianImpl(
const LeafRange&);
 
  233        void offsetImpl(
const LeafRange&, ValueType);
 
  235        LevelSetFilter* mParent;
 
  236        const MaskType* mMask;
 
  237        typename std::function<void (Filter*, 
const LeafRange&)> mTask;
 
  240    AlphaType mMinMask, mMaxMask;
 
 
  248template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  250LevelSetFilter<GridT, MaskT, InterruptT>::Filter::median(
int width)
 
  252    mParent->startInterrupter(
"Median-value flow of level set");
 
  254    mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
 
  256    mTask = std::bind(&Filter::medianImpl,
 
  257        std::placeholders::_1, std::placeholders::_2, std::max(1, width));
 
  262    mParent->endInterrupter();
 
  265template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  267LevelSetFilter<GridT, MaskT, InterruptT>::Filter::mean(
int width)
 
  269    mParent->startInterrupter(
"Mean-value flow of level set");
 
  273    mParent->endInterrupter();
 
  276template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  278LevelSetFilter<GridT, MaskT, InterruptT>::Filter::gaussian(
int width)
 
  280    mParent->startInterrupter(
"Gaussian flow of level set");
 
  282    for (
int n=0; n<4; ++n) this->box(width);
 
  284    mParent->endInterrupter();
 
  287template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  289LevelSetFilter<GridT, MaskT, InterruptT>::Filter::box(
int width)
 
  291    mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
 
  293    width = std::max(1, width);
 
  295    mTask = std::bind(&Filter::boxXImpl, std::placeholders::_1, std::placeholders::_2, width);
 
  298    mTask = std::bind(&Filter::boxYImpl, std::placeholders::_1, std::placeholders::_2, width);
 
  301    mTask = std::bind(&Filter::boxZImpl, std::placeholders::_1, std::placeholders::_2, width);
 
  307template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  309LevelSetFilter<GridT, MaskT, InterruptT>::Filter::meanCurvature()
 
  311    mParent->startInterrupter(
"Mean-curvature flow of level set");
 
  313    mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
 
  315    mTask = std::bind(&Filter::meanCurvatureImpl, std::placeholders::_1, std::placeholders::_2);
 
  320    mParent->endInterrupter();
 
  323template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  325LevelSetFilter<GridT, MaskT, InterruptT>::Filter::fillet()
 
  327    mParent->startInterrupter(
"Filleting level set");
 
  329    mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
 
  331    mTask = std::bind(&Filter::filletImpl, std::placeholders::_1, std::placeholders::_2);
 
  336    mParent->endInterrupter();
 
  339template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  341LevelSetFilter<GridT, MaskT, InterruptT>::Filter::laplacian()
 
  343    mParent->startInterrupter(
"Laplacian flow of level set");
 
  345    mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
 
  347    mTask = std::bind(&Filter::laplacianImpl, std::placeholders::_1, std::placeholders::_2);
 
  352    mParent->endInterrupter();
 
  355template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  357LevelSetFilter<GridT, MaskT, InterruptT>::Filter::offset(ValueType value)
 
  359    mParent->startInterrupter(
"Offsetting level set");
 
  361    mParent->leafs().removeAuxBuffers();
 
  363    const ValueType CFL = ValueType(0.5) * mParent->voxelSize(), offset = openvdb::math::Abs(value);
 
  364    ValueType dist = 0.0;
 
  365    while (offset-dist > ValueType(0.001)*CFL && mParent->checkInterrupter()) {
 
  366        const ValueType delta = openvdb::math::Min(offset-dist, CFL);
 
  369        mTask = std::bind(&Filter::offsetImpl,
 
  370            std::placeholders::_1, std::placeholders::_2, copysign(delta, value));
 
  376    mParent->endInterrupter();
 
  383template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  385LevelSetFilter<GridT, MaskT, InterruptT>::Filter::meanCurvatureImpl(
const LeafRange& range)
 
  387    mParent->checkInterrupter();
 
  389    const ValueType dx = mParent->voxelSize(), dt = math::Pow2(dx) / ValueType(3.0);
 
  390    math::CurvatureStencil<GridType> stencil(mParent->grid(), dx);
 
  392        typename AlphaMaskT::FloatType a, b;
 
  393        AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
 
  394                         mParent->maxMask(), mParent->isMaskInverted());
 
  395        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  396            ValueType* buffer = leafIter.buffer(1).data();
 
  397            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  398                if (alpha(iter.getCoord(), a, b)) {
 
  399                    stencil.moveTo(iter);
 
  400                    const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.meanCurvatureNormGrad();
 
  401                    buffer[iter.pos()] = b * phi0 + a * phi1;
 
  406        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  407            ValueType* buffer = leafIter.buffer(1).data();
 
  408            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  409                stencil.moveTo(iter);
 
  410                buffer[iter.pos()] = *iter + dt*stencil.meanCurvatureNormGrad();
 
  420template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  422LevelSetFilter<GridT, MaskT, InterruptT>::Filter::filletImpl(
const LeafRange& range)
 
  424    mParent->checkInterrupter();
 
  426    const ValueType dx = mParent->voxelSize(), dt = math::Pow2(dx) / ValueType(3);
 
  427    math::CurvatureStencil<GridType> stencil(mParent->grid(), dx);
 
  430        typename AlphaMaskT::FloatType a, b;
 
  431        AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
 
  432                         mParent->maxMask(), mParent->isMaskInverted());
 
  433        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  434            ValueType* buffer = leafIter.buffer(1).data();
 
  435            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  436                if (alpha(iter.getCoord(), a, b)) {
 
  437                    stencil.moveTo(iter);
 
  439                    const ValueType kappa = stencil.principalCurvatures().first;
 
  441                    const ValueType phi0 = *iter,
 
  442                                    phi1 = phi0 + math::Min(ValueType(0), dt*kappa);
 
  443                    buffer[iter.pos()] = b * phi0 + a * phi1;
 
  448        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  449            ValueType* buffer = leafIter.buffer(1).data();
 
  450            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  451                stencil.moveTo(iter);
 
  453                const ValueType kappa = stencil.principalCurvatures().first;
 
  455                if (math::isNegative(kappa))
 
  456                    buffer[iter.pos()] = *iter + dt*kappa;
 
  469template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  471LevelSetFilter<GridT, MaskT, InterruptT>::Filter::laplacianImpl(
const LeafRange& range)
 
  473    mParent->checkInterrupter();
 
  475    const ValueType dx = mParent->voxelSize(), dt = math::Pow2(dx) / ValueType(6.0);
 
  476    math::GradStencil<GridType> stencil(mParent->grid(), dx);
 
  478        typename AlphaMaskT::FloatType a, b;
 
  479        AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
 
  480                         mParent->maxMask(), mParent->isMaskInverted());
 
  481        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  482            ValueType* buffer = leafIter.buffer(1).data();
 
  483            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  484                if (alpha(iter.getCoord(), a, b)) {
 
  485                    stencil.moveTo(iter);
 
  486                    const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.laplacian();
 
  487                    buffer[iter.pos()] = b * phi0 + a * phi1;
 
  492        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  493            ValueType* buffer = leafIter.buffer(1).data();
 
  494            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  495                stencil.moveTo(iter);
 
  496                buffer[iter.pos()] = *iter + dt*stencil.laplacian();
 
  503template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  505LevelSetFilter<GridT, MaskT, InterruptT>::Filter::offsetImpl(
 
  506    const LeafRange& range, ValueType offset)
 
  508    mParent->checkInterrupter();
 
  510        typename AlphaMaskT::FloatType a, b;
 
  511        AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
 
  512                         mParent->maxMask(), mParent->isMaskInverted());
 
  513        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  514            for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
 
  515                if (alpha(iter.getCoord(), a, b)) iter.setValue(*iter + a*offset);
 
  519        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  520            for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
 
  521                iter.setValue(*iter + offset);
 
  528template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  530LevelSetFilter<GridT, MaskT, InterruptT>::Filter::medianImpl(
const LeafRange& range, 
int width)
 
  532    mParent->checkInterrupter();
 
  533    typename math::DenseStencil<GridType> stencil(mParent->grid(), width);
 
  535        typename AlphaMaskT::FloatType a, b;
 
  536        AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
 
  537                         mParent->maxMask(), mParent->isMaskInverted());
 
  538        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  539            ValueType* buffer = leafIter.buffer(1).data();
 
  540            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  541                if (alpha(iter.getCoord(), a, b)) {
 
  542                    stencil.moveTo(iter);
 
  543                    buffer[iter.pos()] = b * (*iter) + a * stencil.median();
 
  548        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  549            ValueType* buffer = leafIter.buffer(1).data();
 
  550            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  551                stencil.moveTo(iter);
 
  552                buffer[iter.pos()] = stencil.median();
 
  559template<
typename Gr
idT, 
typename MaskT, 
typename InterruptT>
 
  560template <
typename AvgT>
 
  562LevelSetFilter<GridT, MaskT, InterruptT>::Filter::boxImpl(
const LeafRange& range, Int32 w)
 
  564    mParent->checkInterrupter();
 
  565    AvgT avg(mParent->grid(), w);
 
  567        typename AlphaMaskT::FloatType a, b;
 
  568        AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
 
  569                         mParent->maxMask(), mParent->isMaskInverted());
 
  570        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  571            ValueType* buffer = leafIter.buffer(1).data();
 
  572            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  573                const Coord xyz = iter.getCoord();
 
  574                if (alpha(xyz, a, b)) buffer[iter.pos()] = b * (*iter)+ a * avg(xyz);
 
  578        for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
 
  579            ValueType* buffer = leafIter.buffer(1).data();
 
  580            for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
 
  581                buffer[iter.pos()] = avg(iter.getCoord());
 
  593#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
  595#ifdef OPENVDB_INSTANTIATE_LEVELSETFILTER 
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
Definition Exceptions.h:65
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Definition LeafManager.h:103
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition LeafManager.h:96
Definition PointDataGrid.h:170
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
int32_t Int32
Definition Types.h:56
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:158