OpenVDB  6.1.0
PointConversion.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 
36 
37 #ifndef OPENVDB_POINTS_POINT_CONVERSION_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_CONVERSION_HAS_BEEN_INCLUDED
39 
40 #include <openvdb/math/Transform.h>
41 
45 
46 #include "AttributeArrayString.h"
47 #include "AttributeSet.h"
48 #include "IndexFilter.h"
49 #include "PointAttribute.h"
50 #include "PointDataGrid.h"
51 #include "PointGroup.h"
52 
53 #include <tbb/parallel_reduce.h>
54 
55 #include <type_traits>
56 
57 namespace openvdb {
59 namespace OPENVDB_VERSION_NAME {
60 namespace points {
61 
62 
79 
80 template<
81  typename CompressionT,
82  typename PointDataGridT,
83  typename PositionArrayT,
84  typename PointIndexGridT>
85 inline typename PointDataGridT::Ptr
86 createPointDataGrid(const PointIndexGridT& pointIndexGrid,
87  const PositionArrayT& positions,
88  const math::Transform& xform,
89  Metadata::Ptr positionDefaultValue = Metadata::Ptr());
90 
91 
101 
102 template <typename CompressionT, typename PointDataGridT, typename ValueT>
103 inline typename PointDataGridT::Ptr
104 createPointDataGrid(const std::vector<ValueT>& positions,
105  const math::Transform& xform,
106  Metadata::Ptr positionDefaultValue = Metadata::Ptr());
107 
108 
120 template <typename PointDataTreeT, typename PointIndexTreeT, typename PointArrayT>
121 inline void
122 populateAttribute( PointDataTreeT& tree,
123  const PointIndexTreeT& pointIndexTree,
124  const openvdb::Name& attributeName,
125  const PointArrayT& data,
126  const Index stride = 1,
127  const bool insertMetadata = true);
128 
138 
139 template <typename PositionAttribute, typename PointDataGridT, typename FilterT = NullFilter>
140 inline void
141 convertPointDataGridPosition( PositionAttribute& positionAttribute,
142  const PointDataGridT& grid,
143  const std::vector<Index64>& pointOffsets,
144  const Index64 startOffset,
145  const FilterT& filter = NullFilter(),
146  const bool inCoreOnly = false);
147 
148 
159 template <typename TypedAttribute, typename PointDataTreeT, typename FilterT = NullFilter>
160 inline void
161 convertPointDataGridAttribute( TypedAttribute& attribute,
162  const PointDataTreeT& tree,
163  const std::vector<Index64>& pointOffsets,
164  const Index64 startOffset,
165  const unsigned arrayIndex,
166  const Index stride = 1,
167  const FilterT& filter = NullFilter(),
168  const bool inCoreOnly = false);
169 
170 
181 
182 template <typename Group, typename PointDataTreeT, typename FilterT = NullFilter>
183 inline void
184 convertPointDataGridGroup( Group& group,
185  const PointDataTreeT& tree,
186  const std::vector<Index64>& pointOffsets,
187  const Index64 startOffset,
188  const AttributeSet::Descriptor::GroupIndex index,
189  const FilterT& filter = NullFilter(),
190  const bool inCoreOnly = false);
191 
204 template<typename PositionWrapper, typename InterrupterT = openvdb::util::NullInterrupter>
205 inline float
206 computeVoxelSize( const PositionWrapper& positions,
207  const uint32_t pointsPerVoxel,
208  const math::Mat4d transform = math::Mat4d::identity(),
209  const Index decimalPlaces = 5,
210  InterrupterT* const interrupter = nullptr);
211 
212 
214 
215 
217 template<typename ValueType>
219 public:
220  using PosType = ValueType;
221  using value_type= ValueType;
222 
223  PointAttributeVector(const std::vector<value_type>& data,
224  const Index stride = 1)
225  : mData(data)
226  , mStride(stride) { }
227 
228  size_t size() const { return mData.size(); }
229  void getPos(size_t n, ValueType& xyz) const { xyz = mData[n]; }
230  void get(ValueType& value, size_t n) const { value = mData[n]; }
231  void get(ValueType& value, size_t n, openvdb::Index m) const { value = mData[n * mStride + m]; }
232 
233 private:
234  const std::vector<value_type>& mData;
235  const Index mStride;
236 }; // PointAttributeVector
237 
238 
240 
241 
242 namespace point_conversion_internal {
243 
244 
245 // ConversionTraits to create the relevant Attribute Handles from a LeafNode
246 template <typename T> struct ConversionTraits
247 {
250  static T zero() { return zeroVal<T>(); }
251  template <typename LeafT>
252  static typename Handle::Ptr handleFromLeaf(LeafT& leaf, Index index) {
253  const AttributeArray& array = leaf.constAttributeArray(index);
254  return Handle::create(array);
255  }
256  template <typename LeafT>
257  static typename WriteHandle::Ptr writeHandleFromLeaf(LeafT& leaf, Index index) {
258  AttributeArray& array = leaf.attributeArray(index);
259  return WriteHandle::create(array);
260  }
261 }; // ConversionTraits
262 template <> struct ConversionTraits<openvdb::Name>
263 {
266  static openvdb::Name zero() { return ""; }
267  template <typename LeafT>
268  static typename Handle::Ptr handleFromLeaf(LeafT& leaf, Index index) {
269  const AttributeArray& array = leaf.constAttributeArray(index);
270  const AttributeSet::Descriptor& descriptor = leaf.attributeSet().descriptor();
271  return Handle::create(array, descriptor.getMetadata());
272  }
273  template <typename LeafT>
274  static typename WriteHandle::Ptr writeHandleFromLeaf(LeafT& leaf, Index index) {
275  AttributeArray& array = leaf.attributeArray(index);
276  const AttributeSet::Descriptor& descriptor = leaf.attributeSet().descriptor();
277  return WriteHandle::create(array, descriptor.getMetadata());
278  }
279 }; // ConversionTraits<openvdb::Name>
280 
281 template< typename PointDataTreeType,
282  typename PointIndexTreeType,
283  typename AttributeListType>
285 
287  using LeafRangeT = typename LeafManagerT::LeafRange;
288  using PointIndexLeafNode = typename PointIndexTreeType::LeafNodeType;
290  using ValueType = typename AttributeListType::value_type;
292 
293  PopulateAttributeOp(const PointIndexTreeType& pointIndexTree,
294  const AttributeListType& data,
295  const size_t index,
296  const Index stride = 1)
297  : mPointIndexTree(pointIndexTree)
298  , mData(data)
299  , mIndex(index)
300  , mStride(stride) { }
301 
302  void operator()(const typename LeafManagerT::LeafRange& range) const {
303 
304  for (auto leaf = range.begin(); leaf; ++leaf) {
305 
306  // obtain the PointIndexLeafNode (using the origin of the current leaf)
307 
308  const PointIndexLeafNode* pointIndexLeaf =
309  mPointIndexTree.probeConstLeaf(leaf->origin());
310 
311  if (!pointIndexLeaf) continue;
312 
313  typename HandleT::Ptr attributeWriteHandle =
314  ConversionTraits<ValueType>::writeHandleFromLeaf(*leaf, static_cast<Index>(mIndex));
315 
316  Index64 index = 0;
317 
318  const IndexArray& indices = pointIndexLeaf->indices();
319 
320  for (const Index64 leafIndex: indices)
321  {
322  ValueType value;
323  for (Index i = 0; i < mStride; i++) {
324  mData.get(value, leafIndex, i);
325  attributeWriteHandle->set(static_cast<Index>(index), i, value);
326  }
327  index++;
328  }
329 
330  // attempt to compact the array
331 
332  attributeWriteHandle->compact();
333  }
334  }
335 
337 
338  const PointIndexTreeType& mPointIndexTree;
339  const AttributeListType& mData;
340  const size_t mIndex;
341  const Index mStride;
342 };
343 
344 template<typename PointDataTreeType, typename Attribute, typename FilterT>
346 
347  using LeafNode = typename PointDataTreeType::LeafNodeType;
348  using ValueType = typename Attribute::ValueType;
349  using HandleT = typename Attribute::Handle;
352  using LeafRangeT = typename LeafManagerT::LeafRange;
353 
354  ConvertPointDataGridPositionOp( Attribute& attribute,
355  const std::vector<Index64>& pointOffsets,
356  const Index64 startOffset,
357  const math::Transform& transform,
358  const size_t index,
359  const FilterT& filter,
360  const bool inCoreOnly)
361  : mAttribute(attribute)
362  , mPointOffsets(pointOffsets)
363  , mStartOffset(startOffset)
364  , mTransform(transform)
365  , mIndex(index)
366  , mFilter(filter)
367  , mInCoreOnly(inCoreOnly)
368  {
369  // only accept Vec3f as ValueType
370  static_assert(VecTraits<ValueType>::Size == 3 &&
371  std::is_floating_point<typename ValueType::ValueType>::value,
372  "ValueType is not Vec3f");
373  }
374 
375  template <typename IterT>
376  void convert(IterT& iter, HandleT& targetHandle,
377  SourceHandleT& sourceHandle, Index64& offset) const
378  {
379  for (; iter; ++iter) {
380  const Vec3d xyz = iter.getCoord().asVec3d();
381  const Vec3d pos = sourceHandle.get(*iter);
382  targetHandle.set(static_cast<Index>(offset++), /*stride=*/0,
383  mTransform.indexToWorld(pos + xyz));
384  }
385  }
386 
387  void operator()(const LeafRangeT& range) const
388  {
389  HandleT pHandle(mAttribute);
390 
391  for (auto leaf = range.begin(); leaf; ++leaf) {
392 
393  assert(leaf.pos() < mPointOffsets.size());
394 
395  if (mInCoreOnly && leaf->buffer().isOutOfCore()) continue;
396 
397  Index64 offset = mStartOffset;
398 
399  if (leaf.pos() > 0) offset += mPointOffsets[leaf.pos() - 1];
400 
401  auto handle = SourceHandleT::create(leaf->constAttributeArray(mIndex));
402 
403  if (mFilter.state() == index::ALL) {
404  auto iter = leaf->beginIndexOn();
405  convert(iter, pHandle, *handle, offset);
406  }
407  else {
408  auto iter = leaf->beginIndexOn(mFilter);
409  convert(iter, pHandle, *handle, offset);
410  }
411  }
412  }
413 
415 
416  Attribute& mAttribute;
417  const std::vector<Index64>& mPointOffsets;
420  const size_t mIndex;
421  const FilterT& mFilter;
422  const bool mInCoreOnly;
423 }; // ConvertPointDataGridPositionOp
424 
425 
426 template<typename PointDataTreeType, typename Attribute, typename FilterT>
428 
429  using LeafNode = typename PointDataTreeType::LeafNodeType;
430  using ValueType = typename Attribute::ValueType;
431  using HandleT = typename Attribute::Handle;
434  using LeafRangeT = typename LeafManagerT::LeafRange;
435 
436  ConvertPointDataGridAttributeOp(Attribute& attribute,
437  const std::vector<Index64>& pointOffsets,
438  const Index64 startOffset,
439  const size_t index,
440  const Index stride,
441  const FilterT& filter,
442  const bool inCoreOnly)
443  : mAttribute(attribute)
444  , mPointOffsets(pointOffsets)
445  , mStartOffset(startOffset)
446  , mIndex(index)
447  , mStride(stride)
448  , mFilter(filter)
449  , mInCoreOnly(inCoreOnly) { }
450 
451  template <typename IterT>
452  void convert(IterT& iter, HandleT& targetHandle,
453  SourceHandleT& sourceHandle, Index64& offset) const
454  {
455  if (sourceHandle.isUniform()) {
456  const ValueType uniformValue(sourceHandle.get(0));
457  for (; iter; ++iter) {
458  for (Index i = 0; i < mStride; i++) {
459  targetHandle.set(static_cast<Index>(offset), i, uniformValue);
460  }
461  offset++;
462  }
463  }
464  else {
465  for (; iter; ++iter) {
466  for (Index i = 0; i < mStride; i++) {
467  targetHandle.set(static_cast<Index>(offset), i,
468  sourceHandle.get(*iter, /*stride=*/i));
469  }
470  offset++;
471  }
472  }
473  }
474 
475  void operator()(const LeafRangeT& range) const
476  {
477  HandleT pHandle(mAttribute);
478 
479  for (auto leaf = range.begin(); leaf; ++leaf) {
480 
481  assert(leaf.pos() < mPointOffsets.size());
482 
483  if (mInCoreOnly && leaf->buffer().isOutOfCore()) continue;
484 
485  Index64 offset = mStartOffset;
486 
487  if (leaf.pos() > 0) offset += mPointOffsets[leaf.pos() - 1];
488 
489  typename SourceHandleT::Ptr handle = ConversionTraits<ValueType>::handleFromLeaf(
490  *leaf, static_cast<Index>(mIndex));
491 
492  if (mFilter.state() == index::ALL) {
493  auto iter = leaf->beginIndexOn();
494  convert(iter, pHandle, *handle, offset);
495  } else {
496  auto iter = leaf->beginIndexOn(mFilter);
497  convert(iter, pHandle, *handle, offset);
498  }
499  }
500  }
501 
503 
504  Attribute& mAttribute;
505  const std::vector<Index64>& mPointOffsets;
507  const size_t mIndex;
508  const Index mStride;
509  const FilterT& mFilter;
510  const bool mInCoreOnly;
511 }; // ConvertPointDataGridAttributeOp
512 
513 template<typename PointDataTreeType, typename Group, typename FilterT>
515 
516  using LeafNode = typename PointDataTreeType::LeafNodeType;
517  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
519  using LeafRangeT = typename LeafManagerT::LeafRange;
520 
522  const std::vector<Index64>& pointOffsets,
523  const Index64 startOffset,
524  const AttributeSet::Descriptor::GroupIndex index,
525  const FilterT& filter,
526  const bool inCoreOnly)
527  : mGroup(group)
528  , mPointOffsets(pointOffsets)
529  , mStartOffset(startOffset)
530  , mIndex(index)
531  , mFilter(filter)
532  , mInCoreOnly(inCoreOnly) { }
533 
534  template <typename IterT>
535  void convert(IterT& iter, const GroupAttributeArray& groupArray, Index64& offset) const
536  {
537  const auto bitmask = static_cast<GroupType>(1 << mIndex.second);
538 
539  if (groupArray.isUniform()) {
540  if (groupArray.get(0) & bitmask) {
541  for (; iter; ++iter) {
542  mGroup.setOffsetOn(static_cast<Index>(offset));
543  offset++;
544  }
545  }
546  }
547  else {
548  for (; iter; ++iter) {
549  if (groupArray.get(*iter) & bitmask) {
550  mGroup.setOffsetOn(static_cast<Index>(offset));
551  }
552  offset++;
553  }
554  }
555  }
556 
557  void operator()(const LeafRangeT& range) const
558  {
559  for (auto leaf = range.begin(); leaf; ++leaf) {
560 
561  assert(leaf.pos() < mPointOffsets.size());
562 
563  if (mInCoreOnly && leaf->buffer().isOutOfCore()) continue;
564 
565  Index64 offset = mStartOffset;
566 
567  if (leaf.pos() > 0) offset += mPointOffsets[leaf.pos() - 1];
568 
569  const AttributeArray& array = leaf->constAttributeArray(mIndex.first);
570  assert(isGroup(array));
571  const GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
572 
573  if (mFilter.state() == index::ALL) {
574  auto iter = leaf->beginIndexOn();
575  convert(iter, groupArray, offset);
576  }
577  else {
578  auto iter = leaf->beginIndexOn(mFilter);
579  convert(iter, groupArray, offset);
580  }
581  }
582  }
583 
585 
586  Group& mGroup;
587  const std::vector<Index64>& mPointOffsets;
590  const FilterT& mFilter;
591  const bool mInCoreOnly;
592 }; // ConvertPointDataGridGroupOp
593 
594 template<typename PositionArrayT>
596 {
597  CalculatePositionBounds(const PositionArrayT& positions,
598  const math::Mat4d& inverse)
599  : mPositions(positions)
600  , mInverseMat(inverse)
601  , mMin(std::numeric_limits<Real>::max())
602  , mMax(-std::numeric_limits<Real>::max()) {}
603 
605  : mPositions(other.mPositions)
606  , mInverseMat(other.mInverseMat)
607  , mMin(std::numeric_limits<Real>::max())
608  , mMax(-std::numeric_limits<Real>::max()) {}
609 
610  void operator()(const tbb::blocked_range<size_t>& range) {
611  Vec3R pos;
612  for (size_t n = range.begin(), N = range.end(); n != N; ++n) {
613  mPositions.getPos(n, pos);
614  pos = mInverseMat.transform(pos);
615  mMin = math::minComponent(mMin, pos);
616  mMax = math::maxComponent(mMax, pos);
617  }
618  }
619 
620  void join(const CalculatePositionBounds& other) {
621  mMin = math::minComponent(mMin, other.mMin);
622  mMax = math::maxComponent(mMax, other.mMax);
623  }
624 
626  return BBoxd(mMin, mMax);
627  }
628 
629 private:
630  const PositionArrayT& mPositions;
631  const math::Mat4d& mInverseMat;
632  Vec3R mMin, mMax;
633 };
634 
635 } // namespace point_conversion_internal
636 
637 
639 
640 
641 template<typename CompressionT, typename PointDataGridT, typename PositionArrayT, typename PointIndexGridT>
642 inline typename PointDataGridT::Ptr
643 createPointDataGrid(const PointIndexGridT& pointIndexGrid, const PositionArrayT& positions,
644  const math::Transform& xform, Metadata::Ptr positionDefaultValue)
645 {
646  using PointDataTreeT = typename PointDataGridT::TreeType;
647  using LeafT = typename PointDataTree::LeafNodeType;
648  using PointIndexLeafT = typename PointIndexGridT::TreeType::LeafNodeType;
649  using PointIndexT = typename PointIndexLeafT::ValueType;
650  using LeafManagerT = typename tree::LeafManager<PointDataTreeT>;
651  using PositionAttributeT = TypedAttributeArray<Vec3f, CompressionT>;
652 
653  const NamePair positionType = PositionAttributeT::attributeType();
654 
655  // construct the Tree using a topology copy of the PointIndexGrid
656 
657  const auto& pointIndexTree = pointIndexGrid.tree();
658  typename PointDataTreeT::Ptr treePtr(new PointDataTreeT(pointIndexTree));
659 
660  // create attribute descriptor from position type
661 
662  auto descriptor = AttributeSet::Descriptor::create(positionType);
663 
664  // add default value for position if provided
665 
666  if (positionDefaultValue) descriptor->setDefaultValue("P", *positionDefaultValue);
667 
668  // retrieve position index
669 
670  const size_t positionIndex = descriptor->find("P");
671  assert(positionIndex != AttributeSet::INVALID_POS);
672 
673  // populate position attribute
674 
675  LeafManagerT leafManager(*treePtr);
676  leafManager.foreach(
677  [&](LeafT& leaf, size_t /*idx*/) {
678 
679  // obtain the PointIndexLeafNode (using the origin of the current leaf)
680 
681  const auto* pointIndexLeaf = pointIndexTree.probeConstLeaf(leaf.origin());
682  assert(pointIndexLeaf);
683 
684  // initialise the attribute storage
685 
686  Index pointCount(static_cast<Index>(pointIndexLeaf->indices().size()));
687  leaf.initializeAttributes(descriptor, pointCount);
688 
689  // create write handle for position
690 
691  auto attributeWriteHandle = AttributeWriteHandle<Vec3f, CompressionT>::create(
692  leaf.attributeArray(positionIndex));
693 
694  Index index = 0;
695 
696  const PointIndexT
697  *begin = static_cast<PointIndexT*>(nullptr),
698  *end = static_cast<PointIndexT*>(nullptr);
699 
700  // iterator over every active voxel in the point index leaf
701 
702  for (auto iter = pointIndexLeaf->cbeginValueOn(); iter; ++iter) {
703 
704  // find the voxel center
705 
706  const Coord& ijk = iter.getCoord();
707  const Vec3d& positionCellCenter(ijk.asVec3d());
708 
709  // obtain pointers for this voxel from begin to end in the indices array
710 
711  pointIndexLeaf->getIndices(ijk, begin, end);
712 
713  while (begin < end) {
714 
715  typename PositionArrayT::value_type positionWorldSpace;
716  positions.getPos(*begin, positionWorldSpace);
717 
718  // compute the index-space position and then subtract the voxel center
719 
720  const Vec3d positionIndexSpace = xform.worldToIndex(positionWorldSpace);
721  const Vec3f positionVoxelSpace(positionIndexSpace - positionCellCenter);
722 
723  attributeWriteHandle->set(index++, positionVoxelSpace);
724 
725  ++begin;
726  }
727  }
728  },
729  /*threaded=*/true);
730 
731  auto grid = PointDataGridT::create(treePtr);
732  grid->setTransform(xform.copy());
733  return grid;
734 }
735 
736 
738 
739 
740 template <typename CompressionT, typename PointDataGridT, typename ValueT>
741 inline typename PointDataGridT::Ptr
742 createPointDataGrid(const std::vector<ValueT>& positions,
743  const math::Transform& xform,
744  Metadata::Ptr positionDefaultValue)
745 {
746  const PointAttributeVector<ValueT> pointList(positions);
747 
748  tools::PointIndexGrid::Ptr pointIndexGrid = tools::createPointIndexGrid<tools::PointIndexGrid>(pointList, xform);
749  return createPointDataGrid<CompressionT, PointDataGridT>(*pointIndexGrid, pointList, xform, positionDefaultValue);
750 }
751 
752 
754 
755 
756 template <typename PointDataTreeT, typename PointIndexTreeT, typename PointArrayT>
757 inline void
758 populateAttribute(PointDataTreeT& tree, const PointIndexTreeT& pointIndexTree,
759  const openvdb::Name& attributeName, const PointArrayT& data, const Index stride,
760  const bool insertMetadata)
761 {
763  using ValueType = typename PointArrayT::value_type;
764 
765  auto iter = tree.cbeginLeaf();
766 
767  if (!iter) return;
768 
769  const size_t index = iter->attributeSet().find(attributeName);
770 
771  if (index == AttributeSet::INVALID_POS) {
772  OPENVDB_THROW(KeyError, "Attribute not found to populate - " << attributeName << ".");
773  }
774 
775  if (insertMetadata) {
777  }
778 
779  // populate attribute
780 
781  typename tree::LeafManager<PointDataTreeT> leafManager(tree);
782 
783  PopulateAttributeOp<PointDataTreeT,
784  PointIndexTreeT,
785  PointArrayT> populate(pointIndexTree, data, index, stride);
786  tbb::parallel_for(leafManager.leafRange(), populate);
787 }
788 
789 
791 
792 
793 template <typename PositionAttribute, typename PointDataGridT, typename FilterT>
794 inline void
795 convertPointDataGridPosition( PositionAttribute& positionAttribute,
796  const PointDataGridT& grid,
797  const std::vector<Index64>& pointOffsets,
798  const Index64 startOffset,
799  const FilterT& filter,
800  const bool inCoreOnly)
801 {
802  using TreeType = typename PointDataGridT::TreeType;
803  using LeafManagerT = typename tree::LeafManager<const TreeType>;
804 
806 
807  const TreeType& tree = grid.tree();
808  auto iter = tree.cbeginLeaf();
809 
810  if (!iter) return;
811 
812  const size_t positionIndex = iter->attributeSet().find("P");
813 
814  positionAttribute.expand();
815  LeafManagerT leafManager(tree);
816  ConvertPointDataGridPositionOp<TreeType, PositionAttribute, FilterT> convert(
817  positionAttribute, pointOffsets, startOffset, grid.transform(), positionIndex,
818  filter, inCoreOnly);
819  tbb::parallel_for(leafManager.leafRange(), convert);
820  positionAttribute.compact();
821 }
822 
823 
825 
826 
827 template <typename TypedAttribute, typename PointDataTreeT, typename FilterT>
828 inline void
829 convertPointDataGridAttribute( TypedAttribute& attribute,
830  const PointDataTreeT& tree,
831  const std::vector<Index64>& pointOffsets,
832  const Index64 startOffset,
833  const unsigned arrayIndex,
834  const Index stride,
835  const FilterT& filter,
836  const bool inCoreOnly)
837 {
838  using LeafManagerT = typename tree::LeafManager<const PointDataTreeT>;
839 
841 
842  auto iter = tree.cbeginLeaf();
843 
844  if (!iter) return;
845 
846  attribute.expand();
847  LeafManagerT leafManager(tree);
848  ConvertPointDataGridAttributeOp<PointDataTreeT, TypedAttribute, FilterT> convert(
849  attribute, pointOffsets, startOffset, arrayIndex, stride,
850  filter, inCoreOnly);
851  tbb::parallel_for(leafManager.leafRange(), convert);
852  attribute.compact();
853 }
854 
855 
857 
858 
859 template <typename Group, typename PointDataTreeT, typename FilterT>
860 inline void
862  const PointDataTreeT& tree,
863  const std::vector<Index64>& pointOffsets,
864  const Index64 startOffset,
865  const AttributeSet::Descriptor::GroupIndex index,
866  const FilterT& filter,
867  const bool inCoreOnly)
868 {
869  using LeafManagerT= typename tree::LeafManager<const PointDataTreeT>;
870 
872 
873  auto iter = tree.cbeginLeaf();
874  if (!iter) return;
875 
876  LeafManagerT leafManager(tree);
877  ConvertPointDataGridGroupOp<PointDataTree, Group, FilterT> convert(
878  group, pointOffsets, startOffset, index,
879  filter, inCoreOnly);
880  tbb::parallel_for(leafManager.leafRange(), convert);
881 
882  // must call this after modifying point groups in parallel
883 
884  group.finalize();
885 }
886 
887 template<typename PositionWrapper, typename InterrupterT>
888 inline float
889 computeVoxelSize( const PositionWrapper& positions,
890  const uint32_t pointsPerVoxel,
891  const math::Mat4d transform,
892  const Index decimalPlaces,
893  InterrupterT* const interrupter)
894 {
895  using namespace point_conversion_internal;
896 
897  struct Local {
898 
899  static bool voxelSizeFromVolume(const double volume,
900  const size_t estimatedVoxelCount,
901  float& voxelSize)
902  {
903  // dictated by the math::ScaleMap limit
904  static const double minimumVoxelVolume(3e-15);
905  static const double maximumVoxelVolume(std::numeric_limits<float>::max());
906 
907  double voxelVolume = volume / static_cast<double>(estimatedVoxelCount);
908  bool valid = true;
909 
910  if (voxelVolume < minimumVoxelVolume) {
911  voxelVolume = minimumVoxelVolume;
912  valid = false;
913  }
914  else if (voxelVolume > maximumVoxelVolume) {
915  voxelVolume = maximumVoxelVolume;
916  valid = false;
917  }
918 
919  voxelSize = static_cast<float>(math::Pow(voxelVolume, 1.0/3.0));
920  return valid;
921  }
922 
923  static float truncate(const float voxelSize, Index decPlaces)
924  {
925  float truncatedVoxelSize = voxelSize;
926 
927  // attempt to truncate from decPlaces -> 11
928  for (int i = decPlaces; i < 11; i++) {
929  truncatedVoxelSize = static_cast<float>(math::Truncate(double(voxelSize), i));
930  if (truncatedVoxelSize != 0.0f) break;
931  }
932 
933  return truncatedVoxelSize;
934  }
935  };
936 
937  if (pointsPerVoxel == 0) OPENVDB_THROW(ValueError, "Points per voxel cannot be zero.");
938 
939  // constructed with the default voxel size as specified by openvdb interface values
940 
941  float voxelSize(0.1f);
942 
943  const size_t numPoints = positions.size();
944 
945  // return the default voxel size if we have zero or only 1 point
946 
947  if (numPoints <= 1) return voxelSize;
948 
949  size_t targetVoxelCount(numPoints / size_t(pointsPerVoxel));
950  if (targetVoxelCount == 0) targetVoxelCount++;
951 
952  // calculate the world space, transform-oriented bounding box
953 
954  math::Mat4d inverseTransform = transform.inverse();
955  inverseTransform = math::unit(inverseTransform);
956 
957  tbb::blocked_range<size_t> range(0, numPoints);
958  CalculatePositionBounds<PositionWrapper> calculateBounds(positions, inverseTransform);
959  tbb::parallel_reduce(range, calculateBounds);
960 
961  BBoxd bbox = calculateBounds.getBoundingBox();
962 
963  // return default size if points are coincident
964 
965  if (bbox.min() == bbox.max()) return voxelSize;
966 
967  double volume = bbox.volume();
968 
969  // handle points that are collinear or coplanar by expanding the volume
970 
971  if (math::isApproxZero(volume)) {
972  Vec3d extents = bbox.extents().sorted().reversed();
973  if (math::isApproxZero(extents[1])) {
974  // colinear (maxExtent^3)
975  volume = extents[0]*extents[0]*extents[0];
976  }
977  else {
978  // coplanar (maxExtent*nextMaxExtent^2)
979  volume = extents[0]*extents[1]*extents[1];
980  }
981  }
982 
983  double previousVolume = volume;
984 
985  if (!Local::voxelSizeFromVolume(volume, targetVoxelCount, voxelSize)) {
986  OPENVDB_LOG_DEBUG("Out of range, clamping voxel size.");
987  return voxelSize;
988  }
989 
990  size_t previousVoxelCount(0);
991  size_t voxelCount(1);
992 
993  if (interrupter) interrupter->start("Computing voxel size");
994 
995  while (voxelCount > previousVoxelCount)
996  {
997  math::Transform::Ptr newTransform;
998 
999  if (!math::isIdentity(transform))
1000  {
1001  // if using a custom transform, pre-scale by coefficients
1002  // which define the new voxel size
1003 
1004  math::Mat4d matrix(transform);
1005  matrix.preScale(Vec3d(voxelSize) / math::getScale(matrix));
1006  newTransform = math::Transform::createLinearTransform(matrix);
1007  }
1008  else
1009  {
1010  newTransform = math::Transform::createLinearTransform(voxelSize);
1011  }
1012 
1013  // create a mask grid of the points from the calculated voxel size
1014  // this is the same function call as tools::createPointMask() which has
1015  // been duplicated to provide an interrupter
1016 
1017  MaskGrid::Ptr mask = createGrid<MaskGrid>(false);
1018  mask->setTransform(newTransform);
1019  tools::PointsToMask<MaskGrid, InterrupterT> pointMaskOp(*mask, interrupter);
1020  pointMaskOp.addPoints(positions);
1021 
1022  if (interrupter && util::wasInterrupted(interrupter)) break;
1023 
1024  previousVoxelCount = voxelCount;
1025  voxelCount = mask->activeVoxelCount();
1026  volume = math::Pow3(voxelSize) * static_cast<float>(voxelCount);
1027 
1028  // stop if no change in the volume or the volume has increased
1029 
1030  if (volume >= previousVolume) break;
1031  previousVolume = volume;
1032 
1033  const float previousVoxelSize = voxelSize;
1034 
1035  // compute the new voxel size and if invalid return the previous value
1036 
1037  if (!Local::voxelSizeFromVolume(volume, targetVoxelCount, voxelSize)) {
1038  voxelSize = previousVoxelSize;
1039  break;
1040  }
1041 
1042  // halt convergence if the voxel size has decreased by less
1043  // than 10% in this iteration
1044 
1045  if (voxelSize / previousVoxelSize > 0.9f) break;
1046  }
1047 
1048  if (interrupter) interrupter->end();
1049 
1050  // truncate the voxel size for readability and return the value
1051 
1052  return Local::truncate(voxelSize, decimalPlaces);
1053 }
1054 
1055 
1057 
1058 
1059 // deprecated functions
1060 
1061 
1062 template <typename PositionAttribute, typename PointDataGridT>
1064 inline void
1065 convertPointDataGridPosition( PositionAttribute& positionAttribute,
1066  const PointDataGridT& grid,
1067  const std::vector<Index64>& pointOffsets,
1068  const Index64 startOffset,
1069  const std::vector<Name>& includeGroups,
1070  const std::vector<Name>& excludeGroups,
1071  const bool inCoreOnly = false)
1072 {
1073  auto leaf = grid.tree().cbeginLeaf();
1074  if (!leaf) return;
1075  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
1076  convertPointDataGridPosition(positionAttribute, grid, pointOffsets, startOffset,
1077  filter, inCoreOnly);
1078 }
1079 
1080 
1081 template <typename TypedAttribute, typename PointDataTreeT>
1083 inline void
1084 convertPointDataGridAttribute( TypedAttribute& attribute,
1085  const PointDataTreeT& tree,
1086  const std::vector<Index64>& pointOffsets,
1087  const Index64 startOffset,
1088  const unsigned arrayIndex,
1089  const Index stride,
1090  const std::vector<Name>& includeGroups,
1091  const std::vector<Name>& excludeGroups,
1092  const bool inCoreOnly = false)
1093 {
1094  auto leaf = tree.cbeginLeaf();
1095  if (!leaf) return;
1096  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
1097  convertPointDataGridAttribute(attribute, tree, pointOffsets, startOffset,
1098  arrayIndex, stride, filter, inCoreOnly);
1099 }
1100 
1101 
1102 template <typename Group, typename PointDataTreeT>
1104 inline void
1106  const PointDataTreeT& tree,
1107  const std::vector<Index64>& pointOffsets,
1108  const Index64 startOffset,
1109  const AttributeSet::Descriptor::GroupIndex index,
1110  const std::vector<Name>& includeGroups,
1111  const std::vector<Name>& excludeGroups,
1112  const bool inCoreOnly = false)
1113 {
1114  auto leaf = tree.cbeginLeaf();
1115  if (!leaf) return;
1116  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
1117  convertPointDataGridGroup(group, tree, pointOffsets, startOffset,
1118  index, filter, inCoreOnly);
1119 }
1120 
1121 
1122 } // namespace points
1123 } // namespace OPENVDB_VERSION_NAME
1124 } // namespace openvdb
1125 
1126 #endif // OPENVDB_POINTS_POINT_CONVERSION_HAS_BEEN_INCLUDED
1127 
1128 // Copyright (c) 2012-2018 DreamWorks Animation LLC
1129 // All rights reserved. This software is distributed under the
1130 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
static Handle::Ptr handleFromLeaf(LeafT &leaf, Index index)
Definition: PointConversion.h:252
static T zero()
Definition: PointConversion.h:250
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointConversion.h:517
typename Attribute::ValueType ValueType
Definition: PointConversion.h:430
#define OPENVDB_DEPRECATED
Definition: Platform.h:69
void addPoints(const PointListT &points, size_t grainSize=1024)
Activates the state of any voxel in the input grid that contains a point.
Definition: PointsToMask.h:150
void operator()(const LeafRangeT &range) const
Definition: PointConversion.h:557
Definition: Exceptions.h:86
Typed class for storing attribute data.
Definition: AttributeArray.h:584
typename PointDataTreeType::LeafNodeType LeafNode
Definition: PointConversion.h:347
typename PointIndexTreeType::LeafNodeType PointIndexLeafNode
Definition: PointConversion.h:288
void join(const CalculatePositionBounds &other)
Definition: PointConversion.h:620
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
#define OPENVDB_LOG_DEBUG(message)
In debug builds only, log a debugging message of the form &#39;someVar << "text" << ...&#39;.
Definition: logging.h:290
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:515
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointConversion.h:302
std::vector< Index > IndexArray
Definition: PointMove.h:188
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
math::BBox< Vec3d > BBoxd
Definition: Types.h:91
Type Pow3(Type x)
Return x3.
Definition: Math.h:506
OPENVDB_API void calculateBounds(const Transform &t, const Vec3d &minWS, const Vec3d &maxWS, Vec3d &minIS, Vec3d &maxIS)
Calculate an axis-aligned bounding box in index space from an axis-aligned bounding box in world spac...
std::shared_ptr< Handle > Ptr
Definition: AttributeArray.h:921
Point-partitioner compatible STL vector attribute wrapper for convenience.
Definition: PointConversion.h:218
const std::vector< Index64 > & mPointOffsets
Definition: PointConversion.h:587
bool isIdentity(const MatType &m)
Determine if a matrix is an identity matrix.
Definition: Mat.h:892
Definition: AttributeArray.h:846
void convert(IterT &iter, HandleT &targetHandle, SourceHandleT &sourceHandle, Index64 &offset) const
Definition: PointConversion.h:452
ConvertPointDataGridAttributeOp(Attribute &attribute, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const size_t index, const Index stride, const FilterT &filter, const bool inCoreOnly)
Definition: PointConversion.h:436
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:530
Definition: Coord.h:608
const math::Transform & mTransform
Definition: PointConversion.h:419
Type Truncate(Type x, unsigned int digits)
Return x truncated to the given number of decimal digits.
Definition: Math.h:824
void populateAttribute(PointDataTreeT &tree, const PointIndexTreeT &pointIndexTree, const openvdb::Name &attributeName, const PointArrayT &data, const Index stride=1, const bool insertMetadata=true)
Stores point attribute data in an existing PointDataGrid attribute.
Definition: PointConversion.h:758
size_t size() const
Definition: PointConversion.h:228
PointDataGridT::Ptr createPointDataGrid(const std::vector< ValueT > &positions, const math::Transform &xform, Metadata::Ptr positionDefaultValue=Metadata::Ptr())
Convenience method to create a PointDataGrid from a std::vector of point positions.
Definition: PointConversion.h:742
MatType unit(const MatType &mat, typename MatType::value_type eps=1.0e-8)
Return a copy of the given matrix with its upper 3×3 rows normalized.
Definition: Mat.h:680
typename Attribute::Handle HandleT
Definition: PointConversion.h:349
std::shared_ptr< Handle > Ptr
Definition: AttributeArray.h:850
Base class for storing attribute data.
Definition: AttributeArray.h:118
std::string Name
Definition: Name.h:44
BBoxd getBoundingBox() const
Definition: PointConversion.h:625
OPENVDB_DEPRECATED void convertPointDataGridAttribute(TypedAttribute &attribute, const PointDataTreeT &tree, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const unsigned arrayIndex, const Index stride, const std::vector< Name > &includeGroups, const std::vector< Name > &excludeGroups, const bool inCoreOnly=false)
Definition: PointConversion.h:1084
void operator()(const tbb::blocked_range< size_t > &range)
Definition: PointConversion.h:610
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
Point attribute manipulation in a VDB Point Grid.
Point group manipulation in a VDB Point Grid.
ConvertPointDataGridGroupOp(Group &group, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const AttributeSet::Descriptor::GroupIndex index, const FilterT &filter, const bool inCoreOnly)
Definition: PointConversion.h:521
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
Index filters primarily designed to be used with a FilterIndexIter.
float computeVoxelSize(const PositionWrapper &positions, const uint32_t pointsPerVoxel, const math::Mat4d transform=math::Mat4d::identity(), const Index decimalPlaces=5, InterrupterT *const interrupter=nullptr)
Definition: PointConversion.h:889
Vec3< double > Vec3d
Definition: Vec3.h:689
static WriteHandle::Ptr writeHandleFromLeaf(LeafT &leaf, Index index)
Definition: PointConversion.h:257
std::shared_ptr< StringAttributeWriteHandle > Ptr
Definition: AttributeArrayString.h:171
Vec3d worldToIndex(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:137
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
CalculatePositionBounds(const CalculatePositionBounds &other, tbb::split)
Definition: PointConversion.h:604
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
Makes every voxel of a grid active if it contains a point.
Definition: PointsToMask.h:94
Definition: AttributeArrayString.h:168
static Handle::Ptr handleFromLeaf(LeafT &leaf, Index index)
Definition: PointConversion.h:268
void operator()(const LeafRangeT &range) const
Definition: PointConversion.h:475
Index32 Index
Definition: Types.h:61
PopulateAttributeOp(const PointIndexTreeType &pointIndexTree, const AttributeListType &data, const size_t index, const Index stride=1)
Definition: PointConversion.h:293
uint64_t Index64
Definition: Types.h:60
void convert(IterT &iter, HandleT &targetHandle, SourceHandleT &sourceHandle, Index64 &offset) const
Definition: PointConversion.h:376
ValueType get(Index n, Index m=0) const
Definition: AttributeArray.h:2190
void preScale(const Vec3< T0 > &v)
Definition: Mat4.h:782
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointConversion.h:287
Vec3< typename MatType::value_type > getScale(const MatType &mat)
Return a Vec3 representing the lengths of the passed matrix&#39;s upper 3×3&#39;s rows.
Definition: Mat.h:665
void convert(IterT &iter, const GroupAttributeArray &groupArray, Index64 &offset) const
Definition: PointConversion.h:535
double Real
Definition: Types.h:67
const AttributeListType & mData
Definition: PointConversion.h:339
CalculatePositionBounds(const PositionArrayT &positions, const math::Mat4d &inverse)
Definition: PointConversion.h:597
Definition: Exceptions.h:40
OPENVDB_DEPRECATED void convertPointDataGridPosition(PositionAttribute &positionAttribute, const PointDataGridT &grid, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const std::vector< Name > &includeGroups, const std::vector< Name > &excludeGroups, const bool inCoreOnly=false)
Definition: PointConversion.h:1065
typename PointIndexLeafNode::IndexArray IndexArray
Definition: PointConversion.h:289
typename AttributeListType::value_type ValueType
Definition: PointConversion.h:290
ValueType value_type
Definition: PointConversion.h:221
std::shared_ptr< StringAttributeHandle > Ptr
Definition: AttributeArrayString.h:139
ElementType volume() const
Return the volume enclosed by this bounding box.
Definition: BBox.h:127
typename PointDataTreeType::LeafNodeType LeafNode
Definition: PointConversion.h:429
const std::vector< Index64 > & mPointOffsets
Definition: PointConversion.h:505
Ptr copy() const
Definition: Transform.h:77
This tool produces a grid where every voxel that contains a point is active. It employes thread-local...
Mat4 inverse(T tolerance=0) const
Definition: Mat4.h:531
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:65
void getPos(size_t n, ValueType &xyz) const
Definition: PointConversion.h:229
PointAttributeVector(const std::vector< value_type > &data, const Index stride=1)
Definition: PointConversion.h:223
typename Attribute::Handle HandleT
Definition: PointConversion.h:431
OPENVDB_DEPRECATED void convertPointDataGridGroup(Group &group, const PointDataTreeT &tree, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const AttributeSet::Descriptor::GroupIndex index, const std::vector< Name > &includeGroups, const std::vector< Name > &excludeGroups, const bool inCoreOnly=false)
Definition: PointConversion.h:1105
static openvdb::Name zero()
Definition: PointConversion.h:266
const size_t mIndex
Definition: PointConversion.h:340
SharedPtr< Transform > Ptr
Definition: Transform.h:69
typename PointDataTreeType::LeafNodeType LeafNode
Definition: PointConversion.h:516
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointConversion.h:434
Definition: Transform.h:66
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: PointCount.h:115
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition: Vec2.h:539
const Vec3T & max() const
Return a const reference to the maximum point of this bounding box.
Definition: BBox.h:91
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:93
typename tree::LeafManager< PointDataTreeType > LeafManagerT
Definition: PointConversion.h:286
typename ConversionTraits< ValueType >::WriteHandle HandleT
Definition: PointConversion.h:291
Vec3< T > sorted() const
Return a vector with the components of this in ascending order.
Definition: Vec3.h:475
Definition: IndexIterator.h:70
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:212
typename tree::LeafManager< const PointDataTreeType > LeafManagerT
Definition: PointConversion.h:433
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointConversion.h:352
typename tree::LeafManager< const PointDataTreeType > LeafManagerT
Definition: PointConversion.h:518
Index64 pointOffsets(std::vector< Index64 > &pointOffsets, const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Populate an array of cumulative point offsets per leaf node.
Definition: PointCount.h:149
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Definition: Types.h:231
const Index mStride
Definition: PointConversion.h:341
Vec3T extents() const
Return the extents of this bounding box, i.e., the length along each axis.
Definition: BBox.h:280
uint8_t GroupType
Definition: AttributeGroup.h:50
bool isUniform() const override
Return true if this array is stored as a single uniform value.
Definition: AttributeArray.h:719
const Vec3T & min() const
Return a const reference to the minimum point of this bounding box.
Definition: BBox.h:89
const std::vector< Index64 > & mPointOffsets
Definition: PointConversion.h:417
Mat4< double > Mat4d
Definition: Mat4.h:1361
Attribute array storage for string data using Descriptor Metadata.
Definition: AttributeArrayString.h:136
Definition: Exceptions.h:92
void operator()(const LeafRangeT &range) const
Definition: PointConversion.h:387
typename ConversionTraits< ValueType >::Handle SourceHandleT
Definition: PointConversion.h:432
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:320
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
SharedPtr< Metadata > Ptr
Definition: Metadata.h:53
SharedPtr< Grid > Ptr
Definition: Grid.h:592
Vec3< T > reversed() const
Return the vector (z, y, x)
Definition: Vec3.h:485
static WriteHandle::Ptr writeHandleFromLeaf(LeafT &leaf, Index index)
Definition: PointConversion.h:274
Write-able version of AttributeHandle.
Definition: AttributeArray.h:917
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:385
typename tree::LeafManager< const PointDataTreeType > LeafManagerT
Definition: PointConversion.h:351
Set of Attribute Arrays which tracks metadata about each array.
typename Attribute::ValueType ValueType
Definition: PointConversion.h:348
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointConversion.h:519
Definition: IndexFilter.h:163
ValueType PosType
Definition: PointConversion.h:220
ConvertPointDataGridPositionOp(Attribute &attribute, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const math::Transform &transform, const size_t index, const FilterT &filter, const bool inCoreOnly)
Definition: PointConversion.h:354
ValueType get(Index n) const
Return the value at index n.
Definition: AttributeArray.h:1414
const PointIndexTreeType & mPointIndexTree
Definition: PointConversion.h:338