16#ifndef OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 
   17#define OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED 
   21#include <openvdb/thread/Threading.h> 
   22#include <openvdb/version.h> 
   32#include <tbb/blocked_range.h> 
   33#include <tbb/parallel_for.h> 
   49template<Index, 
typename> 
struct SameLeafConfig; 
 
   54template<
typename T, Index Log2Dim> 
struct PointIndexLeafNode; 
 
   93template<
typename Gr
idT, 
typename Po
intArrayT>
 
   94inline typename GridT::Ptr
 
  103template<
typename Gr
idT, 
typename Po
intArrayT>
 
  104inline typename GridT::Ptr
 
  113template<
typename Po
intArrayT, 
typename Gr
idT>
 
  119template<
typename Gr
idT, 
typename Po
intArrayT>
 
  120inline typename GridT::ConstPtr
 
  124template<
typename Gr
idT, 
typename Po
intArrayT>
 
  125inline typename GridT::Ptr
 
  133template<
typename TreeType = Po
intIndexTree>
 
  181    template<
typename Po
intArray>
 
  196    template<
typename Po
intArray>
 
  207    template<
typename Po
intArray>
 
  222    template<
typename Po
intArray>
 
  235    bool test()
 const { 
return mRange.first < mRange.second || mIter != mRangeList.end(); }
 
  259    using Range = std::pair<const ValueType*, const ValueType*>;
 
  260    using RangeDeque = std::deque<Range>;
 
  261    using RangeDequeCIter = 
typename RangeDeque::const_iterator;
 
  262    using IndexArray = std::unique_ptr<ValueType[]>;
 
  268    RangeDeque      mRangeList;
 
  269    RangeDequeCIter mIter;
 
  271    IndexArray      mIndexArray;
 
  272    size_t          mIndexArraySize;
 
  305template<
typename Po
intArray, 
typename TreeType = Po
intIndexTree>
 
  326    template<
