33 #ifndef OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
34 #define OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
36 #include <openvdb/Types.h>
37 #include <openvdb/tree/TreeIterator.h>
38 #include <openvdb/tree/ValueAccessor.h>
39 #include <openvdb/tree/LeafManager.h>
56 inline void dilateVoxels(tree::LeafManager<TreeType>& manager,
int count = 1);
66 inline void erodeVoxels(TreeType& tree,
int count=1);
69 inline void erodeVoxels(tree::LeafManager<TreeType>& manager,
int count = 1);
86 template<
typename TreeType>
93 mOwnsManager(true), mManager(new
ManagerType(tree)),
mAcc(tree), mSteps(1) {}
95 mOwnsManager(false), mManager(mgr),
mAcc(mgr->tree()), mSteps(1) {}
99 void erodeVoxels(
int count = 1) { mSteps = count; this->doErosion(); }
104 typedef typename TreeType::LeafNodeType LeafType;
105 typedef typename LeafType::NodeMaskType MaskType;
108 const bool mOwnsManager;
109 ManagerType* mManager;
113 static const int LEAF_DIM = LeafType::DIM;
114 static const int LEAF_LOG2DIM = LeafType::LOG2DIM;
121 Neighbor() : leaf(NULL), init(true) {}
122 inline void clear() { init =
true; }
123 template<
int DX,
int DY,
int DZ>
124 void scatter(AccessorType& acc,
const Coord &xyz,
int indx, Word oldWord)
128 Coord orig = xyz.offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
129 leaf = acc.probeLeaf(orig);
130 if (leaf==NULL && !acc.isValueOn(orig)) leaf = acc.touchLeaf(orig);
132 static const int N = (LEAF_DIM -1 )*(DY + DX*LEAF_DIM);
133 if (leaf) leaf->getValueMask().template getWord<Word>(indx-N) |= oldWord;
135 template<
int DX,
int DY,
int DZ>
136 Word gather(AccessorType& acc,
const Coord &xyz,
int indx)
140 Coord orig = xyz.offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
141 leaf = acc.probeLeaf(orig);
142 isOn = leaf ?
false : acc.isValueOn(orig);
144 static const int N = (LEAF_DIM -1 )*(DY + DX*LEAF_DIM);
145 return leaf ? leaf->getValueMask().template getWord<Word>(indx-N)
146 : isOn ? ~Word(0) : Word(0);
151 struct ErodeVoxelsOp {
152 ErodeVoxelsOp(std::vector<MaskType>& masks, ManagerType& manager)
153 : mSavedMasks(masks) , mManager(manager) {}
155 void runParallel() { tbb::parallel_for(mManager.getRange(), *
this); }
156 void operator()(
const tbb::blocked_range<size_t>& range)
const;
159 std::vector<MaskType>& mSavedMasks;
160 ManagerType& mManager;
165 MaskManager(std::vector<MaskType>& masks, ManagerType& manager)
166 : mMasks(masks) , mManager(manager), mSaveMasks(true) {}
168 void save() { mSaveMasks =
true; tbb::parallel_for(mManager.getRange(), *
this); }
169 void update() { mSaveMasks =
false; tbb::parallel_for(mManager.getRange(), *
this); }
170 void operator()(
const tbb::blocked_range<size_t>& range)
const
173 for (
size_t i = range.begin(); i < range.end(); ++i) {
174 mMasks[i] = mManager.leaf(i).getValueMask();
177 for (
size_t i = range.begin(); i < range.end(); ++i) {
178 mManager.leaf(i).setValueMask(mMasks[i]);
184 std::vector<MaskType>& mMasks;
185 ManagerType& mManager;
191 template<
typename TreeType>
196 const int leafCount = mManager->leafCount();
199 std::vector<MaskType> savedMasks(leafCount);
200 MaskManager masks(savedMasks, *mManager);
205 for (
int leafIdx = 0; leafIdx < leafCount; ++leafIdx) {
206 const MaskType& oldMask = savedMasks[leafIdx];
207 LeafType& leaf = mManager->leaf(leafIdx);
208 leaf.getOrigin(origin);
209 for (
int x = 0; x < LEAF_DIM; ++x ) {
210 for (
int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
212 const Word oldWord = oldMask.template getWord<Word>(n);
213 if (oldWord == 0)
continue;
217 leaf.getValueMask().template getWord<Word>(n-LEAF_DIM) |= oldWord;
219 NN[0].template scatter<-1, 0, 0>(
mAcc, origin, n, oldWord);
222 if (x < LEAF_DIM - 1) {
223 leaf.getValueMask().template getWord<Word>(n+LEAF_DIM) |= oldWord;
225 NN[1].template scatter< 1, 0, 0>(
mAcc, origin, n, oldWord);
229 leaf.getValueMask().template getWord<Word>(n-1) |= oldWord;
231 NN[2].template scatter< 0,-1, 0>(
mAcc, origin, n, oldWord);
234 if (y < LEAF_DIM - 1) {
235 leaf.getValueMask().template getWord<Word>(n+1) |= oldWord;
237 NN[3].template scatter< 0, 1, 0>(
mAcc, origin, n, oldWord);
241 leaf.getValueMask().template getWord<Word>(n) |= (oldWord >> 1) | (oldWord << 1);
243 if (Word w = oldWord<<(LEAF_DIM-1)) {
244 NN[4].template scatter< 0, 0,-1>(
mAcc, origin, n, w);
247 if (Word w = oldWord>>(LEAF_DIM-1)) {
248 NN[5].template scatter< 0, 0, 1>(
mAcc, origin, n, w);
252 for (
int i=0; i<6; ++i) NN[i].clear();
255 mManager->rebuildLeafArray();
259 template <
typename TreeType>
263 AccessorType acc(mManager.tree());
266 for (
size_t leafIdx = range.begin(); leafIdx < range.end(); ++leafIdx) {
267 LeafType& leaf = mManager.leaf(leafIdx);
268 if (leaf.isEmpty())
continue;
269 MaskType& newMask = mSavedMasks[leafIdx];
270 leaf.getOrigin(origin);
271 for (
int x = 0; x < LEAF_DIM; ++x ) {
272 for (
int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
274 Word& w = newMask.template getWord<Word>(n);
275 if (w == 0)
continue;
278 w &= (w<<1 | (NN[4].template gather<0,0,-1>(acc, origin, n)>>(LEAF_DIM-1))) &
279 (w>>1 | (NN[5].template gather<0,0, 1>(acc, origin, n)<<(LEAF_DIM-1)));
282 w &= (x == 0) ? NN[0].
template gather<-1, 0, 0>(acc, origin, n) :
283 leaf.getValueMask().template getWord<Word>(n-LEAF_DIM);
286 w &= (x == LEAF_DIM-1) ? NN[1].
template gather< 1, 0, 0>(acc, origin, n) :
287 leaf.getValueMask().template getWord<Word>(n+LEAF_DIM);
290 w &= (y == 0) ? NN[2].
template gather< 0,-1, 0>(acc, origin, n) :
291 leaf.getValueMask().template getWord<Word>(n-1);
294 w &= (y == LEAF_DIM-1) ? NN[3].
template gather< 0, 1, 0>(acc, origin, n) :
295 leaf.getValueMask().template getWord<Word>(n+1);
298 for (
int i=0; i<6; ++i) NN[i].clear();
303 template<
typename TreeType>
305 Morphology<TreeType>::doErosion()
308 const int leafCount = mManager->leafCount();
311 std::vector<MaskType> savedMasks(leafCount);
312 MaskManager masks(savedMasks, *mManager);
315 ErodeVoxelsOp erode(savedMasks, *mManager);
316 for (
int i = 0; i < mSteps; ++i) {
321 mManager->tree().pruneLevelSet();
328 template<
typename TreeType>
336 template<
typename TreeType>
344 template<
typename TreeType>
352 template<
typename TreeType>
364 #endif // OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
AccessorT mAcc
Definition: GridOperators.h:259
#define OPENVDB_VERSION_NAME
Definition: version.h:45
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:56
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109