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>
87 static constexpr
Index bits = 1 + (3 * BucketLog2Dim);
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; }
143 IndexIterator
indices(
size_t n)
const;
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>
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);
281 using VoxelOffsetType =
typename std::conditional<(bits < 16),
282 int16_t,
typename std::conditional<(bits < 32), int32_t, int64_t>
::type>
::type;
284 using VoxelOffsetArray = std::unique_ptr<VoxelOffsetType[]>;
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) {
326 PointIndexType
count = 0, startOffset;
327 for (
int i = 0; i <
int(voxelCount); ++i) {
336 for (PointIndexType i = 0; i <
pointCount; ++i) {
340 memcpy(&indices[0], &sortedIndices[0],
sizeof(PointIndexType) * pointCount);
344 PointIndexType *
const mIndices;
345 PointIndexType
const *
const mPages;
346 VoxelOffsetType
const *
const mVoxelOffsets;
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
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];
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>
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();
483 CopyData(&data[0], &arrayOffsets[0], indexSegment->data(), offsetSegment->data()));
491 CopyData(IndexPairListPtr** indexLists,
492 const PointIndexType* arrayOffsets,
493 PointIndexType* indices,
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,
550 VoxelOffsetType* voxelOffsets,
551 const math::Transform& m,
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;
584 VoxelOffsetType voxelOffset = 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;
614 voxelOffset = VoxelOffsetType(
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;
649 VoxelOffsetType *
const mVoxelOffsets;
650 math::Transform
const mXForm;
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[]>;
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);
706 pageOffsets.reset(
new PointIndexType[nonemptyBucketCount + 1]);
707 pageOffsets[0] = nonemptyBucketCount + 1;
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);
730 bucketIndices.get(), bucketCounters.get(),
offsets));
733 offsets, bucketIndices.get(),
indices));
735 mIndexSegments[
n]->clear();
739 SegmentPtr *
const mIndexSegments;
740 SegmentPtr *
const mOffsetSegments;
743 Index const mBinVolume;
751 template<
typename Po
intIndexType,
typename VoxelOffsetType,
typename Po
intArray>
752 inline void binAndSegment(
754 const math::Transform& xform,
757 std::vector<Coord>&
coords,
758 const Index binLog2Dim,
759 const Index bucketLog2Dim,
760 VoxelOffsetType* voxelOffsets =
nullptr,
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>;
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();
797 indexSegments.reset(
new SegmentPtr[segmentCount]);
798 offsetSegments.reset(
new SegmentPtr[segmentCount]);
800 using MergeOp = MergeBinsOp<PointIndexType>;
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(
810 const math::Transform& xform,
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,
816 std::unique_ptr<VoxelOffsetType[]>& voxelOffsets,
817 bool recordVoxelOffsets,
818 bool cellCenteredTransform)
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);
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]);
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);
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;
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) {
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
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
#define OPENVDB_USE_VERSION_NAMESPACE
GLuint GLsizei const GLuint const GLintptr * offsets
#define OPENVDB_ASSERT(X)
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
GLint GLint GLsizei GLint GLenum GLenum type
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class IMF_EXPORT_TEMPLATE_TYPE Array
OIIO_UTIL_API void parallel_for(int32_t begin, int32_t end, function_view< void(int32_t)> task, paropt opt=0)
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.