49 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 50 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 56 #include <tbb/parallel_sort.h> 57 #include <tbb/parallel_for.h> 68 template<
typename PointAccessorType,
69 typename RandomGenerator,
70 typename InterruptType = util::NullInterrupter>
111 template<
typename PointAccessorType,
112 typename RandomGenerator,
123 RandomGenerator& randGen,
125 InterruptType* interrupt =
nullptr)
126 :
BaseT(points, randGen, spread, interrupt)
128 , mPointsPerVolume(0.0f)
132 float pointsPerVolume,
133 RandomGenerator& randGen,
135 InterruptType* interrupt =
nullptr)
136 :
BaseT(points, randGen, spread, interrupt)
137 , mTargetPointCount(0)
138 , mPointsPerVolume(pointsPerVolume)
143 template<
typename Gr
idT>
146 mVoxelCount = grid.activeVoxelCount();
147 if (mVoxelCount == 0)
return false;
149 const auto voxelVolume = grid.transform().voxelVolume();
150 if (mPointsPerVolume > 0) {
151 BaseT::start(
"Uniform scattering with fixed point density");
152 mTargetPointCount =
Index64(mPointsPerVolume * voxelVolume *
double(mVoxelCount));
153 }
else if (mTargetPointCount > 0) {
154 BaseT::start(
"Uniform scattering with fixed point count");
155 mPointsPerVolume = mTargetPointCount / float(voxelVolume * mVoxelCount);
160 std::unique_ptr<Index64[]> idList{
new Index64[mTargetPointCount]};
162 for (
Index64 i=0; i<mTargetPointCount; ++i) idList[i] = rand();
163 tbb::parallel_sort(idList.get(), idList.get() + mTargetPointCount);
166 const Vec3R offset(0.5, 0.5, 0.5);
167 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
169 for (
Index64 i=0, n=valueIter.getVoxelCount() ; i != mTargetPointCount; ++i) {
170 if (BaseT::interrupt())
return false;
171 const Index64 voxelId = idList[i];
172 while ( n <= voxelId ) {
174 n += valueIter.getVoxelCount();
176 if (valueIter.isVoxelValue()) {
177 BaseT::addPoint(grid, valueIter.getCoord() - offset);
179 valueIter.getBoundingBox(bbox);
180 BaseT::addPoint(grid, bbox.min() - offset, bbox.extents());
191 void print(
const std::string &name, std::ostream& os = std::cout)
const 193 os <<
"Uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
194 <<
" active voxels in \"" << name <<
"\" corresponding to " 195 << mPointsPerVolume <<
" points per volume." << std::endl;
203 using BaseT::mPointCount;
204 using BaseT::mVoxelCount;
206 float mPointsPerVolume;
212 template<
typename PointAccessorType,
213 typename RandomGenerator,
223 float pointsPerVoxel,
224 RandomGenerator& randGen,
226 InterruptType* interrupt =
nullptr)
227 :
BaseT(points, randGen, spread, interrupt)
228 , mPointsPerVoxel(pointsPerVoxel)
233 template<
typename Gr
idT>
236 using ValueIter =
typename GridT::ValueOnCIter;
237 if (mPointsPerVoxel < 1.0e-6)
return false;
238 mVoxelCount = grid.activeVoxelCount();
239 if (mVoxelCount == 0)
return false;
240 BaseT::start(
"Dense uniform scattering with fixed point count");
242 const Vec3R offset(0.5, 0.5, 0.5);
245 const double delta = mPointsPerVoxel - ppv;
248 for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) {
249 if (BaseT::interrupt())
return false;
250 if (iter.isVoxelValue()) {
251 const Vec3R dmin = iter.getCoord() - offset;
252 for (
int n = 0; n != ppv; ++n) BaseT::addPoint(grid, dmin);
253 if (fractional && BaseT::getRand01() < delta) BaseT::addPoint(grid, dmin);
255 iter.getBoundingBox(bbox);
257 const Vec3R dmin = bbox.
min() - offset;
258 const double d = mPointsPerVoxel * iter.getVoxelCount();
260 for (
int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size);
261 if (BaseT::getRand01() < d - m) BaseT::addPoint(grid, dmin, size);
271 void print(
const std::string &name, std::ostream& os = std::cout)
const 273 os <<
"Dense uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
274 <<
" active voxels in \"" << name <<
"\" corresponding to " 275 << mPointsPerVoxel <<
" points per voxel." << std::endl;
281 using BaseT::mPointCount;
282 using BaseT::mVoxelCount;
283 float mPointsPerVoxel;
294 template<
typename PointAccessorType,
295 typename RandomGenerator,
305 float pointsPerVolume,
306 RandomGenerator& randGen,
308 InterruptType* interrupt =
nullptr)
309 :
BaseT(points, randGen, spread, interrupt)
310 , mPointsPerVolume(pointsPerVolume)
316 template<
typename Gr
idT>
319 if (mPointsPerVolume <= 0.0f)
return false;
320 mVoxelCount = grid.activeVoxelCount();
321 if (mVoxelCount == 0)
return false;
322 BaseT::start(
"Non-uniform scattering with local point density");
323 const Vec3d dim = grid.voxelSize();
324 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
325 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
327 const Vec3R offset(0.5, 0.5, 0.5);
328 for (
typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
329 if (BaseT::interrupt())
return false;
330 const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
331 const int n = int(d);
332 if (iter.isVoxelValue()) {
333 const Vec3R dmin =iter.getCoord() - offset;
334 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin);
335 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin);
337 iter.getBoundingBox(bbox);
339 const Vec3R dmin = bbox.
min() - offset;
340 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin, size);
341 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin, size);
350 void print(
const std::string &name, std::ostream& os = std::cout)
const 352 os <<
"Non-uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
353 <<
" active voxels in \"" << name <<
"\"." << std::endl;
359 using BaseT::mPointCount;
360 using BaseT::mVoxelCount;
361 float mPointsPerVolume;
366 template<
typename PointAccessorType,
367 typename RandomGenerator,
368 typename InterruptType>
369 class BasePointScatter
388 RandomGenerator& randGen,
390 InterruptType* interrupt =
nullptr)
392 , mInterrupter(interrupt)
396 , mSpread(math::
Clamp01(spread))
403 if (mInterrupter) mInterrupter->start(name);
408 if (mInterrupter) mInterrupter->end();
421 inline double getRand() {
return 0.5 + mSpread * (mRand01() - 0.5); }
423 template <
typename Gr
idT>
426 const Vec3R pos(dmin[0] + this->getRand(),
427 dmin[1] + this->getRand(),
428 dmin[2] + this->getRand());
429 mPoints.add(grid.indexToWorld(pos));
433 template <
typename Gr
idT>
436 const Vec3R pos(dmin[0] + size[0]*this->getRand(),
437 dmin[1] + size[1]*this->getRand(),
438 dmin[2] + size[2]*this->getRand());
439 mPoints.add(grid.indexToWorld(pos));
448 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
uint64_t Index64
Definition: Types.h:60
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition: Math.h:320
Coord extents() const
Definition: Coord.h:386
Vec3< double > Vec3d
Definition: Vec3.h:679
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
Simple random integer generator.
Definition: Math.h:171
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
int Floor(float x)
Return the floor of x.
Definition: Math.h:802
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
Type Clamp01(Type x)
Return x clamped to [0, 1].
Definition: Math.h:240
const Coord & min() const
Definition: Coord.h:337
Definition: Exceptions.h:40
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:115
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188