33 #ifndef OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
34 #define OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
36 #include <openvdb/Types.h>
37 #include <openvdb/Grid.h>
38 #include <openvdb/math/Math.h>
39 #include <openvdb/tree/TreeIterator.h>
40 #include <openvdb/tree/ValueAccessor.h>
41 #include <openvdb/tree/LeafManager.h>
59 inline void dilateVoxels(tree::LeafManager<TreeType>& manager,
int count = 1);
69 inline void erodeVoxels(TreeType& tree,
int count=1);
72 inline void erodeVoxels(tree::LeafManager<TreeType>& manager,
int count = 1);
78 template<
typename Gr
idOrTree>
81 const typename GridOrTree::ValueType& value,
82 const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>()
88 template<
typename Gr
idOrTree>
91 const typename GridOrTree::ValueType& value,
92 const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>()
110 template<
typename TreeType>
117 mOwnsManager(true), mManager(new
ManagerType(tree)), mAcc(tree), mSteps(1) {}
119 mOwnsManager(false), mManager(mgr), mAcc(mgr->tree()), mSteps(1) {}
123 void erodeVoxels(
int count = 1) { mSteps = count; this->doErosion(); }
128 typedef typename TreeType::LeafNodeType LeafType;
129 typedef typename LeafType::NodeMaskType MaskType;
132 const bool mOwnsManager;
133 ManagerType* mManager;
137 static const int LEAF_DIM = LeafType::DIM;
138 static const int LEAF_LOG2DIM = LeafType::LOG2DIM;
145 Neighbor() : leaf(NULL), init(true) {}
146 inline void clear() { init =
true; }
147 template<
int DX,
int DY,
int DZ>
148 void scatter(AccessorType& acc,
const Coord &xyz,
int indx, Word oldWord)
152 Coord orig = xyz.offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
153 leaf = acc.probeLeaf(orig);
154 if (leaf==NULL && !acc.isValueOn(orig)) leaf = acc.touchLeaf(orig);
156 static const int N = (LEAF_DIM -1 )*(DY + DX*LEAF_DIM);
157 if (leaf) leaf->getValueMask().template getWord<Word>(indx-N) |= oldWord;
159 template<
int DX,
int DY,
int DZ>
160 Word gather(AccessorType& acc,
const Coord &xyz,
int indx)
164 Coord orig = xyz.offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
165 leaf = acc.probeLeaf(orig);
166 isOn = leaf ?
false : acc.isValueOn(orig);
168 static const int N = (LEAF_DIM -1 )*(DY + DX*LEAF_DIM);
169 return leaf ? leaf->getValueMask().template getWord<Word>(indx-N)
170 : isOn ? ~Word(0) : Word(0);
175 struct ErodeVoxelsOp {
176 ErodeVoxelsOp(std::vector<MaskType>& masks, ManagerType& manager)
177 : mSavedMasks(masks) , mManager(manager) {}
179 void runParallel() { tbb::parallel_for(mManager.getRange(), *
this); }
180 void operator()(
const tbb::blocked_range<size_t>& range)
const;
183 std::vector<MaskType>& mSavedMasks;
184 ManagerType& mManager;
189 MaskManager(std::vector<MaskType>& masks, ManagerType& manager)
190 : mMasks(masks) , mManager(manager), mSaveMasks(true) {}
192 void save() { mSaveMasks =
true; tbb::parallel_for(mManager.getRange(), *
this); }
193 void update() { mSaveMasks =
false; tbb::parallel_for(mManager.getRange(), *
this); }
194 void operator()(
const tbb::blocked_range<size_t>& range)
const
197 for (
size_t i = range.begin(); i < range.end(); ++i) {
198 mMasks[i] = mManager.leaf(i).getValueMask();
201 for (
size_t i = range.begin(); i < range.end(); ++i) {
202 mManager.leaf(i).setValueMask(mMasks[i]);
208 std::vector<MaskType>& mMasks;
209 ManagerType& mManager;
215 template<
typename TreeType>
220 const int leafCount = mManager->leafCount();
223 std::vector<MaskType> savedMasks(leafCount);
224 MaskManager masks(savedMasks, *mManager);
229 for (
int leafIdx = 0; leafIdx < leafCount; ++leafIdx) {
230 const MaskType& oldMask = savedMasks[leafIdx];
231 LeafType& leaf = mManager->leaf(leafIdx);
232 leaf.getOrigin(origin);
233 for (
int x = 0; x < LEAF_DIM; ++x ) {
234 for (
int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
236 const Word oldWord = oldMask.template getWord<Word>(n);
237 if (oldWord == 0)
continue;
241 leaf.getValueMask().template getWord<Word>(n-LEAF_DIM) |= oldWord;
243 NN[0].template scatter<-1, 0, 0>(mAcc, origin, n, oldWord);
246 if (x < LEAF_DIM - 1) {
247 leaf.getValueMask().template getWord<Word>(n+LEAF_DIM) |= oldWord;
249 NN[1].template scatter< 1, 0, 0>(mAcc, origin, n, oldWord);
253 leaf.getValueMask().template getWord<Word>(n-1) |= oldWord;
255 NN[2].template scatter< 0,-1, 0>(mAcc, origin, n, oldWord);
258 if (y < LEAF_DIM - 1) {
259 leaf.getValueMask().template getWord<Word>(n+1) |= oldWord;
261 NN[3].template scatter< 0, 1, 0>(mAcc, origin, n, oldWord);
265 leaf.getValueMask().template getWord<Word>(n) |= (oldWord >> 1) | (oldWord << 1);
267 if (Word w = oldWord<<(LEAF_DIM-1)) {
268 NN[4].template scatter< 0, 0,-1>(mAcc, origin, n, w);
271 if (Word w = oldWord>>(LEAF_DIM-1)) {
272 NN[5].template scatter< 0, 0, 1>(mAcc, origin, n, w);
276 for (
int i=0; i<6; ++i) NN[i].clear();
279 mManager->rebuildLeafArray();
283 template <
typename TreeType>
287 AccessorType acc(mManager.tree());
290 for (
size_t leafIdx = range.begin(); leafIdx < range.end(); ++leafIdx) {
291 LeafType& leaf = mManager.leaf(leafIdx);
292 if (leaf.isEmpty())
continue;
293 MaskType& newMask = mSavedMasks[leafIdx];
294 leaf.getOrigin(origin);
295 for (
int x = 0; x < LEAF_DIM; ++x ) {
296 for (
int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
298 Word& w = newMask.template getWord<Word>(n);
299 if (w == 0)
continue;
302 w &= (w<<1 | (NN[4].template gather<0,0,-1>(acc, origin, n)>>(LEAF_DIM-1))) &
303 (w>>1 | (NN[5].template gather<0,0, 1>(acc, origin, n)<<(LEAF_DIM-1)));
306 w &= (x == 0) ? NN[0].
template gather<-1, 0, 0>(acc, origin, n) :
307 leaf.getValueMask().template getWord<Word>(n-LEAF_DIM);
310 w &= (x == LEAF_DIM-1) ? NN[1].
template gather< 1, 0, 0>(acc, origin, n) :
311 leaf.getValueMask().template getWord<Word>(n+LEAF_DIM);
314 w &= (y == 0) ? NN[2].
template gather< 0,-1, 0>(acc, origin, n) :
315 leaf.getValueMask().template getWord<Word>(n-1);
318 w &= (y == LEAF_DIM-1) ? NN[3].
template gather< 0, 1, 0>(acc, origin, n) :
319 leaf.getValueMask().template getWord<Word>(n+1);
322 for (
int i=0; i<6; ++i) NN[i].clear();
327 template<
typename TreeType>
329 Morphology<TreeType>::doErosion()
332 const int leafCount = mManager->leafCount();
335 std::vector<MaskType> savedMasks(leafCount);
336 MaskManager masks(savedMasks, *mManager);
339 ErodeVoxelsOp erode(savedMasks, *mManager);
340 for (
int i = 0; i < mSteps; ++i) {
345 mManager->tree().pruneLevelSet();
352 template<
typename TreeType>
362 template<
typename TreeType>
372 template<
typename TreeType>
382 template<
typename TreeType>
396 namespace activation {
398 template<
typename TreeType>
402 typedef typename TreeType::ValueType
ValueT;
410 void operator()(
const typename TreeType::ValueOnIter& it)
const
417 void operator()(
const typename TreeType::ValueOffIter& it)
const
420 it.setActiveState(
true);
424 void operator()(
const typename TreeType::LeafIter& lit)
const
426 typedef typename TreeType::LeafNodeType LeafT;
429 for (
typename LeafT::ValueOffIter it = leaf.beginValueOff(); it; ++it) {
431 leaf.setValueOn(it.pos());
435 for (
typename LeafT::ValueOnIter it = leaf.beginValueOn(); it; ++it) {
437 leaf.setValueOff(it.pos());
445 const ValueT mValue, mTolerance;
451 template<
typename Gr
idOrTree>
453 activate(GridOrTree& gridOrTree,
const typename GridOrTree::ValueType& value,
454 const typename GridOrTree::ValueType& tolerance)
457 typedef typename Adapter::TreeType TreeType;
459 TreeType& tree = Adapter::tree(gridOrTree);
464 foreach(tree.beginLeaf(), op);
468 typename TreeType::ValueOffIter it = tree.beginValueOff();
469 it.setMaxDepth(tree.treeDepth() - 2);
470 foreach(it, op,
false);
474 template<
typename Gr
idOrTree>
476 deactivate(GridOrTree& gridOrTree,
const typename GridOrTree::ValueType& value,
477 const typename GridOrTree::ValueType& tolerance)
480 typedef typename Adapter::TreeType TreeType;
482 TreeType& tree = Adapter::tree(gridOrTree);
487 foreach(tree.beginLeaf(), op);
491 typename TreeType::ValueOnIter it = tree.beginValueOn();
492 it.setMaxDepth(tree.treeDepth() - 2);
493 foreach(it, op,
false);
500 #endif // OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:837
#define OPENVDB_VERSION_NAME
Definition: version.h:45
bool isApproxEqual(const Hermite &lhs, const Hermite &rhs)
Definition: Hermite.h:470
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109