16#ifndef OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED
17#define OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED
21#include <openvdb/thread/Threading.h>
22#include <openvdb/version.h>
32#include <tbb/blocked_range.h>
33#include <tbb/parallel_for.h>
49template<Index,
typename>
struct SameLeafConfig;
54template<
typename T, Index Log2Dim>
struct PointIndexLeafNode;
93template<
typename Gr
idT,
typename Po
intArrayT>
94inline typename GridT::Ptr
103template<
typename Gr
idT,
typename Po
intArrayT>
104inline typename GridT::Ptr
113template<
typename Po
intArrayT,
typename Gr
idT>
119template<
typename Gr
idT,
typename Po
intArrayT>
120inline typename GridT::ConstPtr
124template<
typename Gr
idT,
typename Po
intArrayT>
125inline typename GridT::Ptr
133template<
typename TreeType = Po
intIndexTree>
181 template<
typename Po
intArray>
196 template<
typename Po
intArray>
207 template<
typename Po
intArray>
222 template<
typename Po
intArray>
235 bool test()
const {
return mRange.first < mRange.second || mIter != mRangeList.end(); }
259 using Range = std::pair<const ValueType*, const ValueType*>;
260 using RangeDeque = std::deque<Range>;
261 using RangeDequeCIter =
typename RangeDeque::const_iterator;
262 using IndexArray = std::unique_ptr<ValueType[]>;
268 RangeDeque mRangeList;
269 RangeDequeCIter mIter;
271 IndexArray mIndexArray;
272 size_t mIndexArraySize;
305template<
typename Po
intArray,
typename TreeType = Po
intIndexTree>
326 template<
typename FilterType>
344namespace point_index_grid_internal {
346template<
typename Po
intArrayT>
347struct ValidPartitioningOp
349 ValidPartitioningOp(std::atomic<bool>& hasChanged,
353 , mHasChanged(&hasChanged)
357 template <
typename LeafT>
358 void operator()(LeafT &leaf,
size_t )
const
360 if ((*mHasChanged)) {
361 thread::cancelGroupExecution();
365 using IndexArrayT =
typename LeafT::IndexArray;
366 using IndexT =
typename IndexArrayT::value_type;
367 using PosType =
typename PointArrayT::PosType;
369 typename LeafT::ValueOnCIter iter;
374 *begin =
static_cast<IndexT*
>(
nullptr),
375 *end =
static_cast<IndexT*
>(
nullptr);
377 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
379 if ((*mHasChanged))
break;
381 voxelCoord = iter.getCoord();
382 leaf.getIndices(iter.pos(), begin, end);
384 while (begin < end) {
386 mPoints->getPos(*begin, point);
387 if (voxelCoord != mTransform->worldToIndexCellCentered(point)) {
388 mHasChanged->store(
true);
398 PointArrayT
const *
const mPoints;
399 math::Transform
const *
const mTransform;
400 std::atomic<bool> *
const mHasChanged;
404template<
typename LeafNodeT>
405struct PopulateLeafNodesOp
407 using IndexT = uint32_t;
408 using Partitioner = PointPartitioner<IndexT, LeafNodeT::LOG2DIM>;
410 PopulateLeafNodesOp(std::unique_ptr<LeafNodeT*[]>& leafNodes,
411 const Partitioner& partitioner)
412 : mLeafNodes(leafNodes.get())
413 , mPartitioner(&partitioner)
417 void operator()(
const tbb::blocked_range<size_t>& range)
const {
419 using VoxelOffsetT =
typename Partitioner::VoxelOffsetType;
421 size_t maxPointCount = 0;
422 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
423 maxPointCount = std::max(maxPointCount, mPartitioner->indices(n).size());
426 const IndexT voxelCount = LeafNodeT::SIZE;
429 std::unique_ptr<VoxelOffsetT[]> offsets{
new VoxelOffsetT[maxPointCount]};
430 std::unique_ptr<IndexT[]>
histogram{
new IndexT[voxelCount]};
432 VoxelOffsetT
const *
const voxelOffsets = mPartitioner->voxelOffsets().get();
434 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
436 LeafNodeT* node =
new LeafNodeT();
437 node->setOrigin(mPartitioner->origin(n));
439 typename Partitioner::IndexIterator it = mPartitioner->indices(n);
442 IndexT
const *
const indices = &*it;
446 offsets[i] = voxelOffsets[ indices[i] ];
450 memset(&histogram[0], 0, voxelCount *
sizeof(IndexT));
455 typename LeafNodeT::NodeMaskType& mask = node->getValueMask();
456 typename LeafNodeT::Buffer& buffer = node->buffer();
459 IndexT count = 0, startOffset;
460 for (
int i = 0; i < int(voxelCount); ++i) {
461 if (histogram[i] > 0) {
467 buffer.setValue(i, count);
471 node->indices().resize(pointCount);
472 typename LeafNodeT::ValueType *
const orderedIndices = node->indices().data();
476 orderedIndices[
histogram[ offsets[i] ]++ ] = indices[i];
479 mLeafNodes[n] = node;
485 LeafNodeT* *
const mLeafNodes;
486 Partitioner
const *
const mPartitioner;
491template<
typename TreeType,
typename Po
intArray>
493constructPointTree(TreeType& tree,
const math::Transform& xform,
const PointArray& points)
495 using LeafType =
typename TreeType::LeafNodeType;
497 std::unique_ptr<LeafType*[]> leafNodes;
498 size_t leafNodeCount = 0;
504 PointPartitioner<uint32_t, LeafType::LOG2DIM> partitioner;
505 partitioner.construct(points, xform,
false,
true);
507 if (!partitioner.usingCellCenteredTransform()) {
509 "cell-centered transform.");
512 leafNodeCount = partitioner.size();
513 leafNodes.reset(
new LeafType*[leafNodeCount]);
515 const tbb::blocked_range<size_t> range(0, leafNodeCount);
516 tbb::parallel_for(range, PopulateLeafNodesOp<LeafType>(leafNodes, partitioner));
519 tree::ValueAccessor<TreeType> acc(tree);
520 for (
size_t n = 0; n < leafNodeCount; ++n) {
521 acc.addLeaf(leafNodes[n]);
531dequeToArray(
const std::deque<T>& d, std::unique_ptr<T[]>& a,
size_t& size)
534 a.reset(
new T[size]);
535 typename std::deque<T>::const_iterator it = d.begin(), itEnd = d.end();
537 for ( ; it != itEnd; ++it, ++item) *item = *it;
542constructExclusiveRegions(std::vector<CoordBBox>& regions,
543 const CoordBBox& bbox,
const CoordBBox& ibox)
547 Coord cmin = ibox.min();
548 Coord cmax = ibox.max();
551 regions.push_back(bbox);
552 regions.back().max().z() = cmin.z();
555 regions.push_back(bbox);
556 regions.back().min().z() = cmax.z();
562 regions.push_back(bbox);
563 CoordBBox* lastRegion = ®ions.back();
564 lastRegion->min().z() = cmin.z();
565 lastRegion->max().z() = cmax.z();
566 lastRegion->max().x() = cmin.x();
569 regions.push_back(*lastRegion);
570 lastRegion = ®ions.back();
571 lastRegion->min().x() = cmax.x();
572 lastRegion->max().x() = bbox.max().x();
578 regions.push_back(*lastRegion);
579 lastRegion = ®ions.back();
580 lastRegion->min().x() = cmin.x();
581 lastRegion->max().x() = cmax.x();
582 lastRegion->max().y() = cmin.y();
585 regions.push_back(*lastRegion);
586 lastRegion = ®ions.back();
587 lastRegion->min().y() = cmax.y();
588 lastRegion->max().y() = bbox.max().y();
592template<
typename Po
intArray,
typename IndexT>
595 using PosType =
typename PointArray::PosType;
596 using ScalarType =
typename PosType::value_type;
597 using Range = std::pair<const IndexT*, const IndexT*>;
598 using RangeDeque = std::deque<Range>;
599 using IndexDeque = std::deque<IndexT>;
601 BBoxFilter(RangeDeque& ranges, IndexDeque& indices,
const BBoxd& bbox,
602 const PointArray& points,
const math::Transform& xform)
607 , mMap(*xform.baseMap())
611 template <
typename LeafNodeType>
612 void filterLeafNode(
const LeafNodeType& leaf)
614 typename LeafNodeType::ValueOnCIter iter;
616 *begin =
static_cast<IndexT*
>(
nullptr),
617 *end =
static_cast<IndexT*
>(
nullptr);
618 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
619 leaf.getIndices(iter.pos(), begin, end);
620 filterVoxel(iter.getCoord(), begin, end);
624 void filterVoxel(
const Coord&,
const IndexT* begin,
const IndexT* end)
628 for (; begin < end; ++begin) {
629 mPoints.getPos(*begin, vec);
631 if (mRegion.isInside(mMap.applyInverseMap(vec))) {
632 mIndices.push_back(*begin);
639 IndexDeque& mIndices;
641 const PointArray& mPoints;
642 const math::MapBase& mMap;
646template<
typename Po
intArray,
typename IndexT>
647struct RadialRangeFilter
649 using PosType =
typename PointArray::PosType;
650 using ScalarType =
typename PosType::value_type;
651 using Range = std::pair<const IndexT*, const IndexT*>;
652 using RangeDeque = std::deque<Range>;
653 using IndexDeque = std::deque<IndexT>;
655 RadialRangeFilter(RangeDeque& ranges, IndexDeque& indices,
const Vec3d& xyz,
double radius,
656 const PointArray& points,
const math::Transform& xform,
657 const double leafNodeDim,
const bool subvoxelAccuracy)
661 , mWSCenter(xform.indexToWorld(xyz))
662 , mVoxelDist1(ScalarType(0.0))
663 , mVoxelDist2(ScalarType(0.0))
664 , mLeafNodeDist1(ScalarType(0.0))
665 , mLeafNodeDist2(ScalarType(0.0))
666 , mWSRadiusSqr(ScalarType(radius * xform.voxelSize()[0]))
668 , mSubvoxelAccuracy(subvoxelAccuracy)
670 const ScalarType voxelRadius = ScalarType(std::sqrt(3.0) * 0.5);
671 mVoxelDist1 = voxelRadius + ScalarType(radius);
672 mVoxelDist1 *= mVoxelDist1;
674 if (radius > voxelRadius) {
675 mVoxelDist2 = ScalarType(radius) - voxelRadius;
676 mVoxelDist2 *= mVoxelDist2;
679 const ScalarType leafNodeRadius = ScalarType(leafNodeDim * std::sqrt(3.0) * 0.5);
680 mLeafNodeDist1 = leafNodeRadius + ScalarType(radius);
681 mLeafNodeDist1 *= mLeafNodeDist1;
683 if (radius > leafNodeRadius) {
684 mLeafNodeDist2 = ScalarType(radius) - leafNodeRadius;
685 mLeafNodeDist2 *= mLeafNodeDist2;
688 mWSRadiusSqr *= mWSRadiusSqr;
691 template <
typename LeafNodeType>
692 void filterLeafNode(
const LeafNodeType& leaf)
695 const Coord& ijk = leaf.origin();
697 vec[0] = ScalarType(ijk[0]);
698 vec[1] = ScalarType(ijk[1]);
699 vec[2] = ScalarType(ijk[2]);
700 vec += ScalarType(LeafNodeType::DIM - 1) * 0.5;
703 const ScalarType dist = vec.lengthSqr();
704 if (dist > mLeafNodeDist1)
return;
706 if (mLeafNodeDist2 > 0.0 && dist < mLeafNodeDist2) {
707 const IndexT* begin = &leaf.indices().front();
708 mRanges.push_back(Range(begin, begin + leaf.indices().size()));
713 typename LeafNodeType::ValueOnCIter iter;
715 *begin =
static_cast<IndexT*
>(
nullptr),
716 *end =
static_cast<IndexT*
>(
nullptr);
717 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
718 leaf.getIndices(iter.pos(), begin, end);
719 filterVoxel(iter.getCoord(), begin, end);
723 void filterVoxel(
const Coord& ijk,
const IndexT* begin,
const IndexT* end)
728 vec[0] = mCenter[0] - ScalarType(ijk[0]);
729 vec[1] = mCenter[1] - ScalarType(ijk[1]);
730 vec[2] = mCenter[2] - ScalarType(ijk[2]);
732 const ScalarType dist = vec.lengthSqr();
733 if (dist > mVoxelDist1)
return;
735 if (!mSubvoxelAccuracy || (mVoxelDist2 > 0.0 && dist < mVoxelDist2)) {
736 if (!mRanges.empty() && mRanges.back().second == begin) {
737 mRanges.back().second = end;
739 mRanges.push_back(Range(begin, end));
746 while (begin < end) {
747 mPoints.getPos(*begin, vec);
748 vec = mWSCenter - vec;
750 if (vec.lengthSqr() < mWSRadiusSqr) {
751 mIndices.push_back(*begin);
759 IndexDeque& mIndices;
760 const PosType mCenter, mWSCenter;
761 ScalarType mVoxelDist1, mVoxelDist2, mLeafNodeDist1, mLeafNodeDist2, mWSRadiusSqr;
762 const PointArray& mPoints;
763 const bool mSubvoxelAccuracy;
770template<
typename RangeFilterType,
typename LeafNodeType>
772filteredPointIndexSearchVoxels(RangeFilterType& filter,
773 const LeafNodeType& leaf,
const Coord& min,
const Coord& max)
775 using PointIndexT =
typename LeafNodeType::ValueType;
776 Index xPos(0), yPos(0), pos(0);
779 const PointIndexT* dataPtr = &leaf.indices().front();
780 PointIndexT beginOffset, endOffset;
782 for (ijk[0] = min[0]; ijk[0] <=
max[0]; ++ijk[0]) {
783 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
784 for (ijk[1] = min[1]; ijk[1] <=
max[1]; ++ijk[1]) {
785 yPos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
786 for (ijk[2] = min[2]; ijk[2] <=
max[2]; ++ijk[2]) {
787 pos = yPos + (ijk[2] & (LeafNodeType::DIM - 1u));
789 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
790 endOffset = leaf.getValue(pos);
792 if (endOffset > beginOffset) {
793 filter.filterVoxel(ijk, dataPtr + beginOffset, dataPtr + endOffset);
801template<
typename RangeFilterType,
typename ConstAccessor>
803filteredPointIndexSearch(RangeFilterType& filter, ConstAccessor& acc,
const CoordBBox& bbox)
805 using LeafNodeType =
typename ConstAccessor::TreeType::LeafNodeType;
806 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
807 const Coord leafMin = bbox.min() & ~(LeafNodeType::DIM - 1);
808 const Coord leafMax = bbox.max() & ~(LeafNodeType::DIM - 1);
810 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
811 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
812 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
814 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
816 ijkMax.offset(LeafNodeType::DIM - 1);
819 ijkA = Coord::maxComponent(bbox.min(), ijk);
820 ijkB = Coord::minComponent(bbox.max(), ijkMax);
822 if (ijkA != ijk || ijkB != ijkMax) {
823 filteredPointIndexSearchVoxels(filter, *leaf, ijkA, ijkB);
825 filter.filterLeafNode(*leaf);
837template<
typename RangeDeque,
typename LeafNodeType>
839pointIndexSearchVoxels(RangeDeque& rangeList,
840 const LeafNodeType& leaf,
const Coord& min,
const Coord& max)
842 using PointIndexT =
typename LeafNodeType::ValueType;
843 using IntT =
typename PointIndexT::IntType;
844 using Range =
typename RangeDeque::value_type;
846 Index xPos(0), pos(0), zStride =
Index(max[2] - min[2]);
847 const PointIndexT* dataPtr = &leaf.indices().front();
848 PointIndexT beginOffset(0), endOffset(0),
849 previousOffset(
static_cast<IntT
>(leaf.indices().size() + 1u));
852 for (ijk[0] = min[0]; ijk[0] <=
max[0]; ++ijk[0]) {
853 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
855 for (ijk[1] = min[1]; ijk[1] <=
max[1]; ++ijk[1]) {
856 pos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
857 pos += (
min[2] & (LeafNodeType::DIM - 1u));
859 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
860 endOffset = leaf.getValue(pos+zStride);
862 if (endOffset > beginOffset) {
864 if (beginOffset == previousOffset) {
865 rangeList.back().second = dataPtr + endOffset;
867 rangeList.push_back(Range(dataPtr + beginOffset, dataPtr + endOffset));
870 previousOffset = endOffset;
877template<
typename RangeDeque,
typename ConstAccessor>
879pointIndexSearch(RangeDeque& rangeList, ConstAccessor& acc,
const CoordBBox& bbox)
881 using LeafNodeType =
typename ConstAccessor::TreeType::LeafNodeType;
882 using PointIndexT =
typename LeafNodeType::ValueType;
883 using Range =
typename RangeDeque::value_type;
885 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
886 const Coord leafMin = bbox.min() & ~(LeafNodeType::DIM - 1);
887 const Coord leafMax = bbox.max() & ~(LeafNodeType::DIM - 1);
889 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
890 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
891 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
893 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
895 ijkMax.offset(LeafNodeType::DIM - 1);
898 ijkA = Coord::maxComponent(bbox.min(), ijk);
899 ijkB = Coord::minComponent(bbox.max(), ijkMax);
901 if (ijkA != ijk || ijkB != ijkMax) {
902 pointIndexSearchVoxels(rangeList, *leaf, ijkA, ijkB);
905 const PointIndexT* begin = &leaf->indices().front();
906 rangeList.push_back(Range(begin, (begin + leaf->indices().size())));
921template<
typename TreeType>
926 , mIter(mRangeList.begin())
933template<
typename TreeType>
937 , mRangeList(rhs.mRangeList)
938 , mIter(mRangeList.begin())
940 , mIndexArraySize(rhs.mIndexArraySize)
942 if (rhs.mIndexArray) {
943 mIndexArray.reset(new ValueType[mIndexArraySize]);
944 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize * sizeof(ValueType));
949template<
typename TreeType>
955 mRangeList = rhs.mRangeList;
956 mIter = mRangeList.begin();
958 mIndexArraySize = rhs.mIndexArraySize;
960 if (rhs.mIndexArray) {
961 mIndexArray.reset(
new ValueType[mIndexArraySize]);
962 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize *
sizeof(
ValueType));
969template<
typename TreeType>
974 , mIter(mRangeList.begin())
979 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
980 mRangeList.push_back(mRange);
981 mIter = mRangeList.begin();
986template<
typename TreeType>
991 , mIter(mRangeList.begin())
995 point_index_grid_internal::pointIndexSearch(mRangeList, acc, bbox);
997 if (!mRangeList.empty()) {
998 mIter = mRangeList.begin();
999 mRange = mRangeList.front();
1004template<
typename TreeType>
1008 mIter = mRangeList.begin();
1009 if (!mRangeList.empty()) {
1010 mRange = mRangeList.front();
1011 }
else if (mIndexArray) {
1012 mRange.first = mIndexArray.get();
1013 mRange.second = mRange.first + mIndexArraySize;
1015 mRange.first =
static_cast<ValueType*
>(
nullptr);
1016 mRange.second =
static_cast<ValueType*
>(
nullptr);
1021template<
typename TreeType>
1026 if (mRange.first >= mRange.second && mIter != mRangeList.end()) {
1028 if (mIter != mRangeList.end()) {
1030 }
else if (mIndexArray) {
1031 mRange.first = mIndexArray.get();
1032 mRange.second = mRange.first + mIndexArraySize;
1038template<
typename TreeType>
1042 if (!this->
test())
return false;
1044 return this->
test();
1048template<
typename TreeType>
1053 typename RangeDeque::const_iterator it = mRangeList.begin();
1055 for ( ; it != mRangeList.end(); ++it) {
1056 count += it->second - it->first;
1059 return count + mIndexArraySize;
1063template<
typename TreeType>
1065PointIndexIterator<TreeType>::clear()
1067 mRange.first =
static_cast<ValueType*
>(
nullptr);
1068 mRange.second =
static_cast<ValueType*
>(
nullptr);
1070 mIter = mRangeList.end();
1071 mIndexArray.reset();
1072 mIndexArraySize = 0;
1076template<
typename TreeType>
1082 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
1083 mRangeList.push_back(mRange);
1084 mIter = mRangeList.begin();
1089template<
typename TreeType>
1094 point_index_grid_internal::pointIndexSearch(mRangeList, acc, bbox);
1096 if (!mRangeList.empty()) {
1097 mIter = mRangeList.begin();
1098 mRange = mRangeList.front();
1103template<
typename TreeType>
1104template<
typename Po
intArray>
1111 std::vector<CoordBBox> searchRegions;
1115 const int minExtent = std::min(dim[0], std::min(dim[1], dim[2]));
1117 if (minExtent > 2) {
1122 point_index_grid_internal::pointIndexSearch(mRangeList, acc, ibox);
1126 point_index_grid_internal::constructExclusiveRegions(searchRegions, region, ibox);
1128 searchRegions.push_back(region);
1132 std::deque<ValueType> filteredIndices;
1133 point_index_grid_internal::BBoxFilter<PointArray, ValueType>
1134 filter(mRangeList, filteredIndices, bbox,
points, xform);
1136 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1137 point_index_grid_internal::filteredPointIndexSearch(filter, acc, searchRegions[n]);
1140 point_index_grid_internal::dequeToArray(filteredIndices, mIndexArray, mIndexArraySize);
1146template<
typename TreeType>
1147template<
typename Po
intArray>
1151 bool subvoxelAccuracy)
1154 std::vector<CoordBBox> searchRegions;
1158 Coord::round(
Vec3d(center[0] - radius, center[1] - radius, center[2] - radius)),
1159 Coord::round(
Vec3d(center[0] + radius, center[1] + radius, center[2] + radius)));
1162 const double iRadius = radius * double(1.0 / std::sqrt(3.0));
1163 if (iRadius > 2.0) {
1166 Coord::round(
Vec3d(center[0] - iRadius, center[1] - iRadius, center[2] - iRadius)),
1167 Coord::round(
Vec3d(center[0] + iRadius, center[1] + iRadius, center[2] + iRadius)));
1171 point_index_grid_internal::pointIndexSearch(mRangeList, acc, ibox);
1174 point_index_grid_internal::constructExclusiveRegions(searchRegions, bbox, ibox);
1176 searchRegions.push_back(bbox);
1180 std::deque<ValueType> filteredIndices;
1181 const double leafNodeDim = double(TreeType::LeafNodeType::DIM);
1183 using FilterT = point_index_grid_internal::RadialRangeFilter<PointArray, ValueType>;
1185 FilterT filter(mRangeList, filteredIndices,
1186 center, radius,
points, xform, leafNodeDim, subvoxelAccuracy);
1188 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1189 point_index_grid_internal::filteredPointIndexSearch(filter, acc, searchRegions[n]);
1192 point_index_grid_internal::dequeToArray(filteredIndices, mIndexArray, mIndexArraySize);
1198template<
typename TreeType>
1199template<
typename Po
intArray>
1209template<
typename TreeType>
1210template<
typename Po
intArray>
1214 bool subvoxelAccuracy)
1217 (radius / xform.
voxelSize()[0]), acc,
points, xform, subvoxelAccuracy);
1225template<
typename Po
intArray,
typename TreeType>
1229 : mPoints(&
points), mAcc(
tree), mXform(xform), mInvVoxelSize(1.0/xform.voxelSize()[0])
1234template<
typename Po
intArray,
typename TreeType>
1237 : mPoints(rhs.mPoints)
1238 , mAcc(rhs.mAcc.
tree())
1239 , mXform(rhs.mXform)
1240 , mInvVoxelSize(rhs.mInvVoxelSize)
1245template<
typename Po
intArray,
typename TreeType>
1246template<
typename FilterType>
1251 if (radius * mInvVoxelSize <
ScalarType(8.0)) {
1253 mXform.worldToIndexCellCentered(center - radius),
1254 mXform.worldToIndexCellCentered(center + radius)), mAcc);
1256 mIter.worldSpaceSearchAndUpdate(
1257 center, radius, mAcc, *mPoints, mXform,
false);
1260 const ScalarType radiusSqr = radius * radius;
1263 for (; mIter; ++mIter) {
1264 mPoints->getPos(*mIter, pos);
1266 distSqr = pos.lengthSqr();
1268 if (distSqr < radiusSqr) {
1269 op(distSqr, *mIter);
1278template<
typename Gr
idT,
typename Po
intArrayT>
1279inline typename GridT::Ptr
1282 typename GridT::Ptr grid = GridT::create(
typename GridT::ValueType(0));
1283 grid->setTransform(xform.
copy());
1286 point_index_grid_internal::constructPointTree(
1287 grid->tree(), grid->transform(),
points);
1294template<
typename Gr
idT,
typename Po
intArrayT>
1295inline typename GridT::Ptr
1303template<
typename Po
intArrayT,
typename Gr
idT>
1309 size_t pointCount = 0;
1310 for (
size_t n = 0, N = leafs.
leafCount(); n < N; ++n) {
1311 pointCount += leafs.
leaf(n).indices().size();
1314 if (
points.size() != pointCount) {
1318 std::atomic<bool> changed;
1321 point_index_grid_internal::ValidPartitioningOp<PointArrayT>
1322 op(changed,
points, grid.transform());
1326 return !
bool(changed);
1330template<
typename Gr
idT,
typename Po
intArrayT>
1331inline typename GridT::ConstPtr
1342template<
typename Gr
idT,
typename Po
intArrayT>
1343inline typename GridT::Ptr
1357template<
typename T, Index Log2Dim>
1409 const T& value =
zeroVal<T>(),
bool active =
false)
1420 template<
typename OtherType, Index OtherLog2Dim>
1433 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive) {
1437 template<MergePolicy Policy>
1445 template<
typename AccessorT>
1451 template<
typename AccessorT>
1454 template<
typename NodeT,
typename AccessorT>
1458 if (!(std::is_same<NodeT, PointIndexLeafNode>::value))
return nullptr;
1459 return reinterpret_cast<NodeT*
>(
this);
1463 template<
typename AccessorT>
1470 template<
typename AccessorT>
1472 template<
typename AccessorT>
1475 template<
typename NodeT,
typename AccessorT>
1479 if (!(std::is_same<NodeT, PointIndexLeafNode>::value))
return nullptr;
1480 return reinterpret_cast<const NodeT*
>(
this);
1488 void readBuffers(std::istream& is,
bool fromHalf =
false);
1490 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
1503 OPENVDB_ASSERT(
false &&
"Cannot modify voxel values in a PointIndexTree.");
1529 template<
typename ModifyOp>
1532 template<
typename ModifyOp>
1535 template<
typename ModifyOp>
1544 template<
typename AccessorT>
1547 template<
typename ModifyOp,
typename AccessorT>
1552 template<
typename AccessorT>
1555 template<
typename AccessorT>
1611#define VMASK_ this->getValueMask()
1655template<
typename T, Index Log2Dim>
1664template<
typename T, Index Log2Dim>
1670 const ValueType* dataPtr = &mIndices.front();
1671 begin = dataPtr + (offset == 0 ?
ValueType(0) : this->buffer()[offset - 1]);
1672 end = dataPtr + this->buffer()[offset];
1679template<
typename T, Index Log2Dim>
1683 this->buffer().setValue(offset, val);
1688template<
typename T, Index Log2Dim>
1692 this->buffer().setValue(offset, val);
1696template<
typename T, Index Log2Dim>
1703 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
1704 xPos = (ijk[0] & (
DIM - 1u)) << (2 *
LOG2DIM);
1706 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
1707 pos = xPos + ((ijk[1] & (
DIM - 1u)) <<
LOG2DIM);
1708 pos += (bbox.
min()[2] & (
DIM - 1u));
1710 if (this->buffer()[pos+zStride] > (pos == 0 ? T(0) : this->buffer()[pos - 1])) {
1720template<
typename T, Index Log2Dim>
1727 is.read(
reinterpret_cast<char*
>(&numIndices),
sizeof(
Index64));
1729 mIndices.resize(
size_t(numIndices));
1730 is.read(
reinterpret_cast<char*
>(mIndices.data()), numIndices *
sizeof(T));
1734template<
typename T, Index Log2Dim>
1742 is.read(
reinterpret_cast<char*
>(&numIndices),
sizeof(
Index64));
1744 const Index64 numBytes = numIndices *
sizeof(T);
1746 if (bbox.
hasOverlap(this->getNodeBoundingBox())) {
1747 mIndices.resize(
size_t(numIndices));
1748 is.read(
reinterpret_cast<char*
>(mIndices.data()), numBytes);
1754 std::unique_ptr<char[]> buf{
new char[numBytes]};
1755 is.read(buf.get(), numBytes);
1760 is.read(
reinterpret_cast<char*
>(&auxDataBytes),
sizeof(
Index64));
1761 if (auxDataBytes > 0) {
1763 std::unique_ptr<char[]> auxData{
new char[auxDataBytes]};
1764 is.read(auxData.get(), auxDataBytes);
1769template<
typename T, Index Log2Dim>
1776 os.write(
reinterpret_cast<const char*
>(&numIndices),
sizeof(
Index64));
1777 os.write(
reinterpret_cast<const char*
>(mIndices.data()), numIndices *
sizeof(T));
1781 os.write(
reinterpret_cast<const char*
>(&auxDataBytes),
sizeof(
Index64));
1785template<
typename T, Index Log2Dim>
1792template<
typename T, Index Log2Dim>
1809template<Index Dim1,
typename T2>
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
#define VMASK_
Definition PointDataGrid.h:702
Spatially partitions points using a parallel radix-based sorting algorithm.
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion).
Definition Coord.h:51
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
Tag dispatch class that distinguishes constructors during file input.
Definition Types.h:689
const Vec3T & max() const
Return a const reference to the maximum point of this bounding box.
Definition BBox.h:64
const Vec3T & min() const
Return a const reference to the minimum point of this bounding box.
Definition BBox.h:62
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition Coord.h:421
const Coord & min() const
Definition Coord.h:324
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition Coord.h:415
const Coord & max() const
Definition Coord.h:325
Coord dim() const
Return the dimensions of the coordinates spanned by this bounding box.
Definition Coord.h:383
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Definition InternalNode.h:35
Base class for iterators over internal and leaf nodes.
Definition Iterator.h:30
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition LeafManager.h:319
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition LeafManager.h:484
size_t leafCount() const
Return the number of leaf nodes.
Definition LeafManager.h:288
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim....
Definition LeafNode.h:39
void setValueMaskOn(Index n)
Definition LeafNode.h:893
static const Index NUM_VOXELS
Definition LeafNode.h:53
static const Index DIM
Definition LeafNode.h:51
static const Index LEVEL
Definition LeafNode.h:55
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition LeafNode.h:1040
bool hasSameTopology(const LeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition LeafNode.h:1497
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition LeafNode.h:1432
Index64 memUsageIfLoaded() const
Definition LeafNode.h:1469
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition LeafNode.h:1334
static const Index NUM_VALUES
Definition LeafNode.h:52
static const Index LOG2DIM
Definition LeafNode.h:49
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition LeafNode.h:1449
static const Index SIZE
Definition LeafNode.h:54
bool isEmpty() const
Return true if this node has no active voxels.
Definition LeafNode.h:151
static const Index TOTAL
Definition LeafNode.h:50
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition LeafNode.h:1459
bool isValueMaskOn(Index n) const
Definition LeafNode.h:880
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains the voxel coordinate xyz. If no LeafNode exists,...
Definition ValueAccessor.h:838
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition NodeMasks.h:308
DenseMaskIterator< NodeMask > DenseIterator
Definition NodeMasks.h:350
OnMaskIterator< NodeMask > OnIterator
Definition NodeMasks.h:348
OffMaskIterator< NodeMask > OffIterator
Definition NodeMasks.h:349
Selectively extract and filter point data using a custom filter operator.
Partitions points into BucketLog2Dim aligned buckets using a parallel radix-based sorting algorithm.
Vec3< double > Vec3d
Definition Vec3.h:665
Definition AttributeArray.h:42
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 PointCountImpl.h:18
Definition PointDataGrid.h:170
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
Index32 Index
Definition Types.h:54
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
math::BBox< Vec3d > BBoxd
Definition Types.h:84
uint64_t Index64
Definition Types.h:53
std::shared_ptr< T > SharedPtr
Definition Types.h:114
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Definition LeafNode.h:213
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition LeafNode.h:253
Definition LeafNode.h:213
Definition LeafNode.h:213
Definition LeafNode.h:262
Definition LeafNode.h:212
Definition LeafNode.h:221
Definition LeafNode.h:212
Definition LeafNode.h:212
Definition LeafNode.h:920
#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:218