OpenVDB: Morphology.h Source File

OpenVDB 5.1.0

Morphology.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 //
45
46 #ifndef OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
47 #define OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
48
49 #include <openvdb/Types.h>
50 #include <openvdb/Grid.h>
51 #include <openvdb/math/Math.h> // for isApproxEqual()
52 #include <openvdb/tree/TreeIterator.h>
53 #include <openvdb/tree/ValueAccessor.h>
54 #include <openvdb/tree/LeafManager.h>
55 #include "Prune.h"// for pruneLevelSet
56 #include "ValueTransformer.h" // for foreach()
57 #include <tbb/tbb_thread.h>
58 #include <tbb/task_scheduler_init.h>
59 #include <tbb/enumerable_thread_specific.h>
60 #include <tbb/parallel_for.h>
61 #include <type_traits>
62
63
64 namespace openvdb {
65 OPENVDB_USE_VERSION_NAMESPACE
66 namespace OPENVDB_VERSION_NAME {
67 namespace tools {
68
85 enum NearestNeighbors { NN_FACE = 6, NN_FACE_EDGE = 18, NN_FACE_EDGE_VERTEX = 26 };
86
100 enum TilePolicy { IGNORE_TILES, EXPAND_TILES, PRESERVE_TILES };
101
117 template<typename TreeType> OPENVDB_STATIC_SPECIALIZATION
118 inline void dilateActiveValues(TreeType& tree,
119 int iterations = 1,
120 NearestNeighbors nn = NN_FACE,
121 TilePolicy mode = PRESERVE_TILES);
122
147 template<typename TreeType> OPENVDB_STATIC_SPECIALIZATION
148 inline void dilateActiveValues(tree::LeafManager<TreeType>& manager,
149 int iterations = 1,
150 NearestNeighbors nn = NN_FACE,
151 TilePolicy mode = PRESERVE_TILES);
152
153
166 template<typename TreeType> OPENVDB_STATIC_SPECIALIZATION
167 inline void dilateVoxels(TreeType& tree,
168 int iterations = 1,
169 NearestNeighbors nn = NN_FACE);
170
185 template<typename TreeType> OPENVDB_STATIC_SPECIALIZATION
186 inline void dilateVoxels(tree::LeafManager<TreeType>& manager,
187 int iterations = 1,
188 NearestNeighbors nn = NN_FACE);
189
190
192 template<typename TreeType> OPENVDB_STATIC_SPECIALIZATION
198 inline void erodeVoxels(TreeType& tree,
199 int iterations=1,
200 NearestNeighbors nn = NN_FACE);
201
202 template<typename TreeType> OPENVDB_STATIC_SPECIALIZATION
203 inline void erodeVoxels(tree::LeafManager<TreeType>& manager,
204 int iterations = 1,
205 NearestNeighbors nn = NN_FACE);
207
208
211 template<typename GridOrTree>
212 inline void activate(
213 GridOrTree&,
214 const typename GridOrTree::ValueType& value,
215 const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>()
216 );
217
218
221 template<typename GridOrTree>
222 inline void deactivate(
223 GridOrTree&,
224 const typename GridOrTree::ValueType& value,
225 const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>()
226 );
227
228
230
231
233 template<Index Log2Dim> struct DimToWord {};
234 template<> struct DimToWord<3> { typedef uint8_t Type; };
235 template<> struct DimToWord<4> { typedef uint16_t Type; };
236 template<> struct DimToWord<5> { typedef uint32_t Type; };
237 template<> struct DimToWord<6> { typedef uint64_t Type; };
238
239
241
242
243 template<typename TreeType>
244 class Morphology
245 {
246 public:
247 typedef tree::LeafManager<TreeType> ManagerType;
248
249 Morphology(TreeType& tree):
250 mOwnsManager(true), mManager(new ManagerType(tree)), mAcc(tree), mSteps(1) {}
251 Morphology(ManagerType* mgr):
252 mOwnsManager(false), mManager(mgr), mAcc(mgr->tree()), mSteps(1) {}
253 virtual ~Morphology() { if (mOwnsManager) delete mManager; }
254
256 void dilateVoxels6();
258 void dilateVoxels18();
260 void dilateVoxels26();
261 void dilateVoxels(int iterations = 1, NearestNeighbors nn = NN_FACE);
262
264 void erodeVoxels6() { mSteps = 1; this->doErosion(NN_FACE); }
266 void erodeVoxels18() { mSteps = 1; this->doErosion(NN_FACE_EDGE); }
268 void erodeVoxels26() { mSteps = 1; this->doErosion(NN_FACE_EDGE_VERTEX); }
269 void erodeVoxels(int iterations = 1, NearestNeighbors nn = NN_FACE)
270 {
271 mSteps = iterations;
272 this->doErosion(nn);
273 }
274
275 protected:
276
277 void doErosion(NearestNeighbors nn);
278
279 typedef typename TreeType::LeafNodeType LeafType;
280 typedef typename LeafType::NodeMaskType MaskType;
281 typedef tree::ValueAccessor<TreeType> AccessorType;
282
283 const bool mOwnsManager;
284 ManagerType* mManager;
285 AccessorType mAcc;
286 int mSteps;
287
288 static const int LEAF_DIM = LeafType::DIM;
289 static const int LEAF_LOG2DIM = LeafType::LOG2DIM;
290 typedef typename DimToWord<LEAF_LOG2DIM>::Type Word;
291
292 struct Neighbor {
293 LeafType* leaf;//null if a tile
294 bool init;//true if initialization is required
295 bool isOn;//true if an active tile
296 Neighbor() : leaf(nullptr), init(true) {}
297 inline void clear() { leaf = nullptr; init = true; }
298 template<int DX, int DY, int DZ>
299 void scatter(AccessorType& acc, const Coord &xyz, int indx, Word mask)
300 {
301 if (init) {
302 init = false;
303 Coord orig = xyz.offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
304 leaf = acc.probeLeaf(orig);
305 if ((leaf == nullptr) && !acc.isValueOn(orig)) leaf = acc.touchLeaf(orig);
306 }
307 #ifndef _MSC_VER // Visual C++ doesn't guarantee thread-safe initialization of local statics
308 static
309 #endif
310 const int N = (LEAF_DIM - 1)*(DY + DX*LEAF_DIM);
311 if (leaf) leaf->getValueMask().template getWord<Word>(indx-N) |= mask;
312 }
313
314 template<int DX, int DY, int DZ>
315 Word gather(AccessorType& acc, const Coord &xyz, int indx)
316 {
317 if (init) {
318 init = false;
319 Coord orig = xyz.offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
320 leaf = acc.probeLeaf(orig);
321 isOn = leaf ? false : acc.isValueOn(orig);
322 }
323 #ifndef _MSC_VER // Visual C++ doesn't guarantee thread-safe initialization of local statics
324 static
325 #endif
326 const int N = (LEAF_DIM -1 )*(DY + DX*LEAF_DIM);
327 return leaf ? leaf->getValueMask().template getWord<Word>(indx-N)
328 : isOn ? ~Word(0) : Word(0);
329 }
330 };// Neighbor
331
332 struct LeafCache
333 {
334 LeafCache(size_t n, TreeType& tree) : size(n), leafs(new LeafType*[n]), acc(tree)
335 {
336 onTile.setValuesOn();
337 this->clear();
338 }
339 ~LeafCache() { delete [] leafs; }
340 LeafType*& operator[](int offset) { return leafs[offset]; }
341 inline void clear() { for (size_t i = 0; i < size; ++i) leafs[i] = nullptr; }
342 inline void setOrigin(const Coord& xyz) { origin = &xyz; }
343 inline void scatter(int n, int indx)
344 {
345 assert(leafs[n]);
346 leafs[n]->getValueMask().template getWord<Word>(indx) |= mask;
347 }
348 template<int DX, int DY, int DZ>
349 inline void scatter(int n, int indx)
350 {
351 if (!leafs[n]) {
352 const Coord xyz = origin->offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
353 leafs[n] = acc.probeLeaf(xyz);
354 if (!leafs[n]) leafs[n] = acc.isValueOn(xyz) ? &onTile : acc.touchLeaf(xyz);
355 }
356 this->scatter(n, indx - (LEAF_DIM - 1)*(DY + DX*LEAF_DIM));
357 }
358 inline Word gather(int n, int indx)
359 {
360 assert(leafs[n]);
361 return leafs[n]->getValueMask().template getWord<Word>(indx);
362 }
363 template<int DX, int DY, int DZ>
364 inline Word gather(int n, int indx)
365 {
366 if (!leafs[n]) {
367 const Coord xyz = origin->offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
368 leafs[n] = acc.probeLeaf(xyz);
369 if (!leafs[n]) leafs[n] = acc.isValueOn(xyz) ? &onTile : &offTile;
370 }
371 return this->gather(n, indx - (LEAF_DIM -1 )*(DY + DX*LEAF_DIM));
372 }
373 // Scatters in the xy face-directions relative to leaf i1
374 void scatterFacesXY(int x, int y, int i1, int n, int i2);
375
376 // Scatters in the xy edge-directions relative to leaf i1
377 void scatterEdgesXY(int x, int y, int i1, int n, int i2);
378
379 Word gatherFacesXY(int x, int y, int i1, int n, int i2);
380
381 Word gatherEdgesXY(int x, int y, int i1, int n, int i2);
382
383 const Coord* origin;
384 size_t size;
385 LeafType** leafs;
386 LeafType onTile, offTile;
387 AccessorType acc;
388 Word mask;
389 };// LeafCache
390
391 struct ErodeVoxelsOp {
392 typedef tbb::blocked_range<size_t> RangeT;
393 ErodeVoxelsOp(std::vector<MaskType>& masks, ManagerType& manager)
394 : mTask(0), mSavedMasks(masks) , mManager(manager) {}
395 void runParallel(NearestNeighbors nn);
396 void operator()(const RangeT& r) const {mTask(const_cast<ErodeVoxelsOp*>(this), r);}
397 void erode6( const RangeT&) const;
398 void erode18(const RangeT&) const;
399 void erode26(const RangeT&) const;
400 private:
401 using FuncT = typename std::function<void (ErodeVoxelsOp*, const RangeT&)>;
402 FuncT mTask;
403 std::vector<MaskType>& mSavedMasks;
404 ManagerType& mManager;
405 };// ErodeVoxelsOp
406
407 struct MaskManager {
408 MaskManager(std::vector<MaskType>& masks, ManagerType& manager)
409 : mMasks(masks) , mManager(manager), mSaveMasks(true) {}
410
411 void save() { mSaveMasks = true; tbb::parallel_for(mManager.getRange(), *this); }
412 void update() { mSaveMasks = false; tbb::parallel_for(mManager.getRange(), *this); }
413 void operator()(const tbb::blocked_range<size_t>& range) const
414 {
415 if (mSaveMasks) {
416 for (size_t i = range.begin(); i < range.end(); ++i) {
417 mMasks[i] = mManager.leaf(i).getValueMask();
418 }
419 } else {
420 for (size_t i = range.begin(); i < range.end(); ++i) {
421 mManager.leaf(i).setValueMask(mMasks[i]);
422 }
423 }
424 }
425 private:
426 std::vector<MaskType>& mMasks;
427 ManagerType& mManager;
428 bool mSaveMasks;
429 };// MaskManager
430
431 struct UpdateMasks {
432 UpdateMasks(const std::vector<MaskType>& masks, ManagerType& manager)
433 : mMasks(masks), mManager(manager) {}
434 void update() { tbb::parallel_for(mManager.getRange(), *this); }
435 void operator()(const tbb::blocked_range<size_t>& r) const {
436 for (size_t i=r.begin(); i<r.end(); ++i) mManager.leaf(i).setValueMask(mMasks[i]);
437 }
438 const std::vector<MaskType>& mMasks;
439 ManagerType& mManager;
440 };
441 struct CopyMasks {
442 CopyMasks(std::vector<MaskType>& masks, const ManagerType& manager)
443 : mMasks(masks), mManager(manager) {}
444 void copy() { tbb::parallel_for(mManager.getRange(), *this); }
445 void operator()(const tbb::blocked_range<size_t>& r) const {
446 for (size_t i=r.begin(); i<r.end(); ++i) mMasks[i]=mManager.leaf(i).getValueMask();
447 }
448 std::vector<MaskType>& mMasks;
449 const ManagerType& mManager;
450 };
451 void copyMasks(std::vector<MaskType>& a, const ManagerType& b) {CopyMasks c(a, b); c.copy();}
452 };// Morphology
453
454
455 template<typename TreeType>
456 inline void
457 Morphology<TreeType>::dilateVoxels(int iterations, NearestNeighbors nn)
458 {
459 for (int i=0; i<iterations; ++i) {
460 switch (nn) {
461 case NN_FACE_EDGE:
462 this->dilateVoxels18();
463 break;
464 case NN_FACE_EDGE_VERTEX:
465 this->dilateVoxels26();
466 break;
467 case NN_FACE:
468 default:
469 this->dilateVoxels6();
470 }
471 }
472 }
473
474
475 template<typename TreeType>
476 inline void
477 Morphology<TreeType>::dilateVoxels6()
478 {
480 const int leafCount = static_cast<int>(mManager->leafCount());
481
482 // Save the value masks of all leaf nodes.
483 std::vector<MaskType> savedMasks(leafCount);
484 this->copyMasks(savedMasks, *mManager);
485 LeafCache cache(7, mManager->tree());
486 for (int leafIdx = 0; leafIdx < leafCount; ++leafIdx) {
487 const MaskType& oldMask = savedMasks[leafIdx];//original bit-mask of current leaf node
488 cache[0] = &mManager->leaf(leafIdx);
489 cache.setOrigin(cache[0]->origin());
490 for (int x = 0; x < LEAF_DIM; ++x ) {
491 for (int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
492 // Extract the portion of the original mask that corresponds to a row in z.
493 if (const Word w = oldMask.template getWord<Word>(n)) {
494
495 // Dilate the current leaf in the +z and -z direction
496 cache.mask = Word(w | (w>>1) | (w<<1)); cache.scatter(0, n);
497
498 // Dilate into neighbor leaf in the -z direction
499 if ( (cache.mask = Word(w<<(LEAF_DIM-1))) ) {
500 cache.template scatter< 0, 0,-1>(1, n);
501 }
502 // Dilate into neighbor leaf in the +z direction
503 if ( (cache.mask = Word(w>>(LEAF_DIM-1))) ) {
504 cache.template scatter< 0, 0, 1>(2, n);
505 }
506 // Dilate in the xy-face directions relative to the center leaf
507 cache.mask = w; cache.scatterFacesXY(x, y, 0, n, 3);
508 }
509 }// loop over y
510 }//loop over x
511 cache.clear();
512 }//loop over leafs
513
514 mManager->rebuildLeafArray();
515 }//dilateVoxels6
516
517
518 template<typename TreeType>
519 inline void
520 Morphology<TreeType>::dilateVoxels18()
521 {
523 const int leafCount = static_cast<int>(mManager->leafCount());
524
525 // Save the value masks of all leaf nodes.
526 std::vector<MaskType> savedMasks(leafCount);
527 this->copyMasks(savedMasks, *mManager);
528 LeafCache cache(19, mManager->tree());
529 Coord orig_mz, orig_pz;//origins of neighbor leaf nodes in the -z and +z directions
530 for (int leafIdx = 0; leafIdx < leafCount; ++leafIdx) {
531 const MaskType& oldMask = savedMasks[leafIdx];//original bit-mask of current leaf node
532 cache[0] = &mManager->leaf(leafIdx);
533 orig_mz = cache[0]->origin().offsetBy(0, 0, -LEAF_DIM);
534 orig_pz = cache[0]->origin().offsetBy(0, 0, LEAF_DIM);
535 for (int x = 0; x < LEAF_DIM; ++x ) {
536 for (int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
537 if (const Word w = oldMask.template getWord<Word>(n)) {
538 {
539 cache.mask = Word(w | (w>>1) | (w<<1));
540 cache.setOrigin(cache[0]->origin());
541 cache.scatter(0, n);
542 cache.scatterFacesXY(x, y, 0, n, 3);
543 cache.mask = w;
544 cache.scatterEdgesXY(x, y, 0, n, 3);
545 }
546 if ( (cache.mask = Word(w<<(LEAF_DIM-1))) ) {
547 cache.setOrigin(cache[0]->origin());
548 cache.template scatter< 0, 0,-1>(1, n);
549 cache.setOrigin(orig_mz);
550 cache.scatterFacesXY(x, y, 1, n, 11);
551 }
552 if ( (cache.mask = Word(w>>(LEAF_DIM-1))) ) {
553 cache.setOrigin(cache[0]->origin());
554 cache.template scatter< 0, 0, 1>(2, n);
555 cache.setOrigin(orig_pz);
556 cache.scatterFacesXY(x, y, 2, n, 15);
557 }
558 }
559 }// loop over y
560 }//loop over x
561 cache.clear();
562 }//loop over leafs
563
564 mManager->rebuildLeafArray();
565 }// dilateVoxels18
566
567
568 template<typename TreeType>
569 inline void
570 Morphology<TreeType>::dilateVoxels26()
571 {
572 const int leafCount = static_cast<int>(mManager->leafCount());
573
574 // Save the value masks of all leaf nodes.
575 std::vector<MaskType> savedMasks(leafCount);
576 this->copyMasks(savedMasks, *mManager);
577 LeafCache cache(27, mManager->tree());
578 Coord orig_mz, orig_pz;//origins of neighbor leaf nodes in the -z and +z directions
579 for (int leafIdx = 0; leafIdx < leafCount; ++leafIdx) {
580 const MaskType& oldMask = savedMasks[leafIdx];//original bit-mask of current leaf node
581 cache[0] = &mManager->leaf(leafIdx);
582 orig_mz = cache[0]->origin().offsetBy(0, 0, -LEAF_DIM);
583 orig_pz = cache[0]->origin().offsetBy(0, 0, LEAF_DIM);
584 for (int x = 0; x < LEAF_DIM; ++x ) {
585 for (int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
586 if (const Word w = oldMask.template getWord<Word>(n)) {
587 {
588 cache.mask = Word(w | (w>>1) | (w<<1));
589 cache.setOrigin(cache[0]->origin());
590 cache.scatter(0, n);
591 cache.scatterFacesXY(x, y, 0, n, 3);
592 cache.scatterEdgesXY(x, y, 0, n, 3);
593 }
594 if ( (cache.mask = Word(w<<(LEAF_DIM-1))) ) {
595 cache.setOrigin(cache[0]->origin());
596 cache.template scatter< 0, 0,-1>(1, n);
597 cache.setOrigin(orig_mz);
598 cache.scatterFacesXY(x, y, 1, n, 11);
599 cache.scatterEdgesXY(x, y, 1, n, 11);
600 }
601 if ( (cache.mask = Word(w>>(LEAF_DIM-1))) ) {
602 cache.setOrigin(cache[0]->origin());
603 cache.template scatter< 0, 0, 1>(2, n);
604 cache.setOrigin(orig_pz);
605 cache.scatterFacesXY(x, y, 2, n, 19);
606 cache.scatterEdgesXY(x, y, 2, n, 19);
607 }
608 }
609 }// loop over y
610 }//loop over x
611 cache.clear();
612 }//loop over leafs
613
614 mManager->rebuildLeafArray();
615 }// dilateVoxels26
616
617
618 template<typename TreeType>
619 inline void
620 Morphology<TreeType>::LeafCache::scatterFacesXY(int x, int y, int i1, int n, int i2)
621 {
622 // dilate current leaf or neighbor in the -x direction
623 if (x > 0) {
624 this->scatter(i1, n-LEAF_DIM);
625 } else {
626 this->template scatter<-1, 0, 0>(i2, n);
627 }
628 // dilate current leaf or neighbor in the +x direction
629 if (x < LEAF_DIM-1) {
630 this->scatter(i1, n+LEAF_DIM);
631 } else {
632 this->template scatter< 1, 0, 0>(i2+1, n);
633 }
634 // dilate current leaf or neighbor in the -y direction
635 if (y > 0) {
636 this->scatter(i1, n-1);
637 } else {
638 this->template scatter< 0,-1, 0>(i2+2, n);
639 }
640 // dilate current leaf or neighbor in the +y direction
641 if (y < LEAF_DIM-1) {
642 this->scatter(i1, n+1);
643 } else {
644 this->template scatter< 0, 1, 0>(i2+3, n);
645 }
646 }
647
648
649 template<typename TreeType>
650 inline void
651 Morphology<TreeType>::LeafCache::scatterEdgesXY(int x, int y, int i1, int n, int i2)
652 {
653 if (x > 0) {
654 if (y > 0) {
655 this->scatter(i1, n-LEAF_DIM-1);
656 } else {
657 this->template scatter< 0,-1, 0>(i2+2, n-LEAF_DIM);
658 }
659 if (y < LEAF_DIM-1) {
660 this->scatter(i1, n-LEAF_DIM+1);
661 } else {
662 this->template scatter< 0, 1, 0>(i2+3, n-LEAF_DIM);
663 }
664 } else {
665 if (y < LEAF_DIM-1) {
666 this->template scatter<-1, 0, 0>(i2 , n+1);
667 } else {
668 this->template scatter<-1, 1, 0>(i2+7, n );
669 }
670 if (y > 0) {
671 this->template scatter<-1, 0, 0>(i2 , n-1);
672 } else {
673 this->template scatter<-1,-1, 0>(i2+4, n );
674 }
675 }
676 if (x < LEAF_DIM-1) {
677 if (y > 0) {
678 this->scatter(i1, n+LEAF_DIM-1);
679 } else {
680 this->template scatter< 0,-1, 0>(i2+2, n+LEAF_DIM);
681 }
682 if (y < LEAF_DIM-1) {
683 this->scatter(i1, n+LEAF_DIM+1);
684 } else {
685 this->template scatter< 0, 1, 0>(i2+3, n+LEAF_DIM);
686 }
687 } else {
688 if (y > 0) {
689 this->template scatter< 1, 0, 0>(i2+1, n-1);
690 } else {
691 this->template scatter< 1,-1, 0>(i2+6, n );
692 }
693 if (y < LEAF_DIM-1) {
694 this->template scatter< 1, 0, 0>(i2+1, n+1);
695 } else {
696 this->template scatter< 1, 1, 0>(i2+5, n );
697 }
698 }
699 }
700
701
702 template<typename TreeType>
703 inline void
704 Morphology<TreeType>::ErodeVoxelsOp::runParallel(NearestNeighbors nn)
705 {
706 namespace ph = std::placeholders;
707 switch (nn) {
708 case NN_FACE_EDGE:
709 mTask = std::bind(&ErodeVoxelsOp::erode18, ph::_1, ph::_2);
710 break;
711 case NN_FACE_EDGE_VERTEX:
712 mTask = std::bind(&ErodeVoxelsOp::erode26, ph::_1, ph::_2);
713 break;
714 case NN_FACE:
715 default:
716 mTask = std::bind(&ErodeVoxelsOp::erode6, ph::_1, ph::_2);
717 }
718 tbb::parallel_for(mManager.getRange(), *this);
719 }
720
721
722 template<typename TreeType>
723 inline typename Morphology<TreeType>::Word
724 Morphology<TreeType>::LeafCache::gatherFacesXY(int x, int y, int i1, int n, int i2)
725 {
726 // erode current leaf or neighbor in negative x-direction
727 Word w = x>0 ? this->gather(i1,n-LEAF_DIM) : this->template gather<-1,0,0>(i2, n);
728
729 // erode current leaf or neighbor in positive x-direction
730 w = Word(w & (x<LEAF_DIM-1?this->gather(i1,n+LEAF_DIM):this->template gather<1,0,0>(i2+1,n)));
731
732 // erode current leaf or neighbor in negative y-direction
733 w = Word(w & (y>0 ? this->gather(i1, n-1) : this->template gather<0,-1,0>(i2+2, n)));
734
735 // erode current leaf or neighbor in positive y-direction
736 w = Word(w & (y<LEAF_DIM-1 ? this->gather(i1, n+1) : this->template gather<0,1,0>(i2+3, n)));
737
738 return w;
739 }
740
741
742 template<typename TreeType>
743 inline typename Morphology<TreeType>::Word
744 Morphology<TreeType>::LeafCache::gatherEdgesXY(int x, int y, int i1, int n, int i2)
745 {
746 Word w = ~Word(0);
747
748 if (x > 0) {
749 w &= y > 0 ? this->gather(i1, n-LEAF_DIM-1) :
750 this->template gather< 0,-1, 0>(i2+2, n-LEAF_DIM);
751 w &= y < LEAF_DIM-1 ? this->gather(i1, n-LEAF_DIM+1) :
752 this->template gather< 0, 1, 0>(i2+3, n-LEAF_DIM);
753 } else {
754 w &= y < LEAF_DIM-1 ? this->template gather<-1, 0, 0>(i2 , n+1):
755 this->template gather<-1, 1, 0>(i2+7, n );
756 w &= y > 0 ? this->template gather<-1, 0, 0>(i2 , n-1):
757 this->template gather<-1,-1, 0>(i2+4, n );
758 }
759 if (x < LEAF_DIM-1) {
760 w &= y > 0 ? this->gather(i1, n+LEAF_DIM-1) :
761 this->template gather< 0,-1, 0>(i2+2, n+LEAF_DIM);
762 w &= y < LEAF_DIM-1 ? this->gather(i1, n+LEAF_DIM+1) :
763 this->template gather< 0, 1, 0>(i2+3, n+LEAF_DIM);
764 } else {
765 w &= y > 0 ? this->template gather< 1, 0, 0>(i2+1, n-1):
766 this->template gather< 1,-1, 0>(i2+6, n );
767 w &= y < LEAF_DIM-1 ? this->template gather< 1, 0, 0>(i2+1, n+1):
768 this->template gather< 1, 1, 0>(i2+5, n );
769 }
770
771 return w;
772 }
773
774
775 template <typename TreeType>
776 inline void
777 Morphology<TreeType>::ErodeVoxelsOp::erode6(const RangeT& range) const
778 {
779 LeafCache cache(7, mManager.tree());
780 for (size_t leafIdx = range.begin(); leafIdx < range.end(); ++leafIdx) {
781 cache[0] = &mManager.leaf(leafIdx);
782 if (cache[0]->isEmpty()) continue;
783 cache.setOrigin(cache[0]->origin());
784 MaskType& newMask = mSavedMasks[leafIdx];//original bit-mask of current leaf node
785 for (int x = 0; x < LEAF_DIM; ++x ) {
786 for (int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
787 // Extract the portion of the original mask that corresponds to a row in z.
788 if (Word& w = newMask.template getWord<Word>(n)) {
789
790 // erode in two z directions (this is first since it uses the original w)
791 w = Word(w &
792 (Word(w<<1 | (cache.template gather<0,0,-1>(1, n)>>(LEAF_DIM-1))) &
793 Word(w>>1 | (cache.template gather<0,0, 1>(2, n)<<(LEAF_DIM-1)))));
794
795 w = Word(w & cache.gatherFacesXY(x, y, 0, n, 3));
796 }
797 }// loop over y
798 }//loop over x
799 cache.clear();
800 }//loop over leafs
801 }
802
803
804 template <typename TreeType>
805 inline void
806 Morphology<TreeType>::ErodeVoxelsOp::erode18(const RangeT&) const
807 {
808 OPENVDB_THROW(NotImplementedError, "tools::erode18 is not implemented yet!");
809 }
810
811
812 template <typename TreeType>
813 inline void
814 Morphology<TreeType>::ErodeVoxelsOp::erode26(const RangeT&) const
815 {
816 OPENVDB_THROW(NotImplementedError, "tools::erode26 is not implemented yet!");
817 }
818
819
820 template<typename TreeType>
821 inline void
822 Morphology<TreeType>::doErosion(NearestNeighbors nn)
823 {
825 const size_t leafCount = mManager->leafCount();
826
827 // Save the value masks of all leaf nodes.
828 std::vector<MaskType> savedMasks(leafCount);
829 this->copyMasks(savedMasks, *mManager);
830 UpdateMasks a(savedMasks, *mManager);
831 ErodeVoxelsOp erode(savedMasks, *mManager);
832
833 for (int i = 0; i < mSteps; ++i) {
834 erode.runParallel(nn);
835 a.update();
836 }
837
838 tools::pruneLevelSet(mManager->tree());
839 }
840
841
843
844
845 template<typename TreeType>
846 OPENVDB_STATIC_SPECIALIZATION inline void
847 dilateVoxels(tree::LeafManager<TreeType>& manager, int iterations, NearestNeighbors nn)
848 {
849 if (iterations > 0 ) {
850 Morphology<TreeType> m(&manager);
851 m.dilateVoxels(iterations, nn);
852 }
853 }
854
855 template<typename TreeType>
856 OPENVDB_STATIC_SPECIALIZATION inline void
857 dilateVoxels(TreeType& tree, int iterations, NearestNeighbors nn)
858 {
859 if (iterations > 0 ) {
860 Morphology<TreeType> m(tree);
861 m.dilateVoxels(iterations, nn);
862 }
863 }
864
865 template<typename TreeType>
866 OPENVDB_STATIC_SPECIALIZATION inline void
867 erodeVoxels(tree::LeafManager<TreeType>& manager, int iterations, NearestNeighbors nn)
868 {
869 if (iterations > 0 ) {
870 Morphology<TreeType> m(&manager);
871 m.erodeVoxels(iterations, nn);
872 }
873 }
874
875 template<typename TreeType>
876 OPENVDB_STATIC_SPECIALIZATION inline void
877 erodeVoxels(TreeType& tree, int iterations, NearestNeighbors nn)
878 {
879 if (iterations > 0 ) {
880 Morphology<TreeType> m(tree);
881 m.erodeVoxels(iterations, nn);
882 }
883 }
884
885
887
888
889 namespace activation {
890
891 template<typename TreeType>
892 class ActivationOp
893 {
894 public:
895 typedef typename TreeType::ValueType ValueT;
896
897 ActivationOp(bool state, const ValueT& val, const ValueT& tol)
898 : mActivate(state)
899 , mValue(val)
900 , mTolerance(tol)
901 {}
902
903 void operator()(const typename TreeType::ValueOnIter& it) const
904 {
905 if (math::isApproxEqual(*it, mValue, mTolerance)) {
906 it.setValueOff();
907 }
908 }
909
910 void operator()(const typename TreeType::ValueOffIter& it) const
911 {
912 if (math::isApproxEqual(*it, mValue, mTolerance)) {
913 it.setActiveState(/*on=*/true);
914 }
915 }
916
917 void operator()(const typename TreeType::LeafIter& lit) const
918 {
919 typedef typename TreeType::LeafNodeType LeafT;
920 LeafT& leaf = *lit;
921 if (mActivate) {
922 for (typename LeafT::ValueOffIter it = leaf.beginValueOff(); it; ++it) {
923 if (math::isApproxEqual(*it, mValue, mTolerance)) {
924 leaf.setValueOn(it.pos());
925 }
926 }
927 } else {
928 for (typename LeafT::ValueOnIter it = leaf.beginValueOn(); it; ++it) {
929 if (math::isApproxEqual(*it, mValue, mTolerance)) {
930 leaf.setValueOff(it.pos());
931 }
932 }
933 }
934 }
935
936 private:
937 bool mActivate;
938 const ValueT mValue, mTolerance;
939 }; // class ActivationOp
940
941 } // namespace activation
942
943
944 template<typename GridOrTree>
945 inline void
946 activate(GridOrTree& gridOrTree, const typename GridOrTree::ValueType& value,
947 const typename GridOrTree::ValueType& tolerance)
948 {
949 typedef TreeAdapter<GridOrTree> Adapter;
950 typedef typename Adapter::TreeType TreeType;
951
952 TreeType& tree = Adapter::tree(gridOrTree);
953
954 activation::ActivationOp<TreeType> op(/*activate=*/true, value, tolerance);
955
956 // Process all leaf nodes in parallel.
957 foreach(tree.beginLeaf(), op);
958
959 // Process all other inactive values serially (because changing active states
960 // is not thread-safe unless no two threads modify the same node).
961 typename TreeType::ValueOffIter it = tree.beginValueOff();
962 it.setMaxDepth(tree.treeDepth() - 2);
963 foreach(it, op, /*threaded=*/false);
964 }
965
966
967 template<typename GridOrTree>
968 inline void
969 deactivate(GridOrTree& gridOrTree, const typename GridOrTree::ValueType& value,
970 const typename GridOrTree::ValueType& tolerance)
971 {
972 typedef TreeAdapter<GridOrTree> Adapter;
973 typedef typename Adapter::TreeType TreeType;
974
975 TreeType& tree = Adapter::tree(gridOrTree);
976
977 activation::ActivationOp<TreeType> op(/*activate=*/false, value, tolerance);
978
979 // Process all leaf nodes in parallel.
980 foreach(tree.beginLeaf(), op);
981
982 // Process all other active values serially (because changing active states
983 // is not thread-safe unless no two threads modify the same node).
984 typename TreeType::ValueOnIter it = tree.beginValueOn();
985 it.setMaxDepth(tree.treeDepth() - 2);
986 foreach(it, op, /*threaded=*/false);
987 }
988
991 template<typename TreeT>
992 class DilationOp
993 {
994 typedef typename TreeT::template ValueConverter<ValueMask>::Type MaskT;
995 typedef tbb::enumerable_thread_specific<MaskT> PoolT;
996 typedef typename MaskT::LeafNodeType LeafT;
997
998 // Very light-weight member data
999 const int mIter;// number of iterations
1000 const tools::NearestNeighbors mNN;//enum to specify the dilation scheme
1001 PoolT *mPool;// pointer to the thread-local pool of mask trees
1002 LeafT **mLeafs;// raw array of pointers to leaf nodes
1003
1004 public:
1005
1006 DilationOp(TreeT &tree, int iterations, NearestNeighbors nn, TilePolicy mode)
1007 : mIter(iterations), mNN(nn), mPool(nullptr), mLeafs(nullptr)
1008 {
1009 const size_t numLeafs = this->init( tree, mode );
1010 const size_t numThreads = size_t(tbb::task_scheduler_init::default_num_threads());
1011 const size_t grainSize = math::Max(size_t(1), numLeafs/(2*numThreads));
1012
1013 MaskT mask;
1014 PoolT pool(mask);// Scoped thread-local storage of mask trees
1015 mPool = &pool;
1016
1017 tbb::parallel_for(tbb::blocked_range<LeafT**>(mLeafs, mLeafs+numLeafs, grainSize), *this);
1018
1019 delete [] mLeafs;// no more need for the array of leaf node pointers
1020
1021 typedef typename PoolT::iterator IterT;
1022 for (IterT it=pool.begin(); it!=pool.end(); ++it) mask.merge(*it);// fast stealing
1023
1024 if (mode == PRESERVE_TILES) tools::prune(mask);//multithreaded
1025
1026 tree.topologyUnion(mask);//multithreaded
1027 }
1028
1029 // This is required by tbb and should never be called directly
1030 void operator()(const tbb::blocked_range<LeafT**> &r) const
1031 {
1032 MaskT mask;// thread-local temporary mask tree
1033 for (LeafT** it=r.begin(); it!=r.end(); ++it) mask.addLeaf( *it );
1034 tree::LeafManager<MaskT> manager(mask, r.begin(), r.end());
1035 tools::dilateVoxels(manager, mIter, mNN);// serial dilation of active voxels
1036 mPool->local().merge(mask, MERGE_ACTIVE_STATES);
1037 }
1038 private:
1039
1040 // Simple wrapper of a raw double-pointer to mimic a std container
1041 struct MyArray {
1042 typedef LeafT* value_type;//required by Tree::stealNodes
1043 value_type* ptr;
1044 MyArray(value_type* array) : ptr(array) {}
1045 void push_back(value_type leaf) { *ptr++ = leaf; }//required by Tree::stealNodes
1046 };
1047
1048 // Convert active tiles to leafs and de-construct the tree into a linear array of leafs.
1049 size_t linearize(MaskT& mask, TilePolicy mode)
1050 {
1051 if (mode != IGNORE_TILES) mask.voxelizeActiveTiles();//lightweight since this is a mask tree
1052 const size_t numLeafs = mask.leafCount();
1053 mLeafs = new LeafT*[numLeafs];// fast pre-allocation
1054 MyArray tmp(mLeafs);
1055 mask.stealNodes(tmp);// serializes the mask tree and leaves it empty
1056 return numLeafs;
1057 }
1058
1059 template<typename T>
1060 typename std::enable_if<std::is_same<T, MaskT>::value, size_t>::type
1061 init(T& tree, TilePolicy mode)
1062 {
1063 return this->linearize(tree, mode);
1064 }
1065
1066 template<typename T>
1067 typename std::enable_if<!std::is_same<T, MaskT>::value, size_t>::type
1068 init(const T& tree, TilePolicy mode)
1069 {
1070 MaskT mask(tree, false, true, TopologyCopy());
1071 return this->linearize(mask, mode);
1072 }
1073
1074 };// DilationOp
1075
1076 template<typename TreeType>
1077 OPENVDB_STATIC_SPECIALIZATION inline void
1078 dilateActiveValues(TreeType& tree, int iterations, NearestNeighbors nn, TilePolicy mode)
1079 {
1080 if (iterations > 0 ) DilationOp<TreeType> tmp(tree, iterations, nn, mode);
1081 }
1082
1083 template<typename TreeType>
1084 OPENVDB_STATIC_SPECIALIZATION inline void
1085 dilateActiveValues(tree::LeafManager<TreeType>& manager,
1086 int iterations,
1087 NearestNeighbors nn,
1088 TilePolicy mode)
1089 {
1090 if (iterations > 0 ) {
1091 DilationOp<TreeType> tmp(manager.tree(), iterations, nn, mode);
1092 manager.rebuildLeafArray();
1093 }
1094 }
1095
1096 } // namespace tools
1097 } // namespace OPENVDB_VERSION_NAME
1098 } // namespace openvdb
1099
1100 #endif // OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
1101
1102 // Copyright (c) 2012-2018 DreamWorks Animation LLC
1103 // All rights reserved. This software is distributed under the
1104 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v5_1::tools::deactivate
void deactivate(GridOrTree &, const typename GridOrTree::ValueType &value, const typename GridOrTree::ValueType &tolerance=zeroVal< typename GridOrTree::ValueType >())
Mark as inactive any active tiles or voxels in the given grid or tree whose values are equal to value...
Definition: Morphology.h:969
openvdb::v5_1::tools::Morphology::LeafType
TreeType::LeafNodeType LeafType
Definition: Morphology.h:279
Types.h
openvdb::v5_1::TreeAdapter
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:943
openvdb::v5_1::tools::activation::ActivationOp::operator()
void operator()(const typename TreeType::ValueOffIter &it) const
Definition: Morphology.h:910
openvdb::v5_1::tools::Morphology::UpdateMasks
Definition: Morphology.h:431
openvdb::v5_1::tree::ValueAccessor::touchLeaf
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:394
openvdb::v5_1::tools::Morphology::Word
DimToWord< LEAF_LOG2DIM >::Type Word
Definition: Morphology.h:290
openvdb::v5_1::tools::Morphology::Neighbor::isOn
bool isOn
Definition: Morphology.h:295
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
ValueTransformer.h
openvdb::v5_1::tools::Morphology::dilateVoxels
void dilateVoxels(int iterations=1, NearestNeighbors nn=NN_FACE)
Definition: Morphology.h:457
openvdb::v5_1::tools::activation::ActivationOp
Definition: Morphology.h:892
openvdb::v5_1::tree::LeafManager::leaf
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:359
openvdb::v5_1::tools::NN_FACE_EDGE
Definition: Morphology.h:85
openvdb::v5_1::tools::DilationOp
Class that performs multi-threaded dilation with support for active tiles.
Definition: Morphology.h:992
openvdb::v5_1::tools::Morphology::MaskManager::update
void update()
Definition: Morphology.h:412
openvdb::v5_1::tools::DilationOp::DilationOp
DilationOp(TreeT &tree, int iterations, NearestNeighbors nn, TilePolicy mode)
Definition: Morphology.h:1006
openvdb::v5_1::tools::Morphology::Neighbor::leaf
LeafType * leaf
Definition: Morphology.h:293
openvdb::v5_1::tools::Morphology
Definition: Morphology.h:244
openvdb::v5_1::tools::Morphology::LeafCache::operator[]
LeafType *& operator[](int offset)
Definition: Morphology.h:340
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
openvdb::v5_1::tree::LeafManager::tree
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:343
openvdb::v5_1::tools::Morphology::CopyMasks::mMasks
std::vector< MaskType > & mMasks
Definition: Morphology.h:448
openvdb::v5_1::tools::NN_FACE_EDGE_VERTEX
Definition: Morphology.h:85
openvdb::v5_1::tools::DimToWord< 6 >::Type
uint64_t Type
Definition: Morphology.h:237
openvdb::v5_1::tools::Morphology::MaskManager::operator()
void operator()(const tbb::blocked_range< size_t > &range) const
Definition: Morphology.h:413
openvdb::v5_1::NotImplementedError
Definition: Exceptions.h:88
openvdb::v5_1::tools::activation::ActivationOp::ValueT
TreeType::ValueType ValueT
Definition: Morphology.h:895
openvdb::v5_1::tools::TilePolicy
TilePolicy
Different policies when dilating trees with active tiles.
Definition: Morphology.h:100
openvdb::v5_1::tools::Morphology::Neighbor
Definition: Morphology.h:292
openvdb::v5_1::tools::erodeVoxels
void erodeVoxels(tree::LeafManager< TreeType > &manager, int iterations=1, NearestNeighbors nn=NN_FACE)
Topologically erode all leaf-level active voxels in the given tree.
Definition: Morphology.h:867
openvdb::v5_1::tools::Morphology::Neighbor::Neighbor
Neighbor()
Definition: Morphology.h:296
openvdb::v5_1::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
openvdb::v5_1::tools::activation::ActivationOp::ActivationOp
ActivationOp(bool state, const ValueT &val, const ValueT &tol)
Definition: Morphology.h:897
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v5_1::MERGE_ACTIVE_STATES
Definition: Types.h:326
openvdb::v5_1::tools::DimToWord
Mapping from a Log2Dim to a data type of size 2^Log2Dim bits.
Definition: Morphology.h:233
openvdb::v5_1::tools::Morphology::Morphology
Morphology(ManagerType *mgr)
Definition: Morphology.h:251
openvdb::v5_1::tools::Morphology::ManagerType
tree::LeafManager< TreeType > ManagerType
Definition: Morphology.h:247
openvdb::v5_1::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_1::tools::DimToWord< 5 >::Type
uint32_t Type
Definition: Morphology.h:236
openvdb::v5_1::tools::Morphology::LeafCache::clear
void clear()
Definition: Morphology.h:341
openvdb::v5_1::math::Max
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:549
openvdb::v5_1::tools::dilateActiveValues
void dilateActiveValues(tree::LeafManager< TreeType > &manager, 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:1085
openvdb::v5_1::tools::NN_FACE
Definition: Morphology.h:85
openvdb::v5_1::tools::Morphology::erodeVoxels
void erodeVoxels(int iterations=1, NearestNeighbors nn=NN_FACE)
Definition: Morphology.h:269
openvdb::v5_1::tools::activate
void activate(GridOrTree &, const typename GridOrTree::ValueType &value, const typename GridOrTree::ValueType &tolerance=zeroVal< typename GridOrTree::ValueType >())
Mark as active any inactive tiles or voxels in the given grid or tree whose values are equal to value...
Definition: Morphology.h:946
openvdb::v5_1::tools::DimToWord< 4 >::Type
uint16_t Type
Definition: Morphology.h:235
TreeIterator.h
openvdb::v5_1::tools::Morphology::Neighbor::init
bool init
Definition: Morphology.h:294
openvdb::v5_1::tools::NearestNeighbors
NearestNeighbors
Voxel topology of nearest neighbors.
Definition: Morphology.h:85
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
openvdb::v5_1::tools::Morphology::Neighbor::clear
void clear()
Definition: Morphology.h:297
openvdb::v5_1::tree::LeafManager::getRange
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:383
openvdb::v5_1::tools::dilateVoxels
void dilateVoxels(tree::LeafManager< TreeType > &manager, int iterations=1, NearestNeighbors nn=NN_FACE)
Topologically dilate all leaf-level active voxels in a tree using one of three nearest neighbor conne...
Definition: Morphology.h:847
openvdb::v5_1::tools::IGNORE_TILES
Definition: Morphology.h:100
openvdb::v5_1::tree::LeafManager::rebuildLeafArray
void rebuildLeafArray()
Remove the auxiliary buffers and rebuild the leaf array.
Definition: LeafManager.h:316
openvdb::v5_1::tools::Morphology::LeafCache::scatter
void scatter(int n, int indx)
Definition: Morphology.h:349
openvdb::v5_1::tools::DilationOp::operator()
void operator()(const tbb::blocked_range< LeafT **> &r) const
Definition: Morphology.h:1030
openvdb::v5_1::tools::Morphology::mAcc
AccessorType mAcc
Definition: Morphology.h:285
openvdb::v5_1::tools::Morphology::mOwnsManager
const bool mOwnsManager
Definition: Morphology.h:283
openvdb
Definition: Exceptions.h:40
openvdb::v5_1::tools::Morphology::MaskManager::MaskManager
MaskManager(std::vector< MaskType > &masks, ManagerType &manager)
Definition: Morphology.h:408
openvdb::v5_1::tools::Morphology::ErodeVoxelsOp::RangeT
tbb::blocked_range< size_t > RangeT
Definition: Morphology.h:392
openvdb::v5_1::tools::EXPAND_TILES
Definition: Morphology.h:100
openvdb::v5_1::tools::Morphology::CopyMasks
Definition: Morphology.h:441
openvdb::v5_1::tools::Morphology::LeafCache::leafs
LeafType ** leafs
Definition: Morphology.h:385
openvdb::v5_1::tools::Morphology::ErodeVoxelsOp::ErodeVoxelsOp
ErodeVoxelsOp(std::vector< MaskType > &masks, ManagerType &manager)
Definition: Morphology.h:393
openvdb::v5_1::tools::Morphology::LeafCache::mask
Word mask
Definition: Morphology.h:388
openvdb::v5_1::tools::Morphology::ErodeVoxelsOp::operator()
void operator()(const RangeT &r) const
Definition: Morphology.h:396
openvdb::v5_1::math::Coord::offsetBy
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:118
openvdb::v5_1::tools::Morphology::LeafCache::size
size_t size
Definition: Morphology.h:384
openvdb::v5_1::tools::Morphology::UpdateMasks::mManager
ManagerType & mManager
Definition: Morphology.h:439
openvdb::v5_1::tree::ValueAccessor::probeLeaf
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:425
openvdb::v5_1::tools::Morphology::CopyMasks::copy
void copy()
Definition: Morphology.h:444
openvdb::v5_1::tools::Morphology::CopyMasks::mManager
const ManagerType & mManager
Definition: Morphology.h:449
openvdb::v5_1::tools::Morphology::UpdateMasks::operator()
void operator()(const tbb::blocked_range< size_t > &r) const
Definition: Morphology.h:435
openvdb::v5_1::tools::Morphology::copyMasks
void copyMasks(std::vector< MaskType > &a, const ManagerType &b)
Definition: Morphology.h:451
ValueAccessor.h
openvdb::v5_1::tools::Morphology::LeafCache::acc
AccessorType acc
Definition: Morphology.h:387
openvdb::v5_1::tools::Morphology::ErodeVoxelsOp::runParallel
void runParallel(NearestNeighbors nn)
Definition: Morphology.h:704
openvdb::v5_1::tools::Morphology::erodeVoxels26
void erodeVoxels26()
Face-, edge- and vertex-adjacent erosion pattern.
Definition: Morphology.h:268
openvdb::v5_1::tools::Morphology::Neighbor::scatter
void scatter(AccessorType &acc, const Coord &xyz, int indx, Word mask)
Definition: Morphology.h:299
openvdb::v5_1::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
openvdb::v5_1::tools::Morphology::CopyMasks::CopyMasks
CopyMasks(std::vector< MaskType > &masks, const ManagerType &manager)
Definition: Morphology.h:442
OPENVDB_STATIC_SPECIALIZATION
#define OPENVDB_STATIC_SPECIALIZATION
Macro for determining if there are sufficient C++0x/C++11 features.
Definition: Platform.h:91
openvdb::v5_1::tools::Morphology::MaskType
LeafType::NodeMaskType MaskType
Definition: Morphology.h:280
openvdb::v5_1::tools::DimToWord< 3 >::Type
uint8_t Type
Definition: Morphology.h:234
Grid.h
openvdb::v5_1::math::isApproxEqual
bool isApproxEqual(const Type &a, const Type &b)
Return true if a is equal to b to within the default floating-point comparison tolerance.
Definition: Math.h:358
openvdb::v5_1::tools::Morphology::LeafCache::scatter
void scatter(int n, int indx)
Definition: Morphology.h:343
openvdb::v5_1::tools::activation::ActivationOp::operator()
void operator()(const typename TreeType::ValueOnIter &it) const
Definition: Morphology.h:903
openvdb::v5_1::tools::Morphology::erodeVoxels18
void erodeVoxels18()
Face- and edge-adjacent erosion pattern.
Definition: Morphology.h:266
openvdb::v5_1::tools::Morphology::UpdateMasks::mMasks
const std::vector< MaskType > & mMasks
Definition: Morphology.h:438
openvdb::v5_1::tools::Morphology::UpdateMasks::UpdateMasks
UpdateMasks(const std::vector< MaskType > &masks, ManagerType &manager)
Definition: Morphology.h:432
openvdb::v5_1::tools::Morphology::mSteps
int mSteps
Definition: Morphology.h:286
openvdb::v5_1::tree::ValueAccessor< TreeType >
openvdb::v5_1::tools::Morphology::CopyMasks::operator()
void operator()(const tbb::blocked_range< size_t > &r) const
Definition: Morphology.h:445
openvdb::v5_1::tools::Morphology::Morphology
Morphology(TreeType &tree)
Definition: Morphology.h:249
openvdb::v5_1::tools::Morphology::LeafCache::gather
Word gather(int n, int indx)
Definition: Morphology.h:364
openvdb::v5_1::tree::ValueAccessor::isValueOn
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:264
openvdb::v5_1::tools::Morphology::LeafCache::onTile
LeafType onTile
Definition: Morphology.h:386
openvdb::v5_1::tools::Morphology::ErodeVoxelsOp
Definition: Morphology.h:391
openvdb::v5_1::tools::PRESERVE_TILES
Definition: Morphology.h:100
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
openvdb::v5_1::tools::activation::ActivationOp::operator()
void operator()(const typename TreeType::LeafIter &lit) const
Definition: Morphology.h:917
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_1::tools::Morphology::MaskManager::save
void save()
Definition: Morphology.h:411
openvdb::v5_1::tools::Morphology::LeafCache::gather
Word gather(int n, int indx)
Definition: Morphology.h:358
openvdb::v5_1::tools::Morphology::Neighbor::gather
Word gather(AccessorType &acc, const Coord &xyz, int indx)
Definition: Morphology.h:315
openvdb::v5_1::tools::Morphology::LeafCache::~LeafCache
~LeafCache()
Definition: Morphology.h:339
openvdb::v5_1::tools::Morphology::~Morphology
virtual ~Morphology()
Definition: Morphology.h:253
openvdb::v5_1::tools::Morphology::LeafCache::origin
const Coord * origin
Definition: Morphology.h:383
openvdb::v5_1::tools::Morphology::AccessorType
tree::ValueAccessor< TreeType > AccessorType
Definition: Morphology.h:281
openvdb::v5_1::tools::Morphology::mManager
ManagerType * mManager
Definition: Morphology.h:284
openvdb::v5_1::tools::Morphology::MaskManager
Definition: Morphology.h:407
openvdb::v5_1::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_1::tools::Morphology::LeafCache
Definition: Morphology.h:332
openvdb::v5_1::tools::Morphology::LeafCache::LeafCache
LeafCache(size_t n, TreeType &tree)
Definition: Morphology.h:334
openvdb::v5_1::tools::Morphology::LeafCache::setOrigin
void setOrigin(const Coord &xyz)
Definition: Morphology.h:342
openvdb::v5_1::tools::Morphology::erodeVoxels6
void erodeVoxels6()
Face-adjacent erosion pattern.
Definition: Morphology.h:264
openvdb::v5_1::tools::Morphology::UpdateMasks::update
void update()
Definition: Morphology.h:434