typename FilterType>
 
 
  344namespace point_index_grid_internal {
 
  346template<
typename Po
intArrayT>
 
  347struct ValidPartitioningOp
 
  349    ValidPartitioningOp(std::atomic<bool>& hasChanged,
 
  353        , mHasChanged(&hasChanged)
 
  357    template <
typename LeafT>
 
  358    void operator()(LeafT &leaf, 
size_t )
 const 
  360        if ((*mHasChanged)) {
 
  361            thread::cancelGroupExecution();
 
  365        using IndexArrayT = 
typename LeafT::IndexArray;
 
  366        using IndexT = 
typename IndexArrayT::value_type;
 
  367        using PosType = 
typename PointArrayT::PosType;
 
  369        typename LeafT::ValueOnCIter iter;
 
  374            *begin = 
static_cast<IndexT*
>(
nullptr),
 
  375            *end = 
static_cast<IndexT*
>(
nullptr);
 
  377        for (iter = leaf.cbeginValueOn(); iter; ++iter) {
 
  379            if ((*mHasChanged)) 
break;
 
  381            voxelCoord = iter.getCoord();
 
  382            leaf.getIndices(iter.pos(), begin, end);
 
  384            while (begin < end) {
 
  386                mPoints->getPos(*begin, point);
 
  387                if (voxelCoord != mTransform->worldToIndexCellCentered(point)) {
 
  388                    mHasChanged->store(
true);
 
  398    PointArrayT         
const * 
const mPoints;
 
  399    math::Transform     
const * 
const mTransform;
 
  400    std::atomic<bool>         * 
const mHasChanged;
 
  404template<
typename LeafNodeT>
 
  405struct PopulateLeafNodesOp
 
  407    using IndexT = uint32_t;
 
  408    using Partitioner = PointPartitioner<IndexT, LeafNodeT::LOG2DIM>;
 
  410    PopulateLeafNodesOp(std::unique_ptr<LeafNodeT*[]>& leafNodes,
 
  411        const Partitioner& partitioner)
 
  412        : mLeafNodes(leafNodes.get())
 
  413        , mPartitioner(&partitioner)
 
  417    void operator()(
const tbb::blocked_range<size_t>& range)
 const {
 
  419        using VoxelOffsetT = 
typename Partitioner::VoxelOffsetType;
 
  421        size_t maxPointCount = 0;
 
  422        for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
 
  423            maxPointCount = std::max(maxPointCount, mPartitioner->indices(n).size());
 
  426        const IndexT voxelCount = LeafNodeT::SIZE;
 
  429        std::unique_ptr<VoxelOffsetT[]> offsets{
new VoxelOffsetT[maxPointCount]};
 
  430        std::unique_ptr<IndexT[]> 
histogram{
new IndexT[voxelCount]};
 
  432        VoxelOffsetT 
const * 
const voxelOffsets = mPartitioner->voxelOffsets().get();
 
  434        for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
 
  436            LeafNodeT* node = 
new LeafNodeT();
 
  437            node->setOrigin(mPartitioner->origin(n));
 
  439            typename Partitioner::IndexIterator it = mPartitioner->indices(n);
 
  442            IndexT 
const * 
const indices = &*it;
 
  446                offsets[i] = voxelOffsets[ indices[i] ];
 
  450            memset(&histogram[0], 0, voxelCount * 
sizeof(IndexT));
 
  455            typename LeafNodeT::NodeMaskType& mask = node->getValueMask();
 
  456            typename LeafNodeT::Buffer& buffer = node->buffer();
 
  459            IndexT count = 0, startOffset;
 
  460            for (
int i = 0; i < int(voxelCount); ++i) {
 
  461                if (histogram[i] > 0) {
 
  467                buffer.setValue(i, count);
 
  471            node->indices().resize(pointCount);
 
  472            typename LeafNodeT::ValueType * 
const orderedIndices = node->indices().data();
 
  476                orderedIndices[ 
histogram[ offsets[i] ]++ ] = indices[i];
 
  479            mLeafNodes[n] = node;
 
  485    LeafNodeT*        * 
const mLeafNodes;
 
  486    Partitioner 
const * 
const mPartitioner;
 
  491template<
typename TreeType, 
typename Po
intArray>
 
  493constructPointTree(TreeType& tree, 
const math::Transform& xform, 
const PointArray& points)
 
  495    using LeafType = 
typename TreeType::LeafNodeType;
 
  497    std::unique_ptr<LeafType*[]> leafNodes;
 
  498    size_t leafNodeCount = 0;
 
  504        PointPartitioner<uint32_t, LeafType::LOG2DIM> partitioner;
 
  505        partitioner.construct(points, xform, 
false, 
true);
 
  507        if (!partitioner.usingCellCenteredTransform()) {
 
  509                "cell-centered transform.");
 
  512        leafNodeCount = partitioner.size();
 
  513        leafNodes.reset(
new LeafType*[leafNodeCount]);
 
  515        const tbb::blocked_range<size_t> range(0, leafNodeCount);
 
  516        tbb::parallel_for(range, PopulateLeafNodesOp<LeafType>(leafNodes, partitioner));
 
  519    tree::ValueAccessor<TreeType> acc(tree);
 
  520    for (
size_t n = 0; n < leafNodeCount; ++n) {
 
  521        acc.addLeaf(leafNodes[n]);
 
  531dequeToArray(
const std::deque<T>& d, std::unique_ptr<T[]>& a, 
size_t& size)
 
  534    a.reset(
new T[size]);
 
  535    typename std::deque<T>::const_iterator it = d.begin(), itEnd = d.end();
 
  537    for ( ; it != itEnd; ++it, ++item) *item = *it;
 
  542constructExclusiveRegions(std::vector<CoordBBox>& regions,
 
  543    const CoordBBox& bbox, 
const CoordBBox& ibox)
 
  547    Coord cmin = ibox.min();
 
  548    Coord cmax = ibox.max();
 
  551    regions.push_back(bbox);
 
  552    regions.back().max().z() = cmin.z();
 
  555    regions.push_back(bbox);
 
  556    regions.back().min().z() = cmax.z();
 
  562    regions.push_back(bbox);
 
  563    CoordBBox* lastRegion = ®ions.back();
 
  564    lastRegion->min().z() = cmin.z();
 
  565    lastRegion->max().z() = cmax.z();
 
  566    lastRegion->max().x() = cmin.x();
 
  569    regions.push_back(*lastRegion);
 
  570    lastRegion = ®ions.back();
 
  571    lastRegion->min().x() = cmax.x();
 
  572    lastRegion->max().x() = bbox.max().x();
 
  578    regions.push_back(*lastRegion);
 
  579    lastRegion = ®ions.back();
 
  580    lastRegion->min().x() = cmin.x();
 
  581    lastRegion->max().x() = cmax.x();
 
  582    lastRegion->max().y() = cmin.y();
 
  585    regions.push_back(*lastRegion);
 
  586    lastRegion = ®ions.back();
 
  587    lastRegion->min().y() = cmax.y();
 
  588    lastRegion->max().y() = bbox.max().y();
 
  592template<
typename Po
intArray, 
typename IndexT>
 
  595    using PosType = 
typename PointArray::PosType;
 
  596    using ScalarType = 
typename PosType::value_type;
 
  597    using Range = std::pair<const IndexT*, const IndexT*>;
 
  598    using RangeDeque = std::deque<Range>;
 
  599    using IndexDeque = std::deque<IndexT>;
 
  601    BBoxFilter(RangeDeque& ranges, IndexDeque& indices, 
const BBoxd& bbox,
 
  602        const PointArray& points, 
const math::Transform& xform)
 
  607        , mMap(*xform.baseMap())
 
  611    template <
typename LeafNodeType>
 
  612    void filterLeafNode(
const LeafNodeType& leaf)
 
  614        typename LeafNodeType::ValueOnCIter iter;
 
  616            *begin = 
static_cast<IndexT*
>(
nullptr),
 
  617            *end = 
static_cast<IndexT*
>(
nullptr);
 
  618        for (iter = leaf.cbeginValueOn(); iter; ++iter) {
 
  619            leaf.getIndices(iter.pos(), begin, end);
 
  620            filterVoxel(iter.getCoord(), begin, end);
 
  624    void filterVoxel(
const Coord&, 
const IndexT* begin, 
const IndexT* end)
 
  628        for (; begin < end; ++begin) {
 
  629            mPoints.getPos(*begin, vec);
 
  631            if (mRegion.isInside(mMap.applyInverseMap(vec))) {
 
  632                mIndices.push_back(*begin);
 
  639    IndexDeque& mIndices;
 
  641    const PointArray& mPoints;
 
  642    const math::MapBase& mMap;
 
  646template<
typename Po
intArray, 
typename IndexT>
 
  647struct RadialRangeFilter
 
  649    using PosType = 
typename PointArray::PosType;
 
  650    using ScalarType = 
typename PosType::value_type;
 
  651    using Range = std::pair<const IndexT*, const IndexT*>;
 
  652    using RangeDeque = std::deque<Range>;
 
  653    using IndexDeque = std::deque<IndexT>;
 
  655    RadialRangeFilter(RangeDeque& ranges, IndexDeque& indices, 
const Vec3d& xyz, 
double radius,
 
  656        const PointArray& points, 
const math::Transform& xform,
 
  657        const double leafNodeDim, 
const bool subvoxelAccuracy)
 
  661        , mWSCenter(xform.indexToWorld(xyz))
 
  662        , mVoxelDist1(ScalarType(0.0))
 
  663        , mVoxelDist2(ScalarType(0.0))
 
  664        , mLeafNodeDist1(ScalarType(0.0))
 
  665        , mLeafNodeDist2(ScalarType(0.0))
 
  666        , mWSRadiusSqr(ScalarType(radius * xform.voxelSize()[0]))
 
  668        , mSubvoxelAccuracy(subvoxelAccuracy)
 
  670        const ScalarType voxelRadius = ScalarType(std::sqrt(3.0) * 0.5);
 
  671        mVoxelDist1 = voxelRadius + ScalarType(radius);
 
  672        mVoxelDist1 *= mVoxelDist1;
 
  674        if (radius > voxelRadius) {
 
  675            mVoxelDist2 = ScalarType(radius) - voxelRadius;
 
  676            mVoxelDist2 *= mVoxelDist2;
 
  679        const ScalarType leafNodeRadius = ScalarType(leafNodeDim * std::sqrt(3.0) * 0.5);
 
  680        mLeafNodeDist1 = leafNodeRadius + ScalarType(radius);
 
  681        mLeafNodeDist1 *= mLeafNodeDist1;
 
  683        if (radius > leafNodeRadius) {
 
  684            mLeafNodeDist2 = ScalarType(radius) - leafNodeRadius;
 
  685            mLeafNodeDist2 *= mLeafNodeDist2;
 
  688        mWSRadiusSqr *= mWSRadiusSqr;
 
  691    template <
typename LeafNodeType>
 
  692    void filterLeafNode(
const LeafNodeType& leaf)
 
  695            const Coord& ijk = leaf.origin();
 
  697            vec[0] = ScalarType(ijk[0]);
 
  698            vec[1] = ScalarType(ijk[1]);
 
  699            vec[2] = ScalarType(ijk[2]);
 
  700            vec += ScalarType(LeafNodeType::DIM - 1) * 0.5;
 
  703            const ScalarType dist = vec.lengthSqr();
 
  704            if (dist > mLeafNodeDist1) 
return;
 
  706            if (mLeafNodeDist2 > 0.0 && dist < mLeafNodeDist2) {
 
  707                const IndexT* begin = &leaf.indices().front();
 
  708                mRanges.push_back(Range(begin, begin + leaf.indices().size()));
 
  713        typename LeafNodeType::ValueOnCIter iter;
 
  715            *begin = 
static_cast<IndexT*
>(
nullptr),
 
  716            *end = 
static_cast<IndexT*
>(
nullptr);
 
  717        for (iter = leaf.cbeginValueOn(); iter; ++iter) {
 
  718            leaf.getIndices(iter.pos(), begin, end);
 
  719            filterVoxel(iter.getCoord(), begin, end);
 
  723    void filterVoxel(
const Coord& ijk, 
const IndexT* begin, 
const IndexT* end)
 
  728            vec[0] = mCenter[0] - ScalarType(ijk[0]);
 
  729            vec[1] = mCenter[1] - ScalarType(ijk[1]);
 
  730            vec[2] = mCenter[2] - ScalarType(ijk[2]);
 
  732            const ScalarType dist = vec.lengthSqr();
 
  733            if (dist > mVoxelDist1) 
return;
 
  735            if (!mSubvoxelAccuracy || (mVoxelDist2 > 0.0 && dist < mVoxelDist2)) {
 
  736                if (!mRanges.empty() && mRanges.back().second == begin) {
 
  737                    mRanges.back().second = end;
 
  739                    mRanges.push_back(Range(begin, end));
 
  746        while (begin < end) {
 
  747            mPoints.getPos(*begin, vec);
 
  748            vec = mWSCenter - vec;
 
  750            if (vec.lengthSqr() < mWSRadiusSqr) {
 
  751                mIndices.push_back(*begin);
 
  759    IndexDeque& mIndices;
 
  760    const PosType mCenter, mWSCenter;
 
  761    ScalarType mVoxelDist1, mVoxelDist2, mLeafNodeDist1, mLeafNodeDist2, mWSRadiusSqr;
 
  762    const PointArray& mPoints;
 
  763    const bool mSubvoxelAccuracy;
 
  770template<
typename RangeFilterType, 
typename LeafNodeType>
 
  772filteredPointIndexSearchVoxels(RangeFilterType& filter,
 
  773    const LeafNodeType& leaf, 
const Coord& min, 
const Coord& max)
 
  775    using PointIndexT = 
typename LeafNodeType::ValueType;
 
  776    Index xPos(0), yPos(0), pos(0);
 
  779    const PointIndexT* dataPtr = &leaf.indices().front();
 
  780    PointIndexT beginOffset, endOffset;
 
  782    for (ijk[0] = min[0]; ijk[0] <= 
max[0]; ++ijk[0]) {
 
  783        xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
 
  784        for (ijk[1] = min[1]; ijk[1] <= 
max[1]; ++ijk[1]) {
 
  785            yPos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
 
  786            for (ijk[2] = min[2]; ijk[2] <= 
max[2]; ++ijk[2]) {
 
  787                pos = yPos + (ijk[2] & (LeafNodeType::DIM - 1u));
 
  789                beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
 
  790                endOffset = leaf.getValue(pos);
 
  792                if (endOffset > beginOffset) {
 
  793                    filter.filterVoxel(ijk, dataPtr + beginOffset, dataPtr + endOffset);
 
  801template<
typename RangeFilterType, 
typename ConstAccessor>
 
  803filteredPointIndexSearch(RangeFilterType& filter, ConstAccessor& acc, 
const CoordBBox& bbox)
 
  805    using LeafNodeType = 
typename ConstAccessor::TreeType::LeafNodeType;
 
  806    Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
 
  807    const Coord leafMin = bbox.min() & ~(LeafNodeType::DIM - 1);
 
  808    const Coord leafMax = bbox.max() & ~(LeafNodeType::DIM - 1);
 
  810    for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
 
  811        for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
 
  812            for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
 
  814                if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
 
  816                    ijkMax.offset(LeafNodeType::DIM - 1);
 
  819                    ijkA = Coord::maxComponent(bbox.min(), ijk);
 
  820                    ijkB = Coord::minComponent(bbox.max(), ijkMax);
 
  822                    if (ijkA != ijk || ijkB != ijkMax) {
 
  823                        filteredPointIndexSearchVoxels(filter, *leaf, ijkA, ijkB);
 
  825                        filter.filterLeafNode(*leaf);
 
  837template<
typename RangeDeque, 
typename LeafNodeType>
 
  839pointIndexSearchVoxels(RangeDeque& rangeList,
 
  840    const LeafNodeType& leaf, 
const Coord& min, 
const Coord& max)
 
  842    using PointIndexT = 
typename LeafNodeType::ValueType;
 
  843    using IntT = 
typename PointIndexT::IntType;
 
  844    using Range = 
typename RangeDeque::value_type;
 
  846    Index xPos(0), pos(0), zStride = 
Index(max[2] - min[2]);
 
  847    const PointIndexT* dataPtr = &leaf.indices().front();
 
  848    PointIndexT beginOffset(0), endOffset(0),
 
  849        previousOffset(
static_cast<IntT
>(leaf.indices().size() + 1u));
 
  852    for (ijk[0] = min[0]; ijk[0] <= 
max[0]; ++ijk[0]) {
 
  853        xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
 
  855        for (ijk[1] = min[1]; ijk[1] <= 
max[1]; ++ijk[1]) {
 
  856            pos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
 
  857            pos += (
min[2] & (LeafNodeType::DIM - 1u));
 
  859            beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
 
  860            endOffset = leaf.getValue(pos+zStride);
 
  862            if (endOffset > beginOffset) {
 
  864                if (beginOffset == previousOffset) {
 
  865                    rangeList.back().second = dataPtr + endOffset;
 
  867                    rangeList.push_back(Range(dataPtr + beginOffset, dataPtr + endOffset));
 
  870                previousOffset = endOffset;
 
  877template<
typename RangeDeque, 
typename ConstAccessor>
 
  879pointIndexSearch(RangeDeque& rangeList, ConstAccessor& acc, 
const CoordBBox& bbox)
 
  881    using LeafNodeType = 
typename ConstAccessor::TreeType::LeafNodeType;
 
  882    using PointIndexT = 
typename LeafNodeType::ValueType;
 
  883    using Range = 
typename RangeDeque::value_type;
 
  885    Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
 
  886    const Coord leafMin = bbox.min() & ~(LeafNodeType::DIM - 1);
 
  887    const Coord leafMax = bbox.max() & ~(LeafNodeType::DIM - 1);
 
  889    for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
 
  890        for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
 
  891            for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
 
  893                if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
 
  895                    ijkMax.offset(LeafNodeType::DIM - 1);
 
  898                    ijkA = Coord::maxComponent(bbox.min(), ijk);
 
  899                    ijkB = Coord::minComponent(bbox.max(), ijkMax);
 
  901                    if (ijkA != ijk || ijkB != ijkMax) {
 
  902                        pointIndexSearchVoxels(rangeList, *leaf, ijkA, ijkB);
 
  905                        const PointIndexT* begin = &leaf->indices().front();
 
  906                        rangeList.push_back(Range(begin, (begin + leaf->indices().size())));
 
  921template<
typename TreeType>
 
  926    , mIter(mRangeList.begin())
 
 
  933template<
typename TreeType>
 
  937    , mRangeList(rhs.mRangeList)
 
  938    , mIter(mRangeList.begin())
 
  940    , mIndexArraySize(rhs.mIndexArraySize)
 
  942    if (rhs.mIndexArray) {
 
  943        mIndexArray.reset(new ValueType[mIndexArraySize]);
 
  944        memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize * sizeof(ValueType));
 
 
  949template<
typename TreeType>
 
  955        mRangeList = rhs.mRangeList;
 
  956        mIter = mRangeList.begin();
 
  958        mIndexArraySize = rhs.mIndexArraySize;
 
  960        if (rhs.mIndexArray) {
 
  961            mIndexArray.reset(
new ValueType[mIndexArraySize]);
 
  962            memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize * 
sizeof(
ValueType));
 
 
  969template<
typename TreeType>
 
  974    , mIter(mRangeList.begin())
 
  979    if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
 
  980        mRangeList.push_back(mRange);
 
  981        mIter = mRangeList.begin();
 
 
  986template<
typename TreeType>
 
  991    , mIter(mRangeList.begin())
 
  995    point_index_grid_internal::pointIndexSearch(mRangeList, acc, bbox);
 
  997    if (!mRangeList.empty()) {
 
  998        mIter = mRangeList.begin();
 
  999        mRange = mRangeList.front();
 
 
 1004template<
typename TreeType>
 
 1008    mIter = mRangeList.begin();
 
 1009    if (!mRangeList.empty()) {
 
 1010        mRange = mRangeList.front();
 
 1011    } 
else if (mIndexArray) {
 
 1012        mRange.first = mIndexArray.get();
 
 1013        mRange.second = mRange.first + mIndexArraySize;
 
 1015        mRange.first = 
static_cast<ValueType*
>(
nullptr);
 
 1016        mRange.second = 
static_cast<ValueType*
>(
nullptr);
 
 
 1021template<
typename TreeType>
 
 1026    if (mRange.first >= mRange.second && mIter != mRangeList.end()) {
 
 1028        if (mIter != mRangeList.end()) {
 
 1030        } 
else if (mIndexArray) {
 
 1031            mRange.first = mIndexArray.get();
 
 1032            mRange.second = mRange.first + mIndexArraySize;
 
 
 1038template<
typename TreeType>
 
 1042    if (!this->
test()) 
return false;
 
 1044    return this->
test();
 
 
 1048template<
typename TreeType>
 
 1053    typename RangeDeque::const_iterator it = mRangeList.begin();
 
 1055    for ( ; it != mRangeList.end(); ++it) {
 
 1056        count += it->second - it->first;
 
 1059    return count + mIndexArraySize;
 
 
 
 1063template<
typename TreeType>
 
 1065PointIndexIterator<TreeType>::clear()
 
 1067    mRange.first = 
static_cast<ValueType*
>(
nullptr);
 
 1068    mRange.second = 
static_cast<ValueType*
>(
nullptr);
 
 1070    mIter = mRangeList.end();
 
 1071    mIndexArray.reset();
 
 1072    mIndexArraySize = 0;
 
 1076template<
typename TreeType>
 
 1082    if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
 
 1083        mRangeList.push_back(mRange);
 
 1084        mIter = mRangeList.begin();
 
 
 1089template<
typename TreeType>
 
 1094    point_index_grid_internal::pointIndexSearch(mRangeList, acc, bbox);
 
 1096    if (!mRangeList.empty()) {
 
 1097        mIter = mRangeList.begin();
 
 1098        mRange = mRangeList.front();
 
 
 1103template<
typename TreeType>
 
 1104template<
typename Po
intArray>
 
 1111    std::vector<CoordBBox> searchRegions;
 
 1115    const int minExtent = std::min(dim[0], std::min(dim[1], dim[2]));
 
 1117    if (minExtent > 2) {
 
 1122        point_index_grid_internal::pointIndexSearch(mRangeList, acc, ibox);
 
 1126        point_index_grid_internal::constructExclusiveRegions(searchRegions, region, ibox);
 
 1128        searchRegions.push_back(region);
 
 1132    std::deque<ValueType> filteredIndices;
 
 1133    point_index_grid_internal::BBoxFilter<PointArray, ValueType>
 
 1134        filter(mRangeList, filteredIndices, bbox, 
points, xform);
 
 1136    for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
 
 1137        point_index_grid_internal::filteredPointIndexSearch(filter, acc, searchRegions[n]);
 
 1140    point_index_grid_internal::dequeToArray(filteredIndices, mIndexArray, mIndexArraySize);
 
 
 1146template<
typename TreeType>
 
 1147template<
typename Po
intArray>
 
 1151    bool subvoxelAccuracy)
 
 1154    std::vector<CoordBBox> searchRegions;
 
 1158        Coord::round(
Vec3d(center[0] - radius, center[1] - radius, center[2] - radius)),
 
 1159        Coord::round(
Vec3d(center[0] + radius, center[1] + radius, center[2] + radius)));
 
 1162    const double iRadius = radius * double(1.0 / std::sqrt(3.0));
 
 1163    if (iRadius > 2.0) {
 
 1166            Coord::round(
Vec3d(center[0] - iRadius, center[1] - iRadius, center[2] - iRadius)),
 
 1167            Coord::round(
Vec3d(center[0] + iRadius, center[1] + iRadius, center[2] + iRadius)));
 
 1171        point_index_grid_internal::pointIndexSearch(mRangeList, acc, ibox);
 
 1174        point_index_grid_internal::constructExclusiveRegions(searchRegions, bbox, ibox);
 
 1176        searchRegions.push_back(bbox);
 
 1180    std::deque<ValueType> filteredIndices;
 
 1181    const double leafNodeDim = double(TreeType::LeafNodeType::DIM);
 
 1183    using FilterT = point_index_grid_internal::RadialRangeFilter<PointArray, ValueType>;
 
 1185    FilterT filter(mRangeList, filteredIndices,
 
 1186        center, radius, 
points, xform, leafNodeDim, subvoxelAccuracy);
 
 1188    for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
 
 1189        point_index_grid_internal::filteredPointIndexSearch(filter, acc, searchRegions[n]);
 
 1192    point_index_grid_internal::dequeToArray(filteredIndices, mIndexArray, mIndexArraySize);
 
 
 1198template<
typename TreeType>
 
 1199template<
typename Po
intArray>
 
 1209template<
typename TreeType>
 
 1210template<
typename Po
intArray>
 
 1214    bool subvoxelAccuracy)
 
 1217        (radius / xform.
voxelSize()[0]), acc, 
points, xform, subvoxelAccuracy);
 
 
 1225template<
typename Po
intArray, 
typename TreeType>
 
 1229    : mPoints(&
points), mAcc(
tree), mXform(xform), mInvVoxelSize(1.0/xform.voxelSize()[0])
 
 
 1234template<
typename Po
intArray, 
typename TreeType>
 
 1237    : mPoints(rhs.mPoints)
 
 1238    , mAcc(rhs.mAcc.
tree())
 
 1239    , mXform(rhs.mXform)
 
 1240    , mInvVoxelSize(rhs.mInvVoxelSize)
 
 
 1245template<
typename Po
intArray, 
typename TreeType>
 
 1246template<
typename FilterType>
 
 1251    if (radius * mInvVoxelSize < 
ScalarType(8.0)) {
 
 1253            mXform.worldToIndexCellCentered(center - radius),
 
 1254            mXform.worldToIndexCellCentered(center + radius)), mAcc);
 
 1256        mIter.worldSpaceSearchAndUpdate(
 
 1257            center, radius, mAcc, *mPoints, mXform, 
false);
 
 1260    const ScalarType radiusSqr = radius * radius;
 
 1263    for (; mIter; ++mIter) {
 
 1264        mPoints->getPos(*mIter, pos);
 
 1266        distSqr = pos.lengthSqr();
 
 1268        if (distSqr < radiusSqr) {
 
 1269            op(distSqr, *mIter);
 
 
 1278template<
typename Gr
idT, 
typename Po
intArrayT>
 
 1279inline typename GridT::Ptr
 
 1282    typename GridT::Ptr grid = GridT::create(
typename GridT::ValueType(0));
 
 1283    grid->setTransform(xform.
copy());
 
 1286        point_index_grid_internal::constructPointTree(
 
 1287            grid->tree(), grid->transform(), 
points);
 
 
 1294template<
typename Gr
idT, 
typename Po
intArrayT>
 
 1295inline typename GridT::Ptr
 
 1303template<
typename Po
intArrayT, 
typename Gr
idT>
 
 1309    size_t pointCount = 0;
 
 1310    for (
size_t n = 0, N = leafs.
leafCount(); n < N; ++n) {
 
 1311        pointCount += leafs.
leaf(n).indices().size();
 
 1314    if (
points.size() != pointCount) {
 
 1318    std::atomic<bool> changed;
 
 1321    point_index_grid_internal::ValidPartitioningOp<PointArrayT>
 
 1322        op(changed, 
points, grid.transform());
 
 1326    return !
bool(changed);
 
 
 1330template<
typename Gr
idT, 
typename Po
intArrayT>
 
 1331inline typename GridT::ConstPtr
 
 1342template<
typename Gr
idT, 
typename Po
intArrayT>
 
 1343inline typename GridT::Ptr
 
 1357template<
typename T, Index Log2Dim>
 
 1409        const T& value = 
zeroVal<T>(), 
bool active = 
false)
 
 
 1420    template<
typename OtherType, Index OtherLog2Dim>
 
 1433    template<MergePolicy Policy> 
void merge(
const ValueType& tileValue, 
bool tileActive) {
 
 
 1437    template<MergePolicy Policy>
 
 1445    template<
typename AccessorT>
 
 1451    template<
typename AccessorT>
 
 1454    template<
typename NodeT, 
typename AccessorT>
 
 1458        if (!(std::is_same<NodeT, PointIndexLeafNode>::value)) 
return nullptr;
 
 1459        return reinterpret_cast<NodeT*
>(
this);
 
 
 1463    template<
typename AccessorT>
 
 1470    template<
typename AccessorT>
 
 1472    template<
typename AccessorT>
 
 1475    template<
typename NodeT, 
typename AccessorT>
 
 1479        if (!(std::is_same<NodeT, PointIndexLeafNode>::value)) 
return nullptr;
 
 1480        return reinterpret_cast<const NodeT*
>(
this);
 
 
 1488    void readBuffers(std::istream& is, 
bool fromHalf = 
false);
 
 1490    void writeBuffers(std::ostream& os, 
bool toHalf = 
false) 
const;
 
 1503        OPENVDB_ASSERT(
false && 
"Cannot modify voxel values in a PointIndexTree.");
 
 
 1529    template<
typename ModifyOp>
 
 1532    template<
typename ModifyOp>
 
 1535    template<
typename ModifyOp>
 
 1544    template<
typename AccessorT>
 
 1547    template<
typename ModifyOp, 
typename AccessorT>
 
 1552    template<
typename AccessorT>
 
 1555    template<
typename AccessorT>
 
 1611#define VMASK_ this->getValueMask() 
 
 1655template<
typename T, Index Log2Dim>
 
 1664template<
typename T, Index Log2Dim>
 
 1670        const ValueType* dataPtr = &mIndices.front();
 
 1671        begin = dataPtr + (offset == 0 ? 
ValueType(0) : this->buffer()[offset - 1]);
 
 1672        end = dataPtr + this->buffer()[offset];
 
 
 1679template<
typename T, Index Log2Dim>
 
 1683    this->buffer().setValue(offset, val);
 
 
 1688template<
typename T, Index Log2Dim>
 
 1692    this->buffer().setValue(offset, val);
 
 
 1696template<
typename T, Index Log2Dim>
 
 1703    for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
 
 1704        xPos = (ijk[0] & (
DIM - 1u)) << (2 * 
LOG2DIM);
 
 1706        for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
 
 1707            pos = xPos + ((ijk[1] & (
DIM - 1u)) << 
LOG2DIM);
 
 1708            pos += (bbox.
min()[2] & (
DIM - 1u));
 
 1710            if (this->buffer()[pos+zStride] > (pos == 0 ? T(0) : this->buffer()[pos - 1])) {
 
 
 1720template<
typename T, Index Log2Dim>
 
 1727    is.read(
reinterpret_cast<char*
>(&numIndices), 
sizeof(
Index64));
 
 1729    mIndices.resize(
size_t(numIndices));
 
 1730    is.read(
reinterpret_cast<char*
>(mIndices.data()), numIndices * 
sizeof(T));
 
 
 1734template<
typename T, Index Log2Dim>
 
 1742    is.read(
reinterpret_cast<char*
>(&numIndices), 
sizeof(
Index64));
 
 1744    const Index64 numBytes = numIndices * 
sizeof(T);
 
 1746    if (bbox.
hasOverlap(this->getNodeBoundingBox())) {
 
 1747        mIndices.resize(
size_t(numIndices));
 
 1748        is.read(
reinterpret_cast<char*
>(mIndices.data()), numBytes);
 
 1754        std::unique_ptr<char[]> buf{
new char[numBytes]};
 
 1755        is.read(buf.get(), numBytes);
 
 1760    is.read(
reinterpret_cast<char*
>(&auxDataBytes), 
sizeof(
Index64));
 
 1761    if (auxDataBytes > 0) {
 
 1763        std::unique_ptr<char[]> auxData{
new char[auxDataBytes]};
 
 1764        is.read(auxData.get(), auxDataBytes);
 
 
 1769template<
typename T, Index Log2Dim>
 
 1776    os.write(
reinterpret_cast<const char*
>(&numIndices), 
sizeof(
Index64));
 
 1777    os.write(
reinterpret_cast<const char*
>(mIndices.data()), numIndices * 
sizeof(T));
 
 1781    os.write(
reinterpret_cast<const char*
>(&auxDataBytes), 
sizeof(
Index64));
 
 
 1785template<
typename T, Index Log2Dim>
 
 1792template<
typename T, Index Log2Dim>
 
 1809template<Index Dim1, 
typename T2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
#define VMASK_
Definition PointDataGrid.h:702
Spatially partitions points using a parallel radix-based sorting algorithm.
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion).
Definition Coord.h:51
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
Tag dispatch class that distinguishes constructors during file input.
Definition Types.h:689
const Vec3T & max() const
Return a const reference to the maximum point of this bounding box.
Definition BBox.h:64
const Vec3T & min() const
Return a const reference to the minimum point of this bounding box.
Definition BBox.h:62
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition Coord.h:421
const Coord & min() const
Definition Coord.h:324
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition Coord.h:415
const Coord & max() const
Definition Coord.h:325
Coord dim() const
Return the dimensions of the coordinates spanned by this bounding box.
Definition Coord.h:383
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Definition InternalNode.h:35
Base class for iterators over internal and leaf nodes.
Definition Iterator.h:30
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition LeafManager.h:319
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition LeafManager.h:484
size_t leafCount() const
Return the number of leaf nodes.
Definition LeafManager.h:288
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim....
Definition LeafNode.h:39
void setValueMaskOn(Index n)
Definition LeafNode.h:893
static const Index NUM_VOXELS
Definition LeafNode.h:53
static const Index DIM
Definition LeafNode.h:51
static const Index LEVEL
Definition LeafNode.h:55
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition LeafNode.h:1040
bool hasSameTopology(const LeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition LeafNode.h:1497
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition LeafNode.h:1432
Index64 memUsageIfLoaded() const
Definition LeafNode.h:1469
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition LeafNode.h:1334
static const Index NUM_VALUES
Definition LeafNode.h:52
static const Index LOG2DIM
Definition LeafNode.h:49
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition LeafNode.h:1449
static const Index SIZE
Definition LeafNode.h:54
bool isEmpty() const
Return true if this node has no active voxels.
Definition LeafNode.h:151
static const Index TOTAL
Definition LeafNode.h:50
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition LeafNode.h:1459
bool isValueMaskOn(Index n) const
Definition LeafNode.h:880
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains the voxel coordinate xyz. If no LeafNode exists,...
Definition ValueAccessor.h:838
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition NodeMasks.h:308
DenseMaskIterator< NodeMask > DenseIterator
Definition NodeMasks.h:350
OnMaskIterator< NodeMask > OnIterator
Definition NodeMasks.h:348
OffMaskIterator< NodeMask > OffIterator
Definition NodeMasks.h:349
Selectively extract and filter point data using a custom filter operator.
Partitions points into BucketLog2Dim aligned buckets using a parallel radix-based sorting algorithm.
Vec3< double > Vec3d
Definition Vec3.h:665
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
Definition PointDataGrid.h:170
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
Index32 Index
Definition Types.h:54
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
math::BBox< Vec3d > BBoxd
Definition Types.h:84
uint64_t Index64
Definition Types.h:53
std::shared_ptr< T > SharedPtr
Definition Types.h:114
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Definition LeafNode.h:213
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition LeafNode.h:253
Definition LeafNode.h:213
Definition LeafNode.h:213
Definition LeafNode.h:262
Definition LeafNode.h:212
Definition LeafNode.h:221
Definition LeafNode.h:212
Definition LeafNode.h:212
Definition LeafNode.h:920
#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