OpenVDB  3.2.0
PointScatter.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 //
48 
49 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
50 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
51 
52 #include <openvdb/Types.h>
53 #include <openvdb/Grid.h>
54 #include <openvdb/math/Math.h>
55 #include <openvdb/util/NullInterrupter.h>
56 #include <tbb/parallel_sort.h>
57 #include <tbb/parallel_for.h>
58 #include <boost/scoped_array.hpp>
59 
60 namespace openvdb {
62 namespace OPENVDB_VERSION_NAME {
63 namespace tools {
64 
66 template<typename PointAccessorType,
67  typename RandomGenerator,
68  typename InterruptType = util::NullInterrupter>
70 
100 
101 
109 template<typename PointAccessorType,
110  typename RandomGenerator,
111  typename InterruptType = util::NullInterrupter>
112 class UniformPointScatter : public BasePointScatter<PointAccessorType,
113  RandomGenerator,
114  InterruptType>
115 {
116 public:
118 
119  UniformPointScatter(PointAccessorType& points,
120  Index64 pointCount,
121  RandomGenerator& randGen,
122  InterruptType* interrupt = NULL)
123  : BaseT(points, randGen, interrupt)
124  , mTargetPointCount(pointCount)
125  , mPointsPerVolume(0.0f)
126  {
127  }
128  UniformPointScatter(PointAccessorType& points,
129  float pointsPerVolume,
130  RandomGenerator& randGen,
131  InterruptType* interrupt = NULL)
132  : BaseT(points, randGen, interrupt)
133  , mTargetPointCount(0)
134  , mPointsPerVolume(pointsPerVolume)
135  {
136  }
137 
140  template<typename GridT>
141  bool operator()(const GridT& grid)
142  {
143  mVoxelCount = grid.activeVoxelCount();
144  if (mVoxelCount == 0) return false;
145  const Vec3d dim = grid.voxelSize();
146  if (mPointsPerVolume>0) {
147  BaseT::start("Uniform scattering with fixed point density");
148  mTargetPointCount = Index64(mPointsPerVolume*dim[0]*dim[1]*dim[2])*mVoxelCount;
149  } else if (mTargetPointCount>0) {
150  BaseT::start("Uniform scattering with fixed point count");
151  mPointsPerVolume = mTargetPointCount/float(dim[0]*dim[1]*dim[2] * mVoxelCount);
152  } else {
153  return false;
154  }
155 
156  boost::scoped_array<Index64> list(new Index64[mTargetPointCount]);
157  math::RandInt<Index64, RandomGenerator> rand(BaseT::mRand01.engine(), 0, mVoxelCount-1);
158  for (Index64 i=0; i<mTargetPointCount; ++i) list[i] = rand();
159  tbb::parallel_sort(list.get(), list.get() + mTargetPointCount);
160 
161  CoordBBox bbox;
162  const Vec3R offset(0.5, 0.5, 0.5);
163  typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
164  for (Index64 i=0, n=valueIter.getVoxelCount() ; i != mTargetPointCount; ++i) {
165  if (BaseT::interrupt()) return false;
166  const Index64 voxelId = list[i];
167  while ( n <= voxelId ) {
168  ++valueIter;
169  n += valueIter.getVoxelCount();
170  }
171  if (valueIter.isVoxelValue()) {// a majority is expected to be voxels
172  BaseT::addPoint(grid, valueIter.getCoord() - offset);
173  } else {// tiles contain multiple (virtual) voxels
174  valueIter.getBoundingBox(bbox);
175  BaseT::addPoint(grid, bbox.min() - offset, bbox.extents());
176  }
177  }//loop over all the active voxels and tiles
178 
179  BaseT::end();
180  return true;
181  }
182 
183  // The following methods should only be called after the
184  // the operator() method was called
185  void print(const std::string &name, std::ostream& os = std::cout) const
186  {
187  os << "Uniformely scattered " << mPointCount << " points into " << mVoxelCount
188  << " active voxels in \"" << name << "\" corresponding to "
189  << mPointsPerVolume << " points per volume." << std::endl;
190  }
191 
192  float getPointsPerVolume() const { return mPointsPerVolume; }
193  Index64 getTargetPointCount() const { return mTargetPointCount; }
194 
195 private:
196 
197  using BaseT::mPointCount;
198  using BaseT::mVoxelCount;
199  Index64 mTargetPointCount;
200  float mPointsPerVolume;
201 
202 }; // class UniformPointScatter
203 
206 template<typename PointAccessorType,
207  typename RandomGenerator,
208  typename InterruptType = util::NullInterrupter>
209 class DenseUniformPointScatter : public BasePointScatter<PointAccessorType,
210  RandomGenerator,
211  InterruptType>
212 {
213 public:
215 
216  DenseUniformPointScatter(PointAccessorType& points,
217  float pointsPerVoxel,
218  RandomGenerator& randGen,
219  InterruptType* interrupt = NULL)
220  : BaseT(points, randGen, interrupt)
221  , mPointsPerVoxel(pointsPerVoxel)
222  {
223  }
224 
226  template<typename GridT>
227  bool operator()(const GridT& grid)
228  {
229  typedef typename GridT::ValueOnCIter ValueIter;
230  if (mPointsPerVoxel < 1.0e-6) return false;
231  mVoxelCount = grid.activeVoxelCount();
232  if (mVoxelCount == 0) return false;
233  BaseT::start("Dense uniform scattering with fixed point count");
234  CoordBBox bbox;
235  const Vec3R offset(0.5, 0.5, 0.5);
236 
237  const int ppv = math::Floor(mPointsPerVoxel);
238  const double delta = mPointsPerVoxel - ppv;
239  const bool fractional = !math::isApproxZero(delta, 1.0e-6);
240 
241  for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) {
242  if (BaseT::interrupt()) return false;
243  if (iter.isVoxelValue()) {// a majority is expected to be voxels
244  const Vec3R dmin = iter.getCoord() - offset;
245  for (int n = 0; n != ppv; ++n) BaseT::addPoint(grid, dmin);
246  if (fractional && BaseT::getRand() < delta) BaseT::addPoint(grid, dmin);
247  } else {// tiles contain multiple (virtual) voxels
248  iter.getBoundingBox(bbox);
249  const Coord size(bbox.extents());
250  const Vec3R dmin = bbox.min() - offset;
251  const double d = mPointsPerVoxel * iter.getVoxelCount();
252  const int m = math::Floor(d);
253  for (int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size);
254  if (BaseT::getRand() < d - m) BaseT::addPoint(grid, dmin, size);
255  }
256  }//loop over all the active voxels and tiles
257 
258  BaseT::end();
259  return true;
260  }
261 
262  // The following methods should only be called after the
263  // the operator() method was called
264  void print(const std::string &name, std::ostream& os = std::cout) const
265  {
266  os << "Dense uniformly scattered " << mPointCount << " points into " << mVoxelCount
267  << " active voxels in \"" << name << "\" corresponding to "
268  << mPointsPerVoxel << " points per voxel." << std::endl;
269  }
270 
271  float getPointsPerVoxel() const { return mPointsPerVoxel; }
272 
273 private:
274  using BaseT::mPointCount;
275  using BaseT::mVoxelCount;
276  float mPointsPerVoxel;
277 }; // class DenseUniformPointScatter
278 
287 template<typename PointAccessorType,
288  typename RandomGenerator,
289  typename InterruptType = util::NullInterrupter>
290 class NonUniformPointScatter : public BasePointScatter<PointAccessorType,
291  RandomGenerator,
292  InterruptType>
293 {
294 public:
296 
297  NonUniformPointScatter(PointAccessorType& points,
298  float pointsPerVolume,
299  RandomGenerator& randGen,
300  InterruptType* interrupt = NULL)
301  : BaseT(points, randGen, interrupt)
302  , mPointsPerVolume(pointsPerVolume)//note this is merely a
303  //multiplier for the local point density
304  {
305  }
306 
308  template<typename GridT>
309  bool operator()(const GridT& grid)
310  {
311  if (mPointsPerVolume <= 0.0f) return false;
312  mVoxelCount = grid.activeVoxelCount();
313  if (mVoxelCount == 0) return false;
314  BaseT::start("Non-uniform scattering with local point density");
315  const Vec3d dim = grid.voxelSize();
316  const double volumePerVoxel = dim[0]*dim[1]*dim[2],
317  pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
318  CoordBBox bbox;
319  const Vec3R offset(0.5, 0.5, 0.5);
320  for (typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
321  if (BaseT::interrupt()) return false;
322  const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
323  const int n = int(d);
324  if (iter.isVoxelValue()) { // a majority is expected to be voxels
325  const Vec3R dmin =iter.getCoord() - offset;
326  for (int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin);
327  if (BaseT::getRand() < (d - n)) BaseT::addPoint(grid, dmin);
328  } else { // tiles contain multiple (virtual) voxels
329  iter.getBoundingBox(bbox);
330  const Coord size(bbox.extents());
331  const Vec3R dmin = bbox.min() - offset;
332  for (int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin, size);
333  if (BaseT::getRand() < (d - n)) BaseT::addPoint(grid, dmin, size);
334  }
335  }//loop over all the active voxels and tiles
336  BaseT::end();
337  return true;
338  }
339 
340  // The following methods should only be called after the
341  // the operator() method was called
342  void print(const std::string &name, std::ostream& os = std::cout) const
343  {
344  os << "Non-uniformly scattered " << mPointCount << " points into " << mVoxelCount
345  << " active voxels in \"" << name << "\"." << std::endl;
346  }
347 
348  float getPointPerVolume() const { return mPointsPerVolume; }
349 
350 private:
351  using BaseT::mPointCount;
352  using BaseT::mVoxelCount;
353  float mPointsPerVolume;
354 
355 }; // class NonUniformPointScatter
356 
358 template<typename PointAccessorType,
359  typename RandomGenerator,
360  typename InterruptType>
361 class BasePointScatter
362 {
363 public:
364 
365  Index64 getPointCount() const { return mPointCount; }
366  Index64 getVoxelCount() const { return mVoxelCount; }
367 
368 protected:
369 
371  BasePointScatter(PointAccessorType& points,
372  RandomGenerator& randGen,
373  InterruptType* interrupt = NULL)
374  : mPoints(points)
375  , mInterrupter(interrupt)
376  , mPointCount(0)
377  , mVoxelCount(0)
378  , mInterruptCount(0)
379  , mRand01(randGen)
380  {
381  }
382 
383  PointAccessorType& mPoints;
384  InterruptType* mInterrupter;
389 
390  inline void start(const char* name)
391  {
392  if (mInterrupter) mInterrupter->start(name);
393  }
394 
395  inline void end()
396  {
397  if (mInterrupter) mInterrupter->end();
398  }
399 
400  inline bool interrupt()
401  {
402  //only check interrupter for every 32'th call
403  return !(mInterruptCount++ & ((1<<5)-1)) && util::wasInterrupted(mInterrupter);
404  }
405 
406  inline double getRand() { return mRand01(); }
407 
408  template <typename GridT>
409  inline void addPoint(const GridT &grid, const Vec3R &dmin)
410  {
411  const Vec3R pos(dmin[0] + this->getRand(),
412  dmin[1] + this->getRand(),
413  dmin[2] + this->getRand());
414  mPoints.add(grid.indexToWorld(pos));
415  ++mPointCount;
416  }
417 
418  template <typename GridT>
419  inline void addPoint(const GridT &grid, const Vec3R &dmin, const Coord &size)
420  {
421  const Vec3R pos(dmin[0] + size[0]*this->getRand(),
422  dmin[1] + size[1]*this->getRand(),
423  dmin[2] + size[2]*this->getRand());
424  mPoints.add(grid.indexToWorld(pos));
425  ++mPointCount;
426  }
427 };// class BasePointScatter
428 
429 } // namespace tools
430 } // namespace OPENVDB_VERSION_NAME
431 } // namespace openvdb
432 
433 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
434 
435 // Copyright (c) 2012-2016 DreamWorks Animation LLC
436 // All rights reserved. This software is distributed under the
437 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:342
math::Rand01< double, RandomGenerator > mRand01
Definition: PointScatter.h:388
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
BasePointScatter< PointAccessorType, RandomGenerator, InterruptType > BaseT
Definition: PointScatter.h:295
Index64 mPointCount
Definition: PointScatter.h:385
UniformPointScatter(PointAccessorType &points, Index64 pointCount, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:119
Index64 mInterruptCount
Definition: PointScatter.h:387
Index64 getTargetPointCount() const
Definition: PointScatter.h:193
void addPoint(const GridT &grid, const Vec3R &dmin, const Coord &size)
Definition: PointScatter.h:419
DenseUniformPointScatter(PointAccessorType &points, float pointsPerVoxel, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:216
Index64 getPointCount() const
Definition: PointScatter.h:365
Index64 getVoxelCount() const
Definition: PointScatter.h:366
The two point scatters UniformPointScatter and NonUniformPointScatter depend on the following two cla...
Definition: PointScatter.h:112
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:264
Simple random integer generator.
Definition: Math.h:179
float getPointsPerVoxel() const
Definition: PointScatter.h:271
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:227
Index64 mVoxelCount
Definition: PointScatter.h:386
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:185
uint64_t Index64
Definition: Types.h:57
Scatters a fixed (and integer) number of points in all active voxels and tiles.
Definition: PointScatter.h:209
#define OPENVDB_VERSION_NAME
Definition: version.h:43
BasePointScatter< PointAccessorType, RandomGenerator, InterruptType > BaseT
Definition: PointScatter.h:117
Vec3< double > Vec3d
Definition: Vec3.h:651
NonUniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:297
Non-uniform scatters of point in the active voxels. The local point count is implicitly defined as a ...
Definition: PointScatter.h:290
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:141
BasePointScatter(PointAccessorType &points, RandomGenerator &randGen, InterruptType *interrupt=NULL)
This is a base class so the constructor is protected.
Definition: PointScatter.h:371
BasePointScatter< PointAccessorType, RandomGenerator, InterruptType > BaseT
Definition: PointScatter.h:214
bool interrupt()
Definition: PointScatter.h:400
PointAccessorType & mPoints
Definition: PointScatter.h:383
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:309
Definition: Exceptions.h:39
double getRand()
Definition: PointScatter.h:406
InterruptType * mInterrupter
Definition: PointScatter.h:384
UniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:128
Forward declaration of base class.
Definition: PointScatter.h:69
float getPointPerVolume() const
Definition: PointScatter.h:348
int Floor(float x)
Return the floor of x.
Definition: Math.h:814
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:336
float getPointsPerVolume() const
Definition: PointScatter.h:192
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
void end()
Definition: PointScatter.h:395
void start(const char *name)
Definition: PointScatter.h:390
void addPoint(const GridT &grid, const Vec3R &dmin)
Definition: PointScatter.h:409
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76