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)");
153 using LeafT =
typename TreeType::LeafNodeType;
154 using VoxelIterT =
typename LeafT::ValueOnIter;
155 using VoxelCIterT =
typename LeafT::ValueOnCIter;
158 using LeafIterT =
typename LeafRange::Iterator;
174 if (mTask) mTask(const_cast<Filter*>(
this), r);
175 else OPENVDB_THROW(ValueError,
"task is undefined - don\'t call this method directly");
179 const int n = mParent->getGrainSize();
183 (*this)(mParent->leafs().leafRange());
185 if (swap) mParent->leafs().swapLeafBuffer(1, n==0);
188 template <
size_t Axis>
196 for (i -= width; i <=
j; ++i) sum +=
acc.getValue(xyz);
199 typename GridT::ConstAccessor
acc;
204 template<
typename AvgT>
205 void boxImpl(
const LeafRange& r,
Int32 w);
207 void boxXImpl(
const LeafRange& r,
Int32 w) { this->boxImpl<Avg<0> >(
r,
w); }
212 void meanCurvatureImpl(
const LeafRange&);
218 typename std::function<void (Filter*, const LeafRange&)> mTask;
229 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
233 mParent->startInterrupter(
"Median-value flow of level set");
235 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
237 mTask = std::bind(&Filter::medianImpl,
238 std::placeholders::_1, std::placeholders::_2,
std::max(1, width));
243 mParent->endInterrupter();
246 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
248 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::mean(
int width)
250 mParent->startInterrupter(
"Mean-value flow of level set");
254 mParent->endInterrupter();
257 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
259 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::gaussian(
int width)
261 mParent->startInterrupter(
"Gaussian flow of level set");
263 for (
int n=0; n<4; ++
n) this->box(width);
265 mParent->endInterrupter();
268 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
270 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::box(
int width)
272 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
276 mTask = std::bind(&Filter::boxXImpl, std::placeholders::_1, std::placeholders::_2, width);
279 mTask = std::bind(&Filter::boxYImpl, std::placeholders::_1, std::placeholders::_2, width);
282 mTask = std::bind(&Filter::boxZImpl, std::placeholders::_1, std::placeholders::_2, width);
288 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
292 mParent->startInterrupter(
"Mean-curvature flow of level set");
294 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
296 mTask = std::bind(&Filter::meanCurvatureImpl, std::placeholders::_1, std::placeholders::_2);
301 mParent->endInterrupter();
304 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
308 mParent->startInterrupter(
"Laplacian flow of level set");
310 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
312 mTask = std::bind(&Filter::laplacianImpl, std::placeholders::_1, std::placeholders::_2);
317 mParent->endInterrupter();
320 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
324 mParent->startInterrupter(
"Offsetting level set");
326 mParent->leafs().removeAuxBuffers();
330 while (
offset-dist >
ValueType(0.001)*CFL && mParent->checkInterrupter()) {
334 mTask = std::bind(&Filter::offsetImpl,
335 std::placeholders::_1, std::placeholders::_2,
copysign(delta, value));
341 mParent->endInterrupter();
348 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
350 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::meanCurvatureImpl(
const LeafRange&
range)
352 mParent->checkInterrupter();
355 math::CurvatureStencil<GridType>
stencil(mParent->grid(), dx);
358 AlphaMaskT
alpha(mParent->grid(), *
mMask, mParent->minMask(),
359 mParent->maxMask(), mParent->isMaskInverted());
360 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
362 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
363 if (
alpha(iter.getCoord(),
a,
b)) {
365 const ValueType phi0 = *iter, phi1 = phi0 + dt*
stencil.meanCurvatureNormGrad();
366 buffer[iter.pos()] = b * phi0 + a * phi1;
371 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
372 ValueType* buffer = leafIter.buffer(1).data();
373 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
375 buffer[iter.pos()] = *iter + dt*
stencil.meanCurvatureNormGrad();
388 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
390 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::laplacianImpl(
const LeafRange& range)
392 mParent->checkInterrupter();
395 math::GradStencil<GridType>
stencil(mParent->grid(), dx);
398 AlphaMaskT
alpha(mParent->grid(), *
mMask, mParent->minMask(),
399 mParent->maxMask(), mParent->isMaskInverted());
400 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
401 ValueType* buffer = leafIter.buffer(1).data();
402 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
403 if (
alpha(iter.getCoord(),
a,
b)) {
406 buffer[iter.pos()] = b * phi0 + a * phi1;
411 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
412 ValueType* buffer = leafIter.buffer(1).data();
413 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
415 buffer[iter.pos()] = *iter + dt*
stencil.laplacian();
422 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
424 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::offsetImpl(
427 mParent->checkInterrupter();
430 AlphaMaskT
alpha(mParent->grid(), *
mMask, mParent->minMask(),
431 mParent->maxMask(), mParent->isMaskInverted());
432 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
433 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
434 if (
alpha(iter.getCoord(),
a,
b)) iter.setValue(*iter + a*offset);
438 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
439 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
440 iter.setValue(*iter + offset);
447 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
449 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::medianImpl(
const LeafRange& range,
int width)
451 mParent->checkInterrupter();
452 typename math::DenseStencil<GridType>
stencil(mParent->grid(),
width);
455 AlphaMaskT
alpha(mParent->grid(), *
mMask, mParent->minMask(),
456 mParent->maxMask(), mParent->isMaskInverted());
457 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
458 ValueType* buffer = leafIter.buffer(1).data();
459 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
460 if (
alpha(iter.getCoord(),
a,
b)) {
462 buffer[iter.pos()] = b * (*iter) + a *
stencil.median();
467 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
468 ValueType* buffer = leafIter.buffer(1).data();
469 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
471 buffer[iter.pos()] =
stencil.median();
478 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
479 template <
typename AvgT>
481 LevelSetFilter<GridT, MaskT, InterruptT>::Filter::boxImpl(
const LeafRange& range, Int32
w)
483 mParent->checkInterrupter();
484 AvgT avg(mParent->grid(),
w);
487 AlphaMaskT
alpha(mParent->grid(), *
mMask, mParent->minMask(),
488 mParent->maxMask(), mParent->isMaskInverted());
489 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
490 ValueType* buffer = leafIter.buffer(1).data();
491 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
492 const Coord xyz = iter.getCoord();
493 if (
alpha(xyz, a, b)) buffer[iter.pos()] = b * (*iter)+ a * avg(xyz);
497 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
498 ValueType* buffer = leafIter.buffer(1).data();
499 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
500 buffer[iter.pos()] = avg(iter.getCoord());
512 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
514 #ifdef OPENVDB_INSTANTIATE_LEVELSETFILTER
521 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
528 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
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)
ImageBuf OIIO_API laplacian(const ImageBuf &src, ROI roi={}, int nthreads=0)
#define OPENVDB_INSTANTIATE_CLASS
SYS_API double copysign(double x, double y)
GLfloat GLfloat GLfloat alpha
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
GLboolean GLboolean GLboolean b
buffer(size_t sz) FMT_NOEXCEPT
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GLubyte GLubyte GLubyte GLubyte w
GLint GLfloat GLint stencil
void median(I first, I middle, I last, const Pred &pred)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
#define OPENVDB_THROW(exception, message)