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