43 #ifndef OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 44 #define OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 47 #include <openvdb/Grid.h> 48 #include <openvdb/Types.h> 49 #include <openvdb/math/Transform.h> 50 #include <openvdb/tree/Tree.h> 51 #include <openvdb/tree/LeafNode.h> 52 #include <openvdb/tree/LeafManager.h> 55 #include <boost/scoped_array.hpp> 56 #include <tbb/blocked_range.h> 57 #include <tbb/parallel_for.h> 58 #include <tbb/atomic.h> 112 template<
typename Gr
idT,
typename Po
intArrayT>
113 inline typename GridT::Ptr
122 template<
typename Po
intArrayT,
typename Gr
idT>
128 template<
typename Gr
idT,
typename Po
intArrayT>
129 inline typename GridT::ConstPtr
133 template<
typename Gr
idT,
typename Po
intArrayT>
134 inline typename GridT::Ptr
142 template<
typename TreeType = Po
intIndexTree>
173 void searchAndUpdate(
const Coord& ijk, ConstAccessor& acc);
181 void searchAndUpdate(
const CoordBBox& bbox, ConstAccessor& acc);
190 template<
typename Po
intArray>
191 void searchAndUpdate(
const BBoxd& bbox, ConstAccessor& acc,
205 template<
typename Po
intArray>
206 void searchAndUpdate(
const Vec3d& center,
double radius, ConstAccessor& acc,
216 template<
typename Po
intArray>
217 void worldSpaceSearchAndUpdate(
const BBoxd& bbox, ConstAccessor& acc,
231 template<
typename Po
intArray>
232 void worldSpaceSearchAndUpdate(
const Vec3d& center,
double radius, ConstAccessor& acc,
240 const ValueType&
operator*()
const {
return *mRange.first; }
244 bool test()
const {
return mRange.first < mRange.second || mIter != mRangeList.end(); }
245 operator bool()
const {
return this->test(); }
268 typedef std::pair<const ValueType*, const ValueType*> Range;
269 typedef std::deque<Range> RangeDeque;
270 typedef typename RangeDeque::const_iterator RangeDequeCIter;
271 typedef boost::scoped_array<ValueType> IndexArray;
277 RangeDeque mRangeList;
278 RangeDequeCIter mIter;
280 IndexArray mIndexArray;
281 size_t mIndexArraySize;
314 template<
typename Po
intArray,
typename TreeType = Po
intIndexTree>
335 template<
typename FilterType>
336 void searchAndApply(
const PointType& center, PointElementType radius,
FilterType& op);
342 const PointElementType mInvVoxelSize;
352 namespace point_index_grid_internal {
354 template<
typename Po
intArrayT>
361 , mHasChanged(&hasChanged)
365 template <
typename LeafT>
368 if ((*mHasChanged)) {
369 tbb::task::self().cancel_group_execution();
373 typedef typename LeafT::IndexArray IndexArrayT;
374 typedef typename IndexArrayT::value_type IndexT;
375 typedef typename PointArrayT::value_type PointT;
377 typename LeafT::ValueOnCIter iter;
381 const IndexT *begin =
static_cast<IndexT*
>(NULL), *end = static_cast<IndexT*>(NULL);
383 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
385 if ((*mHasChanged))
break;
387 voxelCoord = iter.getCoord();
388 leaf.getIndices(iter.pos(), begin, end);
390 while (begin < end) {
392 mPoints->getPos(*begin, point);
393 if (voxelCoord != mTransform->worldToIndexCellCentered(point)) {
394 mHasChanged->fetch_and_store(
true);
404 PointArrayT
const *
const mPoints;
406 tbb::atomic<bool> *
const mHasChanged;
410 template<
typename LeafNodeT>
417 const Partitioner& partitioner)
418 : mLeafNodes(leafNodes.get())
419 , mPartitioner(&partitioner)
423 void operator()(
const tbb::blocked_range<size_t>& range)
const {
427 size_t maxPointCount = 0;
428 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
429 maxPointCount =
std::max(maxPointCount, mPartitioner->indices(n).size());
432 const IndexT voxelCount = LeafNodeT::SIZE;
435 boost::scoped_array<VoxelOffsetT> offsets(
new VoxelOffsetT[maxPointCount]);
436 boost::scoped_array<IndexT>
histogram(
new IndexT[voxelCount]);
438 VoxelOffsetT
const *
const voxelOffsets = mPartitioner->voxelOffsets().get();
440 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
442 LeafNodeT* node =
new LeafNodeT();
443 node->setOrigin(mPartitioner->origin(n));
447 const size_t pointCount = it.
size();
448 IndexT
const *
const indices = &*it;
451 for (IndexT i = 0; i < pointCount; ++i) {
452 offsets[i] = voxelOffsets[ indices[i] ];
456 memset(&histogram[0], 0, voxelCount *
sizeof(IndexT));
457 for (IndexT i = 0; i < pointCount; ++i) {
458 ++histogram[ offsets[i] ];
461 typename LeafNodeT::NodeMaskType& mask = node->getValueMask();
462 typename LeafNodeT::Buffer& buffer = node->buffer();
465 IndexT count = 0, startOffset;
466 for (
int i = 0; i < int(voxelCount); ++i) {
467 if (histogram[i] > 0) {
469 count += histogram[i];
470 histogram[i] = startOffset;
473 buffer.setValue(i, count);
477 node->indices().resize(pointCount);
478 typename LeafNodeT::ValueType *
const orderedIndices = node->indices().data();
481 for (IndexT i = 0; i < pointCount; ++i) {
482 orderedIndices[ histogram[ offsets[i] ]++ ] = indices[i];
485 mLeafNodes[n] = node;
497 template<
typename TreeType,
typename Po
intArray>
501 typedef typename TreeType::LeafNodeType LeafType;
503 boost::scoped_array<LeafType*> leafNodes;
504 size_t leafNodeCount = 0;
508 partitioner.
construct(points, xform,
false,
true);
510 leafNodeCount = partitioner.
size();
511 leafNodes.reset(
new LeafType*[leafNodeCount]);
513 const tbb::blocked_range<size_t> range(0, leafNodeCount);
518 for (
size_t n = 0; n < leafNodeCount; ++n) {
529 dequeToArray(
const std::deque<T>& d, boost::scoped_array<T>& a,
size_t& size)
532 a.reset(
new T[size]);
533 typename std::deque<T>::const_iterator it = d.begin(), itEnd = d.end();
535 for ( ; it != itEnd; ++it, ++item) *item = *it;
541 const CoordBBox& bbox,
const CoordBBox& ibox)
545 Coord cmin = ibox.min();
546 Coord cmax = ibox.max();
549 regions.push_back(bbox);
550 regions.back().max().z() = cmin.z();
553 regions.push_back(bbox);
554 regions.back().min().z() = cmax.z();
560 regions.push_back(bbox);
561 CoordBBox* lastRegion = ®ions.back();
562 lastRegion->min().z() = cmin.z();
563 lastRegion->max().z() = cmax.z();
564 lastRegion->max().x() = cmin.x();
567 regions.push_back(*lastRegion);
568 lastRegion = ®ions.back();
569 lastRegion->min().x() = cmax.x();
570 lastRegion->max().x() = bbox.max().x();
576 regions.push_back(*lastRegion);
577 lastRegion = ®ions.back();
578 lastRegion->min().x() = cmin.x();
579 lastRegion->max().x() = cmax.x();
580 lastRegion->max().y() = cmin.y();
583 regions.push_back(*lastRegion);
584 lastRegion = ®ions.back();
585 lastRegion->min().y() = cmax.y();
586 lastRegion->max().y() = bbox.max().y();
590 template<
typename Po
intArray,
typename IndexT>
595 typedef std::pair<const IndexT*, const IndexT*>
Range;
605 , mMap(*xform.baseMap())
609 template <
typename LeafNodeType>
612 typename LeafNodeType::ValueOnCIter iter;
613 const IndexT *begin =
static_cast<IndexT*
>(NULL), *end = static_cast<IndexT*>(NULL);
614 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
615 leaf.getIndices(iter.pos(), begin, end);
616 filterVoxel(iter.getCoord(), begin, end);
620 void filterVoxel(
const Coord&,
const IndexT* begin,
const IndexT* end)
625 for (; begin < end; ++begin) {
626 mPoints.getPos(*begin, vec);
629 xyz = mMap.applyInverseMap(vec);
634 if (mRegion.isInside(xyz)) {
635 mIndices.push_back(*begin);
642 IndexDeque& mIndices;
649 template<
typename Po
intArray,
typename IndexT>
654 typedef std::pair<const IndexT*, const IndexT*>
Range;
660 const double leafNodeDim,
const bool subvoxelAccuracy)
664 , mWSCenter(xform.indexToWorld(xyz))
665 , mVoxelDist1(PointElementType(0.0))
666 , mVoxelDist2(PointElementType(0.0))
667 , mLeafNodeDist1(PointElementType(0.0))
668 , mLeafNodeDist2(PointElementType(0.0))
669 , mWSRadiusSqr(PointElementType(radius * xform.voxelSize()[0]))
671 , mSubvoxelAccuracy(subvoxelAccuracy)
673 const PointElementType voxelRadius = PointElementType(std::sqrt(3.0) * 0.5);
674 mVoxelDist1 = voxelRadius + PointElementType(radius);
675 mVoxelDist1 *= mVoxelDist1;
677 if (radius > voxelRadius) {
678 mVoxelDist2 = PointElementType(radius) - voxelRadius;
679 mVoxelDist2 *= mVoxelDist2;
682 const PointElementType leafNodeRadius = PointElementType(leafNodeDim * std::sqrt(3.0) * 0.5);
683 mLeafNodeDist1 = leafNodeRadius + PointElementType(radius);
684 mLeafNodeDist1 *= mLeafNodeDist1;
686 if (radius > leafNodeRadius) {
687 mLeafNodeDist2 = PointElementType(radius) - leafNodeRadius;
688 mLeafNodeDist2 *= mLeafNodeDist2;
691 mWSRadiusSqr *= mWSRadiusSqr;
694 template <
typename LeafNodeType>
698 const Coord& ijk = leaf.origin();
700 vec[0] = PointElementType(ijk[0]);
701 vec[1] = PointElementType(ijk[1]);
702 vec[2] = PointElementType(ijk[2]);
703 vec += PointElementType(LeafNodeType::DIM - 1) * 0.5;
706 const PointElementType dist = vec.lengthSqr();
707 if (dist > mLeafNodeDist1)
return;
709 if (mLeafNodeDist2 > 0.0 && dist < mLeafNodeDist2) {
710 const IndexT* begin = &leaf.indices().front();
711 mRanges.push_back(Range(begin, begin + leaf.indices().size()));
716 typename LeafNodeType::ValueOnCIter iter;
717 const IndexT *begin =
static_cast<IndexT*
>(NULL), *end = static_cast<IndexT*>(NULL);
718 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
719 leaf.getIndices(iter.pos(), begin, end);
720 filterVoxel(iter.getCoord(), begin, end);
724 void filterVoxel(
const Coord& ijk,
const IndexT* begin,
const IndexT* end)
729 vec[0] = mCenter[0] - PointElementType(ijk[0]);
730 vec[1] = mCenter[1] - PointElementType(ijk[1]);
731 vec[2] = mCenter[2] - PointElementType(ijk[2]);
733 const PointElementType dist = vec.lengthSqr();
734 if (dist > mVoxelDist1)
return;
736 if (!mSubvoxelAccuracy || (mVoxelDist2 > 0.0 && dist < mVoxelDist2)) {
737 if (!mRanges.empty() && mRanges.back().second == begin) {
738 mRanges.back().second = end;
740 mRanges.push_back(Range(begin, end));
747 while (begin < end) {
748 mPoints.getPos(*begin, vec);
749 vec = mWSCenter - vec;
751 if (vec.lengthSqr() < mWSRadiusSqr) {
752 mIndices.push_back(*begin);
760 IndexDeque& mIndices;
761 const PointType mCenter, mWSCenter;
762 PointElementType mVoxelDist1, mVoxelDist2, mLeafNodeDist1, mLeafNodeDist2, mWSRadiusSqr;
764 const bool mSubvoxelAccuracy;
771 template<
typename RangeFilterType,
typename LeafNodeType>
774 const LeafNodeType& leaf,
const Coord&
min,
const Coord&
max)
776 typedef typename LeafNodeType::ValueType PointIndexT;
777 Index xPos(0), yPos(0), pos(0);
780 const PointIndexT* dataPtr = &leaf.indices().front();
781 PointIndexT beginOffset, endOffset;
783 for (ijk[0] = min[0]; ijk[0] <= max[0]; ++ijk[0]) {
784 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
785 for (ijk[1] = min[1]; ijk[1] <= max[1]; ++ijk[1]) {
786 yPos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
787 for (ijk[2] = min[2]; ijk[2] <= max[2]; ++ijk[2]) {
788 pos = yPos + (ijk[2] & (LeafNodeType::DIM - 1u));
790 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
791 endOffset = leaf.getValue(pos);
793 if (endOffset > beginOffset) {
794 filter.filterVoxel(ijk, dataPtr + beginOffset, dataPtr + endOffset);
802 template<
typename RangeFilterType,
typename ConstAccessor>
806 typedef typename ConstAccessor::TreeType::LeafNodeType LeafNodeType;
807 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
808 const Coord leafMin = bbox.min() & ~(LeafNodeType::DIM - 1);
809 const Coord leafMax = bbox.max() & ~(LeafNodeType::DIM - 1);
811 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
812 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
813 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
815 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
817 ijkMax.offset(LeafNodeType::DIM - 1);
823 if (ijkA != ijk || ijkB != ijkMax) {
826 filter.filterLeafNode(*leaf);
838 template<
typename RangeDeque,
typename LeafNodeType>
841 const LeafNodeType& leaf,
const Coord&
min,
const Coord&
max)
843 typedef typename LeafNodeType::ValueType PointIndexT;
844 typedef typename PointIndexT::IntType IntT;
845 typedef typename RangeDeque::value_type Range;
847 Index xPos(0), pos(0), zStride =
Index(max[2] - min[2]);
848 const PointIndexT* dataPtr = &leaf.indices().front();
849 PointIndexT beginOffset(0), endOffset(0),
850 previousOffset(static_cast<IntT>(leaf.indices().size() + 1u));
853 for (ijk[0] = min[0]; ijk[0] <= max[0]; ++ijk[0]) {
854 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
856 for (ijk[1] = min[1]; ijk[1] <= max[1]; ++ijk[1]) {
857 pos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
858 pos += (min[2] & (LeafNodeType::DIM - 1u));
860 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
861 endOffset = leaf.getValue(pos+zStride);
863 if (endOffset > beginOffset) {
865 if (beginOffset == previousOffset) {
866 rangeList.back().second = dataPtr + endOffset;
868 rangeList.push_back(Range(dataPtr + beginOffset, dataPtr + endOffset));
871 previousOffset = endOffset;
878 template<
typename RangeDeque,
typename ConstAccessor>
882 typedef typename ConstAccessor::TreeType::LeafNodeType LeafNodeType;
883 typedef typename LeafNodeType::ValueType PointIndexT;
884 typedef typename RangeDeque::value_type Range;
886 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
887 const Coord leafMin = bbox.min() & ~(LeafNodeType::DIM - 1);
888 const Coord leafMax = bbox.max() & ~(LeafNodeType::DIM - 1);
890 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
891 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
892 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
894 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
896 ijkMax.offset(LeafNodeType::DIM - 1);
902 if (ijkA != ijk || ijkB != ijkMax) {
906 const PointIndexT* begin = &leaf->indices().front();
907 rangeList.push_back(Range(begin, (begin + leaf->indices().size())));
921 template<
typename TreeType>
926 , mIter(mRangeList.begin())
933 template<
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));
949 template<
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));
969 template<
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();
986 template<
typename TreeType>
991 , mIter(mRangeList.begin())
997 if (!mRangeList.empty()) {
998 mIter = mRangeList.begin();
999 mRange = mRangeList.front();
1004 template<
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*
>(NULL);
1016 mRange.second =
static_cast<ValueType*
>(NULL);
1021 template<
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;
1038 template<
typename TreeType>
1042 if (!this->
test())
return false;
1044 return this->
test();
1048 template<
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;
1063 template<
typename TreeType>
1067 mRange.first =
static_cast<ValueType*
>(NULL);
1068 mRange.second =
static_cast<ValueType*
>(NULL);
1070 mIter = mRangeList.end();
1071 mIndexArray.reset();
1072 mIndexArraySize = 0;
1076 template<
typename TreeType>
1082 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
1083 mRangeList.push_back(mRange);
1084 mIter = mRangeList.begin();
1089 template<
typename TreeType>
1096 if (!mRangeList.empty()) {
1097 mIter = mRangeList.begin();
1098 mRange = mRangeList.front();
1103 template<
typename TreeType>
1104 template<
typename Po
intArray>
1111 std::vector<CoordBBox> searchRegions;
1112 CoordBBox region(Coord::round(bbox.
min()), Coord::round(bbox.
max()));
1114 const Coord dim = region.dim();
1117 if (minExtent > 2) {
1119 CoordBBox ibox = region;
1128 searchRegions.push_back(region);
1132 std::deque<ValueType> filteredIndices;
1134 filter(mRangeList, filteredIndices, bbox, points, xform);
1136 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1146 template<
typename TreeType>
1147 template<
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)));
1176 searchRegions.push_back(bbox);
1180 std::deque<ValueType> filteredIndices;
1181 const double leafNodeDim = double(TreeType::LeafNodeType::DIM);
1185 FilterT filter(mRangeList, filteredIndices,
1186 center, radius, points, xform, leafNodeDim, subvoxelAccuracy);
1188 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1198 template<
typename TreeType>
1199 template<
typename Po
intArray>
1209 template<
typename TreeType>
1210 template<
typename Po
intArray>
1214 bool subvoxelAccuracy)
1217 (radius / xform.
voxelSize()[0]), acc, points, xform, subvoxelAccuracy);
1225 template<
typename Po
intArray,
typename TreeType>
1229 : mPoints(&points), mAcc(tree), mXform(xform), mInvVoxelSize(1.0/xform.voxelSize()[0])
1234 template<
typename Po
intArray,
typename TreeType>
1237 : mPoints(rhs.mPoints)
1238 , mAcc(rhs.mAcc.tree())
1239 , mXform(rhs.mXform)
1240 , mInvVoxelSize(rhs.mInvVoxelSize)
1245 template<
typename Po
intArray,
typename TreeType>
1246 template<
typename FilterType>
1252 mIter.searchAndUpdate(openvdb::CoordBBox(
1256 mIter.worldSpaceSearchAndUpdate(
1257 center, radius, mAcc, *mPoints, mXform,
false);
1263 for (; mIter; ++mIter) {
1264 mPoints->getPos(*mIter, pos);
1266 distSqr = pos.lengthSqr();
1268 if (distSqr < radiusSqr) {
1269 op(distSqr, *mIter);
1278 template<
typename Gr
idT,
typename Po
intArrayT>
1279 inline typename GridT::Ptr
1282 typename GridT::Ptr grid = GridT::create(
typename GridT::ValueType(0));
1283 grid->setTransform(xform.
copy());
1285 if (points.size() > 0) {
1287 grid->tree(), grid->transform(), points);
1294 template<
typename Po
intArrayT,
typename Gr
idT>
1300 size_t pointCount = 0;
1301 for (
size_t n = 0, N = leafs.leafCount(); n < N; ++n) {
1302 pointCount += leafs.
leaf(n).indices().size();
1305 if (points.size() != pointCount) {
1309 tbb::atomic<bool> changed;
1313 op(changed, points, grid.transform());
1317 return !bool(changed);
1321 template<
typename Gr
idT,
typename Po
intArrayT>
1322 inline typename GridT::ConstPtr
1329 return createPointIndexGrid<GridT>(points, grid->transform());
1333 template<
typename Gr
idT,
typename Po
intArrayT>
1334 inline typename GridT::Ptr
1341 return createPointIndexGrid<GridT>(points, grid->transform());
1348 template<
typename T, Index Log2Dim>
1352 typedef boost::shared_ptr<PointIndexLeafNode>
Ptr;
1359 const IndexArray&
indices()
const {
return mIndices; }
1361 bool getIndices(
const Coord& ijk,
const ValueType*& begin,
const ValueType*& end)
const;
1362 bool getIndices(
Index offset,
const ValueType*& begin,
const ValueType*& end)
const;
1364 void setOffsetOn(
Index offset,
const ValueType& val);
1365 void setOffsetOnly(
Index offset,
const ValueType& val);
1367 bool isEmpty(
const CoordBBox& bbox)
const;
1370 IndexArray mIndices;
1381 using BaseLeaf::LOG2DIM;
1382 using BaseLeaf::TOTAL;
1383 using BaseLeaf::DIM;
1384 using BaseLeaf::NUM_VALUES;
1385 using BaseLeaf::NUM_VOXELS;
1386 using BaseLeaf::SIZE;
1387 using BaseLeaf::LEVEL;
1394 : BaseLeaf(coords, value, active)
1399 #ifndef OPENVDB_2_ABI_COMPATIBLE 1401 const T& value = zeroVal<T>(),
bool active =
false)
1413 template<
typename OtherType, Index OtherLog2Dim>
1415 return BaseLeaf::hasSameTopology(other);
1424 BaseLeaf::merge<Policy>(rhs);
1426 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive) {
1427 BaseLeaf::template merge<Policy>(tileValue, tileActive);
1430 template<MergePolicy Policy>
1432 const ValueType& ,
const ValueType& )
1434 BaseLeaf::template merge<Policy>(other);
1438 template<
typename AccessorT>
1444 template<
typename AccessorT>
1447 template<
typename NodeT,
typename AccessorT>
1451 if (!(boost::is_same<NodeT,PointIndexLeafNode>::value))
return NULL;
1452 return reinterpret_cast<NodeT*
>(
this);
1456 template<
typename AccessorT>
1463 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<const NodeT*
>(
this);
1481 void readBuffers(std::istream& is,
bool fromHalf =
false);
1482 void readBuffers(std::istream& is,
const CoordBBox&,
bool fromHalf =
false);
1483 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
1495 assert(
false &&
"Cannot modify voxel values in a PointIndexTree.");
1501 void setValueOnly(
const Coord&,
const ValueType&) { assertNonmodifiable(); }
1507 void setValueOff(
const Coord&,
const ValueType&) { assertNonmodifiable(); }
1513 void setValueOn(
const Coord&,
const ValueType&) { assertNonmodifiable(); }
1516 void setValue(
const Coord&,
const ValueType&) { assertNonmodifiable(); }
1521 template<
typename ModifyOp>
1524 template<
typename ModifyOp>
1525 void modifyValue(
const Coord&,
const ModifyOp&) { assertNonmodifiable(); }
1527 template<
typename ModifyOp>
1530 void clip(
const CoordBBox&,
const ValueType&) { assertNonmodifiable(); }
1532 void fill(
const CoordBBox&,
const ValueType&,
bool) { assertNonmodifiable(); }
1534 void fill(
const ValueType&,
bool) { assertNonmodifiable(); }
1536 template<
typename AccessorT>
1539 template<
typename ModifyOp,
typename AccessorT>
1541 assertNonmodifiable();
1544 template<
typename AccessorT>
1547 template<
typename AccessorT>
1580 typedef typename BaseLeaf::template
ValueIter<
1582 typedef typename BaseLeaf::template
ValueIter<
1583 MaskOnIterator,
const PointIndexLeafNode,
const ValueType, ValueOn>
ValueOnCIter;
1584 typedef typename BaseLeaf::template
ValueIter<
1585 MaskOffIterator, PointIndexLeafNode,
const ValueType, ValueOff>
ValueOffIter;
1586 typedef typename BaseLeaf::template
ValueIter<
1587 MaskOffIterator,
const PointIndexLeafNode,
const ValueType,ValueOff>
ValueOffCIter;
1588 typedef typename BaseLeaf::template
ValueIter<
1589 MaskDenseIterator, PointIndexLeafNode,
const ValueType, ValueAll>
ValueAllIter;
1590 typedef typename BaseLeaf::template
ValueIter<
1591 MaskDenseIterator,
const PointIndexLeafNode,
const ValueType,ValueAll>
ValueAllCIter;
1592 typedef typename BaseLeaf::template
ChildIter<
1594 typedef typename BaseLeaf::template
ChildIter<
1596 typedef typename BaseLeaf::template
ChildIter<
1598 typedef typename BaseLeaf::template
ChildIter<
1600 typedef typename BaseLeaf::template
DenseIter<
1602 typedef typename BaseLeaf::template
DenseIter<
1605 #define VMASK_ this->getValueMask() 1649 template<
typename T, Index Log2Dim>
1652 const ValueType*& begin,
const ValueType*& end)
const 1654 return getIndices(LeafNodeType::coordToOffset(ijk), begin, end);
1658 template<
typename T, Index Log2Dim>
1661 const ValueType*& begin,
const ValueType*& end)
const 1663 if (this->isValueMaskOn(offset)) {
1664 const ValueType* dataPtr = &mIndices.front();
1665 begin = dataPtr + (offset == 0 ? ValueType(0) : this->buffer()[offset - 1]);
1666 end = dataPtr + this->buffer()[offset];
1673 template<
typename T, Index Log2Dim>
1677 this->buffer().setValue(offset, val);
1678 this->setValueMaskOn(offset);
1682 template<
typename T, Index Log2Dim>
1686 this->buffer().setValue(offset, val);
1690 template<
typename T, Index Log2Dim>
1694 Index xPos, pos, zStride =
Index(bbox.max()[2] - bbox.min()[2]);
1697 for (ijk[0] = bbox.min()[0]; ijk[0] <= bbox.max()[0]; ++ijk[0]) {
1698 xPos = (ijk[0] & (DIM - 1u)) << (2 * LOG2DIM);
1700 for (ijk[1] = bbox.min()[1]; ijk[1] <= bbox.max()[1]; ++ijk[1]) {
1701 pos = xPos + ((ijk[1] & (DIM - 1u)) << LOG2DIM);
1702 pos += (bbox.min()[2] & (DIM - 1u));
1704 if (this->buffer()[pos+zStride] > (pos == 0 ? T(0) : this->buffer()[pos - 1])) {
1714 template<
typename T, Index Log2Dim>
1718 BaseLeaf::readBuffers(is, fromHalf);
1721 is.read(reinterpret_cast<char*>(&numIndices),
sizeof(
Index64));
1723 mIndices.resize(
size_t(numIndices));
1724 is.read(reinterpret_cast<char*>(mIndices.data()), numIndices *
sizeof(T));
1728 template<
typename T, Index Log2Dim>
1733 BaseLeaf::readBuffers(is, bbox, fromHalf);
1736 is.read(reinterpret_cast<char*>(&numIndices),
sizeof(
Index64));
1738 const Index64 numBytes = numIndices *
sizeof(T);
1740 if (bbox.hasOverlap(this->getNodeBoundingBox())) {
1741 mIndices.resize(
size_t(numIndices));
1742 is.read(reinterpret_cast<char*>(mIndices.data()), numBytes);
1748 boost::scoped_array<char> buf(
new char[numBytes]);
1749 is.read(buf.get(), numBytes);
1754 is.read(reinterpret_cast<char*>(&auxDataBytes),
sizeof(
Index64));
1755 if (auxDataBytes > 0) {
1757 boost::scoped_array<char> auxData(
new char[auxDataBytes]);
1758 is.read(auxData.get(), auxDataBytes);
1763 template<
typename T, Index Log2Dim>
1767 BaseLeaf::writeBuffers(os, toHalf);
1770 os.write(reinterpret_cast<const char*>(&numIndices),
sizeof(
Index64));
1771 os.write(reinterpret_cast<const char*>(mIndices.data()), numIndices *
sizeof(T));
1775 os.write(reinterpret_cast<const char*>(&auxDataBytes),
sizeof(
Index64));
1779 template<
typename T, Index Log2Dim>
1783 return BaseLeaf::memUsage() +
Index64((
sizeof(T)*mIndices.capacity()) +
sizeof(mIndices));
1796 template<Index Dim1,
typename T2>
1799 static const bool value =
true;
1806 #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
Index32 Index
Definition: Types.h:58
Definition: LeafNode.h:504
Definition: LeafNode.h:552
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:450
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNode.h:446
Abstract base class for maps.
Definition: Maps.h:159
Definition: LeafNode.h:504
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:304
Definition: NodeMasks.h:205
Definition: NodeMasks.h:236
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition: Vec2.h:520
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:114
Definition: LeafNode.h:508
Definition: LeafNode.h:505
Spatially partitions points using a parallel radix-based sorting algorithm.
const Vec3T & min() const
Return a const reference to the minimum point of the BBox.
Definition: BBox.h:81
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:511
Selectively extract and filter point data using a custom filter operator.
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:323
const Vec3T & max() const
Return a const reference to the maximum point of the BBox.
Definition: BBox.h:84
Definition: RootNode.h:75
Definition: PointIndexGrid.h:68
math::BBox< Vec3d > BBoxd
Definition: Types.h:86
#define OPENVDB_VERSION_NAME
Definition: version.h:43
#define VMASK_
Definition: PointIndexGrid.h:1605
Definition: LeafNode.h:505
Definition: LeafNode.h:505
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
Definition: Exceptions.h:39
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:767
Vec3< double > Vec3d
Definition: Vec3.h:643
Definition: NodeMasks.h:267
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:543
uint64_t Index64
Definition: Types.h:57
Definition: InternalNode.h:66
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:65
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58
Definition: LeafNode.h:504