OpenVDB  3.0.0
Clip.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2014 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 //
35 
36 #ifndef OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED
37 #define OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED
38 
39 #include <openvdb/Grid.h>
40 #include <openvdb/tree/LeafManager.h>
41 #include "GridTransformer.h" // for resampleToMatch()
42 #include <boost/type_traits/is_same.hpp>
43 #include <boost/type_traits/is_signed.hpp>
44 #include <boost/utility/enable_if.hpp>
45 #include <tbb/blocked_range.h>
46 #include <tbb/parallel_reduce.h>
47 #include "Prune.h"
48 
49 
50 namespace openvdb {
52 namespace OPENVDB_VERSION_NAME {
53 namespace tools {
54 
59 template<typename GridType> OPENVDB_STATIC_SPECIALIZATION
60 inline typename GridType::Ptr clip(const GridType& grid, const BBoxd&);
61 
72 template<typename GridType, typename MaskTreeType> OPENVDB_STATIC_SPECIALIZATION
73 inline typename GridType::Ptr clip(const GridType& grid, const Grid<MaskTreeType>& mask);
74 
75 
77 
78 
79 namespace clip_internal {
80 
81 // If T is a signed type, return bool(T < 0).
82 template<typename T>
83 inline typename boost::enable_if<boost::is_signed<T>, bool>::type
84 lessThanZero(const T& v) { return v < zeroVal<T>(); }
85 
86 // If T is an unsigned type, no value of type T is less than zero.
87 template<typename T>
88 inline typename boost::disable_if<boost::is_signed<T>, bool>::type
89 lessThanZero(const T&) { return false; }
90 
91 
93 
94 
95 template<typename TreeT>
97 {
98 public:
99  typedef typename TreeT::ValueType ValueT;
100  typedef typename TreeT::LeafNodeType LeafNodeT;
101 
102  MaskInteriorVoxels(const TreeT& tree): mAcc(tree) {}
103 
104  template <typename LeafNodeType>
105  void operator()(LeafNodeType &leaf, size_t /*leafIndex*/) const
106  {
107  const LeafNodeT *refLeaf = mAcc.probeConstLeaf(leaf.origin());
108  if (refLeaf) {
109  typename LeafNodeType::ValueOffIter iter = leaf.beginValueOff();
110  for ( ; iter; ++iter) {
111  const Index pos = iter.pos();
112  leaf.setActiveState(pos, lessThanZero(refLeaf->getValue(pos)));
113  }
114  }
115  }
116 
117 private:
119 };
120 
121 
123 
124 
125 template<typename TreeT>
127 {
128 public:
129  typedef typename TreeT::template ValueConverter<bool>::Type BoolTreeT;
131 
132  CopyLeafNodes(const TreeT& tree, const BoolLeafManagerT& leafNodes);
133 
134  void run(bool threaded = true);
135 
136  typename TreeT::Ptr tree() const { return mNewTree; }
137 
138  CopyLeafNodes(CopyLeafNodes&, tbb::split);
139  void operator()(const tbb::blocked_range<size_t>&);
140  void join(const CopyLeafNodes& rhs) { mNewTree->merge(*rhs.mNewTree); }
141 
142 private:
143  const BoolTreeT* mClipMask;
144  const TreeT* mTree;
145  const BoolLeafManagerT* mLeafNodes;
146  typename TreeT::Ptr mNewTree;
147 };
148 
149 
150 template<typename TreeT>
151 CopyLeafNodes<TreeT>::CopyLeafNodes(const TreeT& tree, const BoolLeafManagerT& leafNodes)
152  : mTree(&tree)
153  , mLeafNodes(&leafNodes)
154  , mNewTree(new TreeT(mTree->background()))
155 {
156 }
157 
158 
159 template<typename TreeT>
161  : mTree(rhs.mTree)
162  , mLeafNodes(rhs.mLeafNodes)
163  , mNewTree(new TreeT(mTree->background()))
164 {
165 }
166 
167 
168 template<typename TreeT>
169 void
171 {
172  if (threaded) tbb::parallel_reduce(mLeafNodes->getRange(), *this);
173  else (*this)(mLeafNodes->getRange());
174 }
175 
176 
177 template<typename TreeT>
178 void
179 CopyLeafNodes<TreeT>::operator()(const tbb::blocked_range<size_t>& range)
180 {
181  typedef typename TreeT::LeafNodeType LeafT;
182  typedef typename BoolTree::LeafNodeType BoolLeafT;
183  typename BoolLeafT::ValueOnCIter it;
184 
185  tree::ValueAccessor<TreeT> acc(*mNewTree);
186  tree::ValueAccessor<const TreeT> refAcc(*mTree);
187 
188  for (size_t n = range.begin(); n != range.end(); ++n) {
189  const BoolLeafT& maskLeaf = mLeafNodes->leaf(n);
190  const Coord& ijk = maskLeaf.origin();
191  const LeafT* refLeaf = refAcc.probeConstLeaf(ijk);
192 
193  LeafT* newLeaf = acc.touchLeaf(ijk);
194 
195  if (refLeaf) {
196  for (it = maskLeaf.cbeginValueOn(); it; ++it) {
197  const Index pos = it.pos();
198  newLeaf->setValueOnly(pos, refLeaf->getValue(pos));
199  newLeaf->setActiveState(pos, refLeaf->isValueOn(pos));
200  }
201  } else {
202  typename TreeT::ValueType value;
203  bool isActive = refAcc.probeValue(ijk, value);
204 
205  for (it = maskLeaf.cbeginValueOn(); it; ++it) {
206  const Index pos = it.pos();
207  newLeaf->setValueOnly(pos, value);
208  newLeaf->setActiveState(pos, isActive);
209  }
210  }
211  }
212 }
213 
214 
216 
217 
219 {
220  static const char* name() { return "bin"; }
221  static int radius() { return 2; }
222  static bool mipmap() { return false; }
223  static bool consistent() { return true; }
224 
225  template<class TreeT>
226  static bool sample(const TreeT& inTree,
227  const Vec3R& inCoord, typename TreeT::ValueType& result)
228  {
229  Coord ijk;
230  ijk[0] = int(std::floor(inCoord[0]));
231  ijk[1] = int(std::floor(inCoord[1]));
232  ijk[2] = int(std::floor(inCoord[2]));
233  return inTree.probeValue(ijk, result);
234  }
235 };
236 
237 
239 
240 
241 // Convert a grid of one type to a grid of another type
242 template<typename FromGridT, typename ToGridT>
244 {
245  typedef typename FromGridT::Ptr FromGridPtrT;
246  typedef typename ToGridT::Ptr ToGridPtrT;
247  ToGridPtrT operator()(const FromGridPtrT& grid) { return ToGridPtrT(new ToGridT(*grid)); }
248 };
249 
250 // Partial specialization that avoids copying when
251 // the input and output grid types are the same
252 template<typename GridT>
253 struct ConvertGrid<GridT, GridT>
254 {
255  typedef typename GridT::Ptr GridPtrT;
256  GridPtrT operator()(const GridPtrT& grid) { return grid; }
257 };
258 
259 
261 
262 
263 // Convert a grid of arbitrary type to a boolean mask grid and return a pointer to the new grid.
264 template<typename GridT>
265 inline typename boost::disable_if<boost::is_same<bool, typename GridT::ValueType>,
266  typename GridT::template ValueConverter<bool>::Type::Ptr>::type
267 convertToBoolMaskGrid(const GridT& grid)
268 {
269  typedef typename GridT::template ValueConverter<bool>::Type BoolGridT;
270  typedef typename BoolGridT::Ptr BoolGridPtrT;
271 
272  // Convert the input grid to a boolean mask grid (with the same tree configuration).
273  BoolGridPtrT mask = BoolGridT::create(/*background=*/false);
274  mask->topologyUnion(grid);
275  mask->setTransform(grid.constTransform().copy());
276  return mask;
277 }
278 
279 // Overload that avoids any processing if the input grid is already a boolean grid
280 template<typename GridT>
281 inline typename boost::enable_if<boost::is_same<bool, typename GridT::ValueType>,
282  typename GridT::Ptr>::type
283 convertToBoolMaskGrid(const GridT& grid)
284 {
285  return grid.copy(); // shallow copy
286 }
287 
288 
290 
291 
292 template<typename GridType>
293 inline typename GridType::Ptr
294 doClip(const GridType& grid, const typename GridType::template ValueConverter<bool>::Type& aMask)
295 {
296  typedef typename GridType::TreeType TreeT;
297  typedef typename GridType::TreeType::template ValueConverter<bool>::Type BoolTreeT;
298 
299  const GridClass gridClass = grid.getGridClass();
300  const TreeT& tree = grid.tree();
301 
302  BoolTreeT mask(false);
303  mask.topologyUnion(tree);
304 
305  if (gridClass == GRID_LEVEL_SET) {
306  tree::LeafManager<BoolTreeT> leafNodes(mask);
307  leafNodes.foreach(MaskInteriorVoxels<TreeT>(tree));
308 
310 
311  typename BoolTreeT::ValueAllIter iter(mask);
312  iter.setMaxDepth(BoolTreeT::ValueAllIter::LEAF_DEPTH - 1);
313 
314  for ( ; iter; ++iter) {
315  iter.setActiveState(lessThanZero(acc.getValue(iter.getCoord())));
316  }
317  }
318 
319  mask.topologyIntersection(aMask.constTree());
320 
321  typename GridType::Ptr outGrid;
322  {
323  // Copy voxel values and states.
324  tree::LeafManager<const BoolTreeT> leafNodes(mask);
325  CopyLeafNodes<TreeT> maskOp(tree, leafNodes);
326  maskOp.run();
327  outGrid = GridType::create(maskOp.tree());
328  }
329  {
330  // Copy tile values and states.
333 
334  typename TreeT::ValueAllIter it(outGrid->tree());
335  it.setMaxDepth(TreeT::ValueAllIter::LEAF_DEPTH - 1);
336  for ( ; it; ++it) {
337  Coord ijk = it.getCoord();
338 
339  if (maskAcc.isValueOn(ijk)) {
340  typename TreeT::ValueType value;
341  bool isActive = refAcc.probeValue(ijk, value);
342 
343  it.setValue(value);
344  if (!isActive) it.setValueOff();
345  }
346  }
347  }
348 
349  outGrid->setTransform(grid.transform().copy());
350  if (gridClass != GRID_LEVEL_SET) outGrid->setGridClass(gridClass);
351 
352  return outGrid;
353 }
354 
355 } // namespace clip_internal
356 
357 
359 
360 
361 template<typename GridType>
363 inline typename GridType::Ptr
364 clip(const GridType& grid, const BBoxd& bbox)
365 {
366  typedef typename GridType::template ValueConverter<bool>::Type BoolGridT;
367 
368  // Transform the world-space bounding box into the source grid's index space.
369  Vec3d idxMin, idxMax;
370  math::calculateBounds(grid.constTransform(), bbox.min(), bbox.max(), idxMin, idxMax);
371  CoordBBox region(Coord::floor(idxMin), Coord::floor(idxMax));
372  // Construct a boolean mask grid that is true inside the index-space bounding box
373  // and false everywhere else.
374  BoolGridT clipMask(/*background=*/false);
375  clipMask.fill(region, /*value=*/true, /*active=*/true);
376 
377  return clip_internal::doClip(grid, clipMask);
378 }
379 
380 
381 template<typename GridType, typename MaskTreeType>
383 inline typename GridType::Ptr
384 clip(const GridType& grid, const Grid<MaskTreeType>& maskGrid)
385 {
386  typedef typename GridType::template ValueConverter<bool>::Type BoolGridT;
387  typedef typename BoolGridT::Ptr BoolGridPtrT;
388 
389  typedef Grid<MaskTreeType> MaskGridType;
390  typedef typename MaskGridType::template ValueConverter<bool>::Type BoolMaskGridT;
391  typedef typename BoolMaskGridT::Ptr BoolMaskGridPtrT;
392 
393  // Convert the mask grid to a boolean grid with the same tree configuration.
394  BoolMaskGridPtrT boolMaskGrid = clip_internal::convertToBoolMaskGrid(maskGrid);
395 
396  // Resample the boolean mask grid into the source grid's index space.
397  if (grid.constTransform() != boolMaskGrid->constTransform()) {
398  BoolMaskGridPtrT resampledMask = BoolMaskGridT::create(/*background=*/false);
399  resampledMask->setTransform(grid.constTransform().copy());
400  tools::resampleToMatch<clip_internal::BoolSampler>(*boolMaskGrid, *resampledMask);
401  tools::prune(resampledMask->tree());
402  boolMaskGrid = resampledMask;
403  }
404 
405  // Convert the bool mask grid to a bool grid of the same configuration as the source grid.
406  BoolGridPtrT clipMask =
407  clip_internal::ConvertGrid</*from=*/BoolMaskGridT, /*to=*/BoolGridT>()(boolMaskGrid);
408 
409  // Clip the source grid against the boolean mask grid.
410  return clip_internal::doClip(grid, *clipMask);
411 }
412 
413 } // namespace tools
414 } // namespace OPENVDB_VERSION_NAME
415 } // namespace openvdb
416 
417 #endif // OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED
418 
419 // Copyright (c) 2012-2014 DreamWorks Animation LLC
420 // All rights reserved. This software is distributed under the
421 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
static bool mipmap()
Definition: Clip.h:222
TreeT::template ValueConverter< bool >::Type BoolTreeT
Definition: Clip.h:129
static bool consistent()
Definition: Clip.h:223
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
OPENVDB_STATIC_SPECIALIZATION GridType::Ptr clip(const GridType &grid, const Grid< MaskTreeType > &mask)
Clip a grid against the active voxels of another grid and return a new grid containing the result...
Definition: Clip.h:384
TreeT::LeafNodeType LeafNodeT
Definition: Clip.h:100
CopyLeafNodes(const TreeT &tree, const BoolLeafManagerT &leafNodes)
Definition: Clip.h:151
tree::LeafManager< const BoolTreeT > BoolLeafManagerT
Definition: Clip.h:130
Defined various multi-threaded utility functions for trees.
static int radius()
Definition: Clip.h:221
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:476
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:210
boost::disable_if< boost::is_signed< T >, bool >::type lessThanZero(const T &)
Definition: Clip.h:89
void operator()(const tbb::blocked_range< size_t > &)
Definition: Clip.h:179
Definition: Types.h:210
boost::enable_if< boost::is_signed< T >, bool >::type lessThanZero(const T &v)
Definition: Clip.h:84
GridType::Ptr doClip(const GridType &grid, const typename GridType::template ValueConverter< bool >::Type &aMask)
Definition: Clip.h:294
#define OPENVDB_VERSION_NAME
Definition: version.h:43
OPENVDB_API void calculateBounds(const Transform &t, const Vec3d &minWS, const Vec3d &maxWS, Vec3d &minIS, Vec3d &maxIS)
Calculate an axis-aligned bounding box in index space from an axis-aligned bounding box in world spac...
void operator()(LeafNodeType &leaf, size_t) const
Definition: Clip.h:105
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:217
Index32 Index
Definition: Types.h:59
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:383
Definition: Exceptions.h:39
ToGridPtrT operator()(const FromGridPtrT &grid)
Definition: Clip.h:247
boost::disable_if< boost::is_same< bool, typename GridT::ValueType >, typename GridT::template ValueConverter< bool >::Type::Ptr >::type convertToBoolMaskGrid(const GridT &grid)
Definition: Clip.h:267
Vec3< double > Vec3d
Definition: Vec3.h:629
MaskInteriorVoxels(const TreeT &tree)
Definition: Clip.h:102
OPENVDB_STATIC_SPECIALIZATION GridType::Ptr clip(const GridType &grid, const BBoxd &)
Clip the given grid against a world-space bounding box and return a new grid containing the result...
Definition: Clip.h:364
void join(const CopyLeafNodes &rhs)
Definition: Clip.h:140
TreeT::Ptr tree() const
Definition: Clip.h:136
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:347
FromGridT::Ptr FromGridPtrT
Definition: Clip.h:245
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Definition: Clip.h:226
static const char * name()
Definition: Clip.h:220
GridClass
Definition: Types.h:208
#define OPENVDB_STATIC_SPECIALIZATION
Macro for determining if there are sufficient C++0x/C++11 features.
Definition: Platform.h:89
GridPtrT operator()(const GridPtrT &grid)
Definition: Clip.h:256
const Vec3T & min() const
Return a const reference to the minimum point of the BBox.
Definition: BBox.h:81
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
void run(bool threaded=true)
Definition: Clip.h:170
const Vec3T & max() const
Return a const reference to the maximum point of the BBox.
Definition: BBox.h:84
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
ToGridT::Ptr ToGridPtrT
Definition: Clip.h:246
math::BBox< Vec3d > BBoxd
Definition: Types.h:87
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:220
TreeT::ValueType ValueT
Definition: Clip.h:99
RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:211
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:314