39 #ifndef OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED 40 #define OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED 42 #include <tbb/parallel_for.h> 43 #include <openvdb/Types.h> 44 #include <openvdb/math/Math.h> 45 #include <openvdb/math/FiniteDifference.h> 46 #include <openvdb/math/Operators.h> 47 #include <openvdb/math/Stencils.h> 48 #include <openvdb/math/Transform.h> 49 #include <openvdb/Grid.h> 50 #include <openvdb/util/NullInterrupter.h> 51 #include <openvdb/tree/ValueAccessor.h> 52 #include <openvdb/tree/LeafManager.h> 57 #include <type_traits> 81 template<
typename Gr
idT,
typename InterruptT = util::NullInterrupter>
89 using LeafType =
typename TreeType::LeafNodeType;
92 using LeafRange =
typename LeafManagerType::LeafRange;
94 using MaskTreeType =
typename TreeType::template ValueConverter<ValueMask>::Type;
95 static_assert(std::is_floating_point<ValueType>::value,
96 "LevelSetTracker requires a level set grid with floating-point values");
103 : spatialScheme(s), temporalScheme(t), normCount(n), grainSize(g) {}
118 template <
typename MaskType>
122 void normalize() { this->normalize<MaskTreeType>(
nullptr); }
149 void dilate(
int iterations = 1);
153 void erode(
int iterations = 1);
205 void startInterrupter(
const char* msg);
207 void endInterrupter();
210 bool checkInterrupter();
225 template<TrimMode Trimming>
230 void operator()(
const LeafRange& r)
const;
241 using StencilT =
typename SchemeT::template ISStencil<GridType>::StencilType;
242 using MaskLeafT =
typename MaskT::LeafNodeType;
243 using MaskIterT =
typename MaskLeafT::ValueOnCIter;
244 using VoxelIterT =
typename LeafType::ValueOnCIter;
248 void operator()(
const LeafRange& r)
const {mTask(const_cast<Normalizer*>(
this), r);}
249 void cook(
const char* msg,
int swapBuffer=0);
250 template <
int Nominator,
int Denominator>
252 inline void euler01(
const LeafRange& r) {this->euler<0,1>(r, 0, 1);}
253 inline void euler12(
const LeafRange& r) {this->euler<1,2>(r, 1, 1);}
254 inline void euler34(
const LeafRange& r) {this->euler<3,4>(r, 1, 2);}
255 inline void euler13(
const LeafRange& r) {this->euler<1,3>(r, 1, 2);}
256 template <
int Nominator,
int Denominator>
261 typename std::function<void (Normalizer*, const LeafRange&)> mTask;
264 template<math::BiasedGradientScheme SpatialScheme,
typename MaskT>
265 void normalize1(
const MaskT* mask);
269 void normalize2(
const MaskT* mask);
277 InterruptT* mInterrupter;
280 TrimMode mTrimMode = TrimMode::kAll;
283 template<
typename Gr
idT,
typename InterruptT>
288 mInterrupter(interrupt),
289 mDx(static_cast<
ValueType>(grid.voxelSize()[0])),
292 if ( !grid.hasUniformVoxels() ) {
294 "The transform must have uniform scale for the LevelSetTracker to function");
298 "LevelSetTracker expected a level set, got a grid of class \"" 299 + grid.gridClassToString(grid.getGridClass())
300 +
"\" [hint: Grid::setGridClass(openvdb::GRID_LEVEL_SET)]");
304 template<
typename Gr
idT,
typename InterruptT>
313 case TrimMode::kNone:
break;
314 case TrimMode::kInterior: Trim<TrimMode::kInterior>(*this).trim();
break;
315 case TrimMode::kExterior: Trim<TrimMode::kExterior>(*this).trim();
break;
316 case TrimMode::kAll: Trim<TrimMode::kAll>(*this).trim();
break;
323 mLeafs->rebuildLeafArray();
327 template<
typename Gr
idT,
typename InterruptT>
342 template<
typename Gr
idT,
typename InterruptT>
348 for (
int i=0; i < iterations; ++i) {
353 for (
int i=0; i < iterations; ++i) {
358 mask.topologyDifference(mask0);
364 template<
typename Gr
idT,
typename InterruptT>
370 mLeafs->rebuildLeafArray();
371 const ValueType background = mGrid->background() - iterations*mDx;
375 template<
typename Gr
idT,
typename InterruptT>
381 const int wNew =
static_cast<int>(halfWidth);
383 this->
dilate(wNew - wOld);
384 }
else if (wOld > wNew) {
385 this->
erode(wOld - wNew);
390 template<
typename Gr
idT,
typename InterruptT>
395 if (mInterrupter) mInterrupter->start(msg);
398 template<
typename Gr
idT,
typename InterruptT>
403 if (mInterrupter) mInterrupter->end();
406 template<
typename Gr
idT,
typename InterruptT>
412 tbb::task::self().cancel_group_execution();
418 template<
typename Gr
idT,
typename InterruptT>
419 template<
typename MaskT>
426 this->normalize1<math::FIRST_BIAS , MaskT>(mask);
break;
428 this->normalize1<math::SECOND_BIAS, MaskT>(mask);
break;
430 this->normalize1<math::THIRD_BIAS, MaskT>(mask);
break;
432 this->normalize1<math::WENO5_BIAS, MaskT>(mask);
break;
434 this->normalize1<math::HJWENO5_BIAS, MaskT>(mask);
break;
441 template<
typename Gr
idT,
typename InterruptT>
442 template<math::BiasedGradientScheme SpatialScheme,
typename MaskT>
449 this->normalize2<SpatialScheme, math::TVD_RK1, MaskT>(mask);
break;
451 this->normalize2<SpatialScheme, math::TVD_RK2, MaskT>(mask);
break;
453 this->normalize2<SpatialScheme, math::TVD_RK3, MaskT>(mask);
break;
460 template<
typename Gr
idT,
typename InterruptT>
468 Normalizer<SpatialScheme, TemporalScheme, MaskT> tmp(*
this, mask);
476 template<
typename Gr
idT,
typename InterruptT>
477 template<lstrack::TrimMode Trimming>
482 if (Trimming != TrimMode::kNone) {
483 const int grainSize = mTracker.getGrainSize();
484 const LeafRange range = mTracker.leafs().leafRange(grainSize);
487 tbb::parallel_for(range, *
this);
497 template<
typename Gr
idT,
typename InterruptT>
498 template<lstrack::TrimMode Trimming>
503 const ValueType gamma = mTracker.mGrid->background();
506 for (
auto leafIter = range.begin(); leafIter; ++leafIter) {
507 auto& leaf = *leafIter;
508 for (
auto iter = leaf.beginValueOn(); iter; ++iter) {
509 const auto val = *iter;
511 case TrimMode::kNone:
513 case TrimMode::kInterior:
514 if (val <= -gamma) { leaf.setValueOff(iter.pos(), -gamma); }
516 case TrimMode::kExterior:
517 if (val >= gamma) { leaf.setValueOff(iter.pos(), gamma); }
521 leaf.setValueOff(iter.pos(), -gamma);
522 }
else if (val >= gamma) {
523 leaf.setValueOff(iter.pos(), gamma);
535 template<
typename Gr
idT,
typename InterruptT>
552 template<
typename Gr
idT,
typename InterruptT>
561 namespace ph = std::placeholders;
564 mTracker.mLeafs->rebuildAuxBuffers(TemporalScheme ==
math::TVD_RK3 ? 2 : 1);
566 for (
int n=0, e=mTracker.getNormCount(); n < e; ++n) {
569 switch(TemporalScheme) {
573 mTask = std::bind(&Normalizer::euler01, ph::_1, ph::_2);
576 this->cook(
"Normalizing level set using TVD_RK1", 1);
581 mTask = std::bind(&Normalizer::euler01, ph::_1, ph::_2);
584 this->cook(
"Normalizing level set using TVD_RK1 (step 1 of 2)", 1);
588 mTask = std::bind(&Normalizer::euler12, ph::_1, ph::_2);
591 this->cook(
"Normalizing level set using TVD_RK1 (step 2 of 2)", 1);
596 mTask = std::bind(&Normalizer::euler01, ph::_1, ph::_2);
599 this->cook(
"Normalizing level set using TVD_RK3 (step 1 of 3)", 1);
603 mTask = std::bind(&Normalizer::euler34, ph::_1, ph::_2);
606 this->cook(
"Normalizing level set using TVD_RK3 (step 2 of 3)", 2);
610 mTask = std::bind(&Normalizer::euler13, ph::_1, ph::_2);
613 this->cook(
"Normalizing level set using TVD_RK3 (step 3 of 3)", 2);
621 mTracker.mLeafs->removeAuxBuffers();
626 template<
typename Gr
idT,
typename InterruptT>
633 cook(
const char* msg,
int swapBuffer)
637 const int grainSize = mTracker.getGrainSize();
638 const LeafRange range = mTracker.leafs().leafRange(grainSize);
640 grainSize>0 ? tbb::parallel_for(range, *
this) : (*this)(range);
642 mTracker.leafs().swapLeafBuffer(swapBuffer, grainSize==0);
644 mTracker.endInterrupter();
647 template<
typename Gr
idT,
typename InterruptT>
651 template <
int Nominator,
int Denominator>
661 const ValueType normSqGradPhi = GradientT::result(stencil);
662 const ValueType phi0 = stencil.getValue();
665 v = phi0 - mDt * v * (
math::Sqrt(normSqGradPhi) * mInvDx - 1.0f);
666 result[n] = Nominator ? alpha * phi[n] + beta * v : v;
669 template<
typename Gr
idT,
typename InterruptT>
673 template <
int Nominator,
int Denominator>
679 using VoxelIterT =
typename LeafType::ValueOnCIter;
683 StencilT stencil(mTracker.grid());
685 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
686 const ValueType* phi = leafIter.buffer(phiBuffer).data();
687 ValueType* result = leafIter.buffer(resultBuffer).data();
688 if (mMask ==
nullptr) {
689 for (VoxelIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
690 stencil.moveTo(iter);
691 this->eval<Nominator, Denominator>(stencil, phi, result, iter.pos());
693 }
else if (
const MaskLeafT* mask = mMask->probeLeaf(leafIter->origin())) {
694 const ValueType* phi0 = leafIter->buffer().data();
695 for (MaskIterT iter = mask->cbeginValueOn(); iter; ++iter) {
696 const Index i = iter.pos();
697 stencil.moveTo(iter.getCoord(), phi0[i]);
698 this->eval<Nominator, Denominator>(stencil, phi, result, i);
708 #endif // OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
Definition: FiniteDifference.h:197
Efficient multi-threaded replacement of the background values in tree.
Definition: FiniteDifference.h:265
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
Definition: FiniteDifference.h:195
TemporalIntegrationScheme
Temporal integration schemes.
Definition: FiniteDifference.h:261
Definition: FiniteDifference.h:198
Definition: FiniteDifference.h:262
Definition: FiniteDifference.h:193
static T value()
Definition: Math.h:117
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:283
Defined various multi-threaded utility functions for trees.
float RoundDown(float x)
Return x rounded down to the nearest integer.
Definition: Math.h:757
Definition: Operators.h:153
Definition: Operators.h:254
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
Definition: Exceptions.h:92
Implementation of morphological dilation and erosion.
Definition: Exceptions.h:40
Definition: FiniteDifference.h:194
Definition: Exceptions.h:90
Definition: FiniteDifference.h:263
Index32 Index
Definition: Types.h:61
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:715
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:192
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
Definition: FiniteDifference.h:196
Type Pow2(Type x)
Return x2.
Definition: Math.h:502
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
Definition: FiniteDifference.h:264
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:518