37 #ifndef OPENVDB_POINTS_INDEX_FILTER_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_INDEX_FILTER_HAS_BEEN_INCLUDED
50 #include <hboost/ptr_container/ptr_vector.hpp>
56 class TestIndexFilter;
67 namespace index_filter_internal {
71 template <
typename RandGenT,
typename IntType>
75 if (n <= 0)
return std::vector<IntType>();
78 std::vector<IntType>
values(m);
79 std::iota(values.begin(), values.end(), 0);
84 RandGenT randGen(seed);
85 std::shuffle(values.begin(), values.end(), randGen);
91 std::sort(values.begin(), values.end());
112 , mExclude(exclude) { }
115 : mInclude(filter.mInclude)
116 , mExclude(filter.mExclude)
117 , mIncludeHandles(filter.mIncludeHandles)
118 , mExcludeHandles(filter.mExcludeHandles)
119 , mInitialized(filter.mInitialized) { }
123 template <
typename LeafT>
125 mIncludeHandles.clear();
126 mExcludeHandles.clear();
128 if (leaf.attributeSet().descriptor().hasGroup(
name)) {
133 if (leaf.attributeSet().descriptor().hasGroup(
name)) {
140 template <
typename IterT>
141 bool valid(
const IterT& iter)
const {
142 assert(mInitialized);
144 bool includeValid = mIncludeHandles.empty();
145 for (
const GroupHandle& handle : mIncludeHandles) {
146 if (handle.get(*iter)) {
151 if (!includeValid)
return false;
152 for (
const GroupHandle& handle : mExcludeHandles) {
153 if (handle.get(*iter))
return false;
163 bool mInitialized =
false;
168 template <
typename Po
intDataTreeT,
typename RandGenT>
173 using LeafMap = std::map<openvdb::Coord, SeedCountPair>;
177 const unsigned int seed = 0) {
179 for (
auto iter = tree.cbeginLeaf(); iter; ++iter) {
180 currentPoints += iter->pointCount();
183 const float factor = targetPoints > currentPoints ? 1.0f : float(targetPoints) / float(currentPoints);
185 std::mt19937 generator(seed);
189 float totalPointsFloat = 0.0f;
191 for (
auto iter = tree.cbeginLeaf(); iter; ++iter) {
193 if (leafCounter + 1 == tree.leafCount()) {
194 const int leafPoints =
static_cast<int>(targetPoints) - totalPoints;
198 totalPointsFloat += factor * iter->pointCount();
199 const auto leafPoints =
static_cast<int>(
math::Floor(totalPointsFloat));
200 totalPointsFloat -=
static_cast<float>(leafPoints);
201 totalPoints += leafPoints;
211 template <
typename LeafT>
215 auto it = mLeafMap.find(leaf.origin());
216 if (it == mLeafMap.end()) {
218 "Cannot find leaf origin in map for random filter - " << leaf.origin());
222 const unsigned int seed =
static_cast<unsigned int>(value.first);
223 const auto total =
static_cast<Index>(leaf.pointCount());
224 mCount =
std::min(value.second, total);
226 mIndices = generateRandomSubset<RandGenT, int>(seed, mCount, total);
234 mNextIndex = mSubsetOffset >= mCount ?
236 mIndices[mSubsetOffset];
239 template <
typename IterT>
240 bool valid(
const IterT& iter)
const {
241 const int index = *iter;
242 while (mNextIndex < index) this->
next();
243 return mNextIndex ==
index;
247 friend class ::TestIndexFilter;
251 std::vector<int> mIndices;
253 mutable int mSubsetOffset = -1;
254 mutable int mNextIndex = -1;
259 template <
typename RandGenT,
typename IntType>
266 const double percentage,
267 const unsigned int seed = 0)
269 , mFactor(percentage / 100.0)
273 : mIndex(filter.mIndex)
274 , mFactor(filter.mFactor)
275 , mSeed(filter.mSeed)
277 if (filter.mIdHandle) mIdHandle.reset(
new Handle(*filter.mIdHandle));
282 template <
typename LeafT>
284 assert(leaf.hasAttribute(mIndex));
285 mIdHandle.reset(
new Handle(leaf.constAttributeArray(mIndex)));
288 template <
typename IterT>
289 bool valid(
const IterT& iter)
const {
291 const IntType
id = mIdHandle->get(*iter);
292 const unsigned int seed = mSeed +
static_cast<unsigned int>(
id);
293 RandGenT generator(seed);
294 std::uniform_real_distribution<double>
dist(0.0, 1.0);
295 return dist(generator) < mFactor;
300 const double mFactor;
301 const unsigned int mSeed;
306 template <
typename LevelSetGr
idT>
310 using ValueT =
typename LevelSetGridT::ValueType;
317 : mAccessor(grid.getConstAccessor())
318 , mLevelSetTransform(grid.transform())
319 , mTransform(transform)
324 : mAccessor(filter.mAccessor)
325 , mLevelSetTransform(filter.mLevelSetTransform)
326 , mTransform(filter.mTransform)
330 if (filter.mPositionHandle) mPositionHandle.reset(
new Handle(*filter.mPositionHandle));
335 template <
typename LeafT>
337 mPositionHandle.reset(
new Handle(leaf.constAttributeArray(
"P")));
340 template <
typename IterT>
341 bool valid(
const IterT& iter)
const {
342 assert(mPositionHandle);
345 const openvdb::Coord ijk = iter.getCoord();
349 const openvdb::Vec3f& pointVoxelSpace = mPositionHandle->get(*iter);
359 const bool invert = mMin > mMax;
366 const typename LevelSetGridT::ConstAccessor mAccessor;
383 : mTransform(transform)
384 , mBbox(transform.worldToIndex(bboxWS)) { }
387 : mTransform(filter.mTransform)
388 , mBbox(filter.mBbox)
390 if (filter.mPositionHandle) mPositionHandle.reset(
new Handle(*filter.mPositionHandle));
395 template <
typename LeafT>
397 mPositionHandle.reset(
new Handle(leaf.constAttributeArray(
"P")));
400 template <
typename IterT>
401 bool valid(
const IterT& iter)
const {
402 assert(mPositionHandle);
404 const openvdb::Coord ijk = iter.getCoord();
408 const openvdb::Vec3f& pointVoxelSpace = mPositionHandle->get(*iter);
411 const openvdb::Vec3f pointIndexSpace = pointVoxelSpace + voxelIndexSpace;
413 return mBbox.isInside(pointIndexSpace);
417 const openvdb::math::Transform& mTransform;
424 template <
typename T1,
typename T2,
bool And = true>
431 , mFilter2(filter2) { }
433 inline bool initialized()
const {
return mFilter1.initialized() && mFilter2.initialized(); }
435 template <
typename LeafT>
437 mFilter1.reset(leaf);
438 mFilter2.reset(leaf);
441 template <
typename IterT>
442 bool valid(
const IterT& iter)
const {
443 if (And)
return mFilter1.valid(iter) && mFilter2.valid(iter);
444 return mFilter1.valid(iter) || mFilter2.valid(iter);
464 template <
typename T>
468 template <
typename T0,
typename T1,
bool And>
482 #endif // OPENVDB_POINTS_INDEX_FILTER_HAS_BEEN_INCLUDED
GA_API const UT_StringHolder dist
std::unique_ptr< Handle > UniquePtr
static const bool RequiresCoord
void reset(const LeafT &leaf)
RandomLeafFilter(const PointDataTreeT &tree, const Index64 targetPoints, const unsigned int seed=0)
void reset(const LeafT &leaf)
bool valid(const IterT &iter) const
void reset(const LeafT &leaf)
LevelSetFilter(const LevelSetFilter &filter)
MultiGroupFilter(const MultiGroupFilter &filter)
AttributeHandle< openvdb::Vec3f > Handle
bool valid(const IterT &iter) const
std::vector< Name > NameVector
bool valid(const IterT &iter) const
typename LevelSetGridT::ValueType ValueT
#define OPENVDB_VERSION_NAME
bool valid(const IterT &iter) const
void reset(const LeafT &leaf)
GLenum GLsizei GLsizei GLint * values
hboost::ptr_vector< GroupHandle > HandleVector
GLuint const GLchar * name
GA_API const UT_StringHolder transform
bool valid(const IterT &iter) const
AttributeHandle< IntType > Handle
GLsizei const GLfloat * value
AttributeHashFilter(const size_t index, const double percentage, const unsigned int seed=0)
BinaryFilter(const T1 &filter1, const T2 &filter2)
Attribute Group access and filtering for iteration.
AttributeHandle< openvdb::Vec3f > Handle
std::map< openvdb::Coord, SeedCountPair > LeafMap
math::BBox< Vec3d > BBoxd
int Floor(float x)
Return the floor of x.
void reset(const LeafT &leaf)
std::vector< IntType > generateRandomSubset(const unsigned int seed, const IntType n, const IntType m)
#define OPENVDB_USE_VERSION_NAMESPACE
LevelSetFilter(const LevelSetGridT &grid, const math::Transform &transform, const ValueT min, const ValueT max)
bool valid(const IterT &iter) const
BBoxFilter(const openvdb::math::Transform &transform, const openvdb::BBoxd &bboxWS)
Attribute Array storage templated on type and compression codec.
AttributeHashFilter(const AttributeHashFilter &filter)
std::pair< Index, Index > SeedCountPair
BBoxFilter(const BBoxFilter &filter)
void reset(const LeafT &leaf)
#define OPENVDB_THROW(exception, message)
MultiGroupFilter(const NameVector &include, const NameVector &exclude)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
math::Vec3< float > Vec3f