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> 
   76template<
typename Po
intIndexType = u
int32_t, Index BucketLog2Dim = 3>
 
   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; }
 
  151    const Coord& 
origin(
size_t n)
 const  { 
return mPageCoordinates[n]; }
 
  167    std::unique_ptr<IndexType[]>    mPointIndices;
 
  168    VoxelOffsetArray                mVoxelOffsets;
 
  170    std::unique_ptr<IndexType[]>    mPageOffsets;
 
  171    std::unique_ptr<Coord[]>        mPageCoordinates;
 
  172    IndexType mPageCount;
 
  173    bool      mUsingCellCenteredTransform;
 
 
  180template<
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; }
 
 
  227namespace point_partitioner_internal {
 
  230template<
typename Po
intIndexType>
 
  231struct 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;
 
  253template<
typename Po
intIndexType>
 
  254struct 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;
 
  276template<
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];
 
  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) {
 
  328                if (histogram[i] > 0) {
 
  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;
 
  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;
 
  373template<
typename Po
intIndexType>
 
  374struct 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;
 
  416template<
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;
 
  538template<
typename Po
intArray, 
typename Po
intIndexType, 
typename VoxelOffsetType>
 
  539struct 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,
 
  549        const PointArray& points,
 
  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;
 
  648    PointArray           
const * 
const mPoints;
 
  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;
 
  658template<
typename Po
intIndexType>
 
  659struct 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;
 
  743    Index        const mBinVolume;
 
  751template<
typename Po
intIndexType, 
typename VoxelOffsetType, 
typename Po
intArray>
 
  752inline void binAndSegment(
 
  753    const PointArray& points,
 
  754    const math::Transform& xform,
 
  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,
 
  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>;
 
  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));
 
  807template<
typename Po
intIndexType, 
typename VoxelOffsetType, 
typename Po
intArray>
 
  808inline void partition(
 
  809    const PointArray& points,
 
  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)
 
  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()));
 
  944template<
typename Po
intIndexType, Index BucketLog2Dim>
 
  946    : mPointIndices(nullptr)
 
  947    , mVoxelOffsets(nullptr)
 
  948    , mPageOffsets(nullptr)
 
  949    , mPageCoordinates(nullptr)
 
  951    , mUsingCellCenteredTransform(true)
 
 
  956template<
typename Po
intIndexType, Index BucketLog2Dim>
 
  961    mUsingCellCenteredTransform = 
true;
 
  962    mPointIndices.reset();
 
  963    mVoxelOffsets.reset();
 
  964    mPageOffsets.reset();
 
  965    mPageCoordinates.reset();
 
 
  969template<
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;
 
 
  988template<
typename Po
intIndexType, Index BucketLog2Dim>
 
  994        mPointIndices.get() + mPageOffsets[n],
 
  995        mPointIndices.get() + mPageOffsets[n + 1]);
 
 
  999template<
typename Po
intIndexType, Index BucketLog2Dim>
 
 1000template<
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();
 
 
 1028template<
typename Po
intIndexType, Index BucketLog2Dim>
 
 1029template<
typename Po
intArray>
 
 1035    bool recordVoxelOffsets,
 
 1036    bool cellCenteredTransform)
 
 1039    ret->construct(
points, xform, voxelOrder, recordVoxelOffsets, cellCenteredTransform);
 
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition Coord.h:316
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Partitions points into BucketLog2Dim aligned buckets using a parallel radix-based sorting algorithm.
std::vector< Index > IndexArray
Definition PointMoveImpl.h:88
std::pair< Index, Index > IndexPair
Definition PointMoveImpl.h:95
Definition AttributeArray.h:42
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
Index32 Index
Definition Types.h:54
std::shared_ptr< T > SharedPtr
Definition Types.h:114
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