43 #ifndef OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 44 #define OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 56 #include <boost/scoped_array.hpp> 59 #include <tbb/atomic.h> 60 #include <tbb/blocked_range.h> 61 #include <tbb/parallel_for.h> 113 template<
typename Gr
idT,
typename Po
intArrayT>
114 inline typename GridT::Ptr
123 template<
typename Gr
idT,
typename Po
intArrayT>
124 inline typename GridT::Ptr
133 template<
typename Po
intArrayT,
typename Gr
idT>
139 template<
typename Gr
idT,
typename Po
intArrayT>
140 inline typename GridT::ConstPtr
144 template<
typename Gr
idT,
typename Po
intArrayT>
145 inline typename GridT::Ptr
153 template<
typename TreeType = Po
intIndexTree>
184 void searchAndUpdate(
const Coord& ijk, ConstAccessor& acc);
192 void searchAndUpdate(
const CoordBBox& bbox, ConstAccessor& acc);
201 template<
typename Po
intArray>
202 void searchAndUpdate(
const BBoxd& bbox, ConstAccessor& acc,
216 template<
typename Po
intArray>
217 void searchAndUpdate(
const Vec3d& center,
double radius, ConstAccessor& acc,
227 template<
typename Po
intArray>
228 void worldSpaceSearchAndUpdate(
const BBoxd& bbox, ConstAccessor& acc,
242 template<
typename Po
intArray>
243 void worldSpaceSearchAndUpdate(
const Vec3d& center,
double radius, ConstAccessor& acc,
251 const ValueType&
operator*()
const {
return *mRange.first; }
255 bool test()
const {
return mRange.first < mRange.second || mIter != mRangeList.end(); }
256 operator bool()
const {
return this->test(); }
279 typedef std::pair<const ValueType*, const ValueType*> Range;
280 typedef std::deque<Range> RangeDeque;
281 typedef typename RangeDeque::const_iterator RangeDequeCIter;
282 typedef boost::scoped_array<ValueType> IndexArray;
288 RangeDeque mRangeList;
289 RangeDequeCIter mIter;
291 IndexArray mIndexArray;
292 size_t mIndexArraySize;
325 template<
typename Po
intArray,
typename TreeType = Po
intIndexTree>
346 template<
typename FilterType>
347 void searchAndApply(
const PosType& center, ScalarType radius,
FilterType& op);
353 const ScalarType mInvVoxelSize;
363 namespace point_index_grid_internal {
365 template<
typename Po
intArrayT>
372 , mHasChanged(&hasChanged)
376 template <
typename LeafT>
379 if ((*mHasChanged)) {
380 tbb::task::self().cancel_group_execution();
384 typedef typename LeafT::IndexArray IndexArrayT;
385 typedef typename IndexArrayT::value_type IndexT;
386 typedef typename PointArrayT::PosType PosType;
388 typename LeafT::ValueOnCIter iter;
392 const IndexT *begin =
static_cast<IndexT*
>(NULL), *end = static_cast<IndexT*>(NULL);
394 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
396 if ((*mHasChanged))
break;
398 voxelCoord = iter.getCoord();
399 leaf.getIndices(iter.pos(), begin, end);
401 while (begin < end) {
403 mPoints->getPos(*begin, point);
404 if (voxelCoord != mTransform->worldToIndexCellCentered(point)) {
405 mHasChanged->fetch_and_store(
true);
415 PointArrayT
const *
const mPoints;
417 tbb::atomic<bool> *
const mHasChanged;
421 template<
typename LeafNodeT>
428 const Partitioner& partitioner)
429 : mLeafNodes(leafNodes.get())
430 , mPartitioner(&partitioner)
434 void operator()(
const tbb::blocked_range<size_t>& range)
const {
438 size_t maxPointCount = 0;
439 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
440 maxPointCount =
std::max(maxPointCount, mPartitioner->indices(n).size());
443 const IndexT voxelCount = LeafNodeT::SIZE;
446 boost::scoped_array<VoxelOffsetT> offsets(
new VoxelOffsetT[maxPointCount]);
447 boost::scoped_array<IndexT>
histogram(
new IndexT[voxelCount]);
449 VoxelOffsetT
const *
const voxelOffsets = mPartitioner->voxelOffsets().get();
451 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
453 LeafNodeT* node =
new LeafNodeT();
454 node->setOrigin(mPartitioner->origin(n));
458 const size_t pointCount = it.
size();
459 IndexT
const *
const indices = &*it;
462 for (IndexT i = 0; i < pointCount; ++i) {
463 offsets[i] = voxelOffsets[ indices[i] ];
467 memset(&histogram[0], 0, voxelCount *
sizeof(IndexT));
468 for (IndexT i = 0; i < pointCount; ++i) {
469 ++histogram[ offsets[i] ];
472 typename LeafNodeT::NodeMaskType& mask = node->getValueMask();
473 typename LeafNodeT::Buffer& buffer = node->buffer();
476 IndexT count = 0, startOffset;
477 for (
int i = 0; i < int(voxelCount); ++i) {
478 if (histogram[i] > 0) {
480 count += histogram[i];
481 histogram[i] = startOffset;
484 buffer.setValue(i, count);
488 node->indices().resize(pointCount);
489 typename LeafNodeT::ValueType *
const orderedIndices = node->indices().data();
492 for (IndexT i = 0; i < pointCount; ++i) {
493 orderedIndices[ histogram[ offsets[i] ]++ ] = indices[i];
496 mLeafNodes[n] = node;
508 template<
typename TreeType,
typename Po
intArray>
512 typedef typename TreeType::LeafNodeType LeafType;
514 boost::scoped_array<LeafType*> leafNodes;
515 size_t leafNodeCount = 0;
522 partitioner.
construct(points, xform,
false,
true);
526 "cell-centered transform.");
529 leafNodeCount = partitioner.
size();
530 leafNodes.reset(
new LeafType*[leafNodeCount]);
532 const tbb::blocked_range<size_t> range(0, leafNodeCount);
537 for (
size_t n = 0; n < leafNodeCount; ++n) {
548 dequeToArray(
const std::deque<T>& d, boost::scoped_array<T>& a,
size_t& size)
551 a.reset(
new T[size]);
552 typename std::deque<T>::const_iterator it = d.begin(), itEnd = d.end();
554 for ( ; it != itEnd; ++it, ++item) *item = *it;
568 regions.push_back(bbox);
569 regions.back().
max().
z() = cmin.
z();
572 regions.push_back(bbox);
573 regions.back().min().z() = cmax.
z();
579 regions.push_back(bbox);
581 lastRegion->
min().
z() = cmin.
z();
582 lastRegion->
max().
z() = cmax.
z();
583 lastRegion->
max().
x() = cmin.
x();
586 regions.push_back(*lastRegion);
587 lastRegion = ®ions.back();
588 lastRegion->
min().
x() = cmax.
x();
589 lastRegion->
max().
x() = bbox.
max().
x();
595 regions.push_back(*lastRegion);
596 lastRegion = ®ions.back();
597 lastRegion->
min().
x() = cmin.
x();
598 lastRegion->
max().
x() = cmax.
x();
599 lastRegion->
max().
y() = cmin.
y();
602 regions.push_back(*lastRegion);
603 lastRegion = ®ions.back();
604 lastRegion->
min().
y() = cmax.
y();
605 lastRegion->
max().
y() = bbox.
max().
y();
609 template<
typename Po
intArray,
typename IndexT>
614 typedef std::pair<const IndexT*, const IndexT*>
Range;
624 , mMap(*xform.baseMap())
628 template <
typename LeafNodeType>
631 typename LeafNodeType::ValueOnCIter iter;
632 const IndexT *begin =
static_cast<IndexT*
>(NULL), *end = static_cast<IndexT*>(NULL);
633 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
634 leaf.getIndices(iter.pos(), begin, end);
635 filterVoxel(iter.getCoord(), begin, end);
643 for (; begin < end; ++begin) {
644 mPoints.getPos(*begin, vec);
646 if (mRegion.isInside(mMap.applyInverseMap(vec))) {
647 mIndices.push_back(*begin);
654 IndexDeque& mIndices;
661 template<
typename Po
intArray,
typename IndexT>
666 typedef std::pair<const IndexT*, const IndexT*>
Range;
672 const double leafNodeDim,
const bool subvoxelAccuracy)
676 , mWSCenter(xform.indexToWorld(xyz))
677 , mVoxelDist1(ScalarType(0.0))
678 , mVoxelDist2(ScalarType(0.0))
679 , mLeafNodeDist1(ScalarType(0.0))
680 , mLeafNodeDist2(ScalarType(0.0))
681 , mWSRadiusSqr(ScalarType(radius * xform.voxelSize()[0]))
683 , mSubvoxelAccuracy(subvoxelAccuracy)
685 const ScalarType voxelRadius = ScalarType(std::sqrt(3.0) * 0.5);
686 mVoxelDist1 = voxelRadius + ScalarType(radius);
687 mVoxelDist1 *= mVoxelDist1;
689 if (radius > voxelRadius) {
690 mVoxelDist2 = ScalarType(radius) - voxelRadius;
691 mVoxelDist2 *= mVoxelDist2;
694 const ScalarType leafNodeRadius = ScalarType(leafNodeDim * std::sqrt(3.0) * 0.5);
695 mLeafNodeDist1 = leafNodeRadius + ScalarType(radius);
696 mLeafNodeDist1 *= mLeafNodeDist1;
698 if (radius > leafNodeRadius) {
699 mLeafNodeDist2 = ScalarType(radius) - leafNodeRadius;
700 mLeafNodeDist2 *= mLeafNodeDist2;
703 mWSRadiusSqr *= mWSRadiusSqr;
706 template <
typename LeafNodeType>
710 const Coord& ijk = leaf.origin();
712 vec[0] = ScalarType(ijk[0]);
713 vec[1] = ScalarType(ijk[1]);
714 vec[2] = ScalarType(ijk[2]);
715 vec += ScalarType(LeafNodeType::DIM - 1) * 0.5;
718 const ScalarType dist = vec.lengthSqr();
719 if (dist > mLeafNodeDist1)
return;
721 if (mLeafNodeDist2 > 0.0 && dist < mLeafNodeDist2) {
722 const IndexT* begin = &leaf.indices().front();
723 mRanges.push_back(Range(begin, begin + leaf.indices().size()));
728 typename LeafNodeType::ValueOnCIter iter;
729 const IndexT *begin =
static_cast<IndexT*
>(NULL), *end = static_cast<IndexT*>(NULL);
730 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
731 leaf.getIndices(iter.pos(), begin, end);
732 filterVoxel(iter.getCoord(), begin, end);
741 vec[0] = mCenter[0] - ScalarType(ijk[0]);
742 vec[1] = mCenter[1] - ScalarType(ijk[1]);
743 vec[2] = mCenter[2] - ScalarType(ijk[2]);
745 const ScalarType dist = vec.lengthSqr();
746 if (dist > mVoxelDist1)
return;
748 if (!mSubvoxelAccuracy || (mVoxelDist2 > 0.0 && dist < mVoxelDist2)) {
749 if (!mRanges.empty() && mRanges.back().second == begin) {
750 mRanges.back().second = end;
752 mRanges.push_back(Range(begin, end));
759 while (begin < end) {
760 mPoints.getPos(*begin, vec);
761 vec = mWSCenter - vec;
763 if (vec.lengthSqr() < mWSRadiusSqr) {
764 mIndices.push_back(*begin);
772 IndexDeque& mIndices;
773 const PosType mCenter, mWSCenter;
774 ScalarType mVoxelDist1, mVoxelDist2, mLeafNodeDist1, mLeafNodeDist2, mWSRadiusSqr;
776 const bool mSubvoxelAccuracy;
783 template<
typename RangeFilterType,
typename LeafNodeType>
788 typedef typename LeafNodeType::ValueType PointIndexT;
789 Index xPos(0), yPos(0), pos(0);
792 const PointIndexT* dataPtr = &leaf.indices().front();
793 PointIndexT beginOffset, endOffset;
795 for (ijk[0] = min[0]; ijk[0] <= max[0]; ++ijk[0]) {
796 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
797 for (ijk[1] = min[1]; ijk[1] <= max[1]; ++ijk[1]) {
798 yPos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
799 for (ijk[2] = min[2]; ijk[2] <= max[2]; ++ijk[2]) {
800 pos = yPos + (ijk[2] & (LeafNodeType::DIM - 1u));
802 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
803 endOffset = leaf.getValue(pos);
805 if (endOffset > beginOffset) {
806 filter.filterVoxel(ijk, dataPtr + beginOffset, dataPtr + endOffset);
814 template<
typename RangeFilterType,
typename ConstAccessor>
818 typedef typename ConstAccessor::TreeType::LeafNodeType LeafNodeType;
819 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
820 const Coord leafMin = bbox.
min() & ~(LeafNodeType::DIM - 1);
821 const Coord leafMax = bbox.
max() & ~(LeafNodeType::DIM - 1);
823 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
824 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
825 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
827 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
829 ijkMax.
offset(LeafNodeType::DIM - 1);
835 if (ijkA != ijk || ijkB != ijkMax) {
838 filter.filterLeafNode(*leaf);
850 template<
typename RangeDeque,
typename LeafNodeType>
855 typedef typename LeafNodeType::ValueType PointIndexT;
856 typedef typename PointIndexT::IntType IntT;
857 typedef typename RangeDeque::value_type Range;
859 Index xPos(0), pos(0), zStride =
Index(max[2] - min[2]);
860 const PointIndexT* dataPtr = &leaf.indices().front();
861 PointIndexT beginOffset(0), endOffset(0),
862 previousOffset(static_cast<IntT>(leaf.indices().size() + 1u));
865 for (ijk[0] = min[0]; ijk[0] <= max[0]; ++ijk[0]) {
866 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
868 for (ijk[1] = min[1]; ijk[1] <= max[1]; ++ijk[1]) {
869 pos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
870 pos += (min[2] & (LeafNodeType::DIM - 1u));
872 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
873 endOffset = leaf.getValue(pos+zStride);
875 if (endOffset > beginOffset) {
877 if (beginOffset == previousOffset) {
878 rangeList.back().second = dataPtr + endOffset;
880 rangeList.push_back(Range(dataPtr + beginOffset, dataPtr + endOffset));
883 previousOffset = endOffset;
890 template<
typename RangeDeque,
typename ConstAccessor>
894 typedef typename ConstAccessor::TreeType::LeafNodeType LeafNodeType;
895 typedef typename LeafNodeType::ValueType PointIndexT;
896 typedef typename RangeDeque::value_type Range;
898 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
899 const Coord leafMin = bbox.
min() & ~(LeafNodeType::DIM - 1);
900 const Coord leafMax = bbox.
max() & ~(LeafNodeType::DIM - 1);
902 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
903 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
904 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
906 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
908 ijkMax.
offset(LeafNodeType::DIM - 1);
914 if (ijkA != ijk || ijkB != ijkMax) {
918 const PointIndexT* begin = &leaf->indices().front();
919 rangeList.push_back(Range(begin, (begin + leaf->indices().size())));
933 template<
typename TreeType>
938 , mIter(mRangeList.begin())
945 template<
typename TreeType>
949 , mRangeList(rhs.mRangeList)
950 , mIter(mRangeList.begin())
952 , mIndexArraySize(rhs.mIndexArraySize)
954 if (rhs.mIndexArray) {
955 mIndexArray.reset(
new ValueType[mIndexArraySize]);
956 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize *
sizeof(
ValueType));
961 template<
typename TreeType>
967 mRangeList = rhs.mRangeList;
968 mIter = mRangeList.begin();
970 mIndexArraySize = rhs.mIndexArraySize;
972 if (rhs.mIndexArray) {
973 mIndexArray.reset(
new ValueType[mIndexArraySize]);
974 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize *
sizeof(
ValueType));
981 template<
typename TreeType>
986 , mIter(mRangeList.begin())
991 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
992 mRangeList.push_back(mRange);
993 mIter = mRangeList.begin();
998 template<
typename TreeType>
1003 , mIter(mRangeList.begin())
1005 , mIndexArraySize(0)
1009 if (!mRangeList.empty()) {
1010 mIter = mRangeList.begin();
1011 mRange = mRangeList.front();
1016 template<
typename TreeType>
1020 mIter = mRangeList.begin();
1021 if (!mRangeList.empty()) {
1022 mRange = mRangeList.front();
1023 }
else if (mIndexArray) {
1024 mRange.first = mIndexArray.get();
1025 mRange.second = mRange.first + mIndexArraySize;
1027 mRange.first =
static_cast<ValueType*
>(NULL);
1028 mRange.second =
static_cast<ValueType*
>(NULL);
1033 template<
typename TreeType>
1038 if (mRange.first >= mRange.second && mIter != mRangeList.end()) {
1040 if (mIter != mRangeList.end()) {
1042 }
else if (mIndexArray) {
1043 mRange.first = mIndexArray.get();
1044 mRange.second = mRange.first + mIndexArraySize;
1050 template<
typename TreeType>
1054 if (!this->
test())
return false;
1056 return this->
test();
1060 template<
typename TreeType>
1065 typename RangeDeque::const_iterator it = mRangeList.begin();
1067 for ( ; it != mRangeList.end(); ++it) {
1068 count += it->second - it->first;
1071 return count + mIndexArraySize;
1075 template<
typename TreeType>
1079 mRange.first =
static_cast<ValueType*
>(NULL);
1080 mRange.second =
static_cast<ValueType*
>(NULL);
1082 mIter = mRangeList.end();
1083 mIndexArray.reset();
1084 mIndexArraySize = 0;
1088 template<
typename TreeType>
1094 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
1095 mRangeList.push_back(mRange);
1096 mIter = mRangeList.begin();
1101 template<
typename TreeType>
1108 if (!mRangeList.empty()) {
1109 mIter = mRangeList.begin();
1110 mRange = mRangeList.front();
1115 template<
typename TreeType>
1116 template<
typename Po
intArray>
1123 std::vector<CoordBBox> searchRegions;
1129 if (minExtent > 2) {
1140 searchRegions.push_back(region);
1144 std::deque<ValueType> filteredIndices;
1146 filter(mRangeList, filteredIndices, bbox, points, xform);
1148 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1158 template<
typename TreeType>
1159 template<
typename Po
intArray>
1163 bool subvoxelAccuracy)
1166 std::vector<CoordBBox> searchRegions;
1170 Coord::round(
Vec3d(center[0] - radius, center[1] - radius, center[2] - radius)),
1171 Coord::round(
Vec3d(center[0] + radius, center[1] + radius, center[2] + radius)));
1174 const double iRadius = radius * double(1.0 / std::sqrt(3.0));
1175 if (iRadius > 2.0) {
1178 Coord::round(
Vec3d(center[0] - iRadius, center[1] - iRadius, center[2] - iRadius)),
1179 Coord::round(
Vec3d(center[0] + iRadius, center[1] + iRadius, center[2] + iRadius)));
1188 searchRegions.push_back(bbox);
1192 std::deque<ValueType> filteredIndices;
1193 const double leafNodeDim = double(TreeType::LeafNodeType::DIM);
1197 FilterT filter(mRangeList, filteredIndices,
1198 center, radius, points, xform, leafNodeDim, subvoxelAccuracy);
1200 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1210 template<
typename TreeType>
1211 template<
typename Po
intArray>
1221 template<
typename TreeType>
1222 template<
typename Po
intArray>
1226 bool subvoxelAccuracy)
1229 (radius / xform.
voxelSize()[0]), acc, points, xform, subvoxelAccuracy);
1237 template<
typename Po
intArray,
typename TreeType>
1241 : mPoints(&points), mAcc(tree), mXform(xform), mInvVoxelSize(1.0/xform.voxelSize()[0])
1246 template<
typename Po
intArray,
typename TreeType>
1249 : mPoints(rhs.mPoints)
1250 , mAcc(rhs.mAcc.tree())
1251 , mXform(rhs.mXform)
1252 , mInvVoxelSize(rhs.mInvVoxelSize)
1257 template<
typename Po
intArray,
typename TreeType>
1258 template<
typename FilterType>
1263 if (radius * mInvVoxelSize <
ScalarType(8.0)) {
1268 mIter.worldSpaceSearchAndUpdate(
1269 center, radius, mAcc, *mPoints, mXform,
false);
1272 const ScalarType radiusSqr = radius * radius;
1275 for (; mIter; ++mIter) {
1276 mPoints->getPos(*mIter, pos);
1278 distSqr = pos.lengthSqr();
1280 if (distSqr < radiusSqr) {
1281 op(distSqr, *mIter);
1290 template<
typename Gr
idT,
typename Po
intArrayT>
1291 inline typename GridT::Ptr
1294 typename GridT::Ptr grid = GridT::create(
typename GridT::ValueType(0));
1295 grid->setTransform(xform.
copy());
1297 if (points.size() > 0) {
1299 grid->tree(), grid->transform(), points);
1306 template<
typename Gr
idT,
typename Po
intArrayT>
1307 inline typename GridT::Ptr
1311 return createPointIndexGrid<GridT>(points, *xform);
1315 template<
typename Po
intArrayT,
typename Gr
idT>
1321 size_t pointCount = 0;
1322 for (
size_t n = 0, N = leafs.leafCount(); n < N; ++n) {
1323 pointCount += leafs.
leaf(n).indices().size();
1326 if (points.size() != pointCount) {
1330 tbb::atomic<bool> changed;
1334 op(changed, points, grid.transform());
1338 return !bool(changed);
1342 template<
typename Gr
idT,
typename Po
intArrayT>
1343 inline typename GridT::ConstPtr
1350 return createPointIndexGrid<GridT>(points, grid->transform());
1354 template<
typename Gr
idT,
typename Po
intArrayT>
1355 inline typename GridT::Ptr
1362 return createPointIndexGrid<GridT>(points, grid->transform());
1369 template<
typename T, Index Log2Dim>
1373 typedef boost::shared_ptr<PointIndexLeafNode>
Ptr;
1380 const IndexArray&
indices()
const {
return mIndices; }
1382 bool getIndices(
const Coord& ijk,
const ValueType*& begin,
const ValueType*& end)
const;
1383 bool getIndices(
Index offset,
const ValueType*& begin,
const ValueType*& end)
const;
1385 void setOffsetOn(
Index offset,
const ValueType& val);
1386 void setOffsetOnly(
Index offset,
const ValueType& val);
1388 bool isEmpty(
const CoordBBox& bbox)
const;
1391 IndexArray mIndices;
1402 using BaseLeaf::LOG2DIM;
1403 using BaseLeaf::TOTAL;
1404 using BaseLeaf::DIM;
1405 using BaseLeaf::NUM_VALUES;
1406 using BaseLeaf::NUM_VOXELS;
1407 using BaseLeaf::SIZE;
1408 using BaseLeaf::LEVEL;
1415 : BaseLeaf(coords, value, active)
1420 #ifndef OPENVDB_2_ABI_COMPATIBLE 1422 const T& value = zeroVal<T>(),
bool active =
false)
1434 template<
typename OtherType, Index OtherLog2Dim>
1436 return BaseLeaf::hasSameTopology(other);
1445 BaseLeaf::merge<Policy>(rhs);
1447 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive) {
1448 BaseLeaf::template merge<Policy>(tileValue, tileActive);
1451 template<MergePolicy Policy>
1453 const ValueType& ,
const ValueType& )
1455 BaseLeaf::template merge<Policy>(other);
1459 template<
typename AccessorT>
1465 template<
typename AccessorT>
1468 template<
typename NodeT,
typename AccessorT>
1472 if (!(boost::is_same<NodeT,PointIndexLeafNode>::value))
return NULL;
1473 return reinterpret_cast<NodeT*
>(
this);
1477 template<
typename AccessorT>
1484 template<
typename AccessorT>
1486 template<
typename AccessorT>
1489 template<
typename NodeT,
typename AccessorT>
1493 if (!(boost::is_same<NodeT,PointIndexLeafNode>::value))
return NULL;
1494 return reinterpret_cast<const NodeT*
>(
this);
1502 void readBuffers(std::istream& is,
bool fromHalf =
false);
1503 void readBuffers(std::istream& is,
const CoordBBox&,
bool fromHalf =
false);
1504 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
1516 assert(
false &&
"Cannot modify voxel values in a PointIndexTree.");
1542 template<
typename ModifyOp>
1545 template<
typename ModifyOp>
1548 template<
typename ModifyOp>
1555 void fill(
const ValueType&,
bool) { assertNonmodifiable(); }
1557 template<
typename AccessorT>
1560 template<
typename ModifyOp,
typename AccessorT>
1562 assertNonmodifiable();
1565 template<
typename AccessorT>
1568 template<
typename AccessorT>
1601 typedef typename BaseLeaf::template
ValueIter<
1603 typedef typename BaseLeaf::template
ValueIter<
1604 MaskOnIterator,
const PointIndexLeafNode,
const ValueType, ValueOn>
ValueOnCIter;
1605 typedef typename BaseLeaf::template
ValueIter<
1606 MaskOffIterator, PointIndexLeafNode,
const ValueType, ValueOff>
ValueOffIter;
1607 typedef typename BaseLeaf::template
ValueIter<
1608 MaskOffIterator,
const PointIndexLeafNode,
const ValueType,ValueOff>
ValueOffCIter;
1609 typedef typename BaseLeaf::template
ValueIter<
1610 MaskDenseIterator, PointIndexLeafNode,
const ValueType, ValueAll>
ValueAllIter;
1611 typedef typename BaseLeaf::template
ValueIter<
1612 MaskDenseIterator,
const PointIndexLeafNode,
const ValueType,ValueAll>
ValueAllCIter;
1613 typedef typename BaseLeaf::template
ChildIter<
1615 typedef typename BaseLeaf::template
ChildIter<
1617 typedef typename BaseLeaf::template
ChildIter<
1619 typedef typename BaseLeaf::template
ChildIter<
1621 typedef typename BaseLeaf::template
DenseIter<
1623 typedef typename BaseLeaf::template
DenseIter<
1626 #define VMASK_ this->getValueMask() 1670 template<
typename T, Index Log2Dim>
1673 const ValueType*& begin,
const ValueType*& end)
const 1675 return getIndices(LeafNodeType::coordToOffset(ijk), begin, end);
1679 template<
typename T, Index Log2Dim>
1682 const ValueType*& begin,
const ValueType*& end)
const 1684 if (this->isValueMaskOn(offset)) {
1685 const ValueType* dataPtr = &mIndices.front();
1686 begin = dataPtr + (offset == 0 ? ValueType(0) : this->buffer()[offset - 1]);
1687 end = dataPtr + this->buffer()[offset];
1694 template<
typename T, Index Log2Dim>
1698 this->buffer().setValue(offset, val);
1699 this->setValueMaskOn(offset);
1703 template<
typename T, Index Log2Dim>
1707 this->buffer().setValue(offset, val);
1711 template<
typename T, Index Log2Dim>
1718 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
1719 xPos = (ijk[0] & (DIM - 1u)) << (2 * LOG2DIM);
1721 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
1722 pos = xPos + ((ijk[1] & (DIM - 1u)) << LOG2DIM);
1723 pos += (bbox.
min()[2] & (DIM - 1u));
1725 if (this->buffer()[pos+zStride] > (pos == 0 ? T(0) : this->buffer()[pos - 1])) {
1735 template<
typename T, Index Log2Dim>
1739 BaseLeaf::readBuffers(is, fromHalf);
1742 is.read(reinterpret_cast<char*>(&numIndices),
sizeof(
Index64));
1744 mIndices.resize(
size_t(numIndices));
1745 is.read(reinterpret_cast<char*>(mIndices.data()), numIndices *
sizeof(T));
1749 template<
typename T, Index Log2Dim>
1754 BaseLeaf::readBuffers(is, bbox, fromHalf);
1757 is.read(reinterpret_cast<char*>(&numIndices),
sizeof(
Index64));
1759 const Index64 numBytes = numIndices *
sizeof(T);
1761 if (bbox.
hasOverlap(this->getNodeBoundingBox())) {
1762 mIndices.resize(
size_t(numIndices));
1763 is.read(reinterpret_cast<char*>(mIndices.data()), numBytes);
1769 boost::scoped_array<char> buf(
new char[numBytes]);
1770 is.read(buf.get(), numBytes);
1775 is.read(reinterpret_cast<char*>(&auxDataBytes),
sizeof(
Index64));
1776 if (auxDataBytes > 0) {
1778 boost::scoped_array<char> auxData(
new char[auxDataBytes]);
1779 is.read(auxData.get(), auxDataBytes);
1784 template<
typename T, Index Log2Dim>
1788 BaseLeaf::writeBuffers(os, toHalf);
1791 os.write(reinterpret_cast<const char*>(&numIndices),
sizeof(
Index64));
1792 os.write(reinterpret_cast<const char*>(mIndices.data()), numIndices *
sizeof(T));
1796 os.write(reinterpret_cast<const char*>(&auxDataBytes),
sizeof(
Index64));
1800 template<
typename T, Index Log2Dim>
1804 return BaseLeaf::memUsage() +
Index64((
sizeof(T)*mIndices.capacity()) +
sizeof(mIndices));
1817 template<Index Dim1,
typename T2>
1820 static const bool value =
true;
1827 #endif // OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED
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:374
Definition: LeafNode.h:506
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:72
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:191
Coord & offset(Int32 dx, Int32 dy, Int32 dz)
Definition: Coord.h:105
math::BBox< Vec3d > BBoxd
Definition: Types.h:86
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNode.h:448
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:115
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
Definition: PointIndexGrid.h:69
Definition: LeafNode.h:554
void maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition: Coord.h:199
Definition: LeafNode.h:506
Int32 x() const
Definition: Coord.h:146
Spatially partitions points using a parallel radix-based sorting algorithm.
Index32 Index
Definition: Types.h:58
Selectively extract and filter point data using a custom filter operator.
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion). ...
Definition: Coord.h:76
uint64_t Index64
Definition: Types.h:57
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Vec3< double > Vec3d
Definition: Vec3.h:651
Definition: InternalNode.h:64
Definition: LeafNode.h:507
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:401
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:65
#define VMASK_
Definition: PointIndexGrid.h:1626
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:304
Definition: Exceptions.h:39
Abstract base class for maps.
Definition: Maps.h:159
Definition: LeafNode.h:507
const Vec3T & min() const
Return a const reference to the minimum point of the BBox.
Definition: BBox.h:81
Coord dim() const
Return the dimensions of the coordinates spanned by this bounding box.
Definition: Coord.h:363
Int32 z() const
Definition: Coord.h:148
const Vec3T & max() const
Return a const reference to the maximum point of the BBox.
Definition: BBox.h:84
Definition: NodeMasks.h:267
Definition: LeafNode.h:510
const Coord & min() const
Definition: Coord.h:332
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:450
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:395
const Coord & max() const
Definition: Coord.h:333
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:259
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:545
Definition: LeafNode.h:506
Int32 y() const
Definition: Coord.h:147
Definition: LeafNode.h:507
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:354
Definition: NodeMasks.h:205
Definition: NodeMasks.h:236
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Definition: Exceptions.h:83
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:429
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
Definition: RootNode.h:75
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58