15 #ifndef OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
16 #define OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
22 #include <type_traits>
36 template<
typename GridT,
38 typename InterruptT = util::NullInterrupter>
49 "LevelSetFilter requires a mask grid with floating-point values");
79 if (!(min < max))
OPENVDB_THROW(ValueError,
"Invalid mask range (expects min < max)");
170 using LeafT =
typename TreeType::LeafNodeType;
171 using VoxelIterT =
typename LeafT::ValueOnIter;
172 using VoxelCIterT =
typename LeafT::ValueOnCIter;
175 using LeafIterT =
typename LeafRange::Iterator;
192 if (mTask) mTask(const_cast<Filter*>(
this), r);
193 else OPENVDB_THROW(ValueError,
"task is undefined - don\'t call this method directly");
197 const int n = mParent->getGrainSize();
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); }
230 void meanCurvatureImpl(
const LeafRange&);
237 typename std::function<void (Filter*, const LeafRange&)> mTask;
248 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
250 LevelSetFilter<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();
265 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
267 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::mean(
int width)
269 mParent->startInterrupter(
"Mean-value flow of level set");
273 mParent->endInterrupter();
276 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
278 LevelSetFilter<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();
287 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
289 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::box(
int width)
291 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
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);
307 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
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();
323 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
325 LevelSetFilter<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();
339 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
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();
355 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
359 mParent->startInterrupter(
"Offsetting level set");
361 mParent->leafs().removeAuxBuffers();
365 while (
offset-dist >
ValueType(0.001)*CFL && mParent->checkInterrupter()) {
369 mTask = std::bind(&Filter::offsetImpl,
370 std::placeholders::_1, std::placeholders::_2,
copysign(delta, value));
376 mParent->endInterrupter();
383 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
385 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::meanCurvatureImpl(
const LeafRange&
range)
387 mParent->checkInterrupter();
390 math::CurvatureStencil<GridType>
stencil(mParent->grid(), dx);
393 AlphaMaskT
alpha(mParent->grid(), *
mMask, mParent->minMask(),
394 mParent->maxMask(), mParent->isMaskInverted());
395 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
397 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
398 if (
alpha(iter.getCoord(),
a,
b)) {
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) {
410 buffer[iter.pos()] = *iter + dt*
stencil.meanCurvatureNormGrad();
420 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
422 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::filletImpl(
const LeafRange& range)
424 mParent->checkInterrupter();
427 math::CurvatureStencil<GridType>
stencil(mParent->grid(), dx);
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)) {
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) {
456 buffer[iter.pos()] = *iter + dt*kappa;
469 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
471 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::laplacianImpl(
const LeafRange& range)
473 mParent->checkInterrupter();
476 math::GradStencil<GridType>
stencil(mParent->grid(), dx);
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)) {
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) {
496 buffer[iter.pos()] = *iter + dt*
stencil.laplacian();
503 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
505 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::offsetImpl(
508 mParent->checkInterrupter();
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);
528 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
530 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::medianImpl(
const LeafRange& range,
int width)
532 mParent->checkInterrupter();
533 typename math::DenseStencil<GridType>
stencil(mParent->grid(), width);
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)) {
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) {
552 buffer[iter.pos()] =
stencil.median();
559 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
560 template <
typename AvgT>
562 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::boxImpl(
const LeafRange& range, Int32
w)
564 mParent->checkInterrupter();
565 AvgT avg(mParent->grid(),
w);
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
602 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
609 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
GA_API const UT_StringHolder dist
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Type Pow2(Type x)
Return x2.
GLsizei const GLfloat * value
GLboolean GLboolean GLboolean GLboolean a
void swap(T &lhs, T &rhs)
#define OPENVDB_USE_VERSION_NAMESPACE
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
bool isNegative(const Type &x)
Return true if x is less than zero.
ImageBuf OIIO_API laplacian(const ImageBuf &src, ROI roi={}, int nthreads=0)
#define OPENVDB_INSTANTIATE_CLASS
SYS_API double copysign(double x, double y)
OIIO_UTIL_API void parallel_for(int32_t begin, int32_t end, function_view< void(int32_t)> task, paropt opt=0)
GLfloat GLfloat GLfloat alpha
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
GLboolean GLboolean GLboolean b
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
GLubyte GLubyte GLubyte GLubyte w
GLint GLfloat GLint stencil
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
#define OPENVDB_THROW(exception, message)