43 #ifndef OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 44 #define OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 48 #include <openvdb/version.h> 49 #include <openvdb/Exceptions.h> 50 #include <openvdb/Grid.h> 51 #include <openvdb/Types.h> 52 #include <openvdb/math/Transform.h> 53 #include <openvdb/tree/LeafManager.h> 54 #include <openvdb/tree/LeafNode.h> 55 #include <openvdb/tree/Tree.h> 57 #include <tbb/atomic.h> 58 #include <tbb/blocked_range.h> 59 #include <tbb/parallel_for.h> 64 #include <type_traits> 74 template<Index,
typename>
struct SameLeafConfig;
118 template<
typename Gr
idT,
typename Po
intArrayT>
119 inline typename GridT::Ptr
128 template<
typename Gr
idT,
typename Po
intArrayT>
129 inline typename GridT::Ptr
138 template<
typename Po
intArrayT,
typename Gr
idT>
144 template<
typename Gr
idT,
typename Po
intArrayT>
145 inline typename GridT::ConstPtr
149 template<
typename Gr
idT,
typename Po
intArrayT>
150 inline typename GridT::Ptr
158 template<
typename TreeType = Po
intIndexTree>
206 template<
typename Po
intArray>
221 template<
typename Po
intArray>
232 template<
typename Po
intArray>
247 template<
typename Po
intArray>
248 void worldSpaceSearchAndUpdate(
const Vec3d& center,
double radius,
ConstAccessor& acc,
260 bool test()
const {
return mRange.first < mRange.second || mIter != mRangeList.end(); }
261 operator bool()
const {
return this->test(); }
284 using Range = std::pair<const ValueType*, const ValueType*>;
285 using RangeDeque = std::deque<Range>;
286 using RangeDequeCIter =
typename RangeDeque::const_iterator;
287 using IndexArray = std::unique_ptr<ValueType[]>;
293 RangeDeque mRangeList;
294 RangeDequeCIter mIter;
296 IndexArray mIndexArray;
297 size_t mIndexArraySize;
330 template<
typename Po
intArray,
typename TreeType = Po
intIndexTree>
351 template<
typename FilterType>
368 namespace point_index_grid_internal {
370 template<
typename Po
intArrayT>
377 , mHasChanged(&hasChanged)
381 template <
typename LeafT>
384 if ((*mHasChanged)) {
385 tbb::task::self().cancel_group_execution();
390 using IndexT =
typename IndexArrayT::value_type;
391 using PosType =
typename PointArrayT::PosType;
393 typename LeafT::ValueOnCIter iter;
398 *begin =
static_cast<IndexT*
>(
nullptr),
399 *end = static_cast<IndexT*>(
nullptr);
401 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
403 if ((*mHasChanged))
break;
405 voxelCoord = iter.getCoord();
406 leaf.getIndices(iter.pos(), begin, end);
408 while (begin < end) {
410 mPoints->getPos(*begin, point);
411 if (voxelCoord != mTransform->worldToIndexCellCentered(point)) {
412 mHasChanged->fetch_and_store(
true);
422 PointArrayT
const *
const mPoints;
424 tbb::atomic<bool> *
const mHasChanged;
428 template<
typename LeafNodeT>
436 : mLeafNodes(leafNodes.get())
437 , mPartitioner(&partitioner)
441 void operator()(
const tbb::blocked_range<size_t>& range)
const {
445 size_t maxPointCount = 0;
446 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
447 maxPointCount =
std::max(maxPointCount, mPartitioner->indices(n).size());
450 const IndexT voxelCount = LeafNodeT::SIZE;
453 std::unique_ptr<VoxelOffsetT[]> offsets{
new VoxelOffsetT[maxPointCount]};
456 VoxelOffsetT
const *
const voxelOffsets = mPartitioner->voxelOffsets().get();
458 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
460 LeafNodeT* node =
new LeafNodeT();
461 node->setOrigin(mPartitioner->origin(n));
466 IndexT const *
const indices = &*it;
470 offsets[i] = voxelOffsets[ indices[i] ];
479 typename LeafNodeT::NodeMaskType& mask = node->getValueMask();
480 typename LeafNodeT::Buffer& buffer = node->buffer();
483 IndexT count = 0, startOffset;
484 for (
int i = 0; i < int(voxelCount); ++i) {
491 buffer.setValue(i, count);
495 node->indices().resize(pointCount);
496 typename LeafNodeT::ValueType *
const orderedIndices = node->indices().data();
500 orderedIndices[
histogram[ offsets[i] ]++ ] = indices[i];
503 mLeafNodes[n] = node;
515 template<
typename TreeType,
typename Po
intArray>
519 using LeafType =
typename TreeType::LeafNodeType;
521 std::unique_ptr<LeafType*[]> leafNodes;
522 size_t leafNodeCount = 0;
529 partitioner.
construct(points, xform,
false,
true);
533 "cell-centered transform.");
536 leafNodeCount = partitioner.
size();
537 leafNodes.reset(
new LeafType*[leafNodeCount]);
539 const tbb::blocked_range<size_t> range(0, leafNodeCount);
544 for (
size_t n = 0; n < leafNodeCount; ++n) {
555 dequeToArray(
const std::deque<T>& d, std::unique_ptr<T[]>& a,
size_t& size)
558 a.reset(
new T[size]);
559 typename std::deque<T>::const_iterator it = d.begin(), itEnd = d.end();
561 for ( ; it != itEnd; ++it, ++item) *item = *it;
575 regions.push_back(bbox);
576 regions.back().
max().
z() = cmin.
z();
579 regions.push_back(bbox);
580 regions.back().min().z() = cmax.
z();
586 regions.push_back(bbox);
588 lastRegion->
min().
z() = cmin.
z();
589 lastRegion->
max().
z() = cmax.
z();
590 lastRegion->
max().
x() = cmin.
x();
593 regions.push_back(*lastRegion);
594 lastRegion = ®ions.back();
595 lastRegion->
min().
x() = cmax.
x();
596 lastRegion->
max().
x() = bbox.
max().
x();
602 regions.push_back(*lastRegion);
603 lastRegion = ®ions.back();
604 lastRegion->
min().
x() = cmin.
x();
605 lastRegion->
max().
x() = cmax.
x();
606 lastRegion->
max().
y() = cmin.
y();
609 regions.push_back(*lastRegion);
610 lastRegion = ®ions.back();
611 lastRegion->
min().
y() = cmax.
y();
612 lastRegion->
max().
y() = bbox.
max().
y();
616 template<
typename Po
intArray,
typename IndexT>
621 using Range = std::pair<const IndexT*, const IndexT*>;
631 , mMap(*xform.baseMap())
635 template <
typename LeafNodeType>
638 typename LeafNodeType::ValueOnCIter iter;
640 *begin =
static_cast<IndexT*
>(
nullptr),
641 *end = static_cast<IndexT*>(
nullptr);
642 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
643 leaf.getIndices(iter.pos(), begin, end);
644 filterVoxel(iter.getCoord(), begin, end);
652 for (; begin < end; ++begin) {
653 mPoints.getPos(*begin, vec);
655 if (mRegion.isInside(mMap.applyInverseMap(vec))) {
656 mIndices.push_back(*begin);
670 template<
typename Po
intArray,
typename IndexT>
675 using Range = std::pair<const IndexT*, const IndexT*>;
681 const double leafNodeDim,
const bool subvoxelAccuracy)
685 , mWSCenter(xform.indexToWorld(xyz))
690 , mWSRadiusSqr(
ScalarType(radius * xform.voxelSize()[0]))
692 , mSubvoxelAccuracy(subvoxelAccuracy)
695 mVoxelDist1 = voxelRadius +
ScalarType(radius);
696 mVoxelDist1 *= mVoxelDist1;
698 if (radius > voxelRadius) {
699 mVoxelDist2 = ScalarType(radius) - voxelRadius;
700 mVoxelDist2 *= mVoxelDist2;
703 const ScalarType leafNodeRadius = ScalarType(leafNodeDim * std::sqrt(3.0) * 0.5);
704 mLeafNodeDist1 = leafNodeRadius + ScalarType(radius);
705 mLeafNodeDist1 *= mLeafNodeDist1;
707 if (radius > leafNodeRadius) {
708 mLeafNodeDist2 = ScalarType(radius) - leafNodeRadius;
709 mLeafNodeDist2 *= mLeafNodeDist2;
712 mWSRadiusSqr *= mWSRadiusSqr;
715 template <
typename LeafNodeType>
719 const Coord& ijk = leaf.origin();
724 vec +=
ScalarType(LeafNodeType::DIM - 1) * 0.5;
728 if (dist > mLeafNodeDist1)
return;
730 if (mLeafNodeDist2 > 0.0 && dist < mLeafNodeDist2) {
731 const IndexT* begin = &leaf.indices().front();
732 mRanges.push_back(
Range(begin, begin + leaf.indices().size()));
737 typename LeafNodeType::ValueOnCIter iter;
739 *begin =
static_cast<IndexT*
>(
nullptr),
740 *end = static_cast<IndexT*>(
nullptr);
741 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
742 leaf.getIndices(iter.pos(), begin, end);
743 filterVoxel(iter.getCoord(), begin, end);
753 vec[1] = mCenter[1] - ScalarType(ijk[1]);
754 vec[2] = mCenter[2] - ScalarType(ijk[2]);
756 const ScalarType dist = vec.lengthSqr();
757 if (dist > mVoxelDist1)
return;
759 if (!mSubvoxelAccuracy || (mVoxelDist2 > 0.0 && dist < mVoxelDist2)) {
760 if (!mRanges.empty() && mRanges.back().second == begin) {
761 mRanges.back().second = end;
763 mRanges.push_back(
Range(begin, end));
770 while (begin < end) {
771 mPoints.getPos(*begin, vec);
772 vec = mWSCenter - vec;
774 if (vec.lengthSqr() < mWSRadiusSqr) {
775 mIndices.push_back(*begin);
784 const PosType mCenter, mWSCenter;
785 ScalarType mVoxelDist1, mVoxelDist2, mLeafNodeDist1, mLeafNodeDist2, mWSRadiusSqr;
787 const bool mSubvoxelAccuracy;
794 template<
typename RangeFilterType,
typename LeafNodeType>
799 using PointIndexT =
typename LeafNodeType::ValueType;
800 Index xPos(0), yPos(0), pos(0);
803 const PointIndexT* dataPtr = &leaf.indices().front();
804 PointIndexT beginOffset, endOffset;
806 for (ijk[0] = min[0]; ijk[0] <= max[0]; ++ijk[0]) {
807 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
808 for (ijk[1] = min[1]; ijk[1] <= max[1]; ++ijk[1]) {
809 yPos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
810 for (ijk[2] = min[2]; ijk[2] <= max[2]; ++ijk[2]) {
811 pos = yPos + (ijk[2] & (LeafNodeType::DIM - 1u));
813 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
814 endOffset = leaf.getValue(pos);
816 if (endOffset > beginOffset) {
817 filter.filterVoxel(ijk, dataPtr + beginOffset, dataPtr + endOffset);
825 template<
typename RangeFilterType,
typename ConstAccessor>
829 using LeafNodeType =
typename ConstAccessor::TreeType::LeafNodeType;
830 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
831 const Coord leafMin = bbox.
min() & ~(LeafNodeType::DIM - 1);
832 const Coord leafMax = bbox.
max() & ~(LeafNodeType::DIM - 1);
834 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
835 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
836 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
838 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
840 ijkMax.
offset(LeafNodeType::DIM - 1);
846 if (ijkA != ijk || ijkB != ijkMax) {
849 filter.filterLeafNode(*leaf);
861 template<
typename RangeDeque,
typename LeafNodeType>
866 using PointIndexT =
typename LeafNodeType::ValueType;
867 using IntT =
typename PointIndexT::IntType;
868 using Range =
typename RangeDeque::value_type;
870 Index xPos(0), pos(0), zStride =
Index(max[2] - min[2]);
871 const PointIndexT* dataPtr = &leaf.indices().front();
872 PointIndexT beginOffset(0), endOffset(0),
873 previousOffset(static_cast<IntT>(leaf.indices().size() + 1u));
876 for (ijk[0] = min[0]; ijk[0] <= max[0]; ++ijk[0]) {
877 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
879 for (ijk[1] = min[1]; ijk[1] <= max[1]; ++ijk[1]) {
880 pos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
881 pos += (min[2] & (LeafNodeType::DIM - 1u));
883 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
884 endOffset = leaf.getValue(pos+zStride);
886 if (endOffset > beginOffset) {
888 if (beginOffset == previousOffset) {
889 rangeList.back().second = dataPtr + endOffset;
891 rangeList.push_back(Range(dataPtr + beginOffset, dataPtr + endOffset));
894 previousOffset = endOffset;
901 template<
typename RangeDeque,
typename ConstAccessor>
905 using LeafNodeType =
typename ConstAccessor::TreeType::LeafNodeType;
906 using PointIndexT =
typename LeafNodeType::ValueType;
907 using Range =
typename RangeDeque::value_type;
909 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
910 const Coord leafMin = bbox.
min() & ~(LeafNodeType::DIM - 1);
911 const Coord leafMax = bbox.
max() & ~(LeafNodeType::DIM - 1);
913 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
914 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
915 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
917 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
919 ijkMax.
offset(LeafNodeType::DIM - 1);
925 if (ijkA != ijk || ijkB != ijkMax) {
929 const PointIndexT* begin = &leaf->indices().front();
930 rangeList.push_back(Range(begin, (begin + leaf->indices().size())));
944 template<
typename TreeType>
949 , mIter(mRangeList.begin())
956 template<
typename TreeType>
960 , mRangeList(rhs.mRangeList)
961 , mIter(mRangeList.begin())
963 , mIndexArraySize(rhs.mIndexArraySize)
965 if (rhs.mIndexArray) {
966 mIndexArray.reset(
new ValueType[mIndexArraySize]);
967 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize *
sizeof(
ValueType));
972 template<
typename TreeType>
978 mRangeList = rhs.mRangeList;
979 mIter = mRangeList.begin();
981 mIndexArraySize = rhs.mIndexArraySize;
983 if (rhs.mIndexArray) {
984 mIndexArray.reset(
new ValueType[mIndexArraySize]);
985 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize *
sizeof(
ValueType));
992 template<
typename TreeType>
997 , mIter(mRangeList.begin())
1002 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
1003 mRangeList.push_back(mRange);
1004 mIter = mRangeList.begin();
1009 template<
typename TreeType>
1014 , mIter(mRangeList.begin())
1016 , mIndexArraySize(0)
1020 if (!mRangeList.empty()) {
1021 mIter = mRangeList.begin();
1022 mRange = mRangeList.front();
1027 template<
typename TreeType>
1031 mIter = mRangeList.begin();
1032 if (!mRangeList.empty()) {
1033 mRange = mRangeList.front();
1034 }
else if (mIndexArray) {
1035 mRange.first = mIndexArray.get();
1036 mRange.second = mRange.first + mIndexArraySize;
1038 mRange.first =
static_cast<ValueType*
>(
nullptr);
1039 mRange.second =
static_cast<ValueType*
>(
nullptr);
1044 template<
typename TreeType>
1049 if (mRange.first >= mRange.second && mIter != mRangeList.end()) {
1051 if (mIter != mRangeList.end()) {
1053 }
else if (mIndexArray) {
1054 mRange.first = mIndexArray.get();
1055 mRange.second = mRange.first + mIndexArraySize;
1061 template<
typename TreeType>
1065 if (!this->
test())
return false;
1067 return this->
test();
1071 template<
typename TreeType>
1076 typename RangeDeque::const_iterator it = mRangeList.begin();
1078 for ( ; it != mRangeList.end(); ++it) {
1079 count += it->second - it->first;
1082 return count + mIndexArraySize;
1086 template<
typename TreeType>
1090 mRange.first =
static_cast<ValueType*
>(
nullptr);
1091 mRange.second =
static_cast<ValueType*
>(
nullptr);
1093 mIter = mRangeList.end();
1094 mIndexArray.reset();
1095 mIndexArraySize = 0;
1099 template<
typename TreeType>
1105 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
1106 mRangeList.push_back(mRange);
1107 mIter = mRangeList.begin();
1112 template<
typename TreeType>
1119 if (!mRangeList.empty()) {
1120 mIter = mRangeList.begin();
1121 mRange = mRangeList.front();
1126 template<
typename TreeType>
1127 template<
typename Po
intArray>
1134 std::vector<CoordBBox> searchRegions;
1140 if (minExtent > 2) {
1151 searchRegions.push_back(region);
1155 std::deque<ValueType> filteredIndices;
1157 filter(mRangeList, filteredIndices, bbox, points, xform);
1159 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1169 template<
typename TreeType>
1170 template<
typename Po
intArray>
1174 bool subvoxelAccuracy)
1177 std::vector<CoordBBox> searchRegions;
1181 Coord::round(
Vec3d(center[0] - radius, center[1] - radius, center[2] - radius)),
1182 Coord::round(
Vec3d(center[0] + radius, center[1] + radius, center[2] + radius)));
1185 const double iRadius = radius * double(1.0 / std::sqrt(3.0));
1186 if (iRadius > 2.0) {
1189 Coord::round(
Vec3d(center[0] - iRadius, center[1] - iRadius, center[2] - iRadius)),
1190 Coord::round(
Vec3d(center[0] + iRadius, center[1] + iRadius, center[2] + iRadius)));
1199 searchRegions.push_back(bbox);
1203 std::deque<ValueType> filteredIndices;
1204 const double leafNodeDim = double(TreeType::LeafNodeType::DIM);
1208 FilterT filter(mRangeList, filteredIndices,
1209 center, radius, points, xform, leafNodeDim, subvoxelAccuracy);
1211 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1221 template<
typename TreeType>
1222 template<
typename Po
intArray>
1232 template<
typename TreeType>
1233 template<
typename Po
intArray>
1237 bool subvoxelAccuracy)
1240 (radius / xform.
voxelSize()[0]), acc, points, xform, subvoxelAccuracy);
1248 template<
typename Po
intArray,
typename TreeType>
1252 : mPoints(&points), mAcc(tree), mXform(xform), mInvVoxelSize(1.0/xform.voxelSize()[0])
1257 template<
typename Po
intArray,
typename TreeType>
1260 : mPoints(rhs.mPoints)
1261 , mAcc(rhs.mAcc.tree())
1262 , mXform(rhs.mXform)
1263 , mInvVoxelSize(rhs.mInvVoxelSize)
1268 template<
typename Po
intArray,
typename TreeType>
1269 template<
typename FilterType>
1274 if (radius * mInvVoxelSize <
ScalarType(8.0)) {
1279 mIter.worldSpaceSearchAndUpdate(
1280 center, radius, mAcc, *mPoints, mXform,
false);
1283 const ScalarType radiusSqr = radius * radius;
1286 for (; mIter; ++mIter) {
1287 mPoints->getPos(*mIter, pos);
1289 distSqr = pos.lengthSqr();
1291 if (distSqr < radiusSqr) {
1292 op(distSqr, *mIter);
1301 template<
typename Gr
idT,
typename Po
intArrayT>
1302 inline typename GridT::Ptr
1305 typename GridT::Ptr grid = GridT::create(
typename GridT::ValueType(0));
1306 grid->setTransform(xform.
copy());
1308 if (points.size() > 0) {
1310 grid->tree(), grid->transform(), points);
1317 template<
typename Gr
idT,
typename Po
intArrayT>
1318 inline typename GridT::Ptr
1322 return createPointIndexGrid<GridT>(points, *xform);
1326 template<
typename Po
intArrayT,
typename Gr
idT>
1333 for (
size_t n = 0, N = leafs.leafCount(); n < N; ++n) {
1334 pointCount += leafs.
leaf(n).indices().size();
1341 tbb::atomic<bool> changed;
1345 op(changed, points, grid.transform());
1349 return !bool(changed);
1353 template<
typename Gr
idT,
typename Po
intArrayT>
1354 inline typename GridT::ConstPtr
1361 return createPointIndexGrid<GridT>(points, grid->transform());
1365 template<
typename Gr
idT,
typename Po
intArrayT>
1366 inline typename GridT::Ptr
1373 return createPointIndexGrid<GridT>(points, grid->transform());
1380 template<
typename T, Index Log2Dim>
1399 bool isEmpty(
const CoordBBox& bbox)
const;
1413 using BaseLeaf::LOG2DIM;
1414 using BaseLeaf::TOTAL;
1415 using BaseLeaf::DIM;
1416 using BaseLeaf::NUM_VALUES;
1417 using BaseLeaf::NUM_VOXELS;
1418 using BaseLeaf::SIZE;
1419 using BaseLeaf::LEVEL;
1431 #if OPENVDB_ABI_VERSION_NUMBER >= 3 1433 const T& value = zeroVal<T>(),
bool active =
false)
1445 template<
typename OtherType, Index OtherLog2Dim>
1447 return BaseLeaf::hasSameTopology(other);
1456 BaseLeaf::merge<Policy>(rhs);
1458 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive) {
1459 BaseLeaf::template merge<Policy>(tileValue, tileActive);
1462 template<MergePolicy Policy>
1466 BaseLeaf::template merge<Policy>(other);
1470 template<
typename AccessorT>
1476 template<
typename AccessorT>
1479 template<
typename NodeT,
typename AccessorT>
1483 if (!(std::is_same<NodeT, PointIndexLeafNode>::value))
return nullptr;
1484 return reinterpret_cast<NodeT*
>(
this);
1488 template<
typename AccessorT>
1495 template<
typename AccessorT>
1497 template<
typename AccessorT>
1500 template<
typename NodeT,
typename AccessorT>
1504 if (!(std::is_same<NodeT, PointIndexLeafNode>::value))
return nullptr;
1505 return reinterpret_cast<const NodeT*
>(
this);
1513 void readBuffers(std::istream& is,
bool fromHalf =
false);
1514 void readBuffers(std::istream& is,
const CoordBBox&,
bool fromHalf =
false);
1515 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
1527 assert(
false &&
"Cannot modify voxel values in a PointIndexTree.");
1553 template<
typename ModifyOp>
1556 template<
typename ModifyOp>
1559 template<
typename ModifyOp>
1568 template<
typename AccessorT>
1571 template<
typename ModifyOp,
typename AccessorT>
1573 assertNonmodifiable();
1576 template<
typename AccessorT>
1579 template<
typename AccessorT>
1633 const PointIndexLeafNode,
const ValueType, ChildAll>;
1635 #define VMASK_ this->getValueMask() 1679 template<
typename T, Index Log2Dim>
1684 return getIndices(LeafNodeType::coordToOffset(ijk), begin, end);
1688 template<
typename T, Index Log2Dim>
1693 if (this->isValueMaskOn(offset)) {
1694 const ValueType* dataPtr = &mIndices.front();
1695 begin = dataPtr + (offset == 0 ?
ValueType(0) : this->buffer()[offset - 1]);
1696 end = dataPtr + this->buffer()[offset];
1703 template<
typename T, Index Log2Dim>
1707 this->buffer().setValue(offset, val);
1708 this->setValueMaskOn(offset);
1712 template<
typename T, Index Log2Dim>
1716 this->buffer().setValue(offset, val);
1720 template<
typename T, Index Log2Dim>
1727 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
1728 xPos = (ijk[0] & (DIM - 1u)) << (2 * LOG2DIM);
1730 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
1731 pos = xPos + ((ijk[1] & (DIM - 1u)) << LOG2DIM);
1732 pos += (bbox.
min()[2] & (DIM - 1u));
1734 if (this->buffer()[pos+zStride] > (pos == 0 ? T(0) : this->buffer()[pos - 1])) {
1744 template<
typename T, Index Log2Dim>
1748 BaseLeaf::readBuffers(is, fromHalf);
1751 is.read(reinterpret_cast<char*>(&numIndices),
sizeof(
Index64));
1753 mIndices.resize(
size_t(numIndices));
1754 is.read(reinterpret_cast<char*>(mIndices.data()), numIndices *
sizeof(T));
1758 template<
typename T, Index Log2Dim>
1763 BaseLeaf::readBuffers(is, bbox, fromHalf);
1766 is.read(reinterpret_cast<char*>(&numIndices),
sizeof(
Index64));
1768 const Index64 numBytes = numIndices *
sizeof(T);
1770 if (bbox.
hasOverlap(this->getNodeBoundingBox())) {
1771 mIndices.resize(
size_t(numIndices));
1772 is.read(reinterpret_cast<char*>(mIndices.data()), numBytes);
1778 std::unique_ptr<char[]> buf{
new char[numBytes]};
1779 is.read(buf.get(), numBytes);
1784 is.read(reinterpret_cast<char*>(&auxDataBytes),
sizeof(
Index64));
1785 if (auxDataBytes > 0) {
1787 std::unique_ptr<char[]> auxData{
new char[auxDataBytes]};
1788 is.read(auxData.get(), auxDataBytes);
1793 template<
typename T, Index Log2Dim>
1797 BaseLeaf::writeBuffers(os, toHalf);
1800 os.write(reinterpret_cast<const char*>(&numIndices),
sizeof(
Index64));
1801 os.write(reinterpret_cast<const char*>(mIndices.data()), numIndices *
sizeof(T));
1805 os.write(reinterpret_cast<const char*>(&auxDataBytes),
sizeof(
Index64));
1809 template<
typename T, Index Log2Dim>
1813 return BaseLeaf::memUsage() +
Index64((
sizeof(T)*mIndices.capacity()) +
sizeof(mIndices));
1826 template<Index Dim1,
typename T2>
1829 static const bool value =
true;
1836 #endif // OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
Int32 x() const
Definition: Coord.h:157
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:271
Definition: LeafNode.h:232
Coord & offset(Int32 dx, Int32 dy, Int32 dz)
Definition: Coord.h:110
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:430
Definition: LeafNode.h:233
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:375
const Vec3T & min() const
Return a const reference to the minimum point of this bounding box.
Definition: BBox.h:89
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:416
Definition: LeafNode.h:233
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:73
const Coord & min() const
Definition: Coord.h:337
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
Definition: Exceptions.h:87
std::shared_ptr< T > SharedPtr
Definition: Types.h:139
Definition: LeafNode.h:233
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
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:56
Definition: NodeMasks.h:241
Spatially partitions points using a parallel radix-based sorting algorithm.
Selectively extract and filter point data using a custom filter operator.
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:422
Vec3< double > Vec3d
Definition: Vec3.h:679
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
Definition: LeafNode.h:280
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:202
Int32 z() const
Definition: Coord.h:159
#define VMASK_
Definition: PointIndexGrid.h:1635
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:359
Definition: InternalNode.h:60
Definition: Exceptions.h:40
Index32 Index
Definition: Types.h:61
void maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition: Coord.h:210
Abstract base class for maps.
Definition: Maps.h:161
Int32 y() const
Definition: Coord.h:158
Definition: NodeMasks.h:210
Definition: PointDataGrid.h:201
uint64_t Index64
Definition: Types.h:60
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion). ...
Definition: Coord.h:77
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNode.h:174
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:488
Definition: RootNode.h:70
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
const Vec3T & max() const
Return a const reference to the maximum point of this bounding box.
Definition: BBox.h:91
Definition: LeafNode.h:232
const Coord & max() const
Definition: Coord.h:338
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
math::BBox< Vec3d > BBoxd
Definition: Types.h:91
std::vector< Index > IndexArray
Definition: PointMove.h:193
Definition: LeafNode.h:236
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:520
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:64
Definition: NodeMasks.h:272
Coord dim() const
Return the dimensions of the coordinates spanned by this bounding box.
Definition: Coord.h:384
Definition: LeafNode.h:232
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:309