33 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
34 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
36 #include <openvdb/Types.h>
37 #include <openvdb/Grid.h>
38 #include <openvdb/util/NullInterrupter.h>
39 #include <boost/random/uniform_01.hpp>
85 typename PointAccessorType,
86 typename RandomGenerator,
87 typename InterruptType = openvdb::util::NullInterrupter>
99 double getRand() {
return mRandom(mRandomGen); }
101 template <
typename Gr
idT>
104 mPoints.add(grid.indexToWorld(pos + delta));
107 template <
typename Gr
idT>
110 this->addPoint(grid, dmin,
openvdb::Vec3R(getRand(),getRand(),getRand()));
112 template <
typename Gr
idT>
115 const openvdb::Vec3R d(size.
x()*getRand(),size.
y()*getRand(),size.
z()*getRand());
116 this->addPoint(grid, dmin, d);
122 RandomGenerator& randGen,
123 InterruptType* interrupt = NULL):
125 mInterrupter(interrupt),
126 mPointCount(pointCount),
127 mPointsPerVolume(0.0f),
133 float pointsPerVolume,
134 RandomGenerator& randGen,
135 InterruptType* interrupt = NULL):
137 mInterrupter(interrupt),
139 mPointsPerVolume(pointsPerVolume),
146 template<
typename Gr
idT>
147 void operator()(
const GridT& grid)
149 mVoxelCount = grid.activeVoxelCount();
150 if (mVoxelCount == 0)
throw std::runtime_error(
"No voxels in which to scatter points!");
153 if (mPointsPerVolume>0) {
154 if (mInterrupter) mInterrupter->start(
"Uniform scattering with fixed point density");
155 mPointCount = int(mPointsPerVolume * dim[0]*dim[1]*dim[2] * mVoxelCount);
156 }
else if (mPointCount>0) {
157 if (mInterrupter) mInterrupter->start(
"Uniform scattering with fixed point count");
158 mPointsPerVolume = mPointCount/float(dim[0]*dim[1]*dim[2] * mVoxelCount);
160 throw std::runtime_error(
"Invalid point count and point density");
164 std::multiset<openvdb::Index64> mVoxelSet;
165 for (
int i=0, chunks=100000; i<mPointCount; i += chunks) {
166 if (mInterrupter && mInterrupter->wasInterrupted()) {
167 throw std::runtime_error(
"processing was interrupted");
170 for (
int j=i, end=
std::min(i+chunks, mPointCount); j<end; ++j) {
174 std::multiset<openvdb::Index64>::iterator voxelIter =
175 mVoxelSet.begin(), voxelEnd = mVoxelSet.end();
176 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
178 for (
openvdb::Index64 i=valueIter.getVoxelCount(); voxelIter != voxelEnd; ++voxelIter) {
179 if (mInterrupter && mInterrupter->wasInterrupted()) {
180 throw std::runtime_error(
"processing was interrupted");
182 while ( i <= *voxelIter ) {
184 i += valueIter.getVoxelCount();
186 if (valueIter.isVoxelValue()) {
189 this->addPoint(grid, dmin);
191 valueIter.getBoundingBox(bbox);
196 this->addPoint(grid, dmin, size);
199 if (mInterrupter) mInterrupter->end();
204 void print(
const std::string &name, std::ostream& os = std::cout)
const
206 os <<
"Uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
207 <<
" active voxels in \"" << name <<
"\" corresponding to "
208 << mPointsPerVolume <<
" points per volume." << std::endl;
225 typename PointAccessorType,
226 typename RandomGenerator,
227 typename InterruptType = openvdb::util::NullInterrupter>
239 double getRand() {
return mRandom(mRandomGen); }
241 template <
typename Gr
idT>
244 mPoints.add(grid.indexToWorld(pos + delta));
247 template <
typename Gr
idT>
250 this->addPoint(grid, dmin,
openvdb::Vec3R(getRand(),getRand(),getRand()));
252 template <
typename Gr
idT>
255 const openvdb::Vec3R d(size.
x()*getRand(),size.
y()*getRand(),size.
z()*getRand());
256 this->addPoint(grid, dmin, d);
261 float pointsPerVolume,
262 RandomGenerator& randGen,
263 InterruptType* interrupt = NULL):
265 mInterrupter(interrupt),
267 mPointsPerVolume(pointsPerVolume),
274 template<
typename Gr
idT>
275 void operator()(
const GridT& grid)
277 mVoxelCount = grid.activeVoxelCount();
278 if (mVoxelCount == 0)
throw std::runtime_error(
"No voxels in which to scatter points!");
279 if (mInterrupter) mInterrupter->start(
"Non-uniform scattering with local point density");
281 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
282 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
284 for (
typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
285 if (mInterrupter && mInterrupter->wasInterrupted()) {
286 throw std::runtime_error(
"processing was interrupted");
288 const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
289 const int n = int(d);
290 if (iter.isVoxelValue()) {
293 for (
int i = 0; i < n; ++i) this->addPoint(grid, dmin);
294 if (getRand() < (d - n)) this->addPoint(grid, dmin);
296 iter.getBoundingBox(bbox);
301 for (
int i = 0; i < n; ++i) this->addPoint(grid, dmin, size);
302 if (getRand() < (d - n)) this->addPoint(grid, dmin, size);
305 if (mInterrupter) mInterrupter->end();
310 void print(
const std::string &name, std::ostream& os = std::cout)
const
312 os <<
"Non-uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
313 <<
" active voxels in \"" << name <<
"\"." << std::endl;
324 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED