OpenVDB  12.0.0
PointsToMask.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @author Ken Museth
5 ///
6 /// @file tools/PointsToMask.h
7 ///
8 /// @brief This tool produces a grid where every voxel that contains a
9 /// point is active. It employs thread-local storage for best performance.
10 ///
11 /// The @c PointListT template argument below refers to any class
12 /// with the following interface (see unittest/TestPointsToMask.cc
13 /// and SOP_OpenVDB_From_Particles.cc for practical examples):
14 /// @code
15 ///
16 /// class PointList {
17 /// ...
18 /// public:
19 ///
20 /// // Return the total number of particles in list.
21 /// size_t size() const;
22 ///
23 /// // Get the world space position of the nth particle.
24 /// void getPos(size_t n, Vec3R& xyz) const;
25 /// };
26 /// @endcode
27 ///
28 /// @note See unittest/TestPointsToMask.cc for an example.
29 ///
30 /// The @c InterruptT template argument below refers to any class
31 /// with the following interface:
32 /// @code
33 /// class Interrupter {
34 /// ...
35 /// public:
36 /// void start(const char* name = nullptr) // called when computations begin
37 /// void end() // called when computations end
38 /// bool wasInterrupted(int percent = -1) // return true to break computation
39 /// };
40 /// @endcode
41 ///
42 /// @note If no template argument is provided for this InterruptT
43 /// the util::NullInterrupter is used which implies that all
44 /// interrupter calls are no-ops (i.e. incurs no computational overhead).
45 
46 #ifndef OPENVDB_TOOLS_POINTSTOMASK_HAS_BEEN_INCLUDED
47 #define OPENVDB_TOOLS_POINTSTOMASK_HAS_BEEN_INCLUDED
48 
49 
50 #include <openvdb/openvdb.h> // for MaskGrid
51 #include <openvdb/Grid.h>
52 #include <openvdb/Types.h>
54 #include <openvdb/thread/Threading.h>
55 
56 #include <tbb/enumerable_thread_specific.h>
57 #include <tbb/parallel_for.h>
58 #include <tbb/parallel_reduce.h>
59 #include <tbb/blocked_range.h>
60 
61 #include <vector>
62 
63 
64 namespace openvdb {
66 namespace OPENVDB_VERSION_NAME {
67 namespace tools {
68 
69 // Forward declaration of main class
70 template<typename GridT = MaskGrid, typename InterrupterT = util::NullInterrupter>
72 
73 /// @brief Makes every voxel of the @c grid active if it contains a point.
74 ///
75 /// @param points points that active the voxels of @c grid
76 /// @param grid on out its voxels with points are active
77 template<typename PointListT, typename GridT>
78 inline void
79 maskPoints(const PointListT& points, GridT& grid)
80 {
82  tmp.addPoints(points);
83 }
84 
85 /// @brief Return a MaskGrid where each binary voxel value
86 /// is on if the voxel contains one (or more) points (i.e.
87 /// the 3D position of a point is closer to this voxel than
88 /// any other voxels).
89 ///
90 /// @param points points that active the voxels in the returned grid.
91 /// @param xform transform from world space to voxels in grid space.
92 template<typename PointListT>
93 inline MaskGrid::Ptr
94 createPointMask(const PointListT& points, const math::Transform& xform)
95 {
96  MaskGrid::Ptr grid = createGrid<MaskGrid>( false );
97  grid->setTransform( xform.copy() );
98  maskPoints( points, *grid );
99  return grid;
100 }
101 
102 ////////////////////////////////////////
103 
104 /// @brief Makes every voxel of a grid active if it contains a point.
105 template<typename GridT, typename InterrupterT>
106 class PointsToMask
107 {
108 public:
109  using ValueT = typename GridT::ValueType;
110 
111  /// @brief Constructor from a grid and optional interrupter
112  ///
113  /// @param grid Grid whose voxels will have their state activated by points.
114  /// @param interrupter Optional interrupter to prematurely terminate execution.
115  explicit PointsToMask(GridT& grid, InterrupterT* interrupter = nullptr)
116  : mGrid(&grid)
117  , mInterrupter(interrupter)
118  {
119  }
120 
121  /// @brief Activates the state of any voxel in the input grid that contains a point.
122  ///
123  /// @param points List of points that active the voxels in the input grid.
124  /// @param grainSize Set the grain-size used for multi-threading. A value of 0
125  /// disables multi-threading!
126  template<typename PointListT, typename VecT = Vec3R>
127  void addPoints(const PointListT& points, size_t grainSize = 1024)
128  {
129  if (mInterrupter) mInterrupter->start("PointsToMask: adding points");
130  if (grainSize > 0) {
131  typename GridT::Ptr examplar = mGrid->copyWithNewTree();
132  PoolType pool( *examplar );//thread local storage pool of grids
133  AddPoints<PointListT, VecT> tmp(points, pool, grainSize, *this );
134  if ( this->interrupt() ) return;
135  ReducePool reducePool(pool, mGrid, size_t(0));
136  } else {
137  const math::Transform& xform = mGrid->transform();
138  typename GridT::Accessor acc = mGrid->getAccessor();
139  VecT wPos;
140  for (size_t i = 0, n = points.size(); i < n; ++i) {
141  if ( this->interrupt() ) break;
142  points.getPos(i, wPos);
143  acc.setValueOn( xform.worldToIndexCellCentered( wPos ) );
144  }
145  }
146  if (mInterrupter) mInterrupter->end();
147  }
148 
149 private:
150  // Disallow copy construction and copy by assignment!
151  PointsToMask(const PointsToMask&);// not implemented
152  PointsToMask& operator=(const PointsToMask&);// not implemented
153 
154  bool interrupt() const
155  {
156  if (mInterrupter && util::wasInterrupted(mInterrupter)) {
157  thread::cancelGroupExecution();
158  return true;
159  }
160  return false;
161  }
162 
163  // Private struct that implements concurrent thread-local
164  // insersion of points into a grid
165  using PoolType = tbb::enumerable_thread_specific<GridT>;
166  template<typename PointListT, typename VecT = Vec3R> struct AddPoints;
167 
168  // Private class that implements concurrent reduction of a thread-local pool
169  struct ReducePool;
170 
171  GridT* mGrid;
172  InterrupterT* mInterrupter;
173 };// PointsToMask
174 
175 // Private member class that implements concurrent thread-local
176 // insersion of points into a grid
177 template<typename GridT, typename InterrupterT>
178 template<typename PointListT, typename VecT>
179 struct PointsToMask<GridT, InterrupterT>::AddPoints
180 {
181  AddPoints(const PointListT& points,
182  PoolType& pool,
183  size_t grainSize,
184  const PointsToMask& parent)
185  : mPoints(&points)
186  , mParent(&parent)
187  , mPool(&pool)
188  {
189  tbb::parallel_for(tbb::blocked_range<size_t>(0, mPoints->size(), grainSize), *this);
190  }
191  void operator()(const tbb::blocked_range<size_t>& range) const
192  {
193  if (mParent->interrupt()) return;
194  GridT& grid = mPool->local();
195  const math::Transform& xform = grid.transform();
196  typename GridT::Accessor acc = grid.getAccessor();
197  VecT wPos;
198  for (size_t i=range.begin(), n=range.end(); i!=n; ++i) {
199  mPoints->getPos(i, wPos);
200  acc.setValueOn( xform.worldToIndexCellCentered( wPos ) );
201  }
202  }
203  const PointListT* mPoints;
204  const PointsToMask* mParent;
205  PoolType* mPool;
206 
207 };// end of private member class AddPoints
208 
209 // Private member class that implements concurrent reduction of a thread-local pool
210 template<typename GridT, typename InterrupterT>
211 struct PointsToMask<GridT, InterrupterT>::ReducePool
212 {
213  using VecT = std::vector<GridT*>;
214  using IterT = typename VecT::iterator;
215  using RangeT = tbb::blocked_range<IterT>;
216 
217  ReducePool(PoolType& pool, GridT* grid, size_t grainSize = 1)
218  : mOwnsGrid(false)
219  , mGrid(grid)
220  {
221  if (grainSize == 0) {
222  for (typename PoolType::const_iterator i = pool.begin(); i != pool.end(); ++i) {
223  mGrid->topologyUnion(*i);
224  }
225  } else {
226  VecT grids( pool.size() );
227  typename PoolType::iterator i = pool.begin();
228  for (size_t j=0; j != pool.size(); ++i, ++j) grids[j] = &(*i);
229  tbb::parallel_reduce( RangeT( grids.begin(), grids.end(), grainSize ), *this );
230  }
231  }
232 
234  : mOwnsGrid(true)
235  , mGrid(new GridT())
236  {
237  }
238 
239  ~ReducePool() { if (mOwnsGrid) delete mGrid; }
240 
241  void operator()(const RangeT& r)
242  {
243  for (IterT i=r.begin(); i!=r.end(); ++i) mGrid->topologyUnion( *(*i) );
244  }
245 
246  void join(ReducePool& other) { mGrid->topologyUnion(*other.mGrid); }
247 
248  const bool mOwnsGrid;
249  GridT* mGrid;
250 };// end of private member class ReducePool
251 
252 } // namespace tools
253 } // namespace OPENVDB_VERSION_NAME
254 } // namespace openvdb
255 
256 #endif // OPENVDB_TOOLS_POINTSTOMASK_HAS_BEEN_INCLUDED
void maskPoints(const PointListT &points, GridT &grid)
Makes every voxel of the grid active if it contains a point.
Definition: PointsToMask.h:79
tbb::blocked_range< IterT > RangeT
Definition: PointsToMask.h:215
std::vector< GridT * > VecT
Definition: PointsToMask.h:213
typename GridT::ValueType ValueT
Definition: PointsToMask.h:109
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:49
~ReducePool()
Definition: PointsToMask.h:239
void join(ReducePool &other)
Definition: PointsToMask.h:246
ReducePool(const ReducePool &, tbb::split)
Definition: PointsToMask.h:233
void split(ContainerT &out, const std::string &in, const char delim)
Definition: Name.h:43
SharedPtr< Grid > Ptr
Definition: Grid.h:573
void addPoints(const PointListT &points, size_t grainSize=1024)
Activates the state of any voxel in the input grid that contains a point.
Definition: PointsToMask.h:127
Definition: Exceptions.h:13
void operator()(const RangeT &r)
Definition: PointsToMask.h:241
typename VecT::iterator IterT
Definition: PointsToMask.h:214
Coord worldToIndexCellCentered(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:111
Ptr copy() const
Definition: Transform.h:50
PointsToMask(GridT &grid, InterrupterT *interrupter=nullptr)
Constructor from a grid and optional interrupter.
Definition: PointsToMask.h:115
Makes every voxel of a grid active if it contains a point.
Definition: PointsToMask.h:71
GridT * mGrid
Definition: PointsToMask.h:249
MaskGrid::Ptr createPointMask(const PointListT &points, const math::Transform &xform)
Return a MaskGrid where each binary voxel value is on if the voxel contains one (or more) points (i...
Definition: PointsToMask.h:94
const bool mOwnsGrid
Definition: PointsToMask.h:248
Definition: Transform.h:39
ReducePool(PoolType &pool, GridT *grid, size_t grainSize=1)
Definition: PointsToMask.h:217
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218