18 #ifndef OPENVDB_TOOLS_POINT_PARTITIONER_HAS_BEEN_INCLUDED 19 #define OPENVDB_TOOLS_POINT_PARTITIONER_HAS_BEEN_INCLUDED 24 #include <tbb/blocked_range.h> 25 #include <tbb/parallel_for.h> 26 #include <tbb/task_arena.h> 75 template<
typename Po
intIndexType = u
int32_t, Index BucketLog2Dim = 3>
79 enum { LOG2DIM = BucketLog2Dim };
86 static constexpr
Index bits = 1 + (3 * BucketLog2Dim);
89 int16_t,
typename std::conditional<(bits < 32), int32_t, int64_t>::type>::type;
108 template<
typename Po
intArray>
110 bool voxelOrder =
false,
bool recordVoxelOffsets =
false,
111 bool cellCenteredTransform =
true);
123 template<
typename Po
intArray>
125 bool voxelOrder =
false,
bool recordVoxelOffsets =
false,
126 bool cellCenteredTransform =
true);
130 size_t size()
const {
return mPageCount; }
133 bool empty()
const {
return mPageCount == 0; }
146 return CoordBBox::createCube(mPageCoordinates[n], (1u << BucketLog2Dim));
150 const Coord&
origin(
size_t n)
const {
return mPageCoordinates[n]; }
166 std::unique_ptr<IndexType[]> mPointIndices;
169 std::unique_ptr<IndexType[]> mPageOffsets;
170 std::unique_ptr<Coord[]> mPageCoordinates;
172 bool mUsingCellCenteredTransform;
179 template<
typename Po
intIndexType, Index BucketLog2Dim>
186 : mBegin(begin), mEnd(end), mItem(begin) {}
192 size_t size()
const {
return mEnd - mBegin; }
199 operator bool()
const {
return mItem < mEnd; }
200 bool test()
const {
return mItem < mEnd; }
206 bool next() { this->operator++();
return this->test(); }
226 namespace point_partitioner_internal {
229 template<
typename Po
intIndexType>
230 struct ComputePointOrderOp
232 ComputePointOrderOp(PointIndexType* pointOrder,
233 const PointIndexType* bucketCounters,
const PointIndexType* bucketOffsets)
234 : mPointOrder(pointOrder)
235 , mBucketCounters(bucketCounters)
236 , mBucketOffsets(bucketOffsets)
240 void operator()(
const tbb::blocked_range<size_t>& range)
const {
241 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
242 mPointOrder[n] += mBucketCounters[mBucketOffsets[n]];
246 PointIndexType *
const mPointOrder;
247 PointIndexType
const *
const mBucketCounters;
248 PointIndexType
const *
const mBucketOffsets;
252 template<
typename Po
intIndexType>
253 struct CreateOrderedPointIndexArrayOp
255 CreateOrderedPointIndexArrayOp(PointIndexType* orderedIndexArray,
256 const PointIndexType* pointOrder,
const PointIndexType* indices)
257 : mOrderedIndexArray(orderedIndexArray)
258 , mPointOrder(pointOrder)
263 void operator()(
const tbb::blocked_range<size_t>& range)
const {
264 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
265 mOrderedIndexArray[mPointOrder[n]] = mIndices[n];
269 PointIndexType *
const mOrderedIndexArray;
270 PointIndexType
const *
const mPointOrder;
271 PointIndexType
const *
const mIndices;
275 template<
typename Po
intIndexType, Index BucketLog2Dim>
278 static constexpr
Index bits = 1 + (3 * BucketLog2Dim);
281 int16_t,
typename std::conditional<(bits < 32), int32_t, int64_t>::type>::type;
284 using IndexArray = std::unique_ptr<PointIndexType[]>;
286 VoxelOrderOp(IndexArray& indices,
const IndexArray& pages,
const VoxelOffsetArray& offsets)
287 : mIndices(indices.get())
288 , mPages(pages.get())
289 , mVoxelOffsets(offsets.get())
293 void operator()(
const tbb::blocked_range<size_t>& range)
const {
296 for (
size_t n(range.begin()), N(range.end()); n != N; ++n) {
297 pointCount =
std::max(pointCount, (mPages[n + 1] - mPages[n]));
300 const PointIndexType voxelCount = 1 << (3 * BucketLog2Dim);
303 std::unique_ptr<VoxelOffsetType[]> offsets(
new VoxelOffsetType[pointCount]);
304 std::unique_ptr<PointIndexType[]> sortedIndices(
new PointIndexType[pointCount]);
305 std::unique_ptr<PointIndexType[]>
histogram(
new PointIndexType[voxelCount]);
307 for (
size_t n(range.begin()), N(range.end()); n != N; ++n) {
309 PointIndexType *
const indices = mIndices + mPages[n];
310 pointCount = mPages[n + 1] - mPages[n];
313 for (PointIndexType i = 0; i <
pointCount; ++i) {
314 offsets[i] = mVoxelOffsets[ indices[i] ];
318 memset(&histogram[0], 0, voxelCount *
sizeof(PointIndexType));
321 for (PointIndexType i = 0; i <
pointCount; ++i) {
322 ++histogram[ offsets[i] ];
325 PointIndexType count = 0, startOffset;
326 for (
int i = 0; i < int(voxelCount); ++i) {
327 if (histogram[i] > 0) {
329 count += histogram[i];
330 histogram[i] = startOffset;
335 for (PointIndexType i = 0; i <
pointCount; ++i) {
336 sortedIndices[ histogram[ offsets[i] ]++ ] = indices[i];
339 memcpy(&indices[0], &sortedIndices[0],
sizeof(PointIndexType) * pointCount);
343 PointIndexType *
const mIndices;
344 PointIndexType
const *
const mPages;
355 using Ptr = std::unique_ptr<Array>;
357 Array(
size_t size) : mSize(size), mData(
new T[size]) { }
359 size_t size()
const {
return mSize; }
361 T* data() {
return mData.get(); }
362 const T* data()
const {
return mData.get(); }
364 void clear() { mSize = 0; mData.reset(); }
368 std::unique_ptr<T[]> mData;
372 template<
typename Po
intIndexType>
373 struct MoveSegmentDataOp
375 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
377 MoveSegmentDataOp(std::vector<PointIndexType*>& indexLists, SegmentPtr* segments)
378 : mIndexLists(&indexLists[0]), mSegments(segments)
382 void operator()(
const tbb::blocked_range<size_t>& range)
const {
383 for (
size_t n(range.begin()), N(range.end()); n != N; ++n) {
384 PointIndexType* indices = mIndexLists[n];
385 SegmentPtr& segment = mSegments[n];
387 tbb::parallel_for(tbb::blocked_range<size_t>(0, segment->size()),
388 CopyData(indices, segment->data()));
398 CopyData(PointIndexType* lhs,
const PointIndexType* rhs) : mLhs(lhs), mRhs(rhs) { }
400 void operator()(
const tbb::blocked_range<size_t>& range)
const {
401 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
406 PointIndexType *
const mLhs;
407 PointIndexType
const *
const mRhs;
410 PointIndexType *
const *
const mIndexLists;
411 SegmentPtr *
const mSegments;
415 template<
typename Po
intIndexType>
418 using Segment = Array<PointIndexType>;
419 using SegmentPtr =
typename Segment::Ptr;
421 using IndexPair = std::pair<PointIndexType, PointIndexType>;
422 using IndexPairList = std::deque<IndexPair>;
423 using IndexPairListPtr = std::shared_ptr<IndexPairList>;
424 using IndexPairListMap = std::map<Coord, IndexPairListPtr>;
425 using IndexPairListMapPtr = std::shared_ptr<IndexPairListMap>;
427 MergeBinsOp(IndexPairListMapPtr* bins,
428 SegmentPtr* indexSegments,
429 SegmentPtr* offsetSegments,
433 , mIndexSegments(indexSegments)
434 , mOffsetSegments(offsetSegments)
436 , mNumSegments(numSegments)
440 void operator()(
const tbb::blocked_range<size_t>& range)
const {
442 std::vector<IndexPairListPtr*> data;
443 std::vector<PointIndexType> arrayOffsets;
445 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
447 const Coord& ijk = mCoords[n];
448 size_t numIndices = 0;
452 for (
size_t i = 0, I = mNumSegments; i < I; ++i) {
454 IndexPairListMap& idxMap = *mBins[i];
455 typename IndexPairListMap::iterator iter = idxMap.find(ijk);
457 if (iter != idxMap.end() && iter->second) {
458 IndexPairListPtr& idxListPtr = iter->second;
460 data.push_back(&idxListPtr);
461 numIndices += idxListPtr->size();
465 if (data.empty() || numIndices == 0)
continue;
467 SegmentPtr& indexSegment = mIndexSegments[n];
468 SegmentPtr& offsetSegment = mOffsetSegments[n];
470 indexSegment.reset(
new Segment(numIndices));
471 offsetSegment.reset(
new Segment(numIndices));
473 arrayOffsets.clear();
474 arrayOffsets.reserve(data.size());
476 for (
size_t i = 0, count = 0, I = data.size(); i < I; ++i) {
477 arrayOffsets.push_back(PointIndexType(count));
478 count += (*data[i])->size();
481 tbb::parallel_for(tbb::blocked_range<size_t>(0, data.size()),
482 CopyData(&data[0], &arrayOffsets[0], indexSegment->data(), offsetSegment->data()));
490 CopyData(IndexPairListPtr** indexLists,
491 const PointIndexType* arrayOffsets,
492 PointIndexType* indices,
493 PointIndexType* offsets)
494 : mIndexLists(indexLists)
495 , mArrayOffsets(arrayOffsets)
501 void operator()(
const tbb::blocked_range<size_t>& range)
const {
503 using CIter =
typename IndexPairList::const_iterator;
505 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
507 const PointIndexType arrayOffset = mArrayOffsets[n];
508 PointIndexType* indexPtr = &mIndices[arrayOffset];
509 PointIndexType* offsetPtr = &mOffsets[arrayOffset];
511 IndexPairListPtr& list = *mIndexLists[n];
513 for (CIter it = list->begin(), end = list->end(); it != end; ++it) {
515 *indexPtr++ = data.first;
516 *offsetPtr++ = data.second;
523 IndexPairListPtr *
const *
const mIndexLists;
524 PointIndexType
const *
const mArrayOffsets;
525 PointIndexType *
const mIndices;
526 PointIndexType *
const mOffsets;
529 IndexPairListMapPtr *
const mBins;
530 SegmentPtr *
const mIndexSegments;
531 SegmentPtr *
const mOffsetSegments;
532 Coord
const *
const mCoords;
533 size_t const mNumSegments;
537 template<
typename Po
intArray,
typename Po
intIndexType,
typename VoxelOffsetType>
538 struct BinPointIndicesOp
540 using PosType =
typename PointArray::PosType;
541 using IndexPair = std::pair<PointIndexType, PointIndexType>;
542 using IndexPairList = std::deque<IndexPair>;
543 using IndexPairListPtr = std::shared_ptr<IndexPairList>;
544 using IndexPairListMap = std::map<Coord, IndexPairListPtr>;
545 using IndexPairListMapPtr = std::shared_ptr<IndexPairListMap>;
547 BinPointIndicesOp(IndexPairListMapPtr* data,
554 bool cellCenteredTransform)
557 , mVoxelOffsets(voxelOffsets)
559 , mBinLog2Dim(binLog2Dim)
560 , mBucketLog2Dim(bucketLog2Dim)
561 , mNumSegments(numSegments)
562 , mCellCenteredTransform(cellCenteredTransform)
566 void operator()(
const tbb::blocked_range<size_t>& range)
const {
568 const Index log2dim = mBucketLog2Dim;
569 const Index log2dim2 = 2 * log2dim;
570 const Index bucketMask = (1u << log2dim) - 1u;
572 const Index binLog2dim = mBinLog2Dim;
573 const Index binLog2dim2 = 2 * binLog2dim;
575 const Index binMask = (1u << (log2dim + binLog2dim)) - 1u;
576 const Index invBinMask = ~binMask;
578 IndexPairList * idxList =
nullptr;
579 Coord ijk(0, 0, 0), loc(0, 0, 0), binCoord(0, 0, 0), lastBinCoord(1, 2, 3);
582 PointIndexType bucketOffset = 0;
585 const bool cellCentered = mCellCenteredTransform;
587 const size_t numPoints = mPoints->size();
588 const size_t segmentSize = numPoints / mNumSegments;
590 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
592 IndexPairListMapPtr& dataPtr = mData[n];
593 if (!dataPtr) dataPtr.reset(
new IndexPairListMap());
594 IndexPairListMap& idxMap = *dataPtr;
596 const bool isLastSegment = (n + 1) >= mNumSegments;
598 const size_t start = n * segmentSize;
599 const size_t end = isLastSegment ? numPoints : (start + segmentSize);
601 for (
size_t i = start; i != end; ++i) {
603 mPoints->getPos(i, pos);
605 if (std::isfinite(pos[0]) && std::isfinite(pos[1]) && std::isfinite(pos[2])) {
606 ijk = cellCentered ? mXForm.worldToIndexCellCentered(pos) :
607 mXForm.worldToIndexNodeCentered(pos);
610 loc[0] = ijk[0] & bucketMask;
611 loc[1] = ijk[1] & bucketMask;
612 loc[2] = ijk[2] & bucketMask;
614 (loc[0] << log2dim2) + (loc[1] << log2dim) + loc[2]);
617 binCoord[0] = ijk[0] & invBinMask;
618 binCoord[1] = ijk[1] & invBinMask;
619 binCoord[2] = ijk[2] & invBinMask;
629 bucketOffset = PointIndexType(
630 (ijk[0] << binLog2dim2) + (ijk[1] << binLog2dim) + ijk[2]);
632 if (lastBinCoord != binCoord) {
633 lastBinCoord = binCoord;
634 IndexPairListPtr& idxListPtr = idxMap[lastBinCoord];
635 if (!idxListPtr) idxListPtr.reset(
new IndexPairList());
636 idxList = idxListPtr.get();
639 idxList->push_back(
IndexPair(PointIndexType(i), bucketOffset));
640 if (mVoxelOffsets) mVoxelOffsets[i] = voxelOffset;
646 IndexPairListMapPtr *
const mData;
650 Index const mBinLog2Dim;
651 Index const mBucketLog2Dim;
652 size_t const mNumSegments;
653 bool const mCellCenteredTransform;
657 template<
typename Po
intIndexType>
658 struct OrderSegmentsOp
660 using IndexArray = std::unique_ptr<PointIndexType[]>;
661 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
663 OrderSegmentsOp(SegmentPtr* indexSegments, SegmentPtr* offsetSegments,
664 IndexArray* pageOffsetArrays, IndexArray* pageIndexArrays,
Index binVolume)
665 : mIndexSegments(indexSegments)
666 , mOffsetSegments(offsetSegments)
667 , mPageOffsetArrays(pageOffsetArrays)
668 , mPageIndexArrays(pageIndexArrays)
669 , mBinVolume(binVolume)
673 void operator()(
const tbb::blocked_range<size_t>& range)
const {
675 const size_t bucketCountersSize = size_t(mBinVolume);
676 IndexArray bucketCounters(
new PointIndexType[bucketCountersSize]);
678 size_t maxSegmentSize = 0;
679 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
680 maxSegmentSize =
std::max(maxSegmentSize, mIndexSegments[n]->size());
683 IndexArray bucketIndices(
new PointIndexType[maxSegmentSize]);
685 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
687 memset(bucketCounters.get(), 0,
sizeof(PointIndexType) * bucketCountersSize);
689 const size_t segmentSize = mOffsetSegments[n]->size();
690 PointIndexType* offsets = mOffsetSegments[n]->data();
694 for (
size_t i = 0; i < segmentSize; ++i) {
695 bucketIndices[i] = bucketCounters[offsets[i]]++;
698 PointIndexType nonemptyBucketCount = 0;
699 for (
size_t i = 0; i < bucketCountersSize; ++i) {
700 nonemptyBucketCount +=
static_cast<PointIndexType
>(bucketCounters[i] != 0);
704 IndexArray& pageOffsets = mPageOffsetArrays[n];
705 pageOffsets.reset(
new PointIndexType[nonemptyBucketCount + 1]);
706 pageOffsets[0] = nonemptyBucketCount + 1;
708 IndexArray& pageIndices = mPageIndexArrays[n];
709 pageIndices.reset(
new PointIndexType[nonemptyBucketCount]);
712 PointIndexType count = 0, idx = 0;
713 for (
size_t i = 0; i < bucketCountersSize; ++i) {
714 if (bucketCounters[i] != 0) {
715 pageIndices[idx] =
static_cast<PointIndexType
>(i);
716 pageOffsets[idx+1] = bucketCounters[i];
717 bucketCounters[i] = count;
718 count += pageOffsets[idx+1];
723 PointIndexType* indices = mIndexSegments[n]->data();
724 const tbb::blocked_range<size_t> segmentRange(0, segmentSize);
728 tbb::parallel_for(segmentRange, ComputePointOrderOp<PointIndexType>(
729 bucketIndices.get(), bucketCounters.get(), offsets));
731 tbb::parallel_for(segmentRange, CreateOrderedPointIndexArrayOp<PointIndexType>(
732 offsets, bucketIndices.get(), indices));
734 mIndexSegments[n]->clear();
738 SegmentPtr *
const mIndexSegments;
739 SegmentPtr *
const mOffsetSegments;
740 IndexArray *
const mPageOffsetArrays;
741 IndexArray *
const mPageIndexArrays;
742 Index const mBinVolume;
750 template<
typename Po
intIndexType,
typename VoxelOffsetType,
typename Po
intArray>
751 inline void binAndSegment(
754 std::unique_ptr<
typename Array<PointIndexType>::Ptr[]>& indexSegments,
755 std::unique_ptr<
typename Array<PointIndexType>::Ptr[]>& offsetSegments,
756 std::vector<Coord>& coords,
757 const Index binLog2Dim,
758 const Index bucketLog2Dim,
760 bool cellCenteredTransform =
true)
762 using IndexPair = std::pair<PointIndexType, PointIndexType>;
763 using IndexPairList = std::deque<IndexPair>;
764 using IndexPairListPtr = std::shared_ptr<IndexPairList>;
765 using IndexPairListMap = std::map<Coord, IndexPairListPtr>;
766 using IndexPairListMapPtr = std::shared_ptr<IndexPairListMap>;
768 size_t numTasks = 1, numThreads = size_t(tbb::this_task_arena::max_concurrency());
769 if (points.size() > (numThreads * 2)) numTasks = numThreads * 2;
770 else if (points.size() > numThreads) numTasks = numThreads;
772 std::unique_ptr<IndexPairListMapPtr[]> bins(
new IndexPairListMapPtr[numTasks]);
774 using BinOp = BinPointIndicesOp<PointArray, PointIndexType, VoxelOffsetType>;
776 tbb::parallel_for(tbb::blocked_range<size_t>(0, numTasks),
777 BinOp(bins.get(), points, voxelOffsets, xform, binLog2Dim, bucketLog2Dim,
778 numTasks, cellCenteredTransform));
780 std::set<Coord> uniqueCoords;
782 for (
size_t i = 0; i < numTasks; ++i) {
783 IndexPairListMap& idxMap = *bins[i];
784 for (
typename IndexPairListMap::iterator it = idxMap.begin(); it != idxMap.end(); ++it) {
785 uniqueCoords.insert(it->first);
789 coords.assign(uniqueCoords.begin(), uniqueCoords.end());
790 uniqueCoords.clear();
792 size_t segmentCount = coords.size();
794 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
796 indexSegments.reset(
new SegmentPtr[segmentCount]);
797 offsetSegments.reset(
new SegmentPtr[segmentCount]);
799 using MergeOp = MergeBinsOp<PointIndexType>;
801 tbb::parallel_for(tbb::blocked_range<size_t>(0, segmentCount),
802 MergeOp(bins.get(), indexSegments.get(), offsetSegments.get(), &coords[0], numTasks));
806 template<
typename Po
intIndexType,
typename VoxelOffsetType,
typename Po
intArray>
807 inline void partition(
810 const Index bucketLog2Dim,
811 std::unique_ptr<PointIndexType[]>& pointIndices,
812 std::unique_ptr<PointIndexType[]>& pageOffsets,
813 std::unique_ptr<Coord[]>& pageCoordinates,
814 PointIndexType& pageCount,
816 bool recordVoxelOffsets,
817 bool cellCenteredTransform)
819 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
821 if (recordVoxelOffsets) voxelOffsets.reset(
new VoxelOffsetType[points.size()]);
822 else voxelOffsets.reset();
824 const Index binLog2Dim = 5u;
830 std::vector<Coord> segmentCoords;
832 std::unique_ptr<SegmentPtr[]> indexSegments;
833 std::unique_ptr<SegmentPtr[]> offsetSegments;
835 binAndSegment<PointIndexType, VoxelOffsetType, PointArray>(points, xform,
836 indexSegments, offsetSegments, segmentCoords, binLog2Dim, bucketLog2Dim,
837 voxelOffsets.get(), cellCenteredTransform);
839 size_t numSegments = segmentCoords.size();
841 const tbb::blocked_range<size_t> segmentRange(0, numSegments);
843 using IndexArray = std::unique_ptr<PointIndexType[]>;
844 std::unique_ptr<IndexArray[]> pageOffsetArrays(
new IndexArray[numSegments]);
845 std::unique_ptr<IndexArray[]> pageIndexArrays(
new IndexArray[numSegments]);
847 const Index binVolume = 1u << (3u * binLog2Dim);
849 tbb::parallel_for(segmentRange, OrderSegmentsOp<PointIndexType>
850 (indexSegments.get(), offsetSegments.get(),
851 pageOffsetArrays.get(), pageIndexArrays.get(), binVolume));
853 indexSegments.reset();
855 std::vector<Index> segmentOffsets;
856 segmentOffsets.reserve(numSegments);
859 for (
size_t n = 0; n < numSegments; ++n) {
860 segmentOffsets.push_back(pageCount);
861 pageCount += pageOffsetArrays[n][0] - 1;
864 pageOffsets.reset(
new PointIndexType[pageCount + 1]);
866 PointIndexType count = 0;
867 for (
size_t n = 0, idx = 0; n < numSegments; ++n) {
869 PointIndexType* offsets = pageOffsetArrays[n].get();
870 size_t size = size_t(offsets[0]);
872 for (
size_t i = 1; i < size; ++i) {
873 pageOffsets[idx++] = count;
878 pageOffsets[pageCount] = count;
880 pointIndices.reset(
new PointIndexType[points.size()]);
882 std::vector<PointIndexType*> indexArray;
883 indexArray.reserve(numSegments);
885 PointIndexType* index = pointIndices.get();
886 for (
size_t n = 0; n < numSegments; ++n) {
887 indexArray.push_back(index);
888 index += offsetSegments[n]->size();
893 pageCoordinates.reset(
new Coord[pageCount]);
895 tbb::parallel_for(segmentRange,
896 [&](tbb::blocked_range<size_t>& range)
898 for (
size_t n = range.begin(); n < range.end(); n++)
900 Index segmentOffset = segmentOffsets[n];
901 PointIndexType* indices = pageIndexArrays[n].get();
903 const Coord& segmentCoord = segmentCoords[n];
906 const size_t segmentSize = pageOffsetArrays[n][0] - 1;
907 tbb::blocked_range<size_t> copyRange(0, segmentSize);
908 tbb::parallel_for(copyRange,
909 [&](tbb::blocked_range<size_t>& r)
911 for (
size_t i = r.begin(); i < r.end(); i++)
913 Index pageIndex = indices[i];
914 Coord& ijk = pageCoordinates[segmentOffset+i];
916 ijk[0] = pageIndex >> (2 * binLog2Dim);
917 Index pageIndexModulo = pageIndex - (ijk[0] << (2 * binLog2Dim));
918 ijk[1] = pageIndexModulo >> binLog2Dim;
919 ijk[2] = pageIndexModulo - (ijk[1] << binLog2Dim);
921 ijk = (ijk << bucketLog2Dim) + segmentCoord;
931 tbb::parallel_for(segmentRange,
932 MoveSegmentDataOp<PointIndexType>(indexArray, offsetSegments.get()));
943 template<
typename Po
intIndexType, Index BucketLog2Dim>
945 : mPointIndices(nullptr)
946 , mVoxelOffsets(nullptr)
947 , mPageOffsets(nullptr)
948 , mPageCoordinates(nullptr)
950 , mUsingCellCenteredTransform(true)
955 template<
typename Po
intIndexType, Index BucketLog2Dim>
960 mUsingCellCenteredTransform =
true;
961 mPointIndices.reset();
962 mVoxelOffsets.reset();
963 mPageOffsets.reset();
964 mPageCoordinates.reset();
968 template<
typename Po
intIndexType, Index BucketLog2Dim>
972 const IndexType tmpLhsPageCount = mPageCount;
973 mPageCount = rhs.mPageCount;
974 rhs.mPageCount = tmpLhsPageCount;
976 mPointIndices.swap(rhs.mPointIndices);
977 mVoxelOffsets.swap(rhs.mVoxelOffsets);
978 mPageOffsets.swap(rhs.mPageOffsets);
979 mPageCoordinates.swap(rhs.mPageCoordinates);
981 bool lhsCellCenteredTransform = mUsingCellCenteredTransform;
982 mUsingCellCenteredTransform = rhs.mUsingCellCenteredTransform;
983 rhs.mUsingCellCenteredTransform = lhsCellCenteredTransform;
987 template<
typename Po
intIndexType, Index BucketLog2Dim>
991 assert(
bool(mPointIndices) &&
bool(mPageCount));
993 mPointIndices.get() + mPageOffsets[n],
994 mPointIndices.get() + mPageOffsets[n + 1]);
998 template<
typename Po
intIndexType, Index BucketLog2Dim>
999 template<
typename Po
intArray>
1005 bool recordVoxelOffsets,
1006 bool cellCenteredTransform)
1008 mUsingCellCenteredTransform = cellCenteredTransform;
1010 point_partitioner_internal::partition(points, xform, BucketLog2Dim,
1011 mPointIndices, mPageOffsets, mPageCoordinates, mPageCount, mVoxelOffsets,
1012 (voxelOrder || recordVoxelOffsets), cellCenteredTransform);
1014 const tbb::blocked_range<size_t> pageRange(0, mPageCount);
1016 if (mVoxelOffsets && voxelOrder) {
1017 tbb::parallel_for(pageRange, point_partitioner_internal::VoxelOrderOp<
1018 IndexType, BucketLog2Dim>(mPointIndices, mPageOffsets, mVoxelOffsets));
1021 if (mVoxelOffsets && !recordVoxelOffsets) {
1022 mVoxelOffsets.reset();
1027 template<
typename Po
intIndexType, Index BucketLog2Dim>
1028 template<
typename Po
intArray>
1034 bool recordVoxelOffsets,
1035 bool cellCenteredTransform)
1038 ret->construct(points, xform, voxelOrder, recordVoxelOffsets, cellCenteredTransform);
1051 #endif // OPENVDB_TOOLS_POINT_PARTITIONER_HAS_BEEN_INCLUDED 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:88
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
Definition: Exceptions.h:13
Index32 Index
Definition: Types.h:54
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:477
std::pair< Index, Index > IndexPair
Definition: PointMove.h:168
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202