11 #ifndef OPENVDB_TOOLS_LEVEL_SET_MORPH_HAS_BEEN_INCLUDED 12 #define OPENVDB_TOOLS_LEVEL_SET_MORPH_HAS_BEEN_INCLUDED 45 template<
typename GridT,
46 typename InterruptT = util::NullInterrupter>
59 LevelSetMorphing(GridT& sourceGrid,
const GridT& targetGrid, InterruptT* interrupt =
nullptr)
60 : mTracker(sourceGrid, interrupt)
61 , mTarget(&targetGrid)
64 , mTemporalScheme(math::
TVD_RK2)
74 void setTarget(
const GridT& targetGrid) { mTarget = &targetGrid; }
92 return mTracker.getSpatialScheme();
97 mTracker.setSpatialScheme(scheme);
102 return mTracker.getTemporalScheme();
107 mTracker.setTemporalScheme(scheme);
139 mDeltaMask = max-
min;
161 template<math::BiasedGradientScheme SpatialScheme>
174 const GridT *mTarget, *mMask;
188 Morph(
const Morph& other);
190 Morph(Morph& other, tbb::split);
197 void operator()(
const LeafRange& r)
const 199 if (mTask) mTask(const_cast<Morph*>(
this), r);
205 if (mTask) mTask(
this, r);
209 void join(
const Morph& other) { mMaxAbsS =
math::Max(mMaxAbsS, other.mMaxAbsS); }
212 enum ThreadingMode { PARALLEL_FOR, PARALLEL_REDUCE };
214 void cook(ThreadingMode mode,
size_t swapBuffer = 0);
223 template <
int Nominator,
int Denominator>
226 inline void euler12(
const LeafRange& r,
ValueType t) {this->euler<1,2>(r, t, 1, 1, 2);}
227 inline void euler34(
const LeafRange& r,
ValueType t) {this->euler<3,4>(r, t, 1, 2, 3);}
228 inline void euler13(
const LeafRange& r,
ValueType t) {this->euler<1,3>(r, t, 1, 2, 3);}
230 using FuncType =
typename std::function<void (Morph*, const LeafRange&)>;
239 template<
typename Gr
idT,
typename InterruptT>
243 switch (mSpatialScheme) {
245 return this->advect1<math::FIRST_BIAS >(time0, time1);
253 return this->advect1<math::HJWENO5_BIAS>(time0, time1);
264 template<
typename Gr
idT,
typename InterruptT>
265 template<math::BiasedGradientScheme SpatialScheme>
269 switch (mTemporalScheme) {
271 return this->advect2<SpatialScheme, math::TVD_RK1>(time0, time1);
273 return this->advect2<SpatialScheme, math::TVD_RK2>(time0, time1);
275 return this->advect2<SpatialScheme, math::TVD_RK3>(time0, time1);
283 template<
typename Gr
idT,
typename InterruptT>
290 if (trans.
mapType() == math::UniformScaleMap::mapType()) {
291 return this->advect3<SpatialScheme, TemporalScheme, math::UniformScaleMap>(time0, time1);
292 }
else if (trans.
mapType() == math::UniformScaleTranslateMap::mapType()) {
293 return this->advect3<SpatialScheme, TemporalScheme, math::UniformScaleTranslateMap>(
295 }
else if (trans.
mapType() == math::UnitaryMap::mapType()) {
296 return this->advect3<SpatialScheme, TemporalScheme, math::UnitaryMap >(time0, time1);
297 }
else if (trans.
mapType() == math::TranslationMap::mapType()) {
298 return this->advect3<SpatialScheme, TemporalScheme, math::TranslationMap>(time0, time1);
305 template<
typename Gr
idT,
typename InterruptT>
312 Morph<MapT, SpatialScheme, TemporalScheme> tmp(*
this);
313 return tmp.advect(time0, time1);
319 template<
typename Gr
idT,
typename InterruptT>
328 , mMap(parent.mTracker.grid().transform().template constMap<MapT>().
get())
333 template<
typename Gr
idT,
typename InterruptT>
339 Morph(
const Morph& other)
340 : mParent(other.mParent)
341 , mMinAbsS(other.mMinAbsS)
342 , mMaxAbsS(other.mMaxAbsS)
348 template<
typename Gr
idT,
typename InterruptT>
354 Morph(Morph& other, tbb::split)
355 : mParent(other.mParent)
356 , mMinAbsS(other.mMinAbsS)
357 , mMaxAbsS(other.mMaxAbsS)
363 template<
typename Gr
idT,
typename InterruptT>
371 namespace ph = std::placeholders;
377 while (time0 < time1 && mParent->mTracker.checkInterrupter()) {
378 mParent->mTracker.
leafs().rebuildAuxBuffers(auxBuffers);
380 const ValueType dt = this->sampleSpeed(time0, time1, auxBuffers);
384 switch(TemporalScheme) {
388 mTask = std::bind(&Morph::euler01, ph::_1, ph::_2, dt, 2);
391 this->cook(PARALLEL_FOR, 1);
396 mTask = std::bind(&Morph::euler01, ph::_1, ph::_2, dt, 2);
399 this->cook(PARALLEL_FOR, 1);
403 mTask = std::bind(&Morph::euler12, ph::_1, ph::_2, dt);
406 this->cook(PARALLEL_FOR, 1);
411 mTask = std::bind(&Morph::euler01, ph::_1, ph::_2, dt, 3);
414 this->cook(PARALLEL_FOR, 1);
418 mTask = std::bind(&Morph::euler34, ph::_1, ph::_2, dt);
421 this->cook(PARALLEL_FOR, 2);
425 mTask = std::bind(&Morph::euler13, ph::_1, ph::_2, dt);
428 this->cook(PARALLEL_FOR, 2);
438 mParent->mTracker.leafs().removeAuxBuffers();
441 mParent->mTracker.track();
447 template<
typename Gr
idT,
typename InterruptT>
450 inline typename GridT::ValueType
455 namespace ph = std::placeholders;
458 const size_t leafCount = mParent->mTracker.
leafs().leafCount();
459 if (leafCount==0 || time0 >= time1)
return ValueType(0);
462 if (mParent->mTarget->transform() == xform &&
463 (mParent->mMask ==
nullptr || mParent->mMask->transform() == xform)) {
464 mTask = std::bind(&Morph::sampleAlignedSpeed, ph::_1, ph::_2, speedBuffer);
466 mTask = std::bind(&Morph::sampleXformedSpeed, ph::_1, ph::_2, speedBuffer);
468 this->cook(PARALLEL_REDUCE);
473 const ValueType dt =
math::Abs(time1 - time0), dx = mParent->mTracker.voxelSize();
474 return math::Min(dt, ValueType(CFL*dx/mMaxAbsS));
477 template<
typename Gr
idT,
typename InterruptT>
485 using VoxelIterT =
typename LeafType::ValueOnCIter;
488 const MapT& map = *mMap;
489 mParent->mTracker.checkInterrupter();
491 typename GridT::ConstAccessor targetAcc = mParent->mTarget->getAccessor();
492 SamplerT target(targetAcc, mParent->mTarget->transform());
493 if (mParent->mMask ==
nullptr) {
494 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
495 ValueType* speed = leafIter.buffer(speedBuffer).data();
497 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
499 s -= target.wsSample(map.applyMap(voxelIter.getCoord().asVec3d()));
506 const ValueType min = mParent->mMinMask, invNorm = 1.0f/(mParent->mDeltaMask);
507 const bool invMask = mParent->isMaskInverted();
508 typename GridT::ConstAccessor maskAcc = mParent->mMask->getAccessor();
509 SamplerT mask(maskAcc, mParent->mMask->transform());
510 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
511 ValueType* speed = leafIter.buffer(speedBuffer).data();
513 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
514 const Vec3R xyz = map.applyMap(voxelIter.getCoord().asVec3d());
517 s -= target.wsSample(xyz);
518 s *= invMask ? 1 - a : a;
527 template<
typename Gr
idT,
typename InterruptT>
535 using VoxelIterT =
typename LeafType::ValueOnCIter;
539 typename GridT::ConstAccessor target = mParent->mTarget->getAccessor();
541 if (mParent->mMask ==
nullptr) {
542 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
543 ValueType* speed = leafIter.buffer(speedBuffer).data();
545 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
547 s -= target.getValue(voxelIter.getCoord());
554 const ValueType min = mParent->mMinMask, invNorm = 1.0f/(mParent->mDeltaMask);
555 const bool invMask = mParent->isMaskInverted();
556 typename GridT::ConstAccessor mask = mParent->mMask->getAccessor();
557 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
558 ValueType* speed = leafIter.buffer(speedBuffer).data();
560 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
561 const Coord ijk = voxelIter.getCoord();
564 s -= target.getValue(ijk);
565 s *= invMask ? 1 - a : a;
574 template<
typename Gr
idT,
typename InterruptT>
580 cook(ThreadingMode mode,
size_t swapBuffer)
584 const int grainSize = mParent->mTracker.getGrainSize();
585 const LeafRange range = mParent->mTracker.leafs().leafRange(grainSize);
587 if (mParent->mTracker.getGrainSize()==0) {
589 }
else if (mode == PARALLEL_FOR) {
590 tbb::parallel_for(range, *
this);
591 }
else if (mode == PARALLEL_REDUCE) {
592 tbb::parallel_reduce(range, *
this);
595 <<
" or " <<
int(PARALLEL_REDUCE) <<
", got " <<
int(mode));
598 mParent->mTracker.leafs().swapLeafBuffer(swapBuffer, grainSize == 0);
600 mParent->mTracker.endInterrupter();
603 template<
typename Gr
idT,
typename InterruptT>
606 template <
int Nominator,
int Denominator>
614 using StencilT =
typename SchemeT::template ISStencil<GridType>::StencilType;
615 using VoxelIterT =
typename LeafType::ValueOnCIter;
621 mParent->mTracker.checkInterrupter();
622 const MapT& map = *mMap;
623 StencilT stencil(mParent->mTracker.grid());
625 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
626 const ValueType* speed = leafIter.buffer(speedBuffer).data();
628 const ValueType* phi = leafIter.buffer(phiBuffer).data();
629 ValueType* result = leafIter.buffer(resultBuffer).data();
630 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
631 const Index n = voxelIter.pos();
633 stencil.moveTo(voxelIter);
634 const ValueType v = stencil.getValue() - dt * speed[n] * NumGrad::result(map, stencil);
635 result[n] = Nominator ? Alpha * phi[n] + Beta * v : v;
646 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 648 #ifdef OPENVDB_INSTANTIATE_LEVELSETMORPH 655 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 662 #endif // OPENVDB_TOOLS_LEVEL_SET_MORPH_HAS_BEEN_INCLUDED
Type SmoothUnitStep(Type x)
Return 0 if x < 0, 1 if x > 1 or else (3 − 2 x) x².
Definition: Math.h:286
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
Definition: FiniteDifference.h:170
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Definition: FiniteDifference.h:171
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:350
Definition: FiniteDifference.h:167
TemporalIntegrationScheme
Temporal integration schemes.
Definition: FiniteDifference.h:234
Definition: Exceptions.h:65
Definition: Operators.h:857
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:764
Definition: FiniteDifference.h:236
Definition: Exceptions.h:13
Definition: Operators.h:129
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:598
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:659
Definition: FiniteDifference.h:238
Index32 Index
Definition: Types.h:54
#define OPENVDB_INSTANTIATE_CLASS
Definition: version.h.in:143
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:407
Definition: FiniteDifference.h:237
Definition: FiniteDifference.h:168
Coord Abs(const Coord &xyz)
Definition: Coord.h:514
Definition: FiniteDifference.h:169
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:338
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:165
Definition: FiniteDifference.h:235
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202
Definition: FiniteDifference.h:166