OpenVDB 10.0.1
Loading...
Searching...
No Matches
PointsToMask.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-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
64namespace openvdb {
66namespace OPENVDB_VERSION_NAME {
67namespace tools {
68
69// Forward declaration of main class
70template<typename GridT = MaskGrid, typename InterrupterT = util::NullInterrupter>
71class PointsToMask;
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
77template<typename PointListT, typename GridT>
78inline void
79maskPoints(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.
92template<typename PointListT>
93inline MaskGrid::Ptr
94createPointMask(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.
105template<typename GridT, typename InterrupterT>
107{
108public:
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
149private:
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
177template<typename GridT, typename InterrupterT>
178template<typename PointListT, typename VecT>
179struct 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
210template<typename GridT, typename InterrupterT>
211struct 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
233 ReducePool(const ReducePool&, tbb::split)
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
SharedPtr< Grid > Ptr
Definition: Grid.h:573
Definition: Transform.h:40
Coord worldToIndexCellCentered(const Vec3d &xyz) const
Definition: Transform.h:111
Ptr copy() const
Definition: Transform.h:50
Makes every voxel of a grid active if it contains a point.
Definition: PointsToMask.h:107
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
typename GridT::ValueType ValueT
Definition: PointsToMask.h:109
PointsToMask(GridT &grid, InterrupterT *interrupter=nullptr)
Constructor from a grid and optional interrupter.
Definition: PointsToMask.h:115
void maskPoints(const PointListT &points, GridT &grid)
Makes every voxel of the grid active if it contains a point.
Definition: PointsToMask.h:79
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
Definition: Exceptions.h:13
~ReducePool()
Definition: PointsToMask.h:239
typename VecT::iterator IterT
Definition: PointsToMask.h:214
const bool mOwnsGrid
Definition: PointsToMask.h:248
GridT * mGrid
Definition: PointsToMask.h:249
void operator()(const RangeT &r)
Definition: PointsToMask.h:241
std::vector< GridT * > VecT
Definition: PointsToMask.h:213
ReducePool(const ReducePool &, tbb::split)
Definition: PointsToMask.h:233
void join(ReducePool &other)
Definition: PointsToMask.h:246
ReducePool(PoolType &pool, GridT *grid, size_t grainSize=1)
Definition: PointsToMask.h:217
tbb::blocked_range< IterT > RangeT
Definition: PointsToMask.h:215
#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:212