18 #ifndef OPENVDB_TOOLS_POINT_PARTITIONER_HAS_BEEN_INCLUDED 19 #define OPENVDB_TOOLS_POINT_PARTITIONER_HAS_BEEN_INCLUDED 25 #include <tbb/blocked_range.h> 26 #include <tbb/parallel_for.h> 27 #include <tbb/task_arena.h> 76 template<
typename Po
intIndexType = u
int32_t, Index BucketLog2Dim = 3>
80 enum { LOG2DIM = BucketLog2Dim };
87 static constexpr
Index bits = 1 + (3 * BucketLog2Dim);
90 int16_t,
typename std::conditional<(bits < 32), int32_t, int64_t>::type>::type;
109 template<
typename Po
intArray>
111 bool voxelOrder =
false,
bool recordVoxelOffsets =
false,
112 bool cellCenteredTransform =
true);
124 template<
typename Po
intArray>
126 bool voxelOrder =
false,
bool recordVoxelOffsets =
false,
127 bool cellCenteredTransform =
true);
131 size_t size()
const {
return mPageCount; }
134 bool empty()
const {
return mPageCount == 0; }
147 return CoordBBox::createCube(mPageCoordinates[n], (1u << BucketLog2Dim));
151 const Coord&
origin(
size_t n)
const {
return mPageCoordinates[n]; }
167 std::unique_ptr<IndexType[]> mPointIndices;
170 std::unique_ptr<IndexType[]> mPageOffsets;
171 std::unique_ptr<Coord[]> mPageCoordinates;
173 bool mUsingCellCenteredTransform;
180 template<
typename Po
intIndexType, Index BucketLog2Dim>
187 : mBegin(begin), mEnd(end), mItem(begin) {}
193 size_t size()
const {
return mEnd - mBegin; }
200 operator bool()
const {
return mItem < mEnd; }
201 bool test()
const {
return mItem < mEnd; }
207 bool next() { this->operator++();
return this->test(); }
227 namespace point_partitioner_internal {
230 template<
typename Po
intIndexType>
231 struct ComputePointOrderOp
233 ComputePointOrderOp(PointIndexType* pointOrder,
234 const PointIndexType* bucketCounters,
const PointIndexType* bucketOffsets)
235 : mPointOrder(pointOrder)
236 , mBucketCounters(bucketCounters)
237 , mBucketOffsets(bucketOffsets)
241 void operator()(
const tbb::blocked_range<size_t>& range)
const {
242 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
243 mPointOrder[n] += mBucketCounters[mBucketOffsets[n]];
247 PointIndexType *
const mPointOrder;
248 PointIndexType
const *
const mBucketCounters;
249 PointIndexType
const *
const mBucketOffsets;
253 template<
typename Po
intIndexType>
254 struct CreateOrderedPointIndexArrayOp
256 CreateOrderedPointIndexArrayOp(PointIndexType* orderedIndexArray,
257 const PointIndexType* pointOrder,
const PointIndexType* indices)
258 : mOrderedIndexArray(orderedIndexArray)
259 , mPointOrder(pointOrder)
264 void operator()(
const tbb::blocked_range<size_t>& range)
const {
265 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
266 mOrderedIndexArray[mPointOrder[n]] = mIndices[n];
270 PointIndexType *
const mOrderedIndexArray;
271 PointIndexType
const *
const mPointOrder;
272 PointIndexType
const *
const mIndices;
276 template<
typename Po
intIndexType, Index BucketLog2Dim>
279 static constexpr
Index bits = 1 + (3 * BucketLog2Dim);
282 int16_t,
typename std::conditional<(bits < 32), int32_t, int64_t>::type>::type;
285 using IndexArray = std::unique_ptr<PointIndexType[]>;
287 VoxelOrderOp(IndexArray& indices,
const IndexArray& pages,
const VoxelOffsetArray& offsets)
288 : mIndices(indices.get())
289 , mPages(pages.get())
290 , mVoxelOffsets(offsets.get())
294 void operator()(
const tbb::blocked_range<size_t>& range)
const {
297 for (
size_t n(range.begin()), N(range.end()); n != N; ++n) {
298 pointCount =
std::max(pointCount, (mPages[n + 1] - mPages[n]));
301 const PointIndexType voxelCount = 1 << (3 * BucketLog2Dim);
304 std::unique_ptr<VoxelOffsetType[]> offsets(
new VoxelOffsetType[pointCount]);
305 std::unique_ptr<PointIndexType[]> sortedIndices(
new PointIndexType[pointCount]);
306 std::unique_ptr<PointIndexType[]>
histogram(
new PointIndexType[voxelCount]);
308 for (
size_t n(range.begin()), N(range.end()); n != N; ++n) {
310 PointIndexType *
const indices = mIndices + mPages[n];
311 pointCount = mPages[n + 1] - mPages[n];
314 for (PointIndexType i = 0; i <
pointCount; ++i) {
315 offsets[i] = mVoxelOffsets[ indices[i] ];
319 memset(&histogram[0], 0, voxelCount *
sizeof(PointIndexType));
322 for (PointIndexType i = 0; i <
pointCount; ++i) {
323 ++histogram[ offsets[i] ];
326 PointIndexType count = 0, startOffset;
327 for (
int i = 0; i < int(voxelCount); ++i) {
328 if (histogram[i] > 0) {
330 count += histogram[i];
331 histogram[i] = startOffset;
336 for (PointIndexType i = 0; i <
pointCount; ++i) {
337 sortedIndices[ histogram[ offsets[i] ]++ ] = indices[i];
340 memcpy(&indices[0], &sortedIndices[0],
sizeof(PointIndexType) * pointCount);
344 PointIndexType *
const mIndices;
345 PointIndexType
const *
const mPages;
356 using Ptr = std::unique_ptr<Array>;
358 Array(
size_t size) : mSize(size), mData(
new T[size]) { }
360 size_t size()
const {
return mSize; }
362 T* data() {
return mData.get(); }
363 const T* data()
const {
return mData.get(); }
365 void clear() { mSize = 0; mData.reset(); }
369 std::unique_ptr<T[]> mData;
373 template<
typename Po
intIndexType>
374 struct MoveSegmentDataOp
376 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
378 MoveSegmentDataOp(std::vector<PointIndexType*>& indexLists, SegmentPtr* segments)
379 : mIndexLists(&indexLists[0]), mSegments(segments)
383 void operator()(
const tbb::blocked_range<size_t>& range)
const {
384 for (
size_t n(range.begin()), N(range.end()); n != N; ++n) {
385 PointIndexType* indices = mIndexLists[n];
386 SegmentPtr& segment = mSegments[n];
388 tbb::parallel_for(tbb::blocked_range<size_t>(0, segment->size()),
389 CopyData(indices, segment->data()));
399 CopyData(PointIndexType* lhs,
const PointIndexType* rhs) : mLhs(lhs), mRhs(rhs) { }
401 void operator()(
const tbb::blocked_range<size_t>& range)
const {
402 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
407 PointIndexType *
const mLhs;
408 PointIndexType
const *
const mRhs;
411 PointIndexType *
const *
const mIndexLists;
412 SegmentPtr *
const mSegments;
416 template<
typename Po
intIndexType>
419 using Segment = Array<PointIndexType>;
420 using SegmentPtr =
typename Segment::Ptr;
422 using IndexPair = std::pair<PointIndexType, PointIndexType>;
423 using IndexPairList = std::deque<IndexPair>;
424 using IndexPairListPtr = std::shared_ptr<IndexPairList>;
425 using IndexPairListMap = std::map<Coord, IndexPairListPtr>;
426 using IndexPairListMapPtr = std::shared_ptr<IndexPairListMap>;
428 MergeBinsOp(IndexPairListMapPtr* bins,
429 SegmentPtr* indexSegments,
430 SegmentPtr* offsetSegments,
434 , mIndexSegments(indexSegments)
435 , mOffsetSegments(offsetSegments)
437 , mNumSegments(numSegments)
441 void operator()(
const tbb::blocked_range<size_t>& range)
const {
443 std::vector<IndexPairListPtr*> data;
444 std::vector<PointIndexType> arrayOffsets;
446 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
448 const Coord& ijk = mCoords[n];
449 size_t numIndices = 0;
453 for (
size_t i = 0, I = mNumSegments; i < I; ++i) {
455 IndexPairListMap& idxMap = *mBins[i];
456 typename IndexPairListMap::iterator iter = idxMap.find(ijk);
458 if (iter != idxMap.end() && iter->second) {
459 IndexPairListPtr& idxListPtr = iter->second;
461 data.push_back(&idxListPtr);
462 numIndices += idxListPtr->size();
466 if (data.empty() || numIndices == 0)
continue;
468 SegmentPtr& indexSegment = mIndexSegments[n];
469 SegmentPtr& offsetSegment = mOffsetSegments[n];
471 indexSegment.reset(
new Segment(numIndices));
472 offsetSegment.reset(
new Segment(numIndices));
474 arrayOffsets.clear();
475 arrayOffsets.reserve(data.size());
477 for (
size_t i = 0, count = 0, I = data.size(); i < I; ++i) {
478 arrayOffsets.push_back(PointIndexType(count));
479 count += (*data[i])->size();
482 tbb::parallel_for(tbb::blocked_range<size_t>(0, data.size()),
483 CopyData(&data[0], &arrayOffsets[0], indexSegment->data(), offsetSegment->data()));
491 CopyData(IndexPairListPtr** indexLists,
492 const PointIndexType* arrayOffsets,
493 PointIndexType* indices,
494 PointIndexType* offsets)
495 : mIndexLists(indexLists)
496 , mArrayOffsets(arrayOffsets)
502 void operator()(
const tbb::blocked_range<size_t>& range)
const {
504 using CIter =
typename IndexPairList::const_iterator;
506 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
508 const PointIndexType arrayOffset = mArrayOffsets[n];
509 PointIndexType* indexPtr = &mIndices[arrayOffset];
510 PointIndexType* offsetPtr = &mOffsets[arrayOffset];
512 IndexPairListPtr& list = *mIndexLists[n];
514 for (CIter it = list->begin(), end = list->end(); it != end; ++it) {
516 *indexPtr++ = data.first;
517 *offsetPtr++ = data.second;
524 IndexPairListPtr *
const *
const mIndexLists;
525 PointIndexType
const *
const mArrayOffsets;
526 PointIndexType *
const mIndices;
527 PointIndexType *
const mOffsets;
530 IndexPairListMapPtr *
const mBins;
531 SegmentPtr *
const mIndexSegments;
532 SegmentPtr *
const mOffsetSegments;
533 Coord
const *
const mCoords;
534 size_t const mNumSegments;
538 template<
typename Po
intArray,
typename Po
intIndexType,
typename VoxelOffsetType>
539 struct BinPointIndicesOp
541 using PosType =
typename PointArray::PosType;
542 using IndexPair = std::pair<PointIndexType, PointIndexType>;
543 using IndexPairList = std::deque<IndexPair>;
544 using IndexPairListPtr = std::shared_ptr<IndexPairList>;
545 using IndexPairListMap = std::map<Coord, IndexPairListPtr>;
546 using IndexPairListMapPtr = std::shared_ptr<IndexPairListMap>;
548 BinPointIndicesOp(IndexPairListMapPtr* data,
555 bool cellCenteredTransform)
558 , mVoxelOffsets(voxelOffsets)
560 , mBinLog2Dim(binLog2Dim)
561 , mBucketLog2Dim(bucketLog2Dim)
562 , mNumSegments(numSegments)
563 , mCellCenteredTransform(cellCenteredTransform)
567 void operator()(
const tbb::blocked_range<size_t>& range)
const {
569 const Index log2dim = mBucketLog2Dim;
570 const Index log2dim2 = 2 * log2dim;
571 const Index bucketMask = (1u << log2dim) - 1u;
573 const Index binLog2dim = mBinLog2Dim;
574 const Index binLog2dim2 = 2 * binLog2dim;
576 const Index binMask = (1u << (log2dim + binLog2dim)) - 1u;
577 const Index invBinMask = ~binMask;
579 IndexPairList * idxList =
nullptr;
580 Coord ijk(0, 0, 0), loc(0, 0, 0), binCoord(0, 0, 0), lastBinCoord(1, 2, 3);
583 PointIndexType bucketOffset = 0;
586 const bool cellCentered = mCellCenteredTransform;
588 const size_t numPoints = mPoints->size();
589 const size_t segmentSize = numPoints / mNumSegments;
591 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
593 IndexPairListMapPtr& dataPtr = mData[n];
594 if (!dataPtr) dataPtr.reset(
new IndexPairListMap());
595 IndexPairListMap& idxMap = *dataPtr;
597 const bool isLastSegment = (n + 1) >= mNumSegments;
599 const size_t start = n * segmentSize;
600 const size_t end = isLastSegment ? numPoints : (start + segmentSize);
602 for (
size_t i = start; i != end; ++i) {
604 mPoints->getPos(i, pos);
606 if (std::isfinite(pos[0]) && std::isfinite(pos[1]) && std::isfinite(pos[2])) {
607 ijk = cellCentered ? mXForm.worldToIndexCellCentered(pos) :
608 mXForm.worldToIndexNodeCentered(pos);
611 loc[0] = ijk[0] & bucketMask;
612 loc[1] = ijk[1] & bucketMask;
613 loc[2] = ijk[2] & bucketMask;
615 (loc[0] << log2dim2) + (loc[1] << log2dim) + loc[2]);
618 binCoord[0] = ijk[0] & invBinMask;
619 binCoord[1] = ijk[1] & invBinMask;
620 binCoord[2] = ijk[2] & invBinMask;
630 bucketOffset = PointIndexType(
631 (ijk[0] << binLog2dim2) + (ijk[1] << binLog2dim) + ijk[2]);
633 if (lastBinCoord != binCoord) {
634 lastBinCoord = binCoord;
635 IndexPairListPtr& idxListPtr = idxMap[lastBinCoord];
636 if (!idxListPtr) idxListPtr.reset(
new IndexPairList());
637 idxList = idxListPtr.get();
640 idxList->push_back(
IndexPair(PointIndexType(i), bucketOffset));
641 if (mVoxelOffsets) mVoxelOffsets[i] = voxelOffset;
647 IndexPairListMapPtr *
const mData;
651 Index const mBinLog2Dim;
652 Index const mBucketLog2Dim;
653 size_t const mNumSegments;
654 bool const mCellCenteredTransform;
658 template<
typename Po
intIndexType>
659 struct OrderSegmentsOp
661 using IndexArray = std::unique_ptr<PointIndexType[]>;
662 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
664 OrderSegmentsOp(SegmentPtr* indexSegments, SegmentPtr* offsetSegments,
665 IndexArray* pageOffsetArrays, IndexArray* pageIndexArrays,
Index binVolume)
666 : mIndexSegments(indexSegments)
667 , mOffsetSegments(offsetSegments)
668 , mPageOffsetArrays(pageOffsetArrays)
669 , mPageIndexArrays(pageIndexArrays)
670 , mBinVolume(binVolume)
674 void operator()(
const tbb::blocked_range<size_t>& range)
const {
676 const size_t bucketCountersSize = size_t(mBinVolume);
677 IndexArray bucketCounters(
new PointIndexType[bucketCountersSize]);
679 size_t maxSegmentSize = 0;
680 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
681 maxSegmentSize =
std::max(maxSegmentSize, mIndexSegments[n]->size());
684 IndexArray bucketIndices(
new PointIndexType[maxSegmentSize]);
686 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
688 memset(bucketCounters.get(), 0,
sizeof(PointIndexType) * bucketCountersSize);
690 const size_t segmentSize = mOffsetSegments[n]->size();
691 PointIndexType* offsets = mOffsetSegments[n]->data();
695 for (
size_t i = 0; i < segmentSize; ++i) {
696 bucketIndices[i] = bucketCounters[offsets[i]]++;
699 PointIndexType nonemptyBucketCount = 0;
700 for (
size_t i = 0; i < bucketCountersSize; ++i) {
701 nonemptyBucketCount +=
static_cast<PointIndexType
>(bucketCounters[i] != 0);
705 IndexArray& pageOffsets = mPageOffsetArrays[n];
706 pageOffsets.reset(
new PointIndexType[nonemptyBucketCount + 1]);
707 pageOffsets[0] = nonemptyBucketCount + 1;
709 IndexArray& pageIndices = mPageIndexArrays[n];
710 pageIndices.reset(
new PointIndexType[nonemptyBucketCount]);
713 PointIndexType count = 0, idx = 0;
714 for (
size_t i = 0; i < bucketCountersSize; ++i) {
715 if (bucketCounters[i] != 0) {
716 pageIndices[idx] =
static_cast<PointIndexType
>(i);
717 pageOffsets[idx+1] = bucketCounters[i];
718 bucketCounters[i] = count;
719 count += pageOffsets[idx+1];
724 PointIndexType* indices = mIndexSegments[n]->data();
725 const tbb::blocked_range<size_t> segmentRange(0, segmentSize);
729 tbb::parallel_for(segmentRange, ComputePointOrderOp<PointIndexType>(
730 bucketIndices.get(), bucketCounters.get(), offsets));
732 tbb::parallel_for(segmentRange, CreateOrderedPointIndexArrayOp<PointIndexType>(
733 offsets, bucketIndices.get(), indices));
735 mIndexSegments[n]->clear();
739 SegmentPtr *
const mIndexSegments;
740 SegmentPtr *
const mOffsetSegments;
741 IndexArray *
const mPageOffsetArrays;
742 IndexArray *
const mPageIndexArrays;
743 Index const mBinVolume;
751 template<
typename Po
intIndexType,
typename VoxelOffsetType,
typename Po
intArray>
752 inline void binAndSegment(
755 std::unique_ptr<
typename Array<PointIndexType>::Ptr[]>& indexSegments,
756 std::unique_ptr<
typename Array<PointIndexType>::Ptr[]>& offsetSegments,
757 std::vector<Coord>& coords,
758 const Index binLog2Dim,
759 const Index bucketLog2Dim,
761 bool cellCenteredTransform =
true)
763 using IndexPair = std::pair<PointIndexType, PointIndexType>;
764 using IndexPairList = std::deque<IndexPair>;
765 using IndexPairListPtr = std::shared_ptr<IndexPairList>;
766 using IndexPairListMap = std::map<Coord, IndexPairListPtr>;
767 using IndexPairListMapPtr = std::shared_ptr<IndexPairListMap>;
769 size_t numTasks = 1, numThreads = size_t(tbb::this_task_arena::max_concurrency());
770 if (points.size() > (numThreads * 2)) numTasks = numThreads * 2;
771 else if (points.size() > numThreads) numTasks = numThreads;
773 std::unique_ptr<IndexPairListMapPtr[]> bins(
new IndexPairListMapPtr[numTasks]);
775 using BinOp = BinPointIndicesOp<PointArray, PointIndexType, VoxelOffsetType>;
777 tbb::parallel_for(tbb::blocked_range<size_t>(0, numTasks),
778 BinOp(bins.get(), points, voxelOffsets, xform, binLog2Dim, bucketLog2Dim,
779 numTasks, cellCenteredTransform));
781 std::set<Coord> uniqueCoords;
783 for (
size_t i = 0; i < numTasks; ++i) {
784 IndexPairListMap& idxMap = *bins[i];
785 for (
typename IndexPairListMap::iterator it = idxMap.begin(); it != idxMap.end(); ++it) {
786 uniqueCoords.insert(it->first);
790 coords.assign(uniqueCoords.begin(), uniqueCoords.end());
791 uniqueCoords.clear();
793 size_t segmentCount = coords.size();
795 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
797 indexSegments.reset(
new SegmentPtr[segmentCount]);
798 offsetSegments.reset(
new SegmentPtr[segmentCount]);
800 using MergeOp = MergeBinsOp<PointIndexType>;
802 tbb::parallel_for(tbb::blocked_range<size_t>(0, segmentCount),
803 MergeOp(bins.get(), indexSegments.get(), offsetSegments.get(), &coords[0], numTasks));
807 template<
typename Po
intIndexType,
typename VoxelOffsetType,
typename Po
intArray>
808 inline void partition(
811 const Index bucketLog2Dim,
812 std::unique_ptr<PointIndexType[]>& pointIndices,
813 std::unique_ptr<PointIndexType[]>& pageOffsets,
814 std::unique_ptr<Coord[]>& pageCoordinates,
815 PointIndexType& pageCount,
817 bool recordVoxelOffsets,
818 bool cellCenteredTransform)
820 using SegmentPtr =
typename Array<PointIndexType>::Ptr;
822 if (recordVoxelOffsets) voxelOffsets.reset(
new VoxelOffsetType[points.size()]);
823 else voxelOffsets.reset();
825 const Index binLog2Dim = 5u;
831 std::vector<Coord> segmentCoords;
833 std::unique_ptr<SegmentPtr[]> indexSegments;
834 std::unique_ptr<SegmentPtr[]> offsetSegments;
836 binAndSegment<PointIndexType, VoxelOffsetType, PointArray>(points, xform,
837 indexSegments, offsetSegments, segmentCoords, binLog2Dim, bucketLog2Dim,
838 voxelOffsets.get(), cellCenteredTransform);
840 size_t numSegments = segmentCoords.size();
842 const tbb::blocked_range<size_t> segmentRange(0, numSegments);
844 using IndexArray = std::unique_ptr<PointIndexType[]>;
845 std::unique_ptr<IndexArray[]> pageOffsetArrays(
new IndexArray[numSegments]);
846 std::unique_ptr<IndexArray[]> pageIndexArrays(
new IndexArray[numSegments]);
848 const Index binVolume = 1u << (3u * binLog2Dim);
850 tbb::parallel_for(segmentRange, OrderSegmentsOp<PointIndexType>
851 (indexSegments.get(), offsetSegments.get(),
852 pageOffsetArrays.get(), pageIndexArrays.get(), binVolume));
854 indexSegments.reset();
856 std::vector<Index> segmentOffsets;
857 segmentOffsets.reserve(numSegments);
860 for (
size_t n = 0; n < numSegments; ++n) {
861 segmentOffsets.push_back(pageCount);
862 pageCount += pageOffsetArrays[n][0] - 1;
865 pageOffsets.reset(
new PointIndexType[pageCount + 1]);
867 PointIndexType count = 0;
868 for (
size_t n = 0, idx = 0; n < numSegments; ++n) {
870 PointIndexType* offsets = pageOffsetArrays[n].get();
871 size_t size = size_t(offsets[0]);
873 for (
size_t i = 1; i < size; ++i) {
874 pageOffsets[idx++] = count;
879 pageOffsets[pageCount] = count;
881 pointIndices.reset(
new PointIndexType[points.size()]);
883 std::vector<PointIndexType*> indexArray;
884 indexArray.reserve(numSegments);
886 PointIndexType* index = pointIndices.get();
887 for (
size_t n = 0; n < numSegments; ++n) {
888 indexArray.push_back(index);
889 index += offsetSegments[n]->size();
894 pageCoordinates.reset(
new Coord[pageCount]);
896 tbb::parallel_for(segmentRange,
897 [&](tbb::blocked_range<size_t>& range)
899 for (
size_t n = range.begin(); n < range.end(); n++)
901 Index segmentOffset = segmentOffsets[n];
902 PointIndexType* indices = pageIndexArrays[n].get();
904 const Coord& segmentCoord = segmentCoords[n];
907 const size_t segmentSize = pageOffsetArrays[n][0] - 1;
908 tbb::blocked_range<size_t> copyRange(0, segmentSize);
909 tbb::parallel_for(copyRange,
910 [&](tbb::blocked_range<size_t>& r)
912 for (
size_t i = r.begin(); i < r.end(); i++)
914 Index pageIndex = indices[i];
915 Coord& ijk = pageCoordinates[segmentOffset+i];
917 ijk[0] = pageIndex >> (2 * binLog2Dim);
918 Index pageIndexModulo = pageIndex - (ijk[0] << (2 * binLog2Dim));
919 ijk[1] = pageIndexModulo >> binLog2Dim;
920 ijk[2] = pageIndexModulo - (ijk[1] << binLog2Dim);
922 ijk = (ijk << bucketLog2Dim) + segmentCoord;
932 tbb::parallel_for(segmentRange,
933 MoveSegmentDataOp<PointIndexType>(indexArray, offsetSegments.get()));
944 template<
typename Po
intIndexType, Index BucketLog2Dim>
946 : mPointIndices(nullptr)
947 , mVoxelOffsets(nullptr)
948 , mPageOffsets(nullptr)
949 , mPageCoordinates(nullptr)
951 , mUsingCellCenteredTransform(true)
956 template<
typename Po
intIndexType, Index BucketLog2Dim>
961 mUsingCellCenteredTransform =
true;
962 mPointIndices.reset();
963 mVoxelOffsets.reset();
964 mPageOffsets.reset();
965 mPageCoordinates.reset();
969 template<
typename Po
intIndexType, Index BucketLog2Dim>
973 const IndexType tmpLhsPageCount = mPageCount;
974 mPageCount = rhs.mPageCount;
975 rhs.mPageCount = tmpLhsPageCount;
977 mPointIndices.swap(rhs.mPointIndices);
978 mVoxelOffsets.swap(rhs.mVoxelOffsets);
979 mPageOffsets.swap(rhs.mPageOffsets);
980 mPageCoordinates.swap(rhs.mPageCoordinates);
982 bool lhsCellCenteredTransform = mUsingCellCenteredTransform;
983 mUsingCellCenteredTransform = rhs.mUsingCellCenteredTransform;
984 rhs.mUsingCellCenteredTransform = lhsCellCenteredTransform;
988 template<
typename Po
intIndexType, Index BucketLog2Dim>
994 mPointIndices.get() + mPageOffsets[n],
995 mPointIndices.get() + mPageOffsets[n + 1]);
999 template<
typename Po
intIndexType, Index BucketLog2Dim>
1000 template<
typename Po
intArray>
1006 bool recordVoxelOffsets,
1007 bool cellCenteredTransform)
1009 mUsingCellCenteredTransform = cellCenteredTransform;
1011 point_partitioner_internal::partition(points, xform, BucketLog2Dim,
1012 mPointIndices, mPageOffsets, mPageCoordinates, mPageCount, mVoxelOffsets,
1013 (voxelOrder || recordVoxelOffsets), cellCenteredTransform);
1015 const tbb::blocked_range<size_t> pageRange(0, mPageCount);
1017 if (mVoxelOffsets && voxelOrder) {
1018 tbb::parallel_for(pageRange, point_partitioner_internal::VoxelOrderOp<
1019 IndexType, BucketLog2Dim>(mPointIndices, mPageOffsets, mVoxelOffsets));
1022 if (mVoxelOffsets && !recordVoxelOffsets) {
1023 mVoxelOffsets.reset();
1028 template<
typename Po
intIndexType, Index BucketLog2Dim>
1029 template<
typename Po
intArray>
1035 bool recordVoxelOffsets,
1036 bool cellCenteredTransform)
1039 ret->construct(points, xform, voxelOrder, recordVoxelOffsets, cellCenteredTransform);
1052 #endif // OPENVDB_TOOLS_POINT_PARTITIONER_HAS_BEEN_INCLUDED
Index32 Index
Definition: Types.h:54
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:474
std::pair< Index, Index > IndexPair
Definition: PointMoveImpl.h:95
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCountImpl.h:18
Definition: Exceptions.h:13
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218