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>
86 static constexpr
Index bits = 1 + (3 * BucketLog2Dim);
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; }
142 IndexIterator
indices(
size_t n)
const;
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>
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);
280 using VoxelOffsetType =
typename std::conditional<(bits < 16),
281 int16_t,
typename std::conditional<(bits < 32), int32_t, int64_t>
::type>
::type;
283 using VoxelOffsetArray = std::unique_ptr<VoxelOffsetType[]>;
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) {
325 PointIndexType
count = 0, startOffset;
326 for (
int i = 0; i <
int(voxelCount); ++i) {
335 for (PointIndexType i = 0; i <
pointCount; ++i) {
339 memcpy(&indices[0], &sortedIndices[0],
sizeof(PointIndexType) * pointCount);
343 PointIndexType *
const mIndices;
344 PointIndexType
const *
const mPages;
345 VoxelOffsetType
const *
const mVoxelOffsets;
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
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];
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>
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();
482 CopyData(&data[0], &arrayOffsets[0], indexSegment->data(), offsetSegment->data()));
490 CopyData(IndexPairListPtr** indexLists,
491 const PointIndexType* arrayOffsets,
492 PointIndexType* indices,
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,
549 VoxelOffsetType* voxelOffsets,
550 const math::Transform& m,
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;
583 VoxelOffsetType voxelOffset = 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;
613 voxelOffset = VoxelOffsetType(
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;
648 VoxelOffsetType *
const mVoxelOffsets;
649 math::Transform
const mXForm;
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[]>;
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);
705 pageOffsets.reset(
new PointIndexType[nonemptyBucketCount + 1]);
706 pageOffsets[0] = nonemptyBucketCount + 1;
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);
729 bucketIndices.get(), bucketCounters.get(),
offsets));
732 offsets, bucketIndices.get(),
indices));
734 mIndexSegments[
n]->clear();
738 SegmentPtr *
const mIndexSegments;
739 SegmentPtr *
const mOffsetSegments;
742 Index const mBinVolume;
750 template<
typename Po
intIndexType,
typename VoxelOffsetType,
typename Po
intArray>
751 inline void binAndSegment(
753 const math::Transform& xform,
756 std::vector<Coord>&
coords,
757 const Index binLog2Dim,
758 const Index bucketLog2Dim,
759 VoxelOffsetType* voxelOffsets =
nullptr,
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>;
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();
796 indexSegments.reset(
new SegmentPtr[segmentCount]);
797 offsetSegments.reset(
new SegmentPtr[segmentCount]);
799 using MergeOp = MergeBinsOp<PointIndexType>;
802 MergeOp(bins.get(), indexSegments.get(), offsetSegments.get(), &coords[0], numTasks));
806 template<
typename Po
intIndexType,
typename VoxelOffsetType,
typename Po
intArray>
809 const math::Transform& xform,
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,
815 std::unique_ptr<VoxelOffsetType[]>& voxelOffsets,
816 bool recordVoxelOffsets,
817 bool cellCenteredTransform)
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);
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]);
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);
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;
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;
1011 mPointIndices, mPageOffsets, mPageCoordinates, mPageCount, mVoxelOffsets,
1012 (voxelOrder || recordVoxelOffsets), cellCenteredTransform);
1014 const tbb::blocked_range<size_t> pageRange(0, mPageCount);
1016 if (mVoxelOffsets && voxelOrder) {
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
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
__hostdev__ uint64_t pointCount() const
cvex test(vector P=0;int unbound=3;export float s=0;export vector Cf=0;)
GLsizei GLenum const void * indices
GLdouble GLdouble GLint GLint const GLdouble * points
void partition(I begin, I middle, I end, const Pred &pred, I *out_eqbeg, I *out_eqend)
#define OPENVDB_USE_VERSION_NAMESPACE
GLuint GLsizei const GLuint const GLintptr * offsets
std::shared_ptr< T > SharedPtr
SYS_FORCE_INLINE const_iterator end() const
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
std::vector< Index > IndexArray
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class IMF_EXPORT_TEMPLATE_TYPE Array
auto get(const UT_ARTIterator< T > &it) -> decltype(it.key())
LeafData & operator=(const LeafData &)=delete
std::pair< exint, exint > IndexPair
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GA_API const UT_StringHolder N
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.