OpenVDB 3.2.0

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