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>
73 BOOST_STATIC_ASSERT(boost::is_floating_point<AlphaType>::value);
119 Filter f(
this, mask); f.meanCurvature();
126 Filter f(
this, mask); f.laplacian();
137 Filter f(
this, mask); f.gaussian(width);
145 Filter f(
this, mask); f.offset(offset);
156 Filter f(
this, mask); f.median(width);
166 Filter f(
this, mask); f.mean(width);
177 typedef typename TreeType::LeafNodeType LeafT;
178 typedef typename LeafT::ValueOnIter VoxelIterT;
179 typedef typename LeafT::ValueOnCIter VoxelCIterT;
182 typedef typename LeafRange::Iterator LeafIterT;
186 Filter(
const Filter&) =
default;
190 void median(
int width);
191 void mean(
int width);
192 void gaussian(
int width);
195 void offset(ValueType value);
196 void operator()(
const LeafRange& r)
const 198 if (mTask) mTask(const_cast<Filter*>(
this), r);
203 const int n = mParent->getGrainSize();
205 tbb::parallel_for(mParent->leafs().leafRange(n), *
this);
207 (*this)(mParent->leafs().leafRange());
209 if (swap) mParent->leafs().swapLeafBuffer(1, n==0);
212 template <
size_t Axis>
215 acc(grid.tree()), width(w), frac(1/
ValueType(2*w+1)) {}
220 for (
i -= width;
i <= j; ++
i) sum += acc.getValue(xyz);
223 typename GridT::ConstAccessor
acc;
228 template <
typename AvgT>
231 void boxX(
const LeafRange& r,
Int32 w) { this->box<Avg<0> >(r,w); }
232 void boxZ(
const LeafRange& r,
Int32 w) { this->box<Avg<1> >(r,w); }
233 void boxY(
const LeafRange& r,
Int32 w) { this->box<Avg<2> >(r,w); }
235 void median(
const LeafRange&,
int);
238 void offset(
const LeafRange&, ValueType);
240 LevelSetFilter* mParent;
241 const MaskType* mMask;
242 typename boost::function<void (Filter*, const LeafRange&)> mTask;
245 AlphaType mMinMask, mMaxMask;
253 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
255 LevelSetFilter<GridT, MaskT, InterruptT>::
256 Filter::median(
int width)
258 mParent->startInterrupter(
"Median-value flow of level set");
260 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
262 mTask = boost::bind(&Filter::median, _1, _2,
std::max(1, width));
267 mParent->endInterrupter();
270 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
272 LevelSetFilter<GridT, MaskT, InterruptT>::
273 Filter::mean(
int width)
275 mParent->startInterrupter(
"Mean-value flow of level set");
279 mParent->endInterrupter();
282 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
284 LevelSetFilter<GridT, MaskT, InterruptT>::
285 Filter::gaussian(
int width)
287 mParent->startInterrupter(
"Gaussian flow of level set");
289 for (
int n=0; n<4; ++n) this->box(width);
291 mParent->endInterrupter();
294 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
296 LevelSetFilter<GridT, MaskT, InterruptT>::
297 Filter::box(
int width)
299 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
303 mTask = boost::bind(&Filter::boxX, _1, _2, width);
306 mTask = boost::bind(&Filter::boxY, _1, _2, width);
309 mTask = boost::bind(&Filter::boxZ, _1, _2, width);
315 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
320 mParent->startInterrupter(
"Mean-curvature flow of level set");
322 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
329 mParent->endInterrupter();
332 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
337 mParent->startInterrupter(
"Laplacian flow of level set");
339 mParent->leafs().rebuildAuxBuffers(1, mParent->getGrainSize()==0);
346 mParent->endInterrupter();
349 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
351 LevelSetFilter<GridT, MaskT, InterruptT>::
352 Filter::offset(ValueType value)
354 mParent->startInterrupter(
"Offsetting level set");
356 mParent->leafs().removeAuxBuffers();
358 const ValueType CFL = ValueType(0.5) * mParent->voxelSize(), offset =
openvdb::math::Abs(value);
359 ValueType dist = 0.0;
360 while (offset-dist > ValueType(0.001)*CFL && mParent->checkInterrupter()) {
364 mTask = boost::bind(&Filter::offset, _1, _2, copysign(delta, value));
370 mParent->endInterrupter();
377 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
382 mParent->checkInterrupter();
384 const ValueType dx = mParent->voxelSize(), dt =
math::Pow2(dx) / ValueType(3.0);
385 math::CurvatureStencil<GridType> stencil(mParent->grid(), dx);
387 typename AlphaMaskT::FloatType a, b;
388 AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
389 mParent->maxMask(), mParent->isMaskInverted());
390 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
391 ValueType* buffer = leafIter.buffer(1).data();
392 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
393 if (alpha(iter.getCoord(), a, b)) {
394 stencil.moveTo(iter);
395 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.meanCurvatureNormGrad();
396 buffer[iter.pos()] = b * phi0 + a * phi1;
401 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
402 ValueType* buffer = leafIter.buffer(1).data();
403 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
404 stencil.moveTo(iter);
405 buffer[iter.pos()] = *iter + dt*stencil.meanCurvatureNormGrad();
418 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
423 mParent->checkInterrupter();
425 const ValueType dx = mParent->voxelSize(), dt =
math::Pow2(dx) / ValueType(6.0);
426 math::GradStencil<GridType> stencil(mParent->grid(), dx);
428 typename AlphaMaskT::FloatType a, b;
429 AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
430 mParent->maxMask(), mParent->isMaskInverted());
431 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
432 ValueType* buffer = leafIter.buffer(1).data();
433 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
434 if (alpha(iter.getCoord(), a, b)) {
435 stencil.moveTo(iter);
436 const ValueType phi0 = *iter, phi1 = phi0 + dt*stencil.laplacian();
437 buffer[iter.pos()] = b * phi0 + a * phi1;
442 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
443 ValueType* buffer = leafIter.buffer(1).data();
444 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
445 stencil.moveTo(iter);
446 buffer[iter.pos()] = *iter + dt*stencil.laplacian();
453 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
455 LevelSetFilter<GridT, MaskT, InterruptT>::
456 Filter::offset(
const LeafRange& range, ValueType offset)
458 mParent->checkInterrupter();
460 typename AlphaMaskT::FloatType a, b;
461 AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
462 mParent->maxMask(), mParent->isMaskInverted());
463 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
464 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
465 if (alpha(iter.getCoord(), a, b)) iter.setValue(*iter + a*offset);
469 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
470 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
471 iter.setValue(*iter + offset);
478 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
480 LevelSetFilter<GridT, MaskT, InterruptT>::
481 Filter::median(
const LeafRange& range,
int width)
483 mParent->checkInterrupter();
484 typename math::DenseStencil<GridType> stencil(mParent->grid(), width);
486 typename AlphaMaskT::FloatType a, b;
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 if (alpha(iter.getCoord(), a, b)) {
493 stencil.moveTo(iter);
494 buffer[iter.pos()] = b * (*iter) + a * stencil.median();
499 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
500 ValueType* buffer = leafIter.buffer(1).data();
501 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
502 stencil.moveTo(iter);
503 buffer[iter.pos()] = stencil.median();
510 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
511 template <
typename AvgT>
513 LevelSetFilter<GridT, MaskT, InterruptT>::
514 Filter::box(
const LeafRange& range,
Int32 w)
516 mParent->checkInterrupter();
517 AvgT avg(mParent->grid(), w);
519 typename AlphaMaskT::FloatType a, b;
520 AlphaMaskT alpha(mParent->grid(), *mMask, mParent->minMask(),
521 mParent->maxMask(), mParent->isMaskInverted());
522 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
523 ValueType* buffer = leafIter.buffer(1).data();
524 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
525 const Coord xyz = iter.getCoord();
526 if (alpha(xyz, a, b)) buffer[iter.pos()] = b * (*iter)+ a * avg(xyz);
530 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
531 ValueType* buffer = leafIter.buffer(1).data();
532 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
533 buffer[iter.pos()] = avg(iter.getCoord());
543 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:606
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
tbb::atomic< Index32 > i
Definition: LeafBuffer.h:71
Definition: LeafManager.h:127
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Coord Abs(const Coord &xyz)
Definition: Coord.h:509
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:121
Definition: Exceptions.h:39
Definition: Exceptions.h:92
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:48
Type Pow2(Type x)
Return .
Definition: Math.h:498
int32_t Int32
Definition: Types.h:59
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Axis
Definition: Math.h:852