OpenVDB: LevelSetTracker.h Source File

OpenVDB 5.2.0

LevelSetTracker.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30
38
39 #ifndef OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED
40 #define OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED
41
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>
53 #include "ChangeBackground.h"// for changeLevelSetBackground
54 #include "Morphology.h"//for dilateActiveValues
55 #include "Prune.h"// for pruneLevelSet
56 #include <functional>
57 #include <type_traits>
58
59
60 namespace openvdb {
61 OPENVDB_USE_VERSION_NAMESPACE
62 namespace OPENVDB_VERSION_NAME {
63 namespace tools {
64
65 namespace lstrack {
66
70 enum class TrimMode {
71 kNone,
72 kInterior,
73 kExterior,
74 kAll
75 };
76
77 } // namespace lstrack
78
79
81 template<typename GridT, typename InterruptT = util::NullInterrupter>
82 class LevelSetTracker
83 {
84 public:
85 using TrimMode = lstrack::TrimMode;
86
87 using GridType = GridT;
88 using TreeType = typename GridT::TreeType;
89 using LeafType = typename TreeType::LeafNodeType;
90 using ValueType = typename TreeType::ValueType;
91 using LeafManagerType = typename tree::LeafManager<TreeType>; // leafs + buffers
92 using LeafRange = typename LeafManagerType::LeafRange;
93 using BufferType = typename LeafManagerType::BufferType;
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");
97
99 struct State {
100 State(math::BiasedGradientScheme s = math::HJWENO5_BIAS,
101 math::TemporalIntegrationScheme t = math::TVD_RK1,
102 int n = static_cast<int>(LEVEL_SET_HALF_WIDTH), int g = 1)
103 : spatialScheme(s), temporalScheme(t), normCount(n), grainSize(g) {}
104 math::BiasedGradientScheme spatialScheme;
105 math::TemporalIntegrationScheme temporalScheme;
106 int normCount;// Number of iterations of normalization
107 int grainSize;
108 };
109
112 LevelSetTracker(GridT& grid, InterruptT* interrupt = nullptr);
113
114 virtual ~LevelSetTracker() { delete mLeafs; }
115
118 template <typename MaskType>
119 void normalize(const MaskType* mask);
120
122 void normalize() { this->normalize<MaskTreeType>(nullptr); }
123
126 void track();
127
132 void prune();
133
149 void dilate(int iterations = 1);
150
153 void erode(int iterations = 1);
154
157 bool resize(Index halfWidth = static_cast<Index>(LEVEL_SET_HALF_WIDTH));
158
160 ValueType getHalfWidth() const { return mGrid->background()/mDx; }
161
163 State getState() const { return mState; }
164
166 void setState(const State& s) { mState = s; }
167
169 math::BiasedGradientScheme getSpatialScheme() const { return mState.spatialScheme; }
170
172 void setSpatialScheme(math::BiasedGradientScheme s) { mState.spatialScheme = s; }
173
175 math::TemporalIntegrationScheme getTemporalScheme() const { return mState.temporalScheme; }
176
178 void setTemporalScheme(math::TemporalIntegrationScheme s) { mState.temporalScheme = s;}
179
182 int getNormCount() const { return mState.normCount; }
183
186 void setNormCount(int n) { mState.normCount = n; }
187
189 int getGrainSize() const { return mState.grainSize; }
190
193 void setGrainSize(int grainsize) { mState.grainSize = grainsize; }
194
198 TrimMode trimming() const { return mTrimMode; }
201 void setTrimming(TrimMode mode) { mTrimMode = mode; }
202
203 ValueType voxelSize() const { return mDx; }
204
205 void startInterrupter(const char* msg);
206
207 void endInterrupter();
208
210 bool checkInterrupter();
211
212 const GridType& grid() const { return *mGrid; }
213
214 LeafManagerType& leafs() { return *mLeafs; }
215
216 const LeafManagerType& leafs() const { return *mLeafs; }
217
218 private:
219 // disallow copy construction and copy by assignment!
220 LevelSetTracker(const LevelSetTracker&);// not implemented
221 LevelSetTracker& operator=(const LevelSetTracker&);// not implemented
222
223 // Private class to perform multi-threaded trimming of
224 // voxels that are too far away from the zero-crossing.
225 template<TrimMode Trimming>
226 struct Trim
227 {
228 Trim(LevelSetTracker& tracker) : mTracker(tracker) {}
229 void trim();
230 void operator()(const LeafRange& r) const;
231 LevelSetTracker& mTracker;
232 };// Trim
233
234 // Private struct to perform multi-threaded normalization
235 template<math::BiasedGradientScheme SpatialScheme,
236 math::TemporalIntegrationScheme TemporalScheme,
237 typename MaskT>
238 struct Normalizer
239 {
240 using SchemeT = math::BIAS_SCHEME<SpatialScheme>;
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;
245
246 Normalizer(LevelSetTracker& tracker, const MaskT* mask);
247 void normalize();
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>
251 void euler(const LeafRange& range, Index phiBuffer, Index resultBuffer);
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>
257 void eval(StencilT& stencil, const ValueType* phi, ValueType* result, Index n) const;
258 LevelSetTracker& mTracker;
259 const MaskT* mMask;
260 const ValueType mDt, mInvDx;
261 typename std::function<void (Normalizer*, const LeafRange&)> mTask;
262 }; // Normalizer struct
263
264 template<math::BiasedGradientScheme SpatialScheme, typename MaskT>
265 void normalize1(const MaskT* mask);
266
267 template<math::BiasedGradientScheme SpatialScheme,
268 math::TemporalIntegrationScheme TemporalScheme, typename MaskT>
269 void normalize2(const MaskT* mask);
270
271 // Throughout the methods below mLeafs is always assumed to contain
272 // a list of the current LeafNodes! The auxiliary buffers on the
273 // other hand always have to be allocated locally, since some
274 // methods need them and others don't!
275 GridType* mGrid;
276 LeafManagerType* mLeafs;
277 InterruptT* mInterrupter;
278 const ValueType mDx;
279 State mState;
280 TrimMode mTrimMode = TrimMode::kAll;
281 }; // end of LevelSetTracker class
282
283 template<typename GridT, typename InterruptT>
284 LevelSetTracker<GridT, InterruptT>::
285 LevelSetTracker(GridT& grid, InterruptT* interrupt):
286 mGrid(&grid),
287 mLeafs(new LeafManagerType(grid.tree())),
288 mInterrupter(interrupt),
289 mDx(static_cast<ValueType>(grid.voxelSize()[0])),
290 mState()
291 {
292 if ( !grid.hasUniformVoxels() ) {
293 OPENVDB_THROW(RuntimeError,
294 "The transform must have uniform scale for the LevelSetTracker to function");
295 }
296 if ( grid.getGridClass() != GRID_LEVEL_SET) {
297 OPENVDB_THROW(RuntimeError,
298 "LevelSetTracker expected a level set, got a grid of class \""
299 + grid.gridClassToString(grid.getGridClass())
300 + "\" [hint: Grid::setGridClass(openvdb::GRID_LEVEL_SET)]");
301 }
302 }
303
304 template<typename GridT, typename InterruptT>
305 inline void
306 LevelSetTracker<GridT, InterruptT>::
307 prune()
308 {
309 this->startInterrupter("Pruning Level Set");
310
311 // Set voxels that are too far away from the zero crossing to the background value.
312 switch (mTrimMode) {
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;
317 }
318
319 // Remove inactive nodes from tree
320 tools::pruneLevelSet(mGrid->tree());
321
322 // The tree topology has changes so rebuild the list of leafs
323 mLeafs->rebuildLeafArray();
324 this->endInterrupter();
325 }
326
327 template<typename GridT, typename InterruptT>
328 inline void
329 LevelSetTracker<GridT, InterruptT>::
330 track()
331 {
332 // Dilate narrow-band (this also rebuilds the leaf array!)
333 tools::dilateActiveValues( *mLeafs, 1, tools::NN_FACE, tools::IGNORE_TILES);
334
335 // Compute signed distances in dilated narrow-band
336 this->normalize();
337
338 // Remove voxels that are outside the narrow band
339 this->prune();
340 }
341
342 template<typename GridT, typename InterruptT>
343 inline void
344 LevelSetTracker<GridT, InterruptT>::
345 dilate(int iterations)
346 {
347 if (this->getNormCount() == 0) {
348 for (int i=0; i < iterations; ++i) {
349 tools::dilateActiveValues( *mLeafs, 1, tools::NN_FACE, tools::IGNORE_TILES);
350 tools::changeLevelSetBackground(this->leafs(), mDx + mGrid->background());
351 }
352 } else {
353 for (int i=0; i < iterations; ++i) {
354 MaskTreeType mask0(mGrid->tree(), false, TopologyCopy());
355 tools::dilateActiveValues( *mLeafs, 1, tools::NN_FACE, tools::IGNORE_TILES);
356 tools::changeLevelSetBackground(this->leafs(), mDx + mGrid->background());
357 MaskTreeType mask(mGrid->tree(), false, TopologyCopy());
358 mask.topologyDifference(mask0);
359 this->normalize(&mask);
360 }
361 }
362 }
363
364 template<typename GridT, typename InterruptT>
365 inline void
366 LevelSetTracker<GridT, InterruptT>::
367 erode(int iterations)
368 {
369 tools::erodeVoxels(*mLeafs, iterations);
370 mLeafs->rebuildLeafArray();
371 const ValueType background = mGrid->background() - iterations*mDx;
372 tools::changeLevelSetBackground(this->leafs(), background);
373 }
374
375 template<typename GridT, typename InterruptT>
376 inline bool
377 LevelSetTracker<GridT, InterruptT>::
378 resize(Index halfWidth)
379 {
380 const int wOld = static_cast<int>(math::RoundDown(this->getHalfWidth()));
381 const int wNew = static_cast<int>(halfWidth);
382 if (wOld < wNew) {
383 this->dilate(wNew - wOld);
384 } else if (wOld > wNew) {
385 this->erode(wOld - wNew);
386 }
387 return wOld != wNew;
388 }
389
390 template<typename GridT, typename InterruptT>
391 inline void
392 LevelSetTracker<GridT, InterruptT>::
393 startInterrupter(const char* msg)
394 {
395 if (mInterrupter) mInterrupter->start(msg);
396 }
397
398 template<typename GridT, typename InterruptT>
399 inline void
400 LevelSetTracker<GridT, InterruptT>::
401 endInterrupter()
402 {
403 if (mInterrupter) mInterrupter->end();
404 }
405
406 template<typename GridT, typename InterruptT>
407 inline bool
408 LevelSetTracker<GridT, InterruptT>::
409 checkInterrupter()
410 {
411 if (util::wasInterrupted(mInterrupter)) {
412 tbb::task::self().cancel_group_execution();
413 return false;
414 }
415 return true;
416 }
417
418 template<typename GridT, typename InterruptT>
419 template<typename MaskT>
420 inline void
421 LevelSetTracker<GridT, InterruptT>::
422 normalize(const MaskT* mask)
423 {
424 switch (this->getSpatialScheme()) {
425 case math::FIRST_BIAS:
426 this->normalize1<math::FIRST_BIAS , MaskT>(mask); break;
427 case math::SECOND_BIAS:
428 this->normalize1<math::SECOND_BIAS, MaskT>(mask); break;
429 case math::THIRD_BIAS:
430 this->normalize1<math::THIRD_BIAS, MaskT>(mask); break;
431 case math::WENO5_BIAS:
432 this->normalize1<math::WENO5_BIAS, MaskT>(mask); break;
433 case math::HJWENO5_BIAS:
434 this->normalize1<math::HJWENO5_BIAS, MaskT>(mask); break;
435 case math::UNKNOWN_BIAS:
436 default:
437 OPENVDB_THROW(ValueError, "Spatial difference scheme not supported!");
438 }
439 }
440
441 template<typename GridT, typename InterruptT>
442 template<math::BiasedGradientScheme SpatialScheme, typename MaskT>
443 inline void
444 LevelSetTracker<GridT, InterruptT>::
445 normalize1(const MaskT* mask)
446 {
447 switch (this->getTemporalScheme()) {
448 case math::TVD_RK1:
449 this->normalize2<SpatialScheme, math::TVD_RK1, MaskT>(mask); break;
450 case math::TVD_RK2:
451 this->normalize2<SpatialScheme, math::TVD_RK2, MaskT>(mask); break;
452 case math::TVD_RK3:
453 this->normalize2<SpatialScheme, math::TVD_RK3, MaskT>(mask); break;
454 case math::UNKNOWN_TIS:
455 default:
456 OPENVDB_THROW(ValueError, "Temporal integration scheme not supported!");
457 }
458 }
459
460 template<typename GridT, typename InterruptT>
461 template<math::BiasedGradientScheme SpatialScheme,
462 math::TemporalIntegrationScheme TemporalScheme,
463 typename MaskT>
464 inline void
465 LevelSetTracker<GridT, InterruptT>::
466 normalize2(const MaskT* mask)
467 {
468 Normalizer<SpatialScheme, TemporalScheme, MaskT> tmp(*this, mask);
469 tmp.normalize();
470 }
471
472
474
475
476 template<typename GridT, typename InterruptT>
477 template<lstrack::TrimMode Trimming>
478 inline void
479 LevelSetTracker<GridT, InterruptT>::Trim<Trimming>::trim()
480 {
481 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
482 if (Trimming != TrimMode::kNone) {
483 const int grainSize = mTracker.getGrainSize();
484 const LeafRange range = mTracker.leafs().leafRange(grainSize);
485
486 if (grainSize>0) {
487 tbb::parallel_for(range, *this);
488 } else {
489 (*this)(range);
490 }
491 }
492 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
493 }
494
495
497 template<typename GridT, typename InterruptT>
498 template<lstrack::TrimMode Trimming>
499 inline void
500 LevelSetTracker<GridT, InterruptT>::Trim<Trimming>::operator()(const LeafRange& range) const
501 {
502 mTracker.checkInterrupter();
503 const ValueType gamma = mTracker.mGrid->background();
504
505 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
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;
510 switch (Trimming) { // resolved at compile time
511 case TrimMode::kNone:
512 break;
513 case TrimMode::kInterior:
514 if (val <= -gamma) { leaf.setValueOff(iter.pos(), -gamma); }
515 break;
516 case TrimMode::kExterior:
517 if (val >= gamma) { leaf.setValueOff(iter.pos(), gamma); }
518 break;
519 case TrimMode::kAll:
520 if (val <= -gamma) {
521 leaf.setValueOff(iter.pos(), -gamma);
522 } else if (val >= gamma) {
523 leaf.setValueOff(iter.pos(), gamma);
524 }
525 break;
526 }
527 }
528 }
529 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
530 }
531
532
534
535 template<typename GridT, typename InterruptT>
536 template<math::BiasedGradientScheme SpatialScheme,
537 math::TemporalIntegrationScheme TemporalScheme,
538 typename MaskT>
539 inline
540 LevelSetTracker<GridT, InterruptT>::
541 Normalizer<SpatialScheme, TemporalScheme, MaskT>::
542 Normalizer(LevelSetTracker& tracker, const MaskT* mask)
543 : mTracker(tracker)
544 , mMask(mask)
545 , mDt(tracker.voxelSize()*(TemporalScheme == math::TVD_RK1 ? 0.3f :
546 TemporalScheme == math::TVD_RK2 ? 0.9f : 1.0f))
547 , mInvDx(1.0f/tracker.voxelSize())
548 , mTask(0)
549 {
550 }
551
552 template<typename GridT, typename InterruptT>
553 template<math::BiasedGradientScheme SpatialScheme,
554 math::TemporalIntegrationScheme TemporalScheme,
555 typename MaskT>
556 inline void
557 LevelSetTracker<GridT, InterruptT>::
558 Normalizer<SpatialScheme, TemporalScheme, MaskT>::
559 normalize()
560 {
561 namespace ph = std::placeholders;
562
564 mTracker.mLeafs->rebuildAuxBuffers(TemporalScheme == math::TVD_RK3 ? 2 : 1);
565
566 for (int n=0, e=mTracker.getNormCount(); n < e; ++n) {
567
568 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
569 switch(TemporalScheme) {//switch is resolved at compile-time
570 case math::TVD_RK1:
571 // Perform one explicit Euler step: t1 = t0 + dt
572 // Phi_t1(0) = Phi_t0(0) - dt * VdotG_t0(1)
573 mTask = std::bind(&Normalizer::euler01, ph::_1, ph::_2);
574
575 // Cook and swap buffer 0 and 1 such that Phi_t1(0) and Phi_t0(1)
576 this->cook("Normalizing level set using TVD_RK1", 1);
577 break;
578 case math::TVD_RK2:
579 // Perform one explicit Euler step: t1 = t0 + dt
580 // Phi_t1(1) = Phi_t0(0) - dt * VdotG_t0(1)
581 mTask = std::bind(&Normalizer::euler01, ph::_1, ph::_2);
582
583 // Cook and swap buffer 0 and 1 such that Phi_t1(0) and Phi_t0(1)
584 this->cook("Normalizing level set using TVD_RK1 (step 1 of 2)", 1);
585
586 // Convex combine explicit Euler step: t2 = t0 + dt
587 // Phi_t2(1) = 1/2 * Phi_t0(1) + 1/2 * (Phi_t1(0) - dt * V.Grad_t1(0))
588 mTask = std::bind(&Normalizer::euler12, ph::_1, ph::_2);
589
590 // Cook and swap buffer 0 and 1 such that Phi_t2(0) and Phi_t1(1)
591 this->cook("Normalizing level set using TVD_RK1 (step 2 of 2)", 1);
592 break;
593 case math::TVD_RK3:
594 // Perform one explicit Euler step: t1 = t0 + dt
595 // Phi_t1(1) = Phi_t0(0) - dt * VdotG_t0(1)
596 mTask = std::bind(&Normalizer::euler01, ph::_1, ph::_2);
597
598 // Cook and swap buffer 0 and 1 such that Phi_t1(0) and Phi_t0(1)
599 this->cook("Normalizing level set using TVD_RK3 (step 1 of 3)", 1);
600
601 // Convex combine explicit Euler step: t2 = t0 + dt/2
602 // Phi_t2(2) = 3/4 * Phi_t0(1) + 1/4 * (Phi_t1(0) - dt * V.Grad_t1(0))
603 mTask = std::bind(&Normalizer::euler34, ph::_1, ph::_2);
604
605 // Cook and swap buffer 0 and 2 such that Phi_t2(0) and Phi_t1(2)
606 this->cook("Normalizing level set using TVD_RK3 (step 2 of 3)", 2);
607
608 // Convex combine explicit Euler step: t3 = t0 + dt
609 // Phi_t3(2) = 1/3 * Phi_t0(1) + 2/3 * (Phi_t2(0) - dt * V.Grad_t2(0)
610 mTask = std::bind(&Normalizer::euler13, ph::_1, ph::_2);
611
612 // Cook and swap buffer 0 and 2 such that Phi_t3(0) and Phi_t2(2)
613 this->cook("Normalizing level set using TVD_RK3 (step 3 of 3)", 2);
614 break;
615 case math::UNKNOWN_TIS:
616 default:
617 OPENVDB_THROW(ValueError, "Temporal integration scheme not supported!");
618 }
619 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
620 }
621 mTracker.mLeafs->removeAuxBuffers();
622 }
623
626 template<typename GridT, typename InterruptT>
627 template<math::BiasedGradientScheme SpatialScheme,
628 math::TemporalIntegrationScheme TemporalScheme,
629 typename MaskT>
630 inline void
631 LevelSetTracker<GridT, InterruptT>::
632 Normalizer<SpatialScheme, TemporalScheme, MaskT>::
633 cook(const char* msg, int swapBuffer)
634 {
635 mTracker.startInterrupter( msg );
636
637 const int grainSize = mTracker.getGrainSize();
638 const LeafRange range = mTracker.leafs().leafRange(grainSize);
639
640 grainSize>0 ? tbb::parallel_for(range, *this) : (*this)(range);
641
642 mTracker.leafs().swapLeafBuffer(swapBuffer, grainSize==0);
643
644 mTracker.endInterrupter();
645 }
646
647 template<typename GridT, typename InterruptT>
648 template<math::BiasedGradientScheme SpatialScheme,
649 math::TemporalIntegrationScheme TemporalScheme,
650 typename MaskT>
651 template <int Nominator, int Denominator>
652 inline void
653 LevelSetTracker<GridT, InterruptT>::
654 Normalizer<SpatialScheme, TemporalScheme, MaskT>::
655 eval(StencilT& stencil, const ValueType* phi, ValueType* result, Index n) const
656 {
657 using GradientT = typename math::ISGradientNormSqrd<SpatialScheme>;
658 static const ValueType alpha = ValueType(Nominator)/ValueType(Denominator);
659 static const ValueType beta = ValueType(1) - alpha;
660
661 const ValueType normSqGradPhi = GradientT::result(stencil);
662 const ValueType phi0 = stencil.getValue();
663 ValueType v = phi0 / ( math::Sqrt(math::Pow2(phi0) + normSqGradPhi) +
664 math::Tolerance<ValueType>::value() );
665 v = phi0 - mDt * v * (math::Sqrt(normSqGradPhi) * mInvDx - 1.0f);
666 result[n] = Nominator ? alpha * phi[n] + beta * v : v;
667 }
668
669 template<typename GridT, typename InterruptT>
670 template<math::BiasedGradientScheme SpatialScheme,
671 math::TemporalIntegrationScheme TemporalScheme,
672 typename MaskT>
673 template <int Nominator, int Denominator>
674 inline void
675 LevelSetTracker<GridT,InterruptT>::
676 Normalizer<SpatialScheme, TemporalScheme, MaskT>::
677 euler(const LeafRange& range, Index phiBuffer, Index resultBuffer)
678 {
679 using VoxelIterT = typename LeafType::ValueOnCIter;
680
681 mTracker.checkInterrupter();
682
683 StencilT stencil(mTracker.grid());
684
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());
692 }//loop over active voxels in the leaf of the level set
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);
699 }//loop over active voxels in the leaf of the mask
700 }
701 }//loop over leafs of the level set
702 }
703
704 } // namespace tools
705 } // namespace OPENVDB_VERSION_NAME
706 } // namespace openvdb
707
708 #endif // OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED
709
710 // Copyright (c) 2012-2018 DreamWorks Animation LLC
711 // All rights reserved. This software is distributed under the
712 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
FiniteDifference.h
openvdb::v5_2::tools::changeLevelSetBackground
void changeLevelSetBackground(TreeOrLeafManagerT &tree, const typename TreeOrLeafManagerT::ValueType &halfWidth, bool threaded=true, size_t grainSize=32)
Replace the background value in all the nodes of a floating-point tree containing a symmetric narrow-...
Definition: ChangeBackground.h:260
openvdb::v5_2::tools::LevelSetTracker::State::grainSize
int grainSize
Definition: LevelSetTracker.h:107
openvdb::v5_2::tools::LevelSetTracker::getHalfWidth
ValueType getHalfWidth() const
Return the half width of the narrow band in floating-point voxel units.
Definition: LevelSetTracker.h:160
Types.h
openvdb::v5_2::tools::LevelSetTracker::setGrainSize
void setGrainSize(int grainsize)
Set the grain-size used for multi-threading.
Definition: LevelSetTracker.h:193
openvdb::v5_2::tools::normalize
GridType::Ptr normalize(const GridType &grid, bool threaded, InterruptT *interrupt)
Normalize the vectors of the given vector-valued grid.
Definition: GridOperators.h:1091
openvdb::v5_2::tools::LevelSetTracker::setSpatialScheme
void setSpatialScheme(math::BiasedGradientScheme s)
Set the spatial finite difference scheme.
Definition: LevelSetTracker.h:172
NullInterrupter.h
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v5_2::tools::LevelSetTracker
Performs multi-threaded interface tracking of narrow band level sets.
Definition: LevelSetTracker.h:82
openvdb::v5_2::tools::LevelSetTracker::State::normCount
int normCount
Definition: LevelSetTracker.h:106
openvdb::v5_2::tools::LevelSetTracker::setTemporalScheme
void setTemporalScheme(math::TemporalIntegrationScheme s)
Set the spatial finite difference scheme.
Definition: LevelSetTracker.h:178
openvdb::v5_2::tools::LevelSetTracker::voxelSize
ValueType voxelSize() const
Definition: LevelSetTracker.h:203
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
openvdb::v5_2::tools::NN_FACE
Definition: Morphology.h:85
openvdb::v5_2::tools::LevelSetTracker::getNormCount
int getNormCount() const
Definition: LevelSetTracker.h:182
openvdb::v5_2::math::WENO5_BIAS
Definition: FiniteDifference.h:197
ChangeBackground.h
Efficient multi-threaded replacement of the background values in tree.
openvdb::v5_2::math::TVD_RK3
Definition: FiniteDifference.h:265
openvdb::v5_2::util::wasInterrupted
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
openvdb::v5_2::math::SECOND_BIAS
Definition: FiniteDifference.h:195
openvdb::v5_2::tools::prune
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:361
openvdb::v5_2::math::TemporalIntegrationScheme
TemporalIntegrationScheme
Temporal integration schemes.
Definition: FiniteDifference.h:261
openvdb::v5_2::tools::LevelSetTracker::State::spatialScheme
math::BiasedGradientScheme spatialScheme
Definition: LevelSetTracker.h:104
openvdb::v5_2::tools::LevelSetTracker::track
void track()
Track the level set interface, i.e. rebuild and normalize the narrow band of the level set...
Definition: LevelSetTracker.h:330
openvdb::v5_2::math::HJWENO5_BIAS
Definition: FiniteDifference.h:198
openvdb::v5_2::math::UNKNOWN_TIS
Definition: FiniteDifference.h:262
openvdb::v5_2::tools::LevelSetTracker::endInterrupter
void endInterrupter()
Definition: LevelSetTracker.h:401
openvdb::v5_2::math::UNKNOWN_BIAS
Definition: FiniteDifference.h:193
openvdb::v5_2::tools::LevelSetTracker::setTrimming
void setTrimming(TrimMode mode)
Specify whether to trim voxels outside the narrow band prior to pruning.
Definition: LevelSetTracker.h:201
Transform.h
openvdb::v5_2::tools::LevelSetTracker::~LevelSetTracker
virtual ~LevelSetTracker()
Definition: LevelSetTracker.h:114
openvdb::v5_2::tools::LevelSetTracker::dilate
void dilate(int iterations=1)
Fast but approximate dilation of the narrow band - one layer at a time. Normally we recommend using t...
Definition: LevelSetTracker.h:345
openvdb::v5_2::tools::LevelSetTracker::erode
void erode(int iterations=1)
Erodes the width of the narrow-band and update the background values.
Definition: LevelSetTracker.h:367
openvdb::v5_2::tools::lstrack::TrimMode::kNone
Leave out-of-band voxels intact.
openvdb::v5_2::tools::LevelSetTracker::getGrainSize
int getGrainSize() const
Definition: LevelSetTracker.h:189
openvdb::v5_2::math::Tolerance::value
static T value()
Definition: Math.h:117
openvdb::v5_2::GRID_LEVEL_SET
Definition: Types.h:277
openvdb::v5_2::tools::erodeVoxels
void erodeVoxels(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE)
Topologically erode all leaf-level active voxels in the given tree.
Definition: Morphology.h:877
openvdb::v5_2::LEVEL_SET_HALF_WIDTH
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:283
openvdb::v5_2::tools::LevelSetTracker::BufferType
typename LeafManagerType::BufferType BufferType
Definition: LevelSetTracker.h:93
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v5_2::math::RoundDown
float RoundDown(float x)
Return x rounded down to the nearest integer.
Definition: Math.h:757
openvdb::v5_2::math::BIAS_SCHEME
Definition: Operators.h:153
openvdb::v5_2::tools::lstrack::TrimMode::kExterior
Set out-of-band exterior voxels to the background value.
openvdb::v5_2::tools::LevelSetTracker::LeafType
typename TreeType::LeafNodeType LeafType
Definition: LevelSetTracker.h:89
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
openvdb::v5_2::tools::LevelSetTracker::LeafManagerType
typename tree::LeafManager< TreeType > LeafManagerType
Definition: LevelSetTracker.h:91
openvdb::v5_2::ValueError
Definition: Exceptions.h:92
openvdb::v5_2::tools::LevelSetTracker::resize
bool resize(Index halfWidth=static_cast< Index >(LEVEL_SET_HALF_WIDTH))
Resize the width of the narrow band, i.e. perform dilation and renormalization or erosion as required...
Definition: LevelSetTracker.h:378
openvdb::v5_2::tools::LevelSetTracker::ValueType
typename TreeType::ValueType ValueType
Definition: LevelSetTracker.h:90
openvdb::v5_2::tools::LevelSetTracker::State
Lightweight struct that stores the state of the LevelSetTracker.
Definition: LevelSetTracker.h:99
Morphology.h
Implementation of morphological dilation and erosion.
openvdb::v5_2::tools::lstrack::TrimMode
TrimMode
How to handle voxels that fall outside the narrow band.
Definition: LevelSetTracker.h:70
openvdb::v5_2::tools::LevelSetTracker::MaskTreeType
typename TreeType::template ValueConverter< ValueMask >::Type MaskTreeType
Definition: LevelSetTracker.h:94
openvdb
Definition: Exceptions.h:40
openvdb::v5_2::math::FIRST_BIAS
Definition: FiniteDifference.h:194
OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:129
openvdb::v5_2::tools::dilateActiveValues
void dilateActiveValues(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE, TilePolicy mode=PRESERVE_TILES)
Topologically dilate all active values (i.e. both voxels and tiles) in a tree using one of three near...
Definition: Morphology.h:1078
openvdb::v5_2::RuntimeError
Definition: Exceptions.h:90
openvdb::v5_2::tools::LevelSetTracker::getSpatialScheme
math::BiasedGradientScheme getSpatialScheme() const
Definition: LevelSetTracker.h:169
openvdb::v5_2::math::TVD_RK1
Definition: FiniteDifference.h:263
openvdb::v5_2::tools::LevelSetTracker::getTemporalScheme
math::TemporalIntegrationScheme getTemporalScheme() const
Definition: LevelSetTracker.h:175
openvdb::v5_2::Index
Index32 Index
Definition: Types.h:61
openvdb::v5_2::math::Sqrt
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:715
openvdb::v5_2::tools::LevelSetTracker::grid
const GridType & grid() const
Definition: LevelSetTracker.h:212
openvdb::v5_2::math::BiasedGradientScheme
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:192
openvdb::v5_2::tools::LevelSetTracker::leafs
LeafManagerType & leafs()
Definition: LevelSetTracker.h:214
openvdb::v5_2::tools::LevelSetTracker::trimming
TrimMode trimming() const
Return the trimming mode for voxels outside the narrow band.
Definition: LevelSetTracker.h:198
openvdb::v5_2::tools::lstrack::TrimMode::kAll
Set all out-of-band voxels to the background value.
openvdb::v5_2::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:416
ValueAccessor.h
openvdb::v5_2::tree::LeafManager
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
openvdb::v5_2::tools::LevelSetTracker::checkInterrupter
bool checkInterrupter()
Definition: LevelSetTracker.h:409
OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:130
openvdb::v5_2::tools::LevelSetTracker::TreeType
typename GridT::TreeType TreeType
Definition: LevelSetTracker.h:88
openvdb::v5_2::math::THIRD_BIAS
Definition: FiniteDifference.h:196
Grid.h
openvdb::v5_2::math::Pow2
Type Pow2(Type x)
Return x2.
Definition: Math.h:502
openvdb::v5_2::tools::LevelSetTracker::getState
State getState() const
Return the state of the tracker (see struct defined above)
Definition: LevelSetTracker.h:163
openvdb::v5_2::tools::LevelSetTracker::setState
void setState(const State &s)
Set the state of the tracker (see struct defined above)
Definition: LevelSetTracker.h:166
openvdb::v5_2::tools::LevelSetTracker::prune
void prune()
Set voxels that are outside the narrow band to the background value (if trimming is enabled) and prun...
Definition: LevelSetTracker.h:307
Stencils.h
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
openvdb::v5_2::tools::LevelSetTracker::leafs
const LeafManagerType & leafs() const
Definition: LevelSetTracker.h:216
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
LeafManager.h
A LeafManager manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional au...
openvdb::v5_2::tools::LevelSetTracker::State::State
State(math::BiasedGradientScheme s=math::HJWENO5_BIAS, math::TemporalIntegrationScheme t=math::TVD_RK1, int n=static_cast< int >(LEVEL_SET_HALF_WIDTH), int g=1)
Definition: LevelSetTracker.h:100
openvdb::v5_2::math::TVD_RK2
Definition: FiniteDifference.h:264
openvdb::v5_2::tools::LevelSetTracker::setNormCount
void setNormCount(int n)
Set the number of normalizations performed per track or normalize call.
Definition: LevelSetTracker.h:186
openvdb::v5_2::tools::LevelSetTracker::State::temporalScheme
math::TemporalIntegrationScheme temporalScheme
Definition: LevelSetTracker.h:105
openvdb::v5_2::tools::IGNORE_TILES
Definition: Morphology.h:100
openvdb::v5_2::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:518
openvdb::v5_2::tools::LevelSetTracker::normalize
void normalize()
Iterative normalization, i.e. solving the Eikonal equation.
Definition: LevelSetTracker.h:122
openvdb::v5_2::tools::LevelSetTracker::startInterrupter
void startInterrupter(const char *msg)
Definition: LevelSetTracker.h:393
openvdb::v5_2::tools::LevelSetTracker::GridType
GridT GridType
Definition: LevelSetTracker.h:87
openvdb::v5_2::tools::LevelSetTracker::LeafRange
typename LeafManagerType::LeafRange LeafRange
Definition: LevelSetTracker.h:92
openvdb::v5_2::points::index::State
State
Definition: IndexIterator.h:66
Operators.h
openvdb::v5_2::tools::lstrack::TrimMode::kInterior
Set out-of-band interior voxels to the background value.