OpenVDB  7.0.0
ValueAccessor.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
30 
31 #ifndef OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
32 #define OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
33 
34 #include <boost/mpl/front.hpp>
35 #include <boost/mpl/pop_front.hpp>
36 #include <boost/mpl/push_back.hpp>
37 #include <boost/mpl/size.hpp>
38 #include <boost/mpl/at.hpp>
39 #include <boost/mpl/equal_to.hpp>
40 #include <boost/mpl/comparison.hpp>
41 #include <boost/mpl/vector.hpp>
42 #include <boost/mpl/assert.hpp>
43 #include <boost/mpl/erase.hpp>
44 #include <boost/mpl/find.hpp>
45 #include <tbb/null_mutex.h>
46 #include <tbb/spin_mutex.h>
47 #include <openvdb/version.h>
48 #include <openvdb/Types.h>
49 #include <cassert>
50 #include <limits>
51 #include <type_traits>
52 
53 namespace openvdb {
55 namespace OPENVDB_VERSION_NAME {
56 namespace tree {
57 
58 // Forward declarations of local classes that are not intended for general use
59 // The IsSafe template parameter is explained in the warning below.
60 template<typename TreeType, bool IsSafe = true>
62 template<typename TreeType, bool IsSafe = true, Index L0 = 0>
64 template<typename TreeType, bool IsSafe = true, Index L0 = 0, Index L1 = 1>
66 template<typename TreeType, bool IsSafe = true, Index L0 = 0, Index L1 = 1, Index L2 = 2>
68 template<typename TreeCacheT, typename NodeVecT, bool AtRoot> class CacheItem;
69 
70 
94 template<typename TreeType, bool IsSafe>
96 {
97 public:
98  static const bool IsConstTree = std::is_const<TreeType>::value;
99 
106  static bool isSafe() { return IsSafe; }
107 
108  ValueAccessorBase(TreeType& tree): mTree(&tree)
109  {
110  if (IsSafe) tree.attachAccessor(*this);
111  }
112 
113  virtual ~ValueAccessorBase() { if (IsSafe && mTree) mTree->releaseAccessor(*this); }
114 
119  TreeType* getTree() const { return mTree; }
121  TreeType& tree() const { assert(mTree); return *mTree; }
122 
123  ValueAccessorBase(const ValueAccessorBase& other): mTree(other.mTree)
124  {
125  if (IsSafe && mTree) mTree->attachAccessor(*this);
126  }
127 
129  {
130  if (&other != this) {
131  if (IsSafe && mTree) mTree->releaseAccessor(*this);
132  mTree = other.mTree;
133  if (IsSafe && mTree) mTree->attachAccessor(*this);
134  }
135  return *this;
136  }
137 
138  virtual void clear() = 0;
139 
140 protected:
141  // Allow trees to deregister themselves.
142  template<typename> friend class Tree;
143 
144  virtual void release() { mTree = nullptr; }
145 
146  TreeType* mTree;
147 }; // class ValueAccessorBase
148 
149 
151 
152 
189 template<typename _TreeType,
190  bool IsSafe = true,
191  Index CacheLevels = _TreeType::DEPTH-1,
192  typename MutexType = tbb::null_mutex>
193 class ValueAccessor: public ValueAccessorBase<_TreeType, IsSafe>
194 {
195 public:
196  static_assert(CacheLevels < _TreeType::DEPTH, "cache size exceeds tree depth");
197 
198  using TreeType = _TreeType;
199  using RootNodeT = typename TreeType::RootNodeType;
200  using LeafNodeT = typename TreeType::LeafNodeType;
201  using ValueType = typename RootNodeT::ValueType;
203  using LockT = typename MutexType::scoped_lock;
204  using BaseT::IsConstTree;
205 
206  ValueAccessor(TreeType& tree): BaseT(tree), mCache(*this)
207  {
208  mCache.insert(Coord(), &tree.root());
209  }
210 
211  ValueAccessor(const ValueAccessor& other): BaseT(other), mCache(*this, other.mCache) {}
212 
214  {
215  if (&other != this) {
216  this->BaseT::operator=(other);
217  mCache.copy(*this, other.mCache);
218  }
219  return *this;
220  }
221  ~ValueAccessor() override = default;
222 
224  static Index numCacheLevels() { return CacheLevels; }
225 
227  bool isCached(const Coord& xyz) const { LockT lock(mMutex); return mCache.isCached(xyz); }
228 
230  const ValueType& getValue(const Coord& xyz) const
231  {
232  LockT lock(mMutex);
233  return mCache.getValue(xyz);
234  }
235 
237  bool isValueOn(const Coord& xyz) const { LockT lock(mMutex); return mCache.isValueOn(xyz); }
238 
240  bool probeValue(const Coord& xyz, ValueType& value) const
241  {
242  LockT lock(mMutex);
243  return mCache.probeValue(xyz,value);
244  }
245 
249  int getValueDepth(const Coord& xyz) const
250  {
251  LockT lock(mMutex);
252  return mCache.getValueDepth(xyz);
253  }
254 
257  bool isVoxel(const Coord& xyz) const { LockT lock(mMutex); return mCache.isVoxel(xyz); }
258 
260  void setValue(const Coord& xyz, const ValueType& value)
262  {
263  LockT lock(mMutex);
264  mCache.setValue(xyz, value);
265  }
266  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
268 
270  void setValueOnly(const Coord& xyz, const ValueType& value)
271  {
272  LockT lock(mMutex);
273  mCache.setValueOnly(xyz, value);
274  }
275 
277  void setValueOff(const Coord& xyz, const ValueType& value)
278  {
279  LockT lock(mMutex);
280  mCache.setValueOff(xyz, value);
281  }
282 
286  template<typename ModifyOp>
287  void modifyValue(const Coord& xyz, const ModifyOp& op)
288  {
289  LockT lock(mMutex);
290  mCache.modifyValue(xyz, op);
291  }
292 
295  template<typename ModifyOp>
296  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
297  {
298  LockT lock(mMutex);
299  mCache.modifyValueAndActiveState(xyz, op);
300  }
301 
303  void setActiveState(const Coord& xyz, bool on = true)
304  {
305  LockT lock(mMutex);
306  mCache.setActiveState(xyz, on);
307  }
309  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
311  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
312 
314  template<typename NodeType>
315  NodeType* getNode()
316  {
317  LockT lock(mMutex);
318  NodeType* node = nullptr;
319  mCache.getNode(node);
320  return node;
321  }
322 
325  template<typename NodeType>
326  void insertNode(const Coord& xyz, NodeType& node)
327  {
328  LockT lock(mMutex);
329  mCache.insert(xyz, &node);
330  }
331 
335  template<typename NodeType>
336  void eraseNode() { LockT lock(mMutex); NodeType* node = nullptr; mCache.erase(node); }
337 
340  void addLeaf(LeafNodeT* leaf)
341  {
342  LockT lock(mMutex);
343  mCache.addLeaf(leaf);
344  }
345 
348  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
349  {
350  LockT lock(mMutex);
351  mCache.addTile(level, xyz, value, state);
352  }
353 
359  LeafNodeT* touchLeaf(const Coord& xyz)
360  {
361  LockT lock(mMutex);
362  return mCache.touchLeaf(xyz);
363  }
364 
366  template<typename NodeT>
369  NodeT* probeNode(const Coord& xyz)
370  {
371  LockT lock(mMutex);
372  return mCache.template probeNode<NodeT>(xyz);
373  }
374  template<typename NodeT>
375  const NodeT* probeConstNode(const Coord& xyz) const
376  {
377  LockT lock(mMutex);
378  return mCache.template probeConstNode<NodeT>(xyz);
379  }
380  template<typename NodeT>
381  const NodeT* probeNode(const Coord& xyz) const
382  {
383  return this->template probeConstNode<NodeT>(xyz);
384  }
386 
388  LeafNodeT* probeLeaf(const Coord& xyz)
391  {
392  LockT lock(mMutex);
393  return mCache.probeLeaf(xyz);
394  }
395  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
396  {
397  LockT lock(mMutex);
398  return mCache.probeConstLeaf(xyz);
399  }
400  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
402 
404  void clear() override
405  {
406  LockT lock(mMutex);
407  mCache.clear();
408  if (this->mTree) mCache.insert(Coord(), &(this->mTree->root()));
409  }
410 
411 private:
412  // Allow nodes to insert themselves into the cache.
413  template<typename> friend class RootNode;
414  template<typename, Index> friend class InternalNode;
415  template<typename, Index> friend class LeafNode;
416  // Allow trees to deregister themselves.
417  template<typename> friend class Tree;
418 
421  void release() override
422  {
423  LockT lock(mMutex);
424  this->BaseT::release();
425  mCache.clear();
426  }
427 
432  template<typename NodeType>
433  void insert(const Coord& xyz, NodeType* node) { mCache.insert(xyz, node); }
434 
435  // Define a list of all tree node types from LeafNode to RootNode
436  using InvTreeT = typename RootNodeT::NodeChainType;
437  // Remove all tree node types that are excluded from the cache
438  using BeginT = typename boost::mpl::begin<InvTreeT>::type;
439  using FirstT = typename boost::mpl::advance<BeginT, boost::mpl::int_<CacheLevels>>::type;
440  using LastT = typename boost::mpl::find<InvTreeT, RootNodeT>::type;
441  using SubtreeT = typename boost::mpl::erase<InvTreeT, FirstT, LastT>::type;
443 
444  // Private member data
445  mutable CacheItemT mCache;
446  mutable MutexType mMutex;
447 
448 }; // class ValueAccessor
449 
450 
454 template<typename TreeType, bool IsSafe>
455 class ValueAccessor<TreeType, IsSafe, 0, tbb::null_mutex>
456  : public ValueAccessor0<TreeType, IsSafe>
457 {
458 public:
459  ValueAccessor(TreeType& tree): ValueAccessor0<TreeType, IsSafe>(tree) {}
460  ValueAccessor(const ValueAccessor& other): ValueAccessor0<TreeType, IsSafe>(other) {}
461  ~ValueAccessor() override = default;
462 };
463 
464 
466 template<typename TreeType, bool IsSafe>
467 class ValueAccessor<TreeType, IsSafe, 1, tbb::null_mutex>
468  : public ValueAccessor1<TreeType, IsSafe>
469 {
470 public:
471  ValueAccessor(TreeType& tree): ValueAccessor1<TreeType, IsSafe>(tree) {}
472  ValueAccessor(const ValueAccessor& other): ValueAccessor1<TreeType, IsSafe>(other) {}
473  ~ValueAccessor() override = default;
474 };
475 
476 
478 template<typename TreeType, bool IsSafe>
479 class ValueAccessor<TreeType, IsSafe, 2, tbb::null_mutex>
480  : public ValueAccessor2<TreeType, IsSafe>
481 {
482 public:
483  ValueAccessor(TreeType& tree): ValueAccessor2<TreeType, IsSafe>(tree) {}
484  ValueAccessor(const ValueAccessor& other): ValueAccessor2<TreeType, IsSafe>(other) {}
485  ~ValueAccessor() override = default;
486 };
487 
488 
490 template<typename TreeType, bool IsSafe>
491 class ValueAccessor<TreeType, IsSafe, 3, tbb::null_mutex>: public ValueAccessor3<TreeType, IsSafe>
492 {
493 public:
494  ValueAccessor(TreeType& tree): ValueAccessor3<TreeType, IsSafe>(tree) {}
495  ValueAccessor(const ValueAccessor&) = default;
496  ValueAccessor& operator=(const ValueAccessor&) = default;
497  ~ValueAccessor() override = default;
498 };
499 
500 
502 
503 
512 template<typename TreeType, bool IsSafe = true>
513 class ValueAccessorRW: public ValueAccessor<TreeType, IsSafe, TreeType::DEPTH-1, tbb::spin_mutex>
514 {
515 public:
517  : ValueAccessor<TreeType, IsSafe, TreeType::DEPTH-1, tbb::spin_mutex>(tree)
518  {
519  }
520 };
521 
522 
524 
525 
526 //
527 // The classes below are for internal use and should rarely be used directly.
528 //
529 
530 // An element of a compile-time linked list of node pointers, ordered from LeafNode to RootNode
531 template<typename TreeCacheT, typename NodeVecT, bool AtRoot>
532 class CacheItem
533 {
534 public:
535  using NodeType = typename boost::mpl::front<NodeVecT>::type;
536  using ValueType = typename NodeType::ValueType;
537  using LeafNodeType = typename NodeType::LeafNodeType;
538  using CoordLimits = std::numeric_limits<Int32>;
539 
540  CacheItem(TreeCacheT& parent):
541  mParent(&parent),
542  mHash(CoordLimits::max()),
543  mNode(nullptr),
544  mNext(parent)
545  {
546  }
547 
549  CacheItem(TreeCacheT& parent, const CacheItem& other):
551  mParent(&parent),
552  mHash(other.mHash),
553  mNode(other.mNode),
554  mNext(parent, other.mNext)
555  {
556  }
557 
558  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
559  {
560  mParent = &parent;
561  mHash = other.mHash;
562  mNode = other.mNode;
563  mNext.copy(parent, other.mNext);
564  return *this;
565  }
567 
568  bool isCached(const Coord& xyz) const
569  {
570  return (this->isHashed(xyz) || mNext.isCached(xyz));
571  }
572 
574  void insert(const Coord& xyz, const NodeType* node)
575  {
576  mHash = (node != nullptr) ? xyz & ~(NodeType::DIM-1) : Coord::max();
577  mNode = node;
578  }
580  template<typename OtherNodeType>
581  void insert(const Coord& xyz, const OtherNodeType* node) { mNext.insert(xyz, node); }
582 
584  void erase(const NodeType*) { mHash = Coord::max(); mNode = nullptr; }
586  template<typename OtherNodeType>
587  void erase(const OtherNodeType* node) { mNext.erase(node); }
588 
590  void clear() { mHash = Coord::max(); mNode = nullptr; mNext.clear(); }
591 
593  void getNode(const NodeType*& node) const { node = mNode; }
594  void getNode(const NodeType*& node) { node = mNode; }
595  void getNode(NodeType*& node)
596  {
597  // This combination of a static assertion and a const_cast might not be elegant,
598  // but it is a lot simpler than specializing TreeCache for const Trees.
599  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
600  node = const_cast<NodeType*>(mNode);
601  }
603  template<typename OtherNodeType>
604  void getNode(OtherNodeType*& node) { mNext.getNode(node); }
605 
607  const ValueType& getValue(const Coord& xyz)
608  {
609  if (this->isHashed(xyz)) {
610  assert(mNode);
611  return mNode->getValueAndCache(xyz, *mParent);
612  }
613  return mNext.getValue(xyz);
614  }
615 
616  void addLeaf(LeafNodeType* leaf)
617  {
618  static_assert(!TreeCacheT::IsConstTree, "can't add a node to a const tree");
619  if (NodeType::LEVEL == 0) return;
620  if (this->isHashed(leaf->origin())) {
621  assert(mNode);
622  return const_cast<NodeType*>(mNode)->addLeafAndCache(leaf, *mParent);
623  }
624  mNext.addLeaf(leaf);
625  }
626 
627  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
628  {
629  static_assert(!TreeCacheT::IsConstTree, "can't add a tile to a const tree");
630  if (NodeType::LEVEL < level) return;
631  if (this->isHashed(xyz)) {
632  assert(mNode);
633  return const_cast<NodeType*>(mNode)->addTileAndCache(
634  level, xyz, value, state, *mParent);
635  }
636  mNext.addTile(level, xyz, value, state);
637  }
638 
639  LeafNodeType* touchLeaf(const Coord& xyz)
640  {
641  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
642  if (this->isHashed(xyz)) {
643  assert(mNode);
644  return const_cast<NodeType*>(mNode)->touchLeafAndCache(xyz, *mParent);
645  }
646  return mNext.touchLeaf(xyz);
647  }
648 
649  LeafNodeType* probeLeaf(const Coord& xyz)
650  {
651  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
652  if (this->isHashed(xyz)) {
653  assert(mNode);
654  return const_cast<NodeType*>(mNode)->probeLeafAndCache(xyz, *mParent);
655  }
656  return mNext.probeLeaf(xyz);
657  }
658 
659  const LeafNodeType* probeConstLeaf(const Coord& xyz)
660  {
661  if (this->isHashed(xyz)) {
662  assert(mNode);
663  return mNode->probeConstLeafAndCache(xyz, *mParent);
664  }
665  return mNext.probeConstLeaf(xyz);
666  }
667 
668  template<typename NodeT>
669  NodeT* probeNode(const Coord& xyz)
670  {
671  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
673  if (this->isHashed(xyz)) {
674  if ((std::is_same<NodeT, NodeType>::value)) {
675  assert(mNode);
676  return reinterpret_cast<NodeT*>(const_cast<NodeType*>(mNode));
677  }
678  return const_cast<NodeType*>(mNode)->template probeNodeAndCache<NodeT>(xyz, *mParent);
679  }
680  return mNext.template probeNode<NodeT>(xyz);
682  }
683 
684  template<typename NodeT>
685  const NodeT* probeConstNode(const Coord& xyz)
686  {
688  if (this->isHashed(xyz)) {
689  if ((std::is_same<NodeT, NodeType>::value)) {
690  assert(mNode);
691  return reinterpret_cast<const NodeT*>(mNode);
692  }
693  return mNode->template probeConstNodeAndCache<NodeT>(xyz, *mParent);
694  }
695  return mNext.template probeConstNode<NodeT>(xyz);
697  }
698 
700  bool isValueOn(const Coord& xyz)
701  {
702  if (this->isHashed(xyz)) {
703  assert(mNode);
704  return mNode->isValueOnAndCache(xyz, *mParent);
705  }
706  return mNext.isValueOn(xyz);
707  }
708 
710  bool probeValue(const Coord& xyz, ValueType& value)
711  {
712  if (this->isHashed(xyz)) {
713  assert(mNode);
714  return mNode->probeValueAndCache(xyz, value, *mParent);
715  }
716  return mNext.probeValue(xyz, value);
717  }
718 
719  int getValueDepth(const Coord& xyz)
720  {
721  if (this->isHashed(xyz)) {
722  assert(mNode);
723  return static_cast<int>(TreeCacheT::RootNodeT::LEVEL) -
724  static_cast<int>(mNode->getValueLevelAndCache(xyz, *mParent));
725  } else {
726  return mNext.getValueDepth(xyz);
727  }
728  }
729 
730  bool isVoxel(const Coord& xyz)
731  {
732  if (this->isHashed(xyz)) {
733  assert(mNode);
734  return mNode->getValueLevelAndCache(xyz, *mParent)==0;
735  } else {
736  return mNext.isVoxel(xyz);
737  }
738  }
739 
741  void setValue(const Coord& xyz, const ValueType& value)
742  {
743  if (this->isHashed(xyz)) {
744  assert(mNode);
745  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
746  const_cast<NodeType*>(mNode)->setValueAndCache(xyz, value, *mParent);
747  } else {
748  mNext.setValue(xyz, value);
749  }
750  }
751  void setValueOnly(const Coord& xyz, const ValueType& value)
752  {
753  if (this->isHashed(xyz)) {
754  assert(mNode);
755  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
756  const_cast<NodeType*>(mNode)->setValueOnlyAndCache(xyz, value, *mParent);
757  } else {
758  mNext.setValueOnly(xyz, value);
759  }
760  }
761  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
762 
766  template<typename ModifyOp>
767  void modifyValue(const Coord& xyz, const ModifyOp& op)
768  {
769  if (this->isHashed(xyz)) {
770  assert(mNode);
771  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
772  const_cast<NodeType*>(mNode)->modifyValueAndCache(xyz, op, *mParent);
773  } else {
774  mNext.modifyValue(xyz, op);
775  }
776  }
777 
780  template<typename ModifyOp>
781  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
782  {
783  if (this->isHashed(xyz)) {
784  assert(mNode);
785  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
786  const_cast<NodeType*>(mNode)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
787  } else {
788  mNext.modifyValueAndActiveState(xyz, op);
789  }
790  }
791 
793  void setValueOff(const Coord& xyz, const ValueType& value)
794  {
795  if (this->isHashed(xyz)) {
796  assert(mNode);
797  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
798  const_cast<NodeType*>(mNode)->setValueOffAndCache(xyz, value, *mParent);
799  } else {
800  mNext.setValueOff(xyz, value);
801  }
802  }
803 
805  void setActiveState(const Coord& xyz, bool on)
806  {
807  if (this->isHashed(xyz)) {
808  assert(mNode);
809  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
810  const_cast<NodeType*>(mNode)->setActiveStateAndCache(xyz, on, *mParent);
811  } else {
812  mNext.setActiveState(xyz, on);
813  }
814  }
815 
816 private:
817  CacheItem(const CacheItem&);
818  CacheItem& operator=(const CacheItem&);
819 
820  bool isHashed(const Coord& xyz) const
821  {
822  return (xyz[0] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[0]
823  && (xyz[1] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[1]
824  && (xyz[2] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[2];
825  }
826 
827  TreeCacheT* mParent;
828  Coord mHash;
829  const NodeType* mNode;
830  using RestT = typename boost::mpl::pop_front<NodeVecT>::type; // NodeVecT minus its first item
831  CacheItem<TreeCacheT, RestT, /*AtRoot=*/boost::mpl::size<RestT>::value == 1> mNext;
832 };// end of CacheItem
833 
834 
836 template<typename TreeCacheT, typename NodeVecT>
837 class CacheItem<TreeCacheT, NodeVecT, /*AtRoot=*/true>
838 {
839 public:
840  using RootNodeType = typename boost::mpl::front<NodeVecT>::type;
841  using ValueType = typename RootNodeType::ValueType;
842  using LeafNodeType = typename RootNodeType::LeafNodeType;
843 
844  CacheItem(TreeCacheT& parent): mParent(&parent), mRoot(nullptr) {}
845  CacheItem(TreeCacheT& parent, const CacheItem& other): mParent(&parent), mRoot(other.mRoot) {}
846 
847  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
848  {
849  mParent = &parent;
850  mRoot = other.mRoot;
851  return *this;
852  }
853 
854  bool isCached(const Coord& xyz) const { return this->isHashed(xyz); }
855 
856  void insert(const Coord&, const RootNodeType* root) { mRoot = root; }
857 
858  // Needed for node types that are not cached
859  template<typename OtherNodeType>
860  void insert(const Coord&, const OtherNodeType*) {}
861 
862  void erase(const RootNodeType*) { mRoot = nullptr; }
863 
864  void clear() { mRoot = nullptr; }
865 
866  void getNode(RootNodeType*& node)
867  {
868  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
869  node = const_cast<RootNodeType*>(mRoot);
870  }
871  void getNode(const RootNodeType*& node) const { node = mRoot; }
872 
873  void addLeaf(LeafNodeType* leaf)
874  {
875  assert(mRoot);
876  static_assert(!TreeCacheT::IsConstTree, "can't add a node to a const tree");
877  const_cast<RootNodeType*>(mRoot)->addLeafAndCache(leaf, *mParent);
878  }
879 
880  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
881  {
882  assert(mRoot);
883  static_assert(!TreeCacheT::IsConstTree, "can't add a tile to a const tree");
884  const_cast<RootNodeType*>(mRoot)->addTileAndCache(level, xyz, value, state, *mParent);
885  }
886 
887  LeafNodeType* touchLeaf(const Coord& xyz)
888  {
889  assert(mRoot);
890  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
891  return const_cast<RootNodeType*>(mRoot)->touchLeafAndCache(xyz, *mParent);
892  }
893 
894  LeafNodeType* probeLeaf(const Coord& xyz)
895  {
896  assert(mRoot);
897  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
898  return const_cast<RootNodeType*>(mRoot)->probeLeafAndCache(xyz, *mParent);
899  }
900 
901  const LeafNodeType* probeConstLeaf(const Coord& xyz)
902  {
903  assert(mRoot);
904  return mRoot->probeConstLeafAndCache(xyz, *mParent);
905  }
906 
907  template<typename NodeType>
908  NodeType* probeNode(const Coord& xyz)
909  {
910  assert(mRoot);
911  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
912  return const_cast<RootNodeType*>(mRoot)->
913  template probeNodeAndCache<NodeType>(xyz, *mParent);
914  }
915 
916  template<typename NodeType>
917  const NodeType* probeConstNode(const Coord& xyz)
918  {
919  assert(mRoot);
920  return mRoot->template probeConstNodeAndCache<NodeType>(xyz, *mParent);
921  }
922 
923  int getValueDepth(const Coord& xyz)
924  {
925  assert(mRoot);
926  return mRoot->getValueDepthAndCache(xyz, *mParent);
927  }
928  bool isValueOn(const Coord& xyz)
929  {
930  assert(mRoot);
931  return mRoot->isValueOnAndCache(xyz, *mParent);
932  }
933 
934  bool probeValue(const Coord& xyz, ValueType& value)
935  {
936  assert(mRoot);
937  return mRoot->probeValueAndCache(xyz, value, *mParent);
938  }
939  bool isVoxel(const Coord& xyz)
940  {
941  assert(mRoot);
942  return mRoot->getValueDepthAndCache(xyz, *mParent) ==
943  static_cast<int>(RootNodeType::LEVEL);
944  }
945  const ValueType& getValue(const Coord& xyz)
946  {
947  assert(mRoot);
948  return mRoot->getValueAndCache(xyz, *mParent);
949  }
950 
951  void setValue(const Coord& xyz, const ValueType& value)
952  {
953  assert(mRoot);
954  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
955  const_cast<RootNodeType*>(mRoot)->setValueAndCache(xyz, value, *mParent);
956  }
957  void setValueOnly(const Coord& xyz, const ValueType& value)
958  {
959  assert(mRoot);
960  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
961  const_cast<RootNodeType*>(mRoot)->setValueOnlyAndCache(xyz, value, *mParent);
962  }
963  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
964 
965  template<typename ModifyOp>
966  void modifyValue(const Coord& xyz, const ModifyOp& op)
967  {
968  assert(mRoot);
969  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
970  const_cast<RootNodeType*>(mRoot)->modifyValueAndCache(xyz, op, *mParent);
971  }
972 
973  template<typename ModifyOp>
974  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
975  {
976  assert(mRoot);
977  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
978  const_cast<RootNodeType*>(mRoot)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
979  }
980 
981  void setValueOff(const Coord& xyz, const ValueType& value)
982  {
983  assert(mRoot);
984  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
985  const_cast<RootNodeType*>(mRoot)->setValueOffAndCache(xyz, value, *mParent);
986  }
987 
988  void setActiveState(const Coord& xyz, bool on)
989  {
990  assert(mRoot);
991  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
992  const_cast<RootNodeType*>(mRoot)->setActiveStateAndCache(xyz, on, *mParent);
993  }
994 
995 private:
996  CacheItem(const CacheItem&);
997  CacheItem& operator=(const CacheItem&);
998 
999  bool isHashed(const Coord&) const { return false; }
1000 
1001  TreeCacheT* mParent;
1002  const RootNodeType* mRoot;
1003 };// end of CacheItem specialized for RootNode
1004 
1005 
1007 
1008 
1012 template<typename _TreeType, bool IsSafe>
1013 class ValueAccessor0: public ValueAccessorBase<_TreeType, IsSafe>
1014 {
1015 public:
1016  using TreeType = _TreeType;
1017  using ValueType = typename TreeType::ValueType;
1018  using RootNodeT = typename TreeType::RootNodeType;
1019  using LeafNodeT = typename TreeType::LeafNodeType;
1021 
1022  ValueAccessor0(TreeType& tree): BaseT(tree) {}
1023 
1024  ValueAccessor0(const ValueAccessor0& other): BaseT(other) {}
1025 
1027  static Index numCacheLevels() { return 0; }
1028 
1030  {
1031  if (&other != this) this->BaseT::operator=(other);
1032  return *this;
1033  }
1034 
1035  ~ValueAccessor0() override = default;
1036 
1038  bool isCached(const Coord&) const { return false; }
1039 
1041  const ValueType& getValue(const Coord& xyz) const
1042  {
1043  assert(BaseT::mTree);
1044  return BaseT::mTree->getValue(xyz);
1045  }
1046 
1048  bool isValueOn(const Coord& xyz) const
1049  {
1050  assert(BaseT::mTree);
1051  return BaseT::mTree->isValueOn(xyz);
1052  }
1053 
1055  bool probeValue(const Coord& xyz, ValueType& value) const
1056  {
1057  assert(BaseT::mTree);
1058  return BaseT::mTree->probeValue(xyz, value);
1059  }
1060 
1064  int getValueDepth(const Coord& xyz) const
1065  {
1066  assert(BaseT::mTree);
1067  return BaseT::mTree->getValueDepth(xyz);
1068  }
1069 
1072  bool isVoxel(const Coord& xyz) const
1073  {
1074  assert(BaseT::mTree);
1075  return BaseT::mTree->getValueDepth(xyz) == static_cast<int>(RootNodeT::LEVEL);
1076  }
1077 
1079  void setValue(const Coord& xyz, const ValueType& value)
1081  {
1082  assert(BaseT::mTree);
1083  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1084  BaseT::mTree->setValue(xyz, value);
1085  }
1086  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1088 
1090  void setValueOnly(const Coord& xyz, const ValueType& value)
1091  {
1092  assert(BaseT::mTree);
1093  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1094  BaseT::mTree->setValueOnly(xyz, value);
1095  }
1096 
1098  void setValueOff(const Coord& xyz, const ValueType& value)
1099  {
1100  assert(BaseT::mTree);
1101  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1102  BaseT::mTree->root().setValueOff(xyz, value);
1103  }
1104 
1108  template<typename ModifyOp>
1109  void modifyValue(const Coord& xyz, const ModifyOp& op)
1110  {
1111  assert(BaseT::mTree);
1112  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1113  BaseT::mTree->modifyValue(xyz, op);
1114  }
1115 
1118  template<typename ModifyOp>
1119  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1120  {
1121  assert(BaseT::mTree);
1122  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1123  BaseT::mTree->modifyValueAndActiveState(xyz, op);
1124  }
1125 
1127  void setActiveState(const Coord& xyz, bool on = true)
1128  {
1129  assert(BaseT::mTree);
1130  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1131  BaseT::mTree->setActiveState(xyz, on);
1132  }
1134  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1136  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1137 
1139  template<typename NodeT> NodeT* getNode() { return nullptr; }
1140 
1143  template<typename NodeT> void insertNode(const Coord&, NodeT&) {}
1144 
1147  void addLeaf(LeafNodeT* leaf)
1148  {
1149  assert(BaseT::mTree);
1150  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
1151  BaseT::mTree->root().addLeaf(leaf);
1152  }
1153 
1156  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1157  {
1158  assert(BaseT::mTree);
1159  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
1160  BaseT::mTree->root().addTile(level, xyz, value, state);
1161  }
1162 
1166  template<typename NodeT> void eraseNode() {}
1167 
1168  LeafNodeT* touchLeaf(const Coord& xyz)
1169  {
1170  assert(BaseT::mTree);
1171  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1172  return BaseT::mTree->touchLeaf(xyz);
1173  }
1174 
1175  template<typename NodeT>
1176  NodeT* probeNode(const Coord& xyz)
1177  {
1178  assert(BaseT::mTree);
1179  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1180  return BaseT::mTree->template probeNode<NodeT>(xyz);
1181  }
1182 
1183  template<typename NodeT>
1184  const NodeT* probeConstNode(const Coord& xyz) const
1185  {
1186  assert(BaseT::mTree);
1187  return BaseT::mTree->template probeConstNode<NodeT>(xyz);
1188  }
1189 
1190  LeafNodeT* probeLeaf(const Coord& xyz)
1191  {
1192  return this->template probeNode<LeafNodeT>(xyz);
1193  }
1194 
1195  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1196  {
1197  return this->template probeConstNode<LeafNodeT>(xyz);
1198  }
1199 
1200  const LeafNodeT* probeLeaf(const Coord& xyz) const
1201  {
1202  return this->probeConstLeaf(xyz);
1203  }
1204 
1206  void clear() override {}
1207 
1208 private:
1209  // Allow trees to deregister themselves.
1210  template<typename> friend class Tree;
1211 
1214  void release() override { this->BaseT::release(); }
1215 
1216 }; // ValueAccessor0
1217 
1218 
1225 template<typename _TreeType, bool IsSafe, Index L0>
1227 {
1228 public:
1229  static_assert(_TreeType::DEPTH >= 2, "cache size exceeds tree depth");
1230  static_assert(L0 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
1231  using TreeType = _TreeType;
1232  using ValueType = typename TreeType::ValueType;
1233  using RootNodeT = typename TreeType::RootNodeType;
1234  using LeafNodeT = typename TreeType::LeafNodeType;
1236  using InvTreeT = typename RootNodeT::NodeChainType;
1237  using NodeT0 = typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type;
1238 
1240  ValueAccessor1(TreeType& tree) : BaseT(tree), mKey0(Coord::max()), mNode0(nullptr)
1241  {
1242  }
1243 
1245  ValueAccessor1(const ValueAccessor1& other) : BaseT(other) { this->copy(other); }
1246 
1248  static Index numCacheLevels() { return 1; }
1249 
1252  {
1253  if (&other != this) {
1254  this->BaseT::operator=(other);
1255  this->copy(other);
1256  }
1257  return *this;
1258  }
1259 
1261  ~ValueAccessor1() override = default;
1262 
1265  bool isCached(const Coord& xyz) const
1266  {
1267  assert(BaseT::mTree);
1268  return this->isHashed(xyz);
1269  }
1270 
1272  const ValueType& getValue(const Coord& xyz) const
1273  {
1274  assert(BaseT::mTree);
1275  if (this->isHashed(xyz)) {
1276  assert(mNode0);
1277  return mNode0->getValueAndCache(xyz, this->self());
1278  }
1279  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
1280  }
1281 
1283  bool isValueOn(const Coord& xyz) const
1284  {
1285  assert(BaseT::mTree);
1286  if (this->isHashed(xyz)) {
1287  assert(mNode0);
1288  return mNode0->isValueOnAndCache(xyz, this->self());
1289  }
1290  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
1291  }
1292 
1294  bool probeValue(const Coord& xyz, ValueType& value) const
1295  {
1296  assert(BaseT::mTree);
1297  if (this->isHashed(xyz)) {
1298  assert(mNode0);
1299  return mNode0->probeValueAndCache(xyz, value, this->self());
1300  }
1301  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
1302  }
1303 
1307  int getValueDepth(const Coord& xyz) const
1308  {
1309  assert(BaseT::mTree);
1310  if (this->isHashed(xyz)) {
1311  assert(mNode0);
1312  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1313  }
1314  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
1315  }
1316 
1319  bool isVoxel(const Coord& xyz) const
1320  {
1321  assert(BaseT::mTree);
1322  if (this->isHashed(xyz)) {
1323  assert(mNode0);
1324  return mNode0->getValueLevelAndCache(xyz, this->self()) == 0;
1325  }
1326  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
1327  static_cast<int>(RootNodeT::LEVEL);
1328  }
1329 
1331  void setValue(const Coord& xyz, const ValueType& value)
1333  {
1334  assert(BaseT::mTree);
1335  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1336  if (this->isHashed(xyz)) {
1337  assert(mNode0);
1338  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1339  } else {
1340  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
1341  }
1342  }
1343  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1345 
1347  void setValueOnly(const Coord& xyz, const ValueType& value)
1348  {
1349  assert(BaseT::mTree);
1350  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1351  if (this->isHashed(xyz)) {
1352  assert(mNode0);
1353  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1354  } else {
1355  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
1356  }
1357  }
1358 
1360  void setValueOff(const Coord& xyz, const ValueType& value)
1361  {
1362  assert(BaseT::mTree);
1363  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1364  if (this->isHashed(xyz)) {
1365  assert(mNode0);
1366  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1367  } else {
1368  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
1369  }
1370  }
1371 
1375  template<typename ModifyOp>
1376  void modifyValue(const Coord& xyz, const ModifyOp& op)
1377  {
1378  assert(BaseT::mTree);
1379  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1380  if (this->isHashed(xyz)) {
1381  assert(mNode0);
1382  const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
1383  } else {
1384  BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
1385  }
1386  }
1387 
1390  template<typename ModifyOp>
1391  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1392  {
1393  assert(BaseT::mTree);
1394  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1395  if (this->isHashed(xyz)) {
1396  assert(mNode0);
1397  const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
1398  } else {
1399  BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
1400  }
1401  }
1402 
1404  void setActiveState(const Coord& xyz, bool on = true)
1405  {
1406  assert(BaseT::mTree);
1407  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1408  if (this->isHashed(xyz)) {
1409  assert(mNode0);
1410  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1411  } else {
1412  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
1413  }
1414  }
1416  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1418  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1419 
1421  template<typename NodeT>
1422  NodeT* getNode()
1423  {
1424  const NodeT* node = nullptr;
1425  this->getNode(node);
1426  return const_cast<NodeT*>(node);
1427  }
1428 
1431  template<typename NodeT>
1432  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1433 
1437  template<typename NodeT>
1438  void eraseNode()
1439  {
1440  const NodeT* node = nullptr;
1441  this->eraseNode(node);
1442  }
1443 
1446  void addLeaf(LeafNodeT* leaf)
1447  {
1448  assert(BaseT::mTree);
1449  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
1450  BaseT::mTree->root().addLeaf(leaf);
1451  }
1452 
1455  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1456  {
1457  assert(BaseT::mTree);
1458  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
1459  BaseT::mTree->root().addTile(level, xyz, value, state);
1460  }
1461 
1468  LeafNodeT* touchLeaf(const Coord& xyz)
1469  {
1470  assert(BaseT::mTree);
1471  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1472  if (this->isHashed(xyz)) {
1473  assert(mNode0);
1474  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1475  }
1476  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
1477  }
1478 
1481  template<typename NodeT>
1482  NodeT* probeNode(const Coord& xyz)
1483  {
1484  assert(BaseT::mTree);
1485  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1487  if ((std::is_same<NodeT, NodeT0>::value)) {
1488  if (this->isHashed(xyz)) {
1489  assert(mNode0);
1490  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
1491  }
1492  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1493  }
1494  return nullptr;
1496  }
1497  LeafNodeT* probeLeaf(const Coord& xyz)
1498  {
1499  return this->template probeNode<LeafNodeT>(xyz);
1500  }
1501 
1504  template<typename NodeT>
1505  const NodeT* probeConstNode(const Coord& xyz) const
1506  {
1507  assert(BaseT::mTree);
1509  if ((std::is_same<NodeT, NodeT0>::value)) {
1510  if (this->isHashed(xyz)) {
1511  assert(mNode0);
1512  return reinterpret_cast<const NodeT*>(mNode0);
1513  }
1514  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1515  }
1516  return nullptr;
1518  }
1519  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1520  {
1521  return this->template probeConstNode<LeafNodeT>(xyz);
1522  }
1523  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
1524 
1526  void clear() override
1527  {
1528  mKey0 = Coord::max();
1529  mNode0 = nullptr;
1530  }
1531 
1532 private:
1533  // Allow nodes to insert themselves into the cache.
1534  template<typename> friend class RootNode;
1535  template<typename, Index> friend class InternalNode;
1536  template<typename, Index> friend class LeafNode;
1537  // Allow trees to deregister themselves.
1538  template<typename> friend class Tree;
1539 
1540  // This private method is merely for convenience.
1541  inline ValueAccessor1& self() const { return const_cast<ValueAccessor1&>(*this); }
1542 
1543  void getNode(const NodeT0*& node) { node = mNode0; }
1544  void getNode(const RootNodeT*& node)
1545  {
1546  node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
1547  }
1548  template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
1549  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = nullptr; }
1550  template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1551 
1553  inline void copy(const ValueAccessor1& other)
1554  {
1555  mKey0 = other.mKey0;
1556  mNode0 = other.mNode0;
1557  }
1558 
1561  void release() override
1562  {
1563  this->BaseT::release();
1564  this->clear();
1565  }
1570  inline void insert(const Coord& xyz, const NodeT0* node)
1571  {
1572  assert(node);
1573  mKey0 = xyz & ~(NodeT0::DIM-1);
1574  mNode0 = node;
1575  }
1576 
1579  template<typename OtherNodeType> inline void insert(const Coord&, const OtherNodeType*) {}
1580 
1581  inline bool isHashed(const Coord& xyz) const
1582  {
1583  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1584  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1585  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1586  }
1587  mutable Coord mKey0;
1588  mutable const NodeT0* mNode0;
1589 }; // ValueAccessor1
1590 
1591 
1599 template<typename _TreeType, bool IsSafe, Index L0, Index L1>
1601 {
1602 public:
1603  static_assert(_TreeType::DEPTH >= 3, "cache size exceeds tree depth");
1604  static_assert(L0 < L1, "invalid cache level");
1605  static_assert(L1 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
1606 
1607  using TreeType = _TreeType;
1608  using ValueType = typename TreeType::ValueType;
1609  using RootNodeT = typename TreeType::RootNodeType;
1610  using LeafNodeT = typename TreeType::LeafNodeType;
1612  using InvTreeT = typename RootNodeT::NodeChainType;
1613  using NodeT0 = typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0>>::type;
1614  using NodeT1 = typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1>>::type;
1615 
1618  mKey0(Coord::max()), mNode0(nullptr),
1619  mKey1(Coord::max()), mNode1(nullptr) {}
1620 
1622  ValueAccessor2(const ValueAccessor2& other) : BaseT(other) { this->copy(other); }
1623 
1625  static Index numCacheLevels() { return 2; }
1626 
1629  {
1630  if (&other != this) {
1631  this->BaseT::operator=(other);
1632  this->copy(other);
1633  }
1634  return *this;
1635  }
1636 
1638  ~ValueAccessor2() override = default;
1639 
1642  bool isCached(const Coord& xyz) const
1643  {
1644  assert(BaseT::mTree);
1645  return this->isHashed1(xyz) || this->isHashed0(xyz);
1646  }
1647 
1649  const ValueType& getValue(const Coord& xyz) const
1650  {
1651  assert(BaseT::mTree);
1652  if (this->isHashed0(xyz)) {
1653  assert(mNode0);
1654  return mNode0->getValueAndCache(xyz, this->self());
1655  } else if (this->isHashed1(xyz)) {
1656  assert(mNode1);
1657  return mNode1->getValueAndCache(xyz, this->self());
1658  }
1659  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
1660  }
1661 
1663  bool isValueOn(const Coord& xyz) const
1664  {
1665  assert(BaseT::mTree);
1666  if (this->isHashed0(xyz)) {
1667  assert(mNode0);
1668  return mNode0->isValueOnAndCache(xyz, this->self());
1669  } else if (this->isHashed1(xyz)) {
1670  assert(mNode1);
1671  return mNode1->isValueOnAndCache(xyz, this->self());
1672  }
1673  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
1674  }
1675 
1677  bool probeValue(const Coord& xyz, ValueType& value) const
1678  {
1679  assert(BaseT::mTree);
1680  if (this->isHashed0(xyz)) {
1681  assert(mNode0);
1682  return mNode0->probeValueAndCache(xyz, value, this->self());
1683  } else if (this->isHashed1(xyz)) {
1684  assert(mNode1);
1685  return mNode1->probeValueAndCache(xyz, value, this->self());
1686  }
1687  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
1688  }
1689 
1693  int getValueDepth(const Coord& xyz) const
1694  {
1695  assert(BaseT::mTree);
1696  if (this->isHashed0(xyz)) {
1697  assert(mNode0);
1698  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1699  } else if (this->isHashed1(xyz)) {
1700  assert(mNode1);
1701  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
1702  }
1703  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
1704  }
1705 
1708  bool isVoxel(const Coord& xyz) const
1709  {
1710  assert(BaseT::mTree);
1711  if (this->isHashed0(xyz)) {
1712  assert(mNode0);
1713  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
1714  } else if (this->isHashed1(xyz)) {
1715  assert(mNode1);
1716  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
1717  }
1718  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
1719  static_cast<int>(RootNodeT::LEVEL);
1720  }
1721 
1723  void setValue(const Coord& xyz, const ValueType& value)
1725  {
1726  assert(BaseT::mTree);
1727  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1728  if (this->isHashed0(xyz)) {
1729  assert(mNode0);
1730  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1731  } else if (this->isHashed1(xyz)) {
1732  assert(mNode1);
1733  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
1734  } else {
1735  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
1736  }
1737  }
1738  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1740 
1742  void setValueOnly(const Coord& xyz, const ValueType& value)
1743  {
1744  assert(BaseT::mTree);
1745  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1746  if (this->isHashed0(xyz)) {
1747  assert(mNode0);
1748  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1749  } else if (this->isHashed1(xyz)) {
1750  assert(mNode1);
1751  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
1752  } else {
1753  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
1754  }
1755  }
1756 
1758  void setValueOff(const Coord& xyz, const ValueType& value)
1759  {
1760  assert(BaseT::mTree);
1761  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1762  if (this->isHashed0(xyz)) {
1763  assert(mNode0);
1764  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1765  } else if (this->isHashed1(xyz)) {
1766  assert(mNode1);
1767  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
1768  } else {
1769  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
1770  }
1771  }
1772 
1776  template<typename ModifyOp>
1777  void modifyValue(const Coord& xyz, const ModifyOp& op)
1778  {
1779  assert(BaseT::mTree);
1780  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1781  if (this->isHashed0(xyz)) {
1782  assert(mNode0);
1783  const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
1784  } else if (this->isHashed1(xyz)) {
1785  assert(mNode1);
1786  const_cast<NodeT1*>(mNode1)->modifyValueAndCache(xyz, op, *this);
1787  } else {
1788  BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
1789  }
1790  }
1791 
1794  template<typename ModifyOp>
1795  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1796  {
1797  assert(BaseT::mTree);
1798  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1799  if (this->isHashed0(xyz)) {
1800  assert(mNode0);
1801  const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
1802  } else if (this->isHashed1(xyz)) {
1803  assert(mNode1);
1804  const_cast<NodeT1*>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *this);
1805  } else {
1806  BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
1807  }
1808  }
1809 
1811  void setActiveState(const Coord& xyz, bool on = true)
1812  {
1813  assert(BaseT::mTree);
1814  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1815  if (this->isHashed0(xyz)) {
1816  assert(mNode0);
1817  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1818  } else if (this->isHashed1(xyz)) {
1819  assert(mNode1);
1820  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
1821  } else {
1822  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
1823  }
1824  }
1826  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1828  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1829 
1831  template<typename NodeT>
1832  NodeT* getNode()
1833  {
1834  const NodeT* node = nullptr;
1835  this->getNode(node);
1836  return const_cast<NodeT*>(node);
1837  }
1838 
1841  template<typename NodeT>
1842  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1843 
1847  template<typename NodeT>
1848  void eraseNode()
1849  {
1850  const NodeT* node = nullptr;
1851  this->eraseNode(node);
1852  }
1853 
1856  void addLeaf(LeafNodeT* leaf)
1857  {
1858  assert(BaseT::mTree);
1859  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
1860  if (this->isHashed1(leaf->origin())) {
1861  assert(mNode1);
1862  return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
1863  }
1864  BaseT::mTree->root().addLeafAndCache(leaf, *this);
1865  }
1866 
1869  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1870  {
1871  assert(BaseT::mTree);
1872  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
1873  if (this->isHashed1(xyz)) {
1874  assert(mNode1);
1875  return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
1876  }
1877  BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
1878  }
1879 
1886  LeafNodeT* touchLeaf(const Coord& xyz)
1887  {
1888  assert(BaseT::mTree);
1889  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1890  if (this->isHashed0(xyz)) {
1891  assert(mNode0);
1892  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1893  } else if (this->isHashed1(xyz)) {
1894  assert(mNode1);
1895  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
1896  }
1897  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
1898  }
1901  template<typename NodeT>
1902  NodeT* probeNode(const Coord& xyz)
1903  {
1904  assert(BaseT::mTree);
1905  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1907  if ((std::is_same<NodeT, NodeT0>::value)) {
1908  if (this->isHashed0(xyz)) {
1909  assert(mNode0);
1910  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
1911  } else if (this->isHashed1(xyz)) {
1912  assert(mNode1);
1913  return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
1914  }
1915  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1916  } else if ((std::is_same<NodeT, NodeT1>::value)) {
1917  if (this->isHashed1(xyz)) {
1918  assert(mNode1);
1919  return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
1920  }
1921  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1922  }
1923  return nullptr;
1925  }
1928  LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
1929 
1932  template<typename NodeT>
1933  const NodeT* probeConstLeaf(const Coord& xyz) const
1934  {
1936  if ((std::is_same<NodeT, NodeT0>::value)) {
1937  if (this->isHashed0(xyz)) {
1938  assert(mNode0);
1939  return reinterpret_cast<const NodeT*>(mNode0);
1940  } else if (this->isHashed1(xyz)) {
1941  assert(mNode1);
1942  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
1943  }
1944  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1945  } else if ((std::is_same<NodeT, NodeT1>::value)) {
1946  if (this->isHashed1(xyz)) {
1947  assert(mNode1);
1948  return reinterpret_cast<const NodeT*>(mNode1);
1949  }
1950  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1951  }
1952  return nullptr;
1954  }
1957  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1958  {
1959  return this->template probeConstNode<LeafNodeT>(xyz);
1960  }
1961  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
1962 
1965  template<typename NodeT>
1966  const NodeT* probeConstNode(const Coord& xyz) const
1967  {
1968  assert(BaseT::mTree);
1970  if ((std::is_same<NodeT, NodeT0>::value)) {
1971  if (this->isHashed0(xyz)) {
1972  assert(mNode0);
1973  return reinterpret_cast<const NodeT*>(mNode0);
1974  } else if (this->isHashed1(xyz)) {
1975  assert(mNode1);
1976  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
1977  }
1978  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1979  } else if ((std::is_same<NodeT, NodeT1>::value)) {
1980  if (this->isHashed1(xyz)) {
1981  assert(mNode1);
1982  return reinterpret_cast<const NodeT*>(mNode1);
1983  }
1984  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1985  }
1986  return nullptr;
1988  }
1989 
1991  void clear() override
1992  {
1993  mKey0 = Coord::max();
1994  mNode0 = nullptr;
1995  mKey1 = Coord::max();
1996  mNode1 = nullptr;
1997  }
1998 
1999 private:
2000  // Allow nodes to insert themselves into the cache.
2001  template<typename> friend class RootNode;
2002  template<typename, Index> friend class InternalNode;
2003  template<typename, Index> friend class LeafNode;
2004  // Allow trees to deregister themselves.
2005  template<typename> friend class Tree;
2006 
2007  // This private method is merely for convenience.
2008  inline ValueAccessor2& self() const { return const_cast<ValueAccessor2&>(*this); }
2009 
2010  void getNode(const NodeT0*& node) { node = mNode0; }
2011  void getNode(const NodeT1*& node) { node = mNode1; }
2012  void getNode(const RootNodeT*& node)
2013  {
2014  node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
2015  }
2016  template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
2017 
2018  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = nullptr; }
2019  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = nullptr; }
2020  template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
2021 
2023  inline void copy(const ValueAccessor2& other)
2024  {
2025  mKey0 = other.mKey0;
2026  mNode0 = other.mNode0;
2027  mKey1 = other.mKey1;
2028  mNode1 = other.mNode1;
2029  }
2030 
2033  void release() override
2034  {
2035  this->BaseT::release();
2036  this->clear();
2037  }
2038 
2043  inline void insert(const Coord& xyz, const NodeT0* node)
2044  {
2045  assert(node);
2046  mKey0 = xyz & ~(NodeT0::DIM-1);
2047  mNode0 = node;
2048  }
2049  inline void insert(const Coord& xyz, const NodeT1* node)
2050  {
2051  assert(node);
2052  mKey1 = xyz & ~(NodeT1::DIM-1);
2053  mNode1 = node;
2054  }
2057  template<typename NodeT> inline void insert(const Coord&, const NodeT*) {}
2058 
2059  inline bool isHashed0(const Coord& xyz) const
2060  {
2061  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2062  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2063  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2064  }
2065  inline bool isHashed1(const Coord& xyz) const
2066  {
2067  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2068  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2069  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2070  }
2071  mutable Coord mKey0;
2072  mutable const NodeT0* mNode0;
2073  mutable Coord mKey1;
2074  mutable const NodeT1* mNode1;
2075 }; // ValueAccessor2
2076 
2077 
2088 template<typename _TreeType, bool IsSafe, Index L0, Index L1, Index L2>
2090 {
2091 public:
2092  static_assert(_TreeType::DEPTH >= 4, "cache size exceeds tree depth");
2093  static_assert(L0 < L1, "invalid cache level");
2094  static_assert(L1 < L2, "invalid cache level");
2095  static_assert(L2 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
2096 
2097  using TreeType = _TreeType;
2098  using ValueType = typename TreeType::ValueType;
2099  using RootNodeT = typename TreeType::RootNodeType;
2100  using LeafNodeT = typename TreeType::LeafNodeType;
2102  using InvTreeT = typename RootNodeT::NodeChainType;
2103  using NodeT0 = typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type;
2104  using NodeT1 = typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1> >::type;
2105  using NodeT2 = typename boost::mpl::at<InvTreeT, boost::mpl::int_<L2> >::type;
2106 
2109  mKey0(Coord::max()), mNode0(nullptr),
2110  mKey1(Coord::max()), mNode1(nullptr),
2111  mKey2(Coord::max()), mNode2(nullptr) {}
2112 
2114  ValueAccessor3(const ValueAccessor3& other) : BaseT(other) { this->copy(other); }
2115 
2118  {
2119  if (&other != this) {
2120  this->BaseT::operator=(other);
2121  this->copy(other);
2122  }
2123  return *this;
2124  }
2125 
2127  static Index numCacheLevels() { return 3; }
2128 
2130  ~ValueAccessor3() override = default;
2131 
2134  bool isCached(const Coord& xyz) const
2135  {
2136  assert(BaseT::mTree);
2137  return this->isHashed2(xyz) || this->isHashed1(xyz) || this->isHashed0(xyz);
2138  }
2139 
2141  const ValueType& getValue(const Coord& xyz) const
2142  {
2143  assert(BaseT::mTree);
2144  if (this->isHashed0(xyz)) {
2145  assert(mNode0);
2146  return mNode0->getValueAndCache(xyz, this->self());
2147  } else if (this->isHashed1(xyz)) {
2148  assert(mNode1);
2149  return mNode1->getValueAndCache(xyz, this->self());
2150  } else if (this->isHashed2(xyz)) {
2151  assert(mNode2);
2152  return mNode2->getValueAndCache(xyz, this->self());
2153  }
2154  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
2155  }
2156 
2158  bool isValueOn(const Coord& xyz) const
2159  {
2160  assert(BaseT::mTree);
2161  if (this->isHashed0(xyz)) {
2162  assert(mNode0);
2163  return mNode0->isValueOnAndCache(xyz, this->self());
2164  } else if (this->isHashed1(xyz)) {
2165  assert(mNode1);
2166  return mNode1->isValueOnAndCache(xyz, this->self());
2167  } else if (this->isHashed2(xyz)) {
2168  assert(mNode2);
2169  return mNode2->isValueOnAndCache(xyz, this->self());
2170  }
2171  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
2172  }
2173 
2175  bool probeValue(const Coord& xyz, ValueType& value) const
2176  {
2177  assert(BaseT::mTree);
2178  if (this->isHashed0(xyz)) {
2179  assert(mNode0);
2180  return mNode0->probeValueAndCache(xyz, value, this->self());
2181  } else if (this->isHashed1(xyz)) {
2182  assert(mNode1);
2183  return mNode1->probeValueAndCache(xyz, value, this->self());
2184  } else if (this->isHashed2(xyz)) {
2185  assert(mNode2);
2186  return mNode2->probeValueAndCache(xyz, value, this->self());
2187  }
2188  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
2189  }
2190 
2194  int getValueDepth(const Coord& xyz) const
2195  {
2196  assert(BaseT::mTree);
2197  if (this->isHashed0(xyz)) {
2198  assert(mNode0);
2199  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
2200  } else if (this->isHashed1(xyz)) {
2201  assert(mNode1);
2202  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
2203  } else if (this->isHashed2(xyz)) {
2204  assert(mNode2);
2205  return RootNodeT::LEVEL - mNode2->getValueLevelAndCache(xyz, this->self());
2206  }
2207  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
2208  }
2209 
2212  bool isVoxel(const Coord& xyz) const
2213  {
2214  assert(BaseT::mTree);
2215  if (this->isHashed0(xyz)) {
2216  assert(mNode0);
2217  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
2218  } else if (this->isHashed1(xyz)) {
2219  assert(mNode1);
2220  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
2221  } else if (this->isHashed2(xyz)) {
2222  assert(mNode2);
2223  return mNode2->getValueLevelAndCache(xyz, this->self())==0;
2224  }
2225  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
2226  static_cast<int>(RootNodeT::LEVEL);
2227  }
2228 
2230  void setValue(const Coord& xyz, const ValueType& value)
2232  {
2233  assert(BaseT::mTree);
2234  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2235  if (this->isHashed0(xyz)) {
2236  assert(mNode0);
2237  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
2238  } else if (this->isHashed1(xyz)) {
2239  assert(mNode1);
2240  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
2241  } else if (this->isHashed2(xyz)) {
2242  assert(mNode2);
2243  const_cast<NodeT2*>(mNode2)->setValueAndCache(xyz, value, *this);
2244  } else {
2245  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
2246  }
2247  }
2248  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
2250 
2252  void setValueOnly(const Coord& xyz, const ValueType& value)
2253  {
2254  assert(BaseT::mTree);
2255  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2256  if (this->isHashed0(xyz)) {
2257  assert(mNode0);
2258  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
2259  } else if (this->isHashed1(xyz)) {
2260  assert(mNode1);
2261  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
2262  } else if (this->isHashed2(xyz)) {
2263  assert(mNode2);
2264  const_cast<NodeT2*>(mNode2)->setValueOnlyAndCache(xyz, value, *this);
2265  } else {
2266  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
2267  }
2268  }
2269 
2271  void setValueOff(const Coord& xyz, const ValueType& value)
2272  {
2273  assert(BaseT::mTree);
2274  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2275  if (this->isHashed0(xyz)) {
2276  assert(mNode0);
2277  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
2278  } else if (this->isHashed1(xyz)) {
2279  assert(mNode1);
2280  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
2281  } else if (this->isHashed2(xyz)) {
2282  assert(mNode2);
2283  const_cast<NodeT2*>(mNode2)->setValueOffAndCache(xyz, value, *this);
2284  } else {
2285  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
2286  }
2287  }
2288 
2292  template<typename ModifyOp>
2293  void modifyValue(const Coord& xyz, const ModifyOp& op)
2294  {
2295  assert(BaseT::mTree);
2296  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2297  if (this->isHashed0(xyz)) {
2298  assert(mNode0);
2299  const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
2300  } else if (this->isHashed1(xyz)) {
2301  assert(mNode1);
2302  const_cast<NodeT1*>(mNode1)->modifyValueAndCache(xyz, op, *this);
2303  } else if (this->isHashed2(xyz)) {
2304  assert(mNode2);
2305  const_cast<NodeT2*>(mNode2)->modifyValueAndCache(xyz, op, *this);
2306  } else {
2307  BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
2308  }
2309  }
2310 
2313  template<typename ModifyOp>
2314  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
2315  {
2316  assert(BaseT::mTree);
2317  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2318  if (this->isHashed0(xyz)) {
2319  assert(mNode0);
2320  const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
2321  } else if (this->isHashed1(xyz)) {
2322  assert(mNode1);
2323  const_cast<NodeT1*>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *this);
2324  } else if (this->isHashed2(xyz)) {
2325  assert(mNode2);
2326  const_cast<NodeT2*>(mNode2)->modifyValueAndActiveStateAndCache(xyz, op, *this);
2327  } else {
2328  BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
2329  }
2330  }
2331 
2333  void setActiveState(const Coord& xyz, bool on = true)
2334  {
2335  assert(BaseT::mTree);
2336  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2337  if (this->isHashed0(xyz)) {
2338  assert(mNode0);
2339  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
2340  } else if (this->isHashed1(xyz)) {
2341  assert(mNode1);
2342  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
2343  } else if (this->isHashed2(xyz)) {
2344  assert(mNode2);
2345  const_cast<NodeT2*>(mNode2)->setActiveStateAndCache(xyz, on, *this);
2346  } else {
2347  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
2348  }
2349  }
2351  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
2353  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
2354 
2356  template<typename NodeT>
2357  NodeT* getNode()
2358  {
2359  const NodeT* node = nullptr;
2360  this->getNode(node);
2361  return const_cast<NodeT*>(node);
2362  }
2363 
2366  template<typename NodeT>
2367  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
2368 
2372  template<typename NodeT>
2373  void eraseNode()
2374  {
2375  const NodeT* node = nullptr;
2376  this->eraseNode(node);
2377  }
2378 
2381  void addLeaf(LeafNodeT* leaf)
2382  {
2383  assert(BaseT::mTree);
2384  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
2385  if (this->isHashed1(leaf->origin())) {
2386  assert(mNode1);
2387  return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
2388  } else if (this->isHashed2(leaf->origin())) {
2389  assert(mNode2);
2390  return const_cast<NodeT2*>(mNode2)->addLeafAndCache(leaf, *this);
2391  }
2392  BaseT::mTree->root().addLeafAndCache(leaf, *this);
2393  }
2394 
2397  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
2398  {
2399  assert(BaseT::mTree);
2400  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
2401  if (this->isHashed1(xyz)) {
2402  assert(mNode1);
2403  return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
2404  } if (this->isHashed2(xyz)) {
2405  assert(mNode2);
2406  return const_cast<NodeT2*>(mNode2)->addTileAndCache(level, xyz, value, state, *this);
2407  }
2408  BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
2409  }
2410 
2417  LeafNodeT* touchLeaf(const Coord& xyz)
2418  {
2419  assert(BaseT::mTree);
2420  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
2421  if (this->isHashed0(xyz)) {
2422  assert(mNode0);
2423  return const_cast<NodeT0*>(mNode0);
2424  } else if (this->isHashed1(xyz)) {
2425  assert(mNode1);
2426  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
2427  } else if (this->isHashed2(xyz)) {
2428  assert(mNode2);
2429  return const_cast<NodeT2*>(mNode2)->touchLeafAndCache(xyz, *this);
2430  }
2431  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
2432  }
2435  template<typename NodeT>
2436  NodeT* probeNode(const Coord& xyz)
2437  {
2438  assert(BaseT::mTree);
2439  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
2441  if ((std::is_same<NodeT, NodeT0>::value)) {
2442  if (this->isHashed0(xyz)) {
2443  assert(mNode0);
2444  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
2445  } else if (this->isHashed1(xyz)) {
2446  assert(mNode1);
2447  return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
2448  } else if (this->isHashed2(xyz)) {
2449  assert(mNode2);
2450  return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
2451  }
2452  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2453  } else if ((std::is_same<NodeT, NodeT1>::value)) {
2454  if (this->isHashed1(xyz)) {
2455  assert(mNode1);
2456  return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
2457  } else if (this->isHashed2(xyz)) {
2458  assert(mNode2);
2459  return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
2460  }
2461  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2462  } else if ((std::is_same<NodeT, NodeT2>::value)) {
2463  if (this->isHashed2(xyz)) {
2464  assert(mNode2);
2465  return reinterpret_cast<NodeT*>(const_cast<NodeT2*>(mNode2));
2466  }
2467  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2468  }
2469  return nullptr;
2471  }
2474  LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
2475 
2478  template<typename NodeT>
2479  const NodeT* probeConstNode(const Coord& xyz) const
2480  {
2481  assert(BaseT::mTree);
2483  if ((std::is_same<NodeT, NodeT0>::value)) {
2484  if (this->isHashed0(xyz)) {
2485  assert(mNode0);
2486  return reinterpret_cast<const NodeT*>(mNode0);
2487  } else if (this->isHashed1(xyz)) {
2488  assert(mNode1);
2489  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2490  } else if (this->isHashed2(xyz)) {
2491  assert(mNode2);
2492  return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2493  }
2494  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2495  } else if ((std::is_same<NodeT, NodeT1>::value)) {
2496  if (this->isHashed1(xyz)) {
2497  assert(mNode1);
2498  return reinterpret_cast<const NodeT*>(mNode1);
2499  } else if (this->isHashed2(xyz)) {
2500  assert(mNode2);
2501  return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2502  }
2503  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2504  } else if ((std::is_same<NodeT, NodeT2>::value)) {
2505  if (this->isHashed2(xyz)) {
2506  assert(mNode2);
2507  return reinterpret_cast<const NodeT*>(mNode2);
2508  }
2509  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2510  }
2511  return nullptr;
2513  }
2516  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
2517  {
2518  return this->template probeConstNode<LeafNodeT>(xyz);
2519  }
2520  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
2521 
2523  void clear() override
2524  {
2525  mKey0 = Coord::max();
2526  mNode0 = nullptr;
2527  mKey1 = Coord::max();
2528  mNode1 = nullptr;
2529  mKey2 = Coord::max();
2530  mNode2 = nullptr;
2531  }
2532 
2533 private:
2534  // Allow nodes to insert themselves into the cache.
2535  template<typename> friend class RootNode;
2536  template<typename, Index> friend class InternalNode;
2537  template<typename, Index> friend class LeafNode;
2538  // Allow trees to deregister themselves.
2539  template<typename> friend class Tree;
2540 
2541  // This private method is merely for convenience.
2542  inline ValueAccessor3& self() const { return const_cast<ValueAccessor3&>(*this); }
2543 
2545  inline void copy(const ValueAccessor3& other)
2546  {
2547  mKey0 = other.mKey0;
2548  mNode0 = other.mNode0;
2549  mKey1 = other.mKey1;
2550  mNode1 = other.mNode1;
2551  mKey2 = other.mKey2;
2552  mNode2 = other.mNode2;
2553  }
2554 
2557  void release() override
2558  {
2559  this->BaseT::release();
2560  this->clear();
2561  }
2562  void getNode(const NodeT0*& node) { node = mNode0; }
2563  void getNode(const NodeT1*& node) { node = mNode1; }
2564  void getNode(const NodeT2*& node) { node = mNode2; }
2565  void getNode(const RootNodeT*& node)
2566  {
2567  node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
2568  }
2569  template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
2570 
2571  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = nullptr; }
2572  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = nullptr; }
2573  void eraseNode(const NodeT2*) { mKey2 = Coord::max(); mNode2 = nullptr; }
2574  template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
2575 
2580  inline void insert(const Coord& xyz, const NodeT0* node)
2581  {
2582  assert(node);
2583  mKey0 = xyz & ~(NodeT0::DIM-1);
2584  mNode0 = node;
2585  }
2586  inline void insert(const Coord& xyz, const NodeT1* node)
2587  {
2588  assert(node);
2589  mKey1 = xyz & ~(NodeT1::DIM-1);
2590  mNode1 = node;
2591  }
2592  inline void insert(const Coord& xyz, const NodeT2* node)
2593  {
2594  assert(node);
2595  mKey2 = xyz & ~(NodeT2::DIM-1);
2596  mNode2 = node;
2597  }
2600  template<typename OtherNodeType>
2601  inline void insert(const Coord&, const OtherNodeType*)
2602  {
2603  }
2604  inline bool isHashed0(const Coord& xyz) const
2605  {
2606  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2607  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2608  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2609  }
2610  inline bool isHashed1(const Coord& xyz) const
2611  {
2612  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2613  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2614  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2615  }
2616  inline bool isHashed2(const Coord& xyz) const
2617  {
2618  return (xyz[0] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[0]
2619  && (xyz[1] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[1]
2620  && (xyz[2] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[2];
2621  }
2622  mutable Coord mKey0;
2623  mutable const NodeT0* mNode0;
2624  mutable Coord mKey1;
2625  mutable const NodeT1* mNode1;
2626  mutable Coord mKey2;
2627  mutable const NodeT2* mNode2;
2628 }; // ValueAccessor3
2629 
2630 } // namespace tree
2631 } // namespace OPENVDB_VERSION_NAME
2632 } // namespace openvdb
2633 
2634 #endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:2479
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: ValueAccessor.h:1109
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:2516
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:2357
void getNode(RootNodeType *&node)
Definition: ValueAccessor.h:866
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:1272
void erase(const OtherNodeType *node)
Erase the node at another level of the cache.
Definition: ValueAccessor.h:587
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:237
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Definition: ValueAccessor.h:974
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:296
ValueAccessor1(TreeType &tree)
Constructor from a tree.
Definition: ValueAccessor.h:1240
typename boost::mpl::front< SubtreeT >::type NodeType
Definition: ValueAccessor.h:535
ValueAccessor2(TreeType &tree)
Constructor from a tree.
Definition: ValueAccessor.h:1617
void clear()
Erase the nodes at this and lower levels of the cache.
Definition: ValueAccessor.h:590
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition: ValueAccessor.h:793
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don&#39;t change its value.
Definition: ValueAccessor.h:1404
static bool isSafe()
Return true if this accessor is safe, i.e. registered by the tree from which it is constructed...
Definition: ValueAccessor.h:106
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:2474
bool probeValue(const Coord &xyz, ValueType &value)
Return the active state and value of the voxel at the given coordinates.
Definition: ValueAccessor.h:710
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition: ValueAccessor.h:2127
void insertNode(const Coord &xyz, NodeT &node)
Definition: ValueAccessor.h:1842
friend class LeafNode
Definition: ValueAccessor.h:415
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:2158
ValueAccessor2(const ValueAccessor2 &other)
Copy constructor.
Definition: ValueAccessor.h:1622
Definition: ValueAccessor.h:193
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:2134
void erase(const NodeType *)
Erase the node at this level.
Definition: ValueAccessor.h:584
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:1693
void addLeaf(LeafNodeType *leaf)
Definition: ValueAccessor.h:616
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: ValueAccessor.h:287
ValueAccessor0(const ValueAccessor0 &other)
Definition: ValueAccessor.h:1024
LeafNodeType * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:639
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:1482
void insert(const Coord &, const OtherNodeType *)
Definition: ValueAccessor.h:860
ValueAccessorRW(TreeType &tree)
Definition: ValueAccessor.h:516
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state and, in value, the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:1055
void insertNode(const Coord &xyz, NodeT &node)
Definition: ValueAccessor.h:1432
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:1422
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:2314
friend class LeafNode
Definition: ValueAccessor.h:1536
LeafNodeType * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:887
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:206
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:568
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition: ValueAccessor.h:1991
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:1234
typename boost::mpl::front< NodeVecT >::type RootNodeType
Definition: ValueAccessor.h:840
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: ValueAccessor.h:309
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:266
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition: ValueAccessor.h:1869
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:211
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:1966
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: ValueAccessor.h:2293
friend class Tree
Definition: ValueAccessor.h:1210
void erase(const RootNodeType *)
Definition: ValueAccessor.h:862
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
Definition: ValueAccessor.h:1828
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:1610
ValueAccessor1(const ValueAccessor1 &other)
Copy constructor.
Definition: ValueAccessor.h:1245
int getValueDepth(const Coord &xyz)
Definition: ValueAccessor.h:923
void getNode(NodeType *&node)
Definition: ValueAccessor.h:595
virtual void release()
Definition: ValueAccessor.h:144
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition: ValueAccessor.h:1625
void setValue(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:951
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates without changing its value.
Definition: ValueAccessor.h:2333
Definition: ValueAccessor.h:68
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:230
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:1708
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
Definition: ValueAccessor.h:1742
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:1018
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node of the specified type that contains voxel (x, y, z), or nullptr if no su...
Definition: ValueAccessor.h:369
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:1649
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:1795
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:2098
typename RootNodeT::NodeChainType InvTreeT
Definition: ValueAccessor.h:1612
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition: ValueAccessor.h:1360
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:472
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition: ValueAccessor.h:2523
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Definition: ValueAccessor.h:627
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:963
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:1064
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
Definition: ValueAccessor.h:847
friend class RootNode
Definition: ValueAccessor.h:2001
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition: ValueAccessor.h:277
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:1319
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
Definition: ValueAccessor.h:1347
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:1505
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1168
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:1391
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:1048
friend class InternalNode
Definition: ValueAccessor.h:2536
void insert(const Coord &xyz, const NodeType *node)
Cache the given node at this level.
Definition: ValueAccessor.h:574
void eraseNode()
Definition: ValueAccessor.h:1438
void getNode(const RootNodeType *&node) const
Definition: ValueAccessor.h:871
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
Definition: ValueAccessor.h:2353
bool isVoxel(const Coord &xyz)
Definition: ValueAccessor.h:730
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1523
Value accessor with two levels of node caching.
Definition: ValueAccessor.h:65
const NodeT * probeConstNode(const Coord &xyz) const
Return a pointer to the node of the specified type that contains voxel (x, y, z), or nullptr if no su...
Definition: ValueAccessor.h:375
friend class RootNode
Definition: ValueAccessor.h:1534
TreeType TreeType
Definition: ValueAccessor.h:1231
ValueAccessor3(TreeType &tree)
Constructor from a tree.
Definition: ValueAccessor.h:2108
void setValueOff(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:981
void insertNode(const Coord &, NodeT &)
Definition: ValueAccessor.h:1143
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1195
friend class Tree
Definition: ValueAccessor.h:2005
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:484
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:761
void insertNode(const Coord &xyz, NodeType &node)
Definition: ValueAccessor.h:326
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: ValueAccessor.h:1136
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:1086
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition: ValueAccessor.h:1455
Value accessor with three levels of node caching.
Definition: ValueAccessor.h:67
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:460
void insertNode(const Coord &xyz, NodeT &node)
Definition: ValueAccessor.h:2367
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
Definition: ValueAccessor.h:1027
int getValueDepth(const Coord &xyz)
Definition: ValueAccessor.h:719
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:200
void eraseNode()
Definition: ValueAccessor.h:336
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:1608
void setActiveState(const Coord &xyz, bool on)
Definition: ValueAccessor.h:988
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: ValueAccessor.h:767
void eraseNode()
Definition: ValueAccessor.h:2373
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition: ValueAccessor.h:1758
ValueAccessor0 & operator=(const ValueAccessor0 &other)
Definition: ValueAccessor.h:1029
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:2520
bool isValueOn(const Coord &xyz)
Definition: ValueAccessor.h:928
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
Definition: ValueAccessor.h:1826
ValueAccessor2 & operator=(const ValueAccessor2 &other)
Asignment operator.
Definition: ValueAccessor.h:1628
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: ValueAccessor.h:1376
virtual ~ValueAccessorBase()
Definition: ValueAccessor.h:113
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:1041
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:1147
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:1232
void clear() override
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:404
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don&#39;t change its value.
Definition: ValueAccessor.h:1127
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:257
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:249
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
Copy another CacheItem&#39;s node pointers and hash keys, but not its parent pointer. ...
Definition: ValueAccessor.h:558
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
LeafNodeType * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:894
void modifyValue(const Coord &xyz, const ModifyOp &op)
Definition: ValueAccessor.h:966
ValueAccessor3(const ValueAccessor3 &other)
Copy constructor.
Definition: ValueAccessor.h:2114
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: ValueAccessor.h:1777
void setValueOnly(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:751
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:483
friend class Tree
Definition: ValueAccessor.h:2539
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1886
ValueAccessorBase(TreeType &tree)
Definition: ValueAccessor.h:108
typename RootNodeT::NodeChainType InvTreeT
Definition: ValueAccessor.h:1236
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
Definition: ValueAccessor.h:95
NodeType * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:908
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1497
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:1902
bool isVoxel(const Coord &xyz)
Definition: ValueAccessor.h:939
bool isValueOn(const Coord &xyz)
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:700
Value accessor with one level of node caching.
Definition: ValueAccessor.h:63
typename NodeType::LeafNodeType LeafNodeType
Definition: ValueAccessor.h:537
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:669
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition: ValueAccessor.h:2271
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1961
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:1265
TreeType * getTree() const
Return a pointer to the tree associated with this accessor.
Definition: ValueAccessor.h:119
const LeafNodeType * probeConstLeaf(const Coord &xyz)
Definition: ValueAccessor.h:659
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: ValueAccessor.h:1416
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:459
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:1738
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:2212
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
Definition: ValueAccessor.h:2252
void getNode(const NodeType *&node) const
Return the cached node (if any) at this level.
Definition: ValueAccessor.h:593
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:2099
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:2141
ValueAccessor3 & operator=(const ValueAccessor3 &other)
Asignment operator.
Definition: ValueAccessor.h:2117
Definition: Exceptions.h:13
friend class Tree
Definition: ValueAccessor.h:1538
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition: ValueAccessor.h:348
typename tbb::null_mutex::scoped_lock LockT
Definition: ValueAccessor.h:203
friend class LeafNode
Definition: ValueAccessor.h:2537
const LeafNodeT * probeLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:400
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:2381
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:114
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:199
void setValueOnly(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:957
void clear() override
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:1206
friend class RootNode
Definition: ValueAccessor.h:2535
ValueAccessor0(TreeType &tree)
Definition: ValueAccessor.h:1022
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:395
bool isCached(const Coord &) const
Return true if nodes along the path to the given voxel have been cached.
Definition: ValueAccessor.h:1038
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:805
void insert(const Coord &xyz, const OtherNodeType *node)
Forward the given node to another level of the cache.
Definition: ValueAccessor.h:581
friend class InternalNode
Definition: ValueAccessor.h:2002
typename RootNodeT::ValueType ValueType
Definition: ValueAccessor.h:201
const ValueType & getValue(const Coord &xyz)
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:607
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: ValueAccessor.h:311
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:2436
bool isCached(const Coord &xyz) const
Return true if nodes along the path to the given voxel have been cached.
Definition: ValueAccessor.h:227
const NodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1933
CacheItem(TreeCacheT &parent)
Definition: ValueAccessor.h:540
Library and file format version numbers.
void insert(const Coord &, const RootNodeType *root)
Definition: ValueAccessor.h:856
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:471
friend class RootNode
Definition: ValueAccessor.h:413
CacheItem(TreeCacheT &parent)
Definition: ValueAccessor.h:844
void getNode(OtherNodeType *&node)
Forward the request to another level of the cache.
Definition: ValueAccessor.h:604
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:1072
CacheItem(TreeCacheT &parent, const CacheItem &other)
Definition: ValueAccessor.h:845
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:1176
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but don&#39;t change its active state.
Definition: ValueAccessor.h:1090
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:1184
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:1609
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:1294
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:1139
friend class LeafNode
Definition: ValueAccessor.h:2003
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:1119
void eraseNode()
Definition: ValueAccessor.h:1848
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1200
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:1019
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:494
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
Definition: ValueAccessor.h:2351
friend class Tree
Definition: ValueAccessor.h:417
TreeType TreeType
Definition: ValueAccessor.h:1016
Index32 Index
Definition: Types.h:31
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:854
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1928
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:115
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:359
ValueAccessorBase & operator=(const ValueAccessorBase &other)
Definition: ValueAccessor.h:128
ValueAccessor with no mutex and no node caching.
Definition: ValueAccessor.h:61
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1519
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Definition: ValueAccessor.h:880
typename RootNodeType::LeafNodeType LeafNodeType
Definition: ValueAccessor.h:842
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:1663
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: ValueAccessor.h:1418
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:1642
TreeType * mTree
Definition: ValueAccessor.h:146
TreeType TreeType
Definition: ValueAccessor.h:2097
Definition: Coord.h:16
const LeafNodeType * probeConstLeaf(const Coord &xyz)
Definition: ValueAccessor.h:901
ValueAccessor & operator=(const ValueAccessor &other)
Definition: ValueAccessor.h:213
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:2175
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:2417
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:781
ValueAccessorBase(const ValueAccessorBase &other)
Definition: ValueAccessor.h:123
Definition: Tree.h:176
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition: ValueAccessor.h:2397
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:1233
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:1446
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:1017
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:240
friend class InternalNode
Definition: ValueAccessor.h:1535
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition: ValueAccessor.h:1098
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:2100
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:2248
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:1307
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:340
void getNode(const NodeType *&node)
Definition: ValueAccessor.h:594
const NodeType * probeConstNode(const Coord &xyz)
Definition: ValueAccessor.h:917
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but don&#39;t change its active state.
Definition: ValueAccessor.h:270
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:741
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1957
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:1832
const NodeT * probeConstNode(const Coord &xyz)
Definition: ValueAccessor.h:685
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1468
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:1856
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:1283
void eraseNode()
Definition: ValueAccessor.h:1166
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates without changing its value.
Definition: ValueAccessor.h:1811
LeafNodeType * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:649
This accessor is thread-safe (at the cost of speed) for both reading and writing to a tree...
Definition: ValueAccessor.h:513
TreeType TreeType
Definition: ValueAccessor.h:1607
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1190
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:1677
const ValueType & getValue(const Coord &xyz)
Definition: ValueAccessor.h:945
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:121
typename RootNodeT::NodeChainType InvTreeT
Definition: ValueAccessor.h:2102
ValueAccessor1 & operator=(const ValueAccessor1 &other)
Asignment operator.
Definition: ValueAccessor.h:1251
bool probeValue(const Coord &xyz, ValueType &value)
Definition: ValueAccessor.h:934
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: ValueAccessor.h:1134
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:1343
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:2194
void addLeaf(LeafNodeType *leaf)
Definition: ValueAccessor.h:873
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
Definition: ValueAccessor.h:224
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition: ValueAccessor.h:1156
const NodeT * probeNode(const Coord &xyz) const
Return a pointer to the node of the specified type that contains voxel (x, y, z), or nullptr if no su...
Definition: ValueAccessor.h:381
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition: ValueAccessor.h:1248
typename RootNodeType::ValueType ValueType
Definition: ValueAccessor.h:841
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don&#39;t change its value.
Definition: ValueAccessor.h:303
NodeType * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:315
TreeType TreeType
Definition: ValueAccessor.h:198
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:106
friend class InternalNode
Definition: ValueAccessor.h:414
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition: ValueAccessor.h:1526