OpenVDB  8.0.1
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 <tbb/null_mutex.h>
35 #include <tbb/spin_mutex.h>
36 #include <openvdb/version.h>
37 #include <openvdb/Types.h>
38 #include <cassert>
39 #include <limits>
40 #include <type_traits>
41 
42 namespace openvdb {
44 namespace OPENVDB_VERSION_NAME {
45 namespace tree {
46 
47 // Forward declarations of local classes that are not intended for general use
48 // The IsSafe template parameter is explained in the warning below.
49 template<typename TreeType, bool IsSafe = true>
51 template<typename TreeType, bool IsSafe = true, Index L0 = 0>
53 template<typename TreeType, bool IsSafe = true, Index L0 = 0, Index L1 = 1>
55 template<typename TreeType, bool IsSafe = true, Index L0 = 0, Index L1 = 1, Index L2 = 2>
57 template<typename TreeCacheT, typename NodeVecT, bool AtRoot> class CacheItem;
58 
59 
83 template<typename TreeType, bool IsSafe>
85 {
86 public:
87  static const bool IsConstTree = std::is_const<TreeType>::value;
88 
95  static bool isSafe() { return IsSafe; }
96 
97  ValueAccessorBase(TreeType& tree): mTree(&tree)
98  {
99  if (IsSafe) tree.attachAccessor(*this);
100  }
101 
102  virtual ~ValueAccessorBase() { if (IsSafe && mTree) mTree->releaseAccessor(*this); }
103 
108  TreeType* getTree() const { return mTree; }
110  TreeType& tree() const { assert(mTree); return *mTree; }
111 
112  ValueAccessorBase(const ValueAccessorBase& other): mTree(other.mTree)
113  {
114  if (IsSafe && mTree) mTree->attachAccessor(*this);
115  }
116 
118  {
119  if (&other != this) {
120  if (IsSafe && mTree) mTree->releaseAccessor(*this);
121  mTree = other.mTree;
122  if (IsSafe && mTree) mTree->attachAccessor(*this);
123  }
124  return *this;
125  }
126 
127  virtual void clear() = 0;
128 
129 protected:
130  // Allow trees to deregister themselves.
131  template<typename> friend class Tree;
132 
133  virtual void release() { mTree = nullptr; }
134 
135  TreeType* mTree;
136 }; // class ValueAccessorBase
137 
138 
140 
141 
178 template<typename _TreeType,
179  bool IsSafe = true,
180  Index CacheLevels = _TreeType::DEPTH-1,
181  typename MutexType = tbb::null_mutex>
182 class ValueAccessor: public ValueAccessorBase<_TreeType, IsSafe>
183 {
184 public:
185  static_assert(CacheLevels < _TreeType::DEPTH, "cache size exceeds tree depth");
186 
187  using TreeType = _TreeType;
188  using RootNodeT = typename TreeType::RootNodeType;
189  using LeafNodeT = typename TreeType::LeafNodeType;
190  using ValueType = typename RootNodeT::ValueType;
192  using LockT = typename MutexType::scoped_lock;
193  using BaseT::IsConstTree;
194 
195  ValueAccessor(TreeType& tree): BaseT(tree), mCache(*this)
196  {
197  mCache.insert(Coord(), &tree.root());
198  }
199 
200  ValueAccessor(const ValueAccessor& other): BaseT(other), mCache(*this, other.mCache) {}
201 
203  {
204  if (&other != this) {
205  this->BaseT::operator=(other);
206  mCache.copy(*this, other.mCache);
207  }
208  return *this;
209  }
210  ~ValueAccessor() override = default;
211 
213  static Index numCacheLevels() { return CacheLevels; }
214 
216  bool isCached(const Coord& xyz) const { LockT lock(mMutex); return mCache.isCached(xyz); }
217 
219  const ValueType& getValue(const Coord& xyz) const
220  {
221  LockT lock(mMutex);
222  return mCache.getValue(xyz);
223  }
224 
226  bool isValueOn(const Coord& xyz) const { LockT lock(mMutex); return mCache.isValueOn(xyz); }
227 
229  bool probeValue(const Coord& xyz, ValueType& value) const
230  {
231  LockT lock(mMutex);
232  return mCache.probeValue(xyz,value);
233  }
234 
238  int getValueDepth(const Coord& xyz) const
239  {
240  LockT lock(mMutex);
241  return mCache.getValueDepth(xyz);
242  }
243 
246  bool isVoxel(const Coord& xyz) const { LockT lock(mMutex); return mCache.isVoxel(xyz); }
247 
249  void setValue(const Coord& xyz, const ValueType& value)
251  {
252  LockT lock(mMutex);
253  mCache.setValue(xyz, value);
254  }
255  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
257 
259  void setValueOnly(const Coord& xyz, const ValueType& value)
260  {
261  LockT lock(mMutex);
262  mCache.setValueOnly(xyz, value);
263  }
264 
266  void setValueOff(const Coord& xyz, const ValueType& value)
267  {
268  LockT lock(mMutex);
269  mCache.setValueOff(xyz, value);
270  }
271 
275  template<typename ModifyOp>
276  void modifyValue(const Coord& xyz, const ModifyOp& op)
277  {
278  LockT lock(mMutex);
279  mCache.modifyValue(xyz, op);
280  }
281 
284  template<typename ModifyOp>
285  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
286  {
287  LockT lock(mMutex);
288  mCache.modifyValueAndActiveState(xyz, op);
289  }
290 
292  void setActiveState(const Coord& xyz, bool on = true)
293  {
294  LockT lock(mMutex);
295  mCache.setActiveState(xyz, on);
296  }
298  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
300  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
301 
303  template<typename NodeType>
304  NodeType* getNode()
305  {
306  LockT lock(mMutex);
307  NodeType* node = nullptr;
308  mCache.getNode(node);
309  return node;
310  }
311 
314  template<typename NodeType>
315  void insertNode(const Coord& xyz, NodeType& node)
316  {
317  LockT lock(mMutex);
318  mCache.insert(xyz, &node);
319  }
320 
324  template<typename NodeType>
325  void eraseNode() { LockT lock(mMutex); NodeType* node = nullptr; mCache.erase(node); }
326 
329  void addLeaf(LeafNodeT* leaf)
330  {
331  LockT lock(mMutex);
332  mCache.addLeaf(leaf);
333  }
334 
337  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
338  {
339  LockT lock(mMutex);
340  mCache.addTile(level, xyz, value, state);
341  }
342 
348  LeafNodeT* touchLeaf(const Coord& xyz)
349  {
350  LockT lock(mMutex);
351  return mCache.touchLeaf(xyz);
352  }
353 
355  template<typename NodeT>
358  NodeT* probeNode(const Coord& xyz)
359  {
360  LockT lock(mMutex);
361  return mCache.template probeNode<NodeT>(xyz);
362  }
363  template<typename NodeT>
364  const NodeT* probeConstNode(const Coord& xyz) const
365  {
366  LockT lock(mMutex);
367  return mCache.template probeConstNode<NodeT>(xyz);
368  }
369  template<typename NodeT>
370  const NodeT* probeNode(const Coord& xyz) const
371  {
372  return this->template probeConstNode<NodeT>(xyz);
373  }
375 
377  LeafNodeT* probeLeaf(const Coord& xyz)
380  {
381  LockT lock(mMutex);
382  return mCache.probeLeaf(xyz);
383  }
384  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
385  {
386  LockT lock(mMutex);
387  return mCache.probeConstLeaf(xyz);
388  }
389  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
391 
393  void clear() override
394  {
395  LockT lock(mMutex);
396  mCache.clear();
397  if (this->mTree) mCache.insert(Coord(), &(this->mTree->root()));
398  }
399 
400 private:
401  // Allow nodes to insert themselves into the cache.
402  template<typename> friend class RootNode;
403  template<typename, Index> friend class InternalNode;
404  template<typename, Index> friend class LeafNode;
405  // Allow trees to deregister themselves.
406  template<typename> friend class Tree;
407 
410  void release() override
411  {
412  LockT lock(mMutex);
413  this->BaseT::release();
414  mCache.clear();
415  }
416 
421  template<typename NodeType>
422  void insert(const Coord& xyz, NodeType* node) { mCache.insert(xyz, node); }
423 
424  // Define a list of all tree node types from LeafNode to RootNode
425  using InvTreeT = typename RootNodeT::NodeChainType;
426  // Remove all tree node types that are excluded from the cache
427  static constexpr int64_t First = CacheLevels;
428  static constexpr int64_t Last = InvTreeT::template Index<RootNodeT>;
429  using SubtreeT = typename InvTreeT::template RemoveByIndex<First, Last-1>;
431 
432  // Private member data
433  mutable CacheItemT mCache;
434  mutable MutexType mMutex;
435 
436 }; // class ValueAccessor
437 
438 
442 template<typename TreeType, bool IsSafe>
443 class ValueAccessor<TreeType, IsSafe, 0, tbb::null_mutex>
444  : public ValueAccessor0<TreeType, IsSafe>
445 {
446 public:
447  ValueAccessor(TreeType& tree): ValueAccessor0<TreeType, IsSafe>(tree) {}
448  ValueAccessor(const ValueAccessor& other): ValueAccessor0<TreeType, IsSafe>(other) {}
449  ~ValueAccessor() override = default;
450 };
451 
452 
454 template<typename TreeType, bool IsSafe>
455 class ValueAccessor<TreeType, IsSafe, 1, tbb::null_mutex>
456  : public ValueAccessor1<TreeType, IsSafe>
457 {
458 public:
459  ValueAccessor(TreeType& tree): ValueAccessor1<TreeType, IsSafe>(tree) {}
460  ValueAccessor(const ValueAccessor& other): ValueAccessor1<TreeType, IsSafe>(other) {}
461  ~ValueAccessor() override = default;
462 };
463 
464 
466 template<typename TreeType, bool IsSafe>
467 class ValueAccessor<TreeType, IsSafe, 2, tbb::null_mutex>
468  : public ValueAccessor2<TreeType, IsSafe>
469 {
470 public:
471  ValueAccessor(TreeType& tree): ValueAccessor2<TreeType, IsSafe>(tree) {}
472  ValueAccessor(const ValueAccessor& other): ValueAccessor2<TreeType, IsSafe>(other) {}
473  ~ValueAccessor() override = default;
474 };
475 
476 
478 template<typename TreeType, bool IsSafe>
479 class ValueAccessor<TreeType, IsSafe, 3, tbb::null_mutex>: public ValueAccessor3<TreeType, IsSafe>
480 {
481 public:
482  ValueAccessor(TreeType& tree): ValueAccessor3<TreeType, IsSafe>(tree) {}
483  ValueAccessor(const ValueAccessor&) = default;
484  ValueAccessor& operator=(const ValueAccessor&) = default;
485  ~ValueAccessor() override = default;
486 };
487 
488 
490 
491 
500 template<typename TreeType, bool IsSafe = true>
501 class ValueAccessorRW: public ValueAccessor<TreeType, IsSafe, TreeType::DEPTH-1, tbb::spin_mutex>
502 {
503 public:
505  : ValueAccessor<TreeType, IsSafe, TreeType::DEPTH-1, tbb::spin_mutex>(tree)
506  {
507  }
508 };
509 
510 
512 
513 
514 //
515 // The classes below are for internal use and should rarely be used directly.
516 //
517 
518 // An element of a compile-time linked list of node pointers, ordered from LeafNode to RootNode
519 template<typename TreeCacheT, typename NodeVecT, bool AtRoot>
520 class CacheItem
521 {
522 public:
523  using NodeType = typename NodeVecT::Front;
524  using ValueType = typename NodeType::ValueType;
525  using LeafNodeType = typename NodeType::LeafNodeType;
526  using CoordLimits = std::numeric_limits<Int32>;
527 
528  CacheItem(TreeCacheT& parent):
529  mParent(&parent),
530  mHash(CoordLimits::max()),
531  mNode(nullptr),
532  mNext(parent)
533  {
534  }
535 
537  CacheItem(TreeCacheT& parent, const CacheItem& other):
539  mParent(&parent),
540  mHash(other.mHash),
541  mNode(other.mNode),
542  mNext(parent, other.mNext)
543  {
544  }
545 
546  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
547  {
548  mParent = &parent;
549  mHash = other.mHash;
550  mNode = other.mNode;
551  mNext.copy(parent, other.mNext);
552  return *this;
553  }
555 
556  bool isCached(const Coord& xyz) const
557  {
558  return (this->isHashed(xyz) || mNext.isCached(xyz));
559  }
560 
562  void insert(const Coord& xyz, const NodeType* node)
563  {
564  mHash = (node != nullptr) ? xyz & ~(NodeType::DIM-1) : Coord::max();
565  mNode = node;
566  }
568  template<typename OtherNodeType>
569  void insert(const Coord& xyz, const OtherNodeType* node) { mNext.insert(xyz, node); }
570 
572  void erase(const NodeType*) { mHash = Coord::max(); mNode = nullptr; }
574  template<typename OtherNodeType>
575  void erase(const OtherNodeType* node) { mNext.erase(node); }
576 
578  void clear() { mHash = Coord::max(); mNode = nullptr; mNext.clear(); }
579 
581  void getNode(const NodeType*& node) const { node = mNode; }
582  void getNode(const NodeType*& node) { node = mNode; }
583  void getNode(NodeType*& node)
584  {
585  // This combination of a static assertion and a const_cast might not be elegant,
586  // but it is a lot simpler than specializing TreeCache for const Trees.
587  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
588  node = const_cast<NodeType*>(mNode);
589  }
591  template<typename OtherNodeType>
592  void getNode(OtherNodeType*& node) { mNext.getNode(node); }
593 
595  const ValueType& getValue(const Coord& xyz)
596  {
597  if (this->isHashed(xyz)) {
598  assert(mNode);
599  return mNode->getValueAndCache(xyz, *mParent);
600  }
601  return mNext.getValue(xyz);
602  }
603 
604  void addLeaf(LeafNodeType* leaf)
605  {
606  static_assert(!TreeCacheT::IsConstTree, "can't add a node to a const tree");
607  if (NodeType::LEVEL == 0) return;
608  if (this->isHashed(leaf->origin())) {
609  assert(mNode);
610  return const_cast<NodeType*>(mNode)->addLeafAndCache(leaf, *mParent);
611  }
612  mNext.addLeaf(leaf);
613  }
614 
615  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
616  {
617  static_assert(!TreeCacheT::IsConstTree, "can't add a tile to a const tree");
618  if (NodeType::LEVEL < level) return;
619  if (this->isHashed(xyz)) {
620  assert(mNode);
621  return const_cast<NodeType*>(mNode)->addTileAndCache(
622  level, xyz, value, state, *mParent);
623  }
624  mNext.addTile(level, xyz, value, state);
625  }
626 
627  LeafNodeType* touchLeaf(const Coord& xyz)
628  {
629  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
630  if (this->isHashed(xyz)) {
631  assert(mNode);
632  return const_cast<NodeType*>(mNode)->touchLeafAndCache(xyz, *mParent);
633  }
634  return mNext.touchLeaf(xyz);
635  }
636 
637  LeafNodeType* probeLeaf(const Coord& xyz)
638  {
639  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
640  if (this->isHashed(xyz)) {
641  assert(mNode);
642  return const_cast<NodeType*>(mNode)->probeLeafAndCache(xyz, *mParent);
643  }
644  return mNext.probeLeaf(xyz);
645  }
646 
647  const LeafNodeType* probeConstLeaf(const Coord& xyz)
648  {
649  if (this->isHashed(xyz)) {
650  assert(mNode);
651  return mNode->probeConstLeafAndCache(xyz, *mParent);
652  }
653  return mNext.probeConstLeaf(xyz);
654  }
655 
656  template<typename NodeT>
657  NodeT* probeNode(const Coord& xyz)
658  {
659  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
661  if (this->isHashed(xyz)) {
662  if ((std::is_same<NodeT, NodeType>::value)) {
663  assert(mNode);
664  return reinterpret_cast<NodeT*>(const_cast<NodeType*>(mNode));
665  }
666  return const_cast<NodeType*>(mNode)->template probeNodeAndCache<NodeT>(xyz, *mParent);
667  }
668  return mNext.template probeNode<NodeT>(xyz);
670  }
671 
672  template<typename NodeT>
673  const NodeT* probeConstNode(const Coord& xyz)
674  {
676  if (this->isHashed(xyz)) {
677  if ((std::is_same<NodeT, NodeType>::value)) {
678  assert(mNode);
679  return reinterpret_cast<const NodeT*>(mNode);
680  }
681  return mNode->template probeConstNodeAndCache<NodeT>(xyz, *mParent);
682  }
683  return mNext.template probeConstNode<NodeT>(xyz);
685  }
686 
688  bool isValueOn(const Coord& xyz)
689  {
690  if (this->isHashed(xyz)) {
691  assert(mNode);
692  return mNode->isValueOnAndCache(xyz, *mParent);
693  }
694  return mNext.isValueOn(xyz);
695  }
696 
698  bool probeValue(const Coord& xyz, ValueType& value)
699  {
700  if (this->isHashed(xyz)) {
701  assert(mNode);
702  return mNode->probeValueAndCache(xyz, value, *mParent);
703  }
704  return mNext.probeValue(xyz, value);
705  }
706 
707  int getValueDepth(const Coord& xyz)
708  {
709  if (this->isHashed(xyz)) {
710  assert(mNode);
711  return static_cast<int>(TreeCacheT::RootNodeT::LEVEL) -
712  static_cast<int>(mNode->getValueLevelAndCache(xyz, *mParent));
713  } else {
714  return mNext.getValueDepth(xyz);
715  }
716  }
717 
718  bool isVoxel(const Coord& xyz)
719  {
720  if (this->isHashed(xyz)) {
721  assert(mNode);
722  return mNode->getValueLevelAndCache(xyz, *mParent)==0;
723  } else {
724  return mNext.isVoxel(xyz);
725  }
726  }
727 
729  void setValue(const Coord& xyz, const ValueType& value)
730  {
731  if (this->isHashed(xyz)) {
732  assert(mNode);
733  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
734  const_cast<NodeType*>(mNode)->setValueAndCache(xyz, value, *mParent);
735  } else {
736  mNext.setValue(xyz, value);
737  }
738  }
739  void setValueOnly(const Coord& xyz, const ValueType& value)
740  {
741  if (this->isHashed(xyz)) {
742  assert(mNode);
743  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
744  const_cast<NodeType*>(mNode)->setValueOnlyAndCache(xyz, value, *mParent);
745  } else {
746  mNext.setValueOnly(xyz, value);
747  }
748  }
749  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
750 
754  template<typename ModifyOp>
755  void modifyValue(const Coord& xyz, const ModifyOp& op)
756  {
757  if (this->isHashed(xyz)) {
758  assert(mNode);
759  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
760  const_cast<NodeType*>(mNode)->modifyValueAndCache(xyz, op, *mParent);
761  } else {
762  mNext.modifyValue(xyz, op);
763  }
764  }
765 
768  template<typename ModifyOp>
769  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
770  {
771  if (this->isHashed(xyz)) {
772  assert(mNode);
773  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
774  const_cast<NodeType*>(mNode)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
775  } else {
776  mNext.modifyValueAndActiveState(xyz, op);
777  }
778  }
779 
781  void setValueOff(const Coord& xyz, const ValueType& value)
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)->setValueOffAndCache(xyz, value, *mParent);
787  } else {
788  mNext.setValueOff(xyz, value);
789  }
790  }
791 
793  void setActiveState(const Coord& xyz, bool on)
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)->setActiveStateAndCache(xyz, on, *mParent);
799  } else {
800  mNext.setActiveState(xyz, on);
801  }
802  }
803 
804 private:
805  CacheItem(const CacheItem&);
806  CacheItem& operator=(const CacheItem&);
807 
808  bool isHashed(const Coord& xyz) const
809  {
810  return (xyz[0] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[0]
811  && (xyz[1] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[1]
812  && (xyz[2] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[2];
813  }
814 
815  TreeCacheT* mParent;
816  Coord mHash;
817  const NodeType* mNode;
818  using RestT = typename NodeVecT::PopFront;
819  CacheItem<TreeCacheT, RestT, /*AtRoot=*/RestT::Size == 1> mNext;
820 };// end of CacheItem
821 
822 
824 template<typename TreeCacheT, typename NodeVecT>
825 class CacheItem<TreeCacheT, NodeVecT, /*AtRoot=*/true>
826 {
827 public:
828  using RootNodeType = typename NodeVecT::Front;
829  using ValueType = typename RootNodeType::ValueType;
830  using LeafNodeType = typename RootNodeType::LeafNodeType;
831 
832  CacheItem(TreeCacheT& parent): mParent(&parent), mRoot(nullptr) {}
833  CacheItem(TreeCacheT& parent, const CacheItem& other): mParent(&parent), mRoot(other.mRoot) {}
834 
835  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
836  {
837  mParent = &parent;
838  mRoot = other.mRoot;
839  return *this;
840  }
841 
842  bool isCached(const Coord& xyz) const { return this->isHashed(xyz); }
843 
844  void insert(const Coord&, const RootNodeType* root) { mRoot = root; }
845 
846  // Needed for node types that are not cached
847  template<typename OtherNodeType>
848  void insert(const Coord&, const OtherNodeType*) {}
849 
850  void erase(const RootNodeType*) { mRoot = nullptr; }
851 
852  void clear() { mRoot = nullptr; }
853 
854  void getNode(RootNodeType*& node)
855  {
856  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
857  node = const_cast<RootNodeType*>(mRoot);
858  }
859  void getNode(const RootNodeType*& node) const { node = mRoot; }
860 
861  void addLeaf(LeafNodeType* leaf)
862  {
863  assert(mRoot);
864  static_assert(!TreeCacheT::IsConstTree, "can't add a node to a const tree");
865  const_cast<RootNodeType*>(mRoot)->addLeafAndCache(leaf, *mParent);
866  }
867 
868  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
869  {
870  assert(mRoot);
871  static_assert(!TreeCacheT::IsConstTree, "can't add a tile to a const tree");
872  const_cast<RootNodeType*>(mRoot)->addTileAndCache(level, xyz, value, state, *mParent);
873  }
874 
875  LeafNodeType* touchLeaf(const Coord& xyz)
876  {
877  assert(mRoot);
878  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
879  return const_cast<RootNodeType*>(mRoot)->touchLeafAndCache(xyz, *mParent);
880  }
881 
882  LeafNodeType* probeLeaf(const Coord& xyz)
883  {
884  assert(mRoot);
885  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
886  return const_cast<RootNodeType*>(mRoot)->probeLeafAndCache(xyz, *mParent);
887  }
888 
889  const LeafNodeType* probeConstLeaf(const Coord& xyz)
890  {
891  assert(mRoot);
892  return mRoot->probeConstLeafAndCache(xyz, *mParent);
893  }
894 
895  template<typename NodeType>
896  NodeType* probeNode(const Coord& xyz)
897  {
898  assert(mRoot);
899  static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
900  return const_cast<RootNodeType*>(mRoot)->
901  template probeNodeAndCache<NodeType>(xyz, *mParent);
902  }
903 
904  template<typename NodeType>
905  const NodeType* probeConstNode(const Coord& xyz)
906  {
907  assert(mRoot);
908  return mRoot->template probeConstNodeAndCache<NodeType>(xyz, *mParent);
909  }
910 
911  int getValueDepth(const Coord& xyz)
912  {
913  assert(mRoot);
914  return mRoot->getValueDepthAndCache(xyz, *mParent);
915  }
916  bool isValueOn(const Coord& xyz)
917  {
918  assert(mRoot);
919  return mRoot->isValueOnAndCache(xyz, *mParent);
920  }
921 
922  bool probeValue(const Coord& xyz, ValueType& value)
923  {
924  assert(mRoot);
925  return mRoot->probeValueAndCache(xyz, value, *mParent);
926  }
927  bool isVoxel(const Coord& xyz)
928  {
929  assert(mRoot);
930  return mRoot->getValueDepthAndCache(xyz, *mParent) ==
931  static_cast<int>(RootNodeType::LEVEL);
932  }
933  const ValueType& getValue(const Coord& xyz)
934  {
935  assert(mRoot);
936  return mRoot->getValueAndCache(xyz, *mParent);
937  }
938 
939  void setValue(const Coord& xyz, const ValueType& value)
940  {
941  assert(mRoot);
942  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
943  const_cast<RootNodeType*>(mRoot)->setValueAndCache(xyz, value, *mParent);
944  }
945  void setValueOnly(const Coord& xyz, const ValueType& value)
946  {
947  assert(mRoot);
948  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
949  const_cast<RootNodeType*>(mRoot)->setValueOnlyAndCache(xyz, value, *mParent);
950  }
951  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
952 
953  template<typename ModifyOp>
954  void modifyValue(const Coord& xyz, const ModifyOp& op)
955  {
956  assert(mRoot);
957  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
958  const_cast<RootNodeType*>(mRoot)->modifyValueAndCache(xyz, op, *mParent);
959  }
960 
961  template<typename ModifyOp>
962  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
963  {
964  assert(mRoot);
965  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
966  const_cast<RootNodeType*>(mRoot)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
967  }
968 
969  void setValueOff(const Coord& xyz, const ValueType& value)
970  {
971  assert(mRoot);
972  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
973  const_cast<RootNodeType*>(mRoot)->setValueOffAndCache(xyz, value, *mParent);
974  }
975 
976  void setActiveState(const Coord& xyz, bool on)
977  {
978  assert(mRoot);
979  static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
980  const_cast<RootNodeType*>(mRoot)->setActiveStateAndCache(xyz, on, *mParent);
981  }
982 
983 private:
984  CacheItem(const CacheItem&);
985  CacheItem& operator=(const CacheItem&);
986 
987  bool isHashed(const Coord&) const { return false; }
988 
989  TreeCacheT* mParent;
990  const RootNodeType* mRoot;
991 };// end of CacheItem specialized for RootNode
992 
993 
995 
996 
1000 template<typename _TreeType, bool IsSafe>
1001 class ValueAccessor0: public ValueAccessorBase<_TreeType, IsSafe>
1002 {
1003 public:
1004  using TreeType = _TreeType;
1005  using ValueType = typename TreeType::ValueType;
1006  using RootNodeT = typename TreeType::RootNodeType;
1007  using LeafNodeT = typename TreeType::LeafNodeType;
1009 
1010  ValueAccessor0(TreeType& tree): BaseT(tree) {}
1011 
1012  ValueAccessor0(const ValueAccessor0& other): BaseT(other) {}
1013 
1015  static Index numCacheLevels() { return 0; }
1016 
1018  {
1019  if (&other != this) this->BaseT::operator=(other);
1020  return *this;
1021  }
1022 
1023  ~ValueAccessor0() override = default;
1024 
1026  bool isCached(const Coord&) const { return false; }
1027 
1029  const ValueType& getValue(const Coord& xyz) const
1030  {
1031  assert(BaseT::mTree);
1032  return BaseT::mTree->getValue(xyz);
1033  }
1034 
1036  bool isValueOn(const Coord& xyz) const
1037  {
1038  assert(BaseT::mTree);
1039  return BaseT::mTree->isValueOn(xyz);
1040  }
1041 
1043  bool probeValue(const Coord& xyz, ValueType& value) const
1044  {
1045  assert(BaseT::mTree);
1046  return BaseT::mTree->probeValue(xyz, value);
1047  }
1048 
1052  int getValueDepth(const Coord& xyz) const
1053  {
1054  assert(BaseT::mTree);
1055  return BaseT::mTree->getValueDepth(xyz);
1056  }
1057 
1060  bool isVoxel(const Coord& xyz) const
1061  {
1062  assert(BaseT::mTree);
1063  return BaseT::mTree->getValueDepth(xyz) == static_cast<int>(RootNodeT::LEVEL);
1064  }
1065 
1067  void setValue(const Coord& xyz, const ValueType& value)
1069  {
1070  assert(BaseT::mTree);
1071  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1072  BaseT::mTree->setValue(xyz, value);
1073  }
1074  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1076 
1078  void setValueOnly(const Coord& xyz, const ValueType& value)
1079  {
1080  assert(BaseT::mTree);
1081  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1082  BaseT::mTree->setValueOnly(xyz, value);
1083  }
1084 
1086  void setValueOff(const Coord& xyz, const ValueType& value)
1087  {
1088  assert(BaseT::mTree);
1089  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1090  BaseT::mTree->root().setValueOff(xyz, value);
1091  }
1092 
1096  template<typename ModifyOp>
1097  void modifyValue(const Coord& xyz, const ModifyOp& op)
1098  {
1099  assert(BaseT::mTree);
1100  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1101  BaseT::mTree->modifyValue(xyz, op);
1102  }
1103 
1106  template<typename ModifyOp>
1107  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1108  {
1109  assert(BaseT::mTree);
1110  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1111  BaseT::mTree->modifyValueAndActiveState(xyz, op);
1112  }
1113 
1115  void setActiveState(const Coord& xyz, bool on = true)
1116  {
1117  assert(BaseT::mTree);
1118  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1119  BaseT::mTree->setActiveState(xyz, on);
1120  }
1122  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1124  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1125 
1127  template<typename NodeT> NodeT* getNode() { return nullptr; }
1128 
1131  template<typename NodeT> void insertNode(const Coord&, NodeT&) {}
1132 
1135  void addLeaf(LeafNodeT* leaf)
1136  {
1137  assert(BaseT::mTree);
1138  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
1139  BaseT::mTree->root().addLeaf(leaf);
1140  }
1141 
1144  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1145  {
1146  assert(BaseT::mTree);
1147  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
1148  BaseT::mTree->root().addTile(level, xyz, value, state);
1149  }
1150 
1154  template<typename NodeT> void eraseNode() {}
1155 
1156  LeafNodeT* touchLeaf(const Coord& xyz)
1157  {
1158  assert(BaseT::mTree);
1159  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1160  return BaseT::mTree->touchLeaf(xyz);
1161  }
1162 
1163  template<typename NodeT>
1164  NodeT* probeNode(const Coord& xyz)
1165  {
1166  assert(BaseT::mTree);
1167  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1168  return BaseT::mTree->template probeNode<NodeT>(xyz);
1169  }
1170 
1171  template<typename NodeT>
1172  const NodeT* probeConstNode(const Coord& xyz) const
1173  {
1174  assert(BaseT::mTree);
1175  return BaseT::mTree->template probeConstNode<NodeT>(xyz);
1176  }
1177 
1178  LeafNodeT* probeLeaf(const Coord& xyz)
1179  {
1180  return this->template probeNode<LeafNodeT>(xyz);
1181  }
1182 
1183  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1184  {
1185  return this->template probeConstNode<LeafNodeT>(xyz);
1186  }
1187 
1188  const LeafNodeT* probeLeaf(const Coord& xyz) const
1189  {
1190  return this->probeConstLeaf(xyz);
1191  }
1192 
1194  void clear() override {}
1195 
1196 private:
1197  // Allow trees to deregister themselves.
1198  template<typename> friend class Tree;
1199 
1202  void release() override { this->BaseT::release(); }
1203 
1204 }; // ValueAccessor0
1205 
1206 
1213 template<typename _TreeType, bool IsSafe, Index L0>
1215 {
1216 public:
1217  static_assert(_TreeType::DEPTH >= 2, "cache size exceeds tree depth");
1218  static_assert(L0 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
1219  using TreeType = _TreeType;
1220  using ValueType = typename TreeType::ValueType;
1221  using RootNodeT = typename TreeType::RootNodeType;
1222  using LeafNodeT = typename TreeType::LeafNodeType;
1224  using InvTreeT = typename RootNodeT::NodeChainType;
1225  using NodeT0 = typename InvTreeT::template Get<L0>;
1226 
1228  ValueAccessor1(TreeType& tree) : BaseT(tree), mKey0(Coord::max()), mNode0(nullptr)
1229  {
1230  }
1231 
1233  ValueAccessor1(const ValueAccessor1& other) : BaseT(other) { this->copy(other); }
1234 
1236  static Index numCacheLevels() { return 1; }
1237 
1240  {
1241  if (&other != this) {
1242  this->BaseT::operator=(other);
1243  this->copy(other);
1244  }
1245  return *this;
1246  }
1247 
1249  ~ValueAccessor1() override = default;
1250 
1253  bool isCached(const Coord& xyz) const
1254  {
1255  assert(BaseT::mTree);
1256  return this->isHashed(xyz);
1257  }
1258 
1260  const ValueType& getValue(const Coord& xyz) const
1261  {
1262  assert(BaseT::mTree);
1263  if (this->isHashed(xyz)) {
1264  assert(mNode0);
1265  return mNode0->getValueAndCache(xyz, this->self());
1266  }
1267  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
1268  }
1269 
1271  bool isValueOn(const Coord& xyz) const
1272  {
1273  assert(BaseT::mTree);
1274  if (this->isHashed(xyz)) {
1275  assert(mNode0);
1276  return mNode0->isValueOnAndCache(xyz, this->self());
1277  }
1278  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
1279  }
1280 
1282  bool probeValue(const Coord& xyz, ValueType& value) const
1283  {
1284  assert(BaseT::mTree);
1285  if (this->isHashed(xyz)) {
1286  assert(mNode0);
1287  return mNode0->probeValueAndCache(xyz, value, this->self());
1288  }
1289  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
1290  }
1291 
1295  int getValueDepth(const Coord& xyz) const
1296  {
1297  assert(BaseT::mTree);
1298  if (this->isHashed(xyz)) {
1299  assert(mNode0);
1300  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1301  }
1302  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
1303  }
1304 
1307  bool isVoxel(const Coord& xyz) const
1308  {
1309  assert(BaseT::mTree);
1310  if (this->isHashed(xyz)) {
1311  assert(mNode0);
1312  return mNode0->getValueLevelAndCache(xyz, this->self()) == 0;
1313  }
1314  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
1315  static_cast<int>(RootNodeT::LEVEL);
1316  }
1317 
1319  void setValue(const Coord& xyz, const ValueType& value)
1321  {
1322  assert(BaseT::mTree);
1323  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1324  if (this->isHashed(xyz)) {
1325  assert(mNode0);
1326  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1327  } else {
1328  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
1329  }
1330  }
1331  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1333 
1335  void setValueOnly(const Coord& xyz, const ValueType& value)
1336  {
1337  assert(BaseT::mTree);
1338  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1339  if (this->isHashed(xyz)) {
1340  assert(mNode0);
1341  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1342  } else {
1343  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
1344  }
1345  }
1346 
1348  void setValueOff(const Coord& xyz, const ValueType& value)
1349  {
1350  assert(BaseT::mTree);
1351  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1352  if (this->isHashed(xyz)) {
1353  assert(mNode0);
1354  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1355  } else {
1356  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
1357  }
1358  }
1359 
1363  template<typename ModifyOp>
1364  void modifyValue(const Coord& xyz, const ModifyOp& op)
1365  {
1366  assert(BaseT::mTree);
1367  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1368  if (this->isHashed(xyz)) {
1369  assert(mNode0);
1370  const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
1371  } else {
1372  BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
1373  }
1374  }
1375 
1378  template<typename ModifyOp>
1379  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1380  {
1381  assert(BaseT::mTree);
1382  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1383  if (this->isHashed(xyz)) {
1384  assert(mNode0);
1385  const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
1386  } else {
1387  BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
1388  }
1389  }
1390 
1392  void setActiveState(const Coord& xyz, bool on = true)
1393  {
1394  assert(BaseT::mTree);
1395  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1396  if (this->isHashed(xyz)) {
1397  assert(mNode0);
1398  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1399  } else {
1400  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
1401  }
1402  }
1404  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1406  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1407 
1409  template<typename NodeT>
1410  NodeT* getNode()
1411  {
1412  const NodeT* node = nullptr;
1413  this->getNode(node);
1414  return const_cast<NodeT*>(node);
1415  }
1416 
1419  template<typename NodeT>
1420  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1421 
1425  template<typename NodeT>
1426  void eraseNode()
1427  {
1428  const NodeT* node = nullptr;
1429  this->eraseNode(node);
1430  }
1431 
1434  void addLeaf(LeafNodeT* leaf)
1435  {
1436  assert(BaseT::mTree);
1437  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
1438  BaseT::mTree->root().addLeaf(leaf);
1439  }
1440 
1443  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1444  {
1445  assert(BaseT::mTree);
1446  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
1447  BaseT::mTree->root().addTile(level, xyz, value, state);
1448  }
1449 
1456  LeafNodeT* touchLeaf(const Coord& xyz)
1457  {
1458  assert(BaseT::mTree);
1459  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1460  if (this->isHashed(xyz)) {
1461  assert(mNode0);
1462  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1463  }
1464  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
1465  }
1466 
1469  template<typename NodeT>
1470  NodeT* probeNode(const Coord& xyz)
1471  {
1472  assert(BaseT::mTree);
1473  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1475  if ((std::is_same<NodeT, NodeT0>::value)) {
1476  if (this->isHashed(xyz)) {
1477  assert(mNode0);
1478  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
1479  }
1480  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1481  }
1482  return nullptr;
1484  }
1485  LeafNodeT* probeLeaf(const Coord& xyz)
1486  {
1487  return this->template probeNode<LeafNodeT>(xyz);
1488  }
1489 
1492  template<typename NodeT>
1493  const NodeT* probeConstNode(const Coord& xyz) const
1494  {
1495  assert(BaseT::mTree);
1497  if ((std::is_same<NodeT, NodeT0>::value)) {
1498  if (this->isHashed(xyz)) {
1499  assert(mNode0);
1500  return reinterpret_cast<const NodeT*>(mNode0);
1501  }
1502  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1503  }
1504  return nullptr;
1506  }
1507  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1508  {
1509  return this->template probeConstNode<LeafNodeT>(xyz);
1510  }
1511  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
1512 
1514  void clear() override
1515  {
1516  mKey0 = Coord::max();
1517  mNode0 = nullptr;
1518  }
1519 
1520 private:
1521  // Allow nodes to insert themselves into the cache.
1522  template<typename> friend class RootNode;
1523  template<typename, Index> friend class InternalNode;
1524  template<typename, Index> friend class LeafNode;
1525  // Allow trees to deregister themselves.
1526  template<typename> friend class Tree;
1527 
1528  // This private method is merely for convenience.
1529  inline ValueAccessor1& self() const { return const_cast<ValueAccessor1&>(*this); }
1530 
1531  void getNode(const NodeT0*& node) { node = mNode0; }
1532  void getNode(const RootNodeT*& node)
1533  {
1534  node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
1535  }
1536  template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
1537  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = nullptr; }
1538  template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1539 
1541  inline void copy(const ValueAccessor1& other)
1542  {
1543  mKey0 = other.mKey0;
1544  mNode0 = other.mNode0;
1545  }
1546 
1549  void release() override
1550  {
1551  this->BaseT::release();
1552  this->clear();
1553  }
1558  inline void insert(const Coord& xyz, const NodeT0* node)
1559  {
1560  assert(node);
1561  mKey0 = xyz & ~(NodeT0::DIM-1);
1562  mNode0 = node;
1563  }
1564 
1567  template<typename OtherNodeType> inline void insert(const Coord&, const OtherNodeType*) {}
1568 
1569  inline bool isHashed(const Coord& xyz) const
1570  {
1571  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1572  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1573  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1574  }
1575  mutable Coord mKey0;
1576  mutable const NodeT0* mNode0;
1577 }; // ValueAccessor1
1578 
1579 
1587 template<typename _TreeType, bool IsSafe, Index L0, Index L1>
1589 {
1590 public:
1591  static_assert(_TreeType::DEPTH >= 3, "cache size exceeds tree depth");
1592  static_assert(L0 < L1, "invalid cache level");
1593  static_assert(L1 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
1594 
1595  using TreeType = _TreeType;
1596  using ValueType = typename TreeType::ValueType;
1597  using RootNodeT = typename TreeType::RootNodeType;
1598  using LeafNodeT = typename TreeType::LeafNodeType;
1600  using InvTreeT = typename RootNodeT::NodeChainType;
1601  using NodeT0 = typename InvTreeT::template Get<L0>;
1602  using NodeT1 = typename InvTreeT::template Get<L1>;
1603 
1606  mKey0(Coord::max()), mNode0(nullptr),
1607  mKey1(Coord::max()), mNode1(nullptr) {}
1608 
1610  ValueAccessor2(const ValueAccessor2& other) : BaseT(other) { this->copy(other); }
1611 
1613  static Index numCacheLevels() { return 2; }
1614 
1617  {
1618  if (&other != this) {
1619  this->BaseT::operator=(other);
1620  this->copy(other);
1621  }
1622  return *this;
1623  }
1624 
1626  ~ValueAccessor2() override = default;
1627 
1630  bool isCached(const Coord& xyz) const
1631  {
1632  assert(BaseT::mTree);
1633  return this->isHashed1(xyz) || this->isHashed0(xyz);
1634  }
1635 
1637  const ValueType& getValue(const Coord& xyz) const
1638  {
1639  assert(BaseT::mTree);
1640  if (this->isHashed0(xyz)) {
1641  assert(mNode0);
1642  return mNode0->getValueAndCache(xyz, this->self());
1643  } else if (this->isHashed1(xyz)) {
1644  assert(mNode1);
1645  return mNode1->getValueAndCache(xyz, this->self());
1646  }
1647  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
1648  }
1649 
1651  bool isValueOn(const Coord& xyz) const
1652  {
1653  assert(BaseT::mTree);
1654  if (this->isHashed0(xyz)) {
1655  assert(mNode0);
1656  return mNode0->isValueOnAndCache(xyz, this->self());
1657  } else if (this->isHashed1(xyz)) {
1658  assert(mNode1);
1659  return mNode1->isValueOnAndCache(xyz, this->self());
1660  }
1661  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
1662  }
1663 
1665  bool probeValue(const Coord& xyz, ValueType& value) const
1666  {
1667  assert(BaseT::mTree);
1668  if (this->isHashed0(xyz)) {
1669  assert(mNode0);
1670  return mNode0->probeValueAndCache(xyz, value, this->self());
1671  } else if (this->isHashed1(xyz)) {
1672  assert(mNode1);
1673  return mNode1->probeValueAndCache(xyz, value, this->self());
1674  }
1675  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
1676  }
1677 
1681  int getValueDepth(const Coord& xyz) const
1682  {
1683  assert(BaseT::mTree);
1684  if (this->isHashed0(xyz)) {
1685  assert(mNode0);
1686  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1687  } else if (this->isHashed1(xyz)) {
1688  assert(mNode1);
1689  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
1690  }
1691  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
1692  }
1693 
1696  bool isVoxel(const Coord& xyz) const
1697  {
1698  assert(BaseT::mTree);
1699  if (this->isHashed0(xyz)) {
1700  assert(mNode0);
1701  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
1702  } else if (this->isHashed1(xyz)) {
1703  assert(mNode1);
1704  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
1705  }
1706  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
1707  static_cast<int>(RootNodeT::LEVEL);
1708  }
1709 
1711  void setValue(const Coord& xyz, const ValueType& value)
1713  {
1714  assert(BaseT::mTree);
1715  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1716  if (this->isHashed0(xyz)) {
1717  assert(mNode0);
1718  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1719  } else if (this->isHashed1(xyz)) {
1720  assert(mNode1);
1721  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
1722  } else {
1723  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
1724  }
1725  }
1726  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1728 
1730  void setValueOnly(const Coord& xyz, const ValueType& value)
1731  {
1732  assert(BaseT::mTree);
1733  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1734  if (this->isHashed0(xyz)) {
1735  assert(mNode0);
1736  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1737  } else if (this->isHashed1(xyz)) {
1738  assert(mNode1);
1739  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
1740  } else {
1741  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
1742  }
1743  }
1744 
1746  void setValueOff(const Coord& xyz, const ValueType& value)
1747  {
1748  assert(BaseT::mTree);
1749  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1750  if (this->isHashed0(xyz)) {
1751  assert(mNode0);
1752  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1753  } else if (this->isHashed1(xyz)) {
1754  assert(mNode1);
1755  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
1756  } else {
1757  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
1758  }
1759  }
1760 
1764  template<typename ModifyOp>
1765  void modifyValue(const Coord& xyz, const ModifyOp& op)
1766  {
1767  assert(BaseT::mTree);
1768  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1769  if (this->isHashed0(xyz)) {
1770  assert(mNode0);
1771  const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
1772  } else if (this->isHashed1(xyz)) {
1773  assert(mNode1);
1774  const_cast<NodeT1*>(mNode1)->modifyValueAndCache(xyz, op, *this);
1775  } else {
1776  BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
1777  }
1778  }
1779 
1782  template<typename ModifyOp>
1783  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1784  {
1785  assert(BaseT::mTree);
1786  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1787  if (this->isHashed0(xyz)) {
1788  assert(mNode0);
1789  const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
1790  } else if (this->isHashed1(xyz)) {
1791  assert(mNode1);
1792  const_cast<NodeT1*>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *this);
1793  } else {
1794  BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
1795  }
1796  }
1797 
1799  void setActiveState(const Coord& xyz, bool on = true)
1800  {
1801  assert(BaseT::mTree);
1802  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
1803  if (this->isHashed0(xyz)) {
1804  assert(mNode0);
1805  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1806  } else if (this->isHashed1(xyz)) {
1807  assert(mNode1);
1808  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
1809  } else {
1810  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
1811  }
1812  }
1814  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1816  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1817 
1819  template<typename NodeT>
1820  NodeT* getNode()
1821  {
1822  const NodeT* node = nullptr;
1823  this->getNode(node);
1824  return const_cast<NodeT*>(node);
1825  }
1826 
1829  template<typename NodeT>
1830  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1831 
1835  template<typename NodeT>
1836  void eraseNode()
1837  {
1838  const NodeT* node = nullptr;
1839  this->eraseNode(node);
1840  }
1841 
1844  void addLeaf(LeafNodeT* leaf)
1845  {
1846  assert(BaseT::mTree);
1847  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
1848  if (this->isHashed1(leaf->origin())) {
1849  assert(mNode1);
1850  return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
1851  }
1852  BaseT::mTree->root().addLeafAndCache(leaf, *this);
1853  }
1854 
1857  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1858  {
1859  assert(BaseT::mTree);
1860  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
1861  if (this->isHashed1(xyz)) {
1862  assert(mNode1);
1863  return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
1864  }
1865  BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
1866  }
1867 
1874  LeafNodeT* touchLeaf(const Coord& xyz)
1875  {
1876  assert(BaseT::mTree);
1877  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1878  if (this->isHashed0(xyz)) {
1879  assert(mNode0);
1880  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1881  } else if (this->isHashed1(xyz)) {
1882  assert(mNode1);
1883  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
1884  }
1885  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
1886  }
1889  template<typename NodeT>
1890  NodeT* probeNode(const Coord& xyz)
1891  {
1892  assert(BaseT::mTree);
1893  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
1895  if ((std::is_same<NodeT, NodeT0>::value)) {
1896  if (this->isHashed0(xyz)) {
1897  assert(mNode0);
1898  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
1899  } else if (this->isHashed1(xyz)) {
1900  assert(mNode1);
1901  return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
1902  }
1903  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1904  } else if ((std::is_same<NodeT, NodeT1>::value)) {
1905  if (this->isHashed1(xyz)) {
1906  assert(mNode1);
1907  return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
1908  }
1909  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1910  }
1911  return nullptr;
1913  }
1916  LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
1917 
1920  template<typename NodeT>
1921  const NodeT* probeConstLeaf(const Coord& xyz) const
1922  {
1924  if ((std::is_same<NodeT, NodeT0>::value)) {
1925  if (this->isHashed0(xyz)) {
1926  assert(mNode0);
1927  return reinterpret_cast<const NodeT*>(mNode0);
1928  } else if (this->isHashed1(xyz)) {
1929  assert(mNode1);
1930  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
1931  }
1932  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1933  } else if ((std::is_same<NodeT, NodeT1>::value)) {
1934  if (this->isHashed1(xyz)) {
1935  assert(mNode1);
1936  return reinterpret_cast<const NodeT*>(mNode1);
1937  }
1938  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1939  }
1940  return nullptr;
1942  }
1945  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1946  {
1947  return this->template probeConstNode<LeafNodeT>(xyz);
1948  }
1949  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
1950 
1953  template<typename NodeT>
1954  const NodeT* probeConstNode(const Coord& xyz) const
1955  {
1956  assert(BaseT::mTree);
1958  if ((std::is_same<NodeT, NodeT0>::value)) {
1959  if (this->isHashed0(xyz)) {
1960  assert(mNode0);
1961  return reinterpret_cast<const NodeT*>(mNode0);
1962  } else if (this->isHashed1(xyz)) {
1963  assert(mNode1);
1964  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
1965  }
1966  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1967  } else if ((std::is_same<NodeT, NodeT1>::value)) {
1968  if (this->isHashed1(xyz)) {
1969  assert(mNode1);
1970  return reinterpret_cast<const NodeT*>(mNode1);
1971  }
1972  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1973  }
1974  return nullptr;
1976  }
1977 
1979  void clear() override
1980  {
1981  mKey0 = Coord::max();
1982  mNode0 = nullptr;
1983  mKey1 = Coord::max();
1984  mNode1 = nullptr;
1985  }
1986 
1987 private:
1988  // Allow nodes to insert themselves into the cache.
1989  template<typename> friend class RootNode;
1990  template<typename, Index> friend class InternalNode;
1991  template<typename, Index> friend class LeafNode;
1992  // Allow trees to deregister themselves.
1993  template<typename> friend class Tree;
1994 
1995  // This private method is merely for convenience.
1996  inline ValueAccessor2& self() const { return const_cast<ValueAccessor2&>(*this); }
1997 
1998  void getNode(const NodeT0*& node) { node = mNode0; }
1999  void getNode(const NodeT1*& node) { node = mNode1; }
2000  void getNode(const RootNodeT*& node)
2001  {
2002  node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
2003  }
2004  template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
2005 
2006  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = nullptr; }
2007  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = nullptr; }
2008  template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
2009 
2011  inline void copy(const ValueAccessor2& other)
2012  {
2013  mKey0 = other.mKey0;
2014  mNode0 = other.mNode0;
2015  mKey1 = other.mKey1;
2016  mNode1 = other.mNode1;
2017  }
2018 
2021  void release() override
2022  {
2023  this->BaseT::release();
2024  this->clear();
2025  }
2026 
2031  inline void insert(const Coord& xyz, const NodeT0* node)
2032  {
2033  assert(node);
2034  mKey0 = xyz & ~(NodeT0::DIM-1);
2035  mNode0 = node;
2036  }
2037  inline void insert(const Coord& xyz, const NodeT1* node)
2038  {
2039  assert(node);
2040  mKey1 = xyz & ~(NodeT1::DIM-1);
2041  mNode1 = node;
2042  }
2045  template<typename NodeT> inline void insert(const Coord&, const NodeT*) {}
2046 
2047  inline bool isHashed0(const Coord& xyz) const
2048  {
2049  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2050  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2051  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2052  }
2053  inline bool isHashed1(const Coord& xyz) const
2054  {
2055  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2056  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2057  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2058  }
2059  mutable Coord mKey0;
2060  mutable const NodeT0* mNode0;
2061  mutable Coord mKey1;
2062  mutable const NodeT1* mNode1;
2063 }; // ValueAccessor2
2064 
2065 
2076 template<typename _TreeType, bool IsSafe, Index L0, Index L1, Index L2>
2078 {
2079 public:
2080  static_assert(_TreeType::DEPTH >= 4, "cache size exceeds tree depth");
2081  static_assert(L0 < L1, "invalid cache level");
2082  static_assert(L1 < L2, "invalid cache level");
2083  static_assert(L2 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
2084 
2085  using TreeType = _TreeType;
2086  using ValueType = typename TreeType::ValueType;
2087  using RootNodeT = typename TreeType::RootNodeType;
2088  using LeafNodeT = typename TreeType::LeafNodeType;
2090  using InvTreeT = typename RootNodeT::NodeChainType;
2091  using NodeT0 = typename InvTreeT::template Get<L0>;
2092  using NodeT1 = typename InvTreeT::template Get<L1>;
2093  using NodeT2 = typename InvTreeT::template Get<L2>;
2094 
2097  mKey0(Coord::max()), mNode0(nullptr),
2098  mKey1(Coord::max()), mNode1(nullptr),
2099  mKey2(Coord::max()), mNode2(nullptr) {}
2100 
2102  ValueAccessor3(const ValueAccessor3& other) : BaseT(other) { this->copy(other); }
2103 
2106  {
2107  if (&other != this) {
2108  this->BaseT::operator=(other);
2109  this->copy(other);
2110  }
2111  return *this;
2112  }
2113 
2115  static Index numCacheLevels() { return 3; }
2116 
2118  ~ValueAccessor3() override = default;
2119 
2122  bool isCached(const Coord& xyz) const
2123  {
2124  assert(BaseT::mTree);
2125  return this->isHashed2(xyz) || this->isHashed1(xyz) || this->isHashed0(xyz);
2126  }
2127 
2129  const ValueType& getValue(const Coord& xyz) const
2130  {
2131  assert(BaseT::mTree);
2132  if (this->isHashed0(xyz)) {
2133  assert(mNode0);
2134  return mNode0->getValueAndCache(xyz, this->self());
2135  } else if (this->isHashed1(xyz)) {
2136  assert(mNode1);
2137  return mNode1->getValueAndCache(xyz, this->self());
2138  } else if (this->isHashed2(xyz)) {
2139  assert(mNode2);
2140  return mNode2->getValueAndCache(xyz, this->self());
2141  }
2142  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
2143  }
2144 
2146  bool isValueOn(const Coord& xyz) const
2147  {
2148  assert(BaseT::mTree);
2149  if (this->isHashed0(xyz)) {
2150  assert(mNode0);
2151  return mNode0->isValueOnAndCache(xyz, this->self());
2152  } else if (this->isHashed1(xyz)) {
2153  assert(mNode1);
2154  return mNode1->isValueOnAndCache(xyz, this->self());
2155  } else if (this->isHashed2(xyz)) {
2156  assert(mNode2);
2157  return mNode2->isValueOnAndCache(xyz, this->self());
2158  }
2159  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
2160  }
2161 
2163  bool probeValue(const Coord& xyz, ValueType& value) const
2164  {
2165  assert(BaseT::mTree);
2166  if (this->isHashed0(xyz)) {
2167  assert(mNode0);
2168  return mNode0->probeValueAndCache(xyz, value, this->self());
2169  } else if (this->isHashed1(xyz)) {
2170  assert(mNode1);
2171  return mNode1->probeValueAndCache(xyz, value, this->self());
2172  } else if (this->isHashed2(xyz)) {
2173  assert(mNode2);
2174  return mNode2->probeValueAndCache(xyz, value, this->self());
2175  }
2176  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
2177  }
2178 
2182  int getValueDepth(const Coord& xyz) const
2183  {
2184  assert(BaseT::mTree);
2185  if (this->isHashed0(xyz)) {
2186  assert(mNode0);
2187  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
2188  } else if (this->isHashed1(xyz)) {
2189  assert(mNode1);
2190  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
2191  } else if (this->isHashed2(xyz)) {
2192  assert(mNode2);
2193  return RootNodeT::LEVEL - mNode2->getValueLevelAndCache(xyz, this->self());
2194  }
2195  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
2196  }
2197 
2200  bool isVoxel(const Coord& xyz) const
2201  {
2202  assert(BaseT::mTree);
2203  if (this->isHashed0(xyz)) {
2204  assert(mNode0);
2205  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
2206  } else if (this->isHashed1(xyz)) {
2207  assert(mNode1);
2208  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
2209  } else if (this->isHashed2(xyz)) {
2210  assert(mNode2);
2211  return mNode2->getValueLevelAndCache(xyz, this->self())==0;
2212  }
2213  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
2214  static_cast<int>(RootNodeT::LEVEL);
2215  }
2216 
2218  void setValue(const Coord& xyz, const ValueType& value)
2220  {
2221  assert(BaseT::mTree);
2222  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2223  if (this->isHashed0(xyz)) {
2224  assert(mNode0);
2225  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
2226  } else if (this->isHashed1(xyz)) {
2227  assert(mNode1);
2228  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
2229  } else if (this->isHashed2(xyz)) {
2230  assert(mNode2);
2231  const_cast<NodeT2*>(mNode2)->setValueAndCache(xyz, value, *this);
2232  } else {
2233  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
2234  }
2235  }
2236  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
2238 
2240  void setValueOnly(const Coord& xyz, const ValueType& value)
2241  {
2242  assert(BaseT::mTree);
2243  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2244  if (this->isHashed0(xyz)) {
2245  assert(mNode0);
2246  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
2247  } else if (this->isHashed1(xyz)) {
2248  assert(mNode1);
2249  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
2250  } else if (this->isHashed2(xyz)) {
2251  assert(mNode2);
2252  const_cast<NodeT2*>(mNode2)->setValueOnlyAndCache(xyz, value, *this);
2253  } else {
2254  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
2255  }
2256  }
2257 
2259  void setValueOff(const Coord& xyz, const ValueType& value)
2260  {
2261  assert(BaseT::mTree);
2262  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2263  if (this->isHashed0(xyz)) {
2264  assert(mNode0);
2265  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
2266  } else if (this->isHashed1(xyz)) {
2267  assert(mNode1);
2268  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
2269  } else if (this->isHashed2(xyz)) {
2270  assert(mNode2);
2271  const_cast<NodeT2*>(mNode2)->setValueOffAndCache(xyz, value, *this);
2272  } else {
2273  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
2274  }
2275  }
2276 
2280  template<typename ModifyOp>
2281  void modifyValue(const Coord& xyz, const ModifyOp& op)
2282  {
2283  assert(BaseT::mTree);
2284  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2285  if (this->isHashed0(xyz)) {
2286  assert(mNode0);
2287  const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
2288  } else if (this->isHashed1(xyz)) {
2289  assert(mNode1);
2290  const_cast<NodeT1*>(mNode1)->modifyValueAndCache(xyz, op, *this);
2291  } else if (this->isHashed2(xyz)) {
2292  assert(mNode2);
2293  const_cast<NodeT2*>(mNode2)->modifyValueAndCache(xyz, op, *this);
2294  } else {
2295  BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
2296  }
2297  }
2298 
2301  template<typename ModifyOp>
2302  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
2303  {
2304  assert(BaseT::mTree);
2305  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2306  if (this->isHashed0(xyz)) {
2307  assert(mNode0);
2308  const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
2309  } else if (this->isHashed1(xyz)) {
2310  assert(mNode1);
2311  const_cast<NodeT1*>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *this);
2312  } else if (this->isHashed2(xyz)) {
2313  assert(mNode2);
2314  const_cast<NodeT2*>(mNode2)->modifyValueAndActiveStateAndCache(xyz, op, *this);
2315  } else {
2316  BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
2317  }
2318  }
2319 
2321  void setActiveState(const Coord& xyz, bool on = true)
2322  {
2323  assert(BaseT::mTree);
2324  static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
2325  if (this->isHashed0(xyz)) {
2326  assert(mNode0);
2327  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
2328  } else if (this->isHashed1(xyz)) {
2329  assert(mNode1);
2330  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
2331  } else if (this->isHashed2(xyz)) {
2332  assert(mNode2);
2333  const_cast<NodeT2*>(mNode2)->setActiveStateAndCache(xyz, on, *this);
2334  } else {
2335  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
2336  }
2337  }
2339  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
2341  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
2342 
2344  template<typename NodeT>
2345  NodeT* getNode()
2346  {
2347  const NodeT* node = nullptr;
2348  this->getNode(node);
2349  return const_cast<NodeT*>(node);
2350  }
2351 
2354  template<typename NodeT>
2355  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
2356 
2360  template<typename NodeT>
2361  void eraseNode()
2362  {
2363  const NodeT* node = nullptr;
2364  this->eraseNode(node);
2365  }
2366 
2369  void addLeaf(LeafNodeT* leaf)
2370  {
2371  assert(BaseT::mTree);
2372  static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
2373  if (this->isHashed1(leaf->origin())) {
2374  assert(mNode1);
2375  return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
2376  } else if (this->isHashed2(leaf->origin())) {
2377  assert(mNode2);
2378  return const_cast<NodeT2*>(mNode2)->addLeafAndCache(leaf, *this);
2379  }
2380  BaseT::mTree->root().addLeafAndCache(leaf, *this);
2381  }
2382 
2385  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
2386  {
2387  assert(BaseT::mTree);
2388  static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
2389  if (this->isHashed1(xyz)) {
2390  assert(mNode1);
2391  return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
2392  } if (this->isHashed2(xyz)) {
2393  assert(mNode2);
2394  return const_cast<NodeT2*>(mNode2)->addTileAndCache(level, xyz, value, state, *this);
2395  }
2396  BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
2397  }
2398 
2405  LeafNodeT* touchLeaf(const Coord& xyz)
2406  {
2407  assert(BaseT::mTree);
2408  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
2409  if (this->isHashed0(xyz)) {
2410  assert(mNode0);
2411  return const_cast<NodeT0*>(mNode0);
2412  } else if (this->isHashed1(xyz)) {
2413  assert(mNode1);
2414  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
2415  } else if (this->isHashed2(xyz)) {
2416  assert(mNode2);
2417  return const_cast<NodeT2*>(mNode2)->touchLeafAndCache(xyz, *this);
2418  }
2419  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
2420  }
2423  template<typename NodeT>
2424  NodeT* probeNode(const Coord& xyz)
2425  {
2426  assert(BaseT::mTree);
2427  static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
2429  if ((std::is_same<NodeT, NodeT0>::value)) {
2430  if (this->isHashed0(xyz)) {
2431  assert(mNode0);
2432  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
2433  } else if (this->isHashed1(xyz)) {
2434  assert(mNode1);
2435  return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
2436  } else if (this->isHashed2(xyz)) {
2437  assert(mNode2);
2438  return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
2439  }
2440  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2441  } else if ((std::is_same<NodeT, NodeT1>::value)) {
2442  if (this->isHashed1(xyz)) {
2443  assert(mNode1);
2444  return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
2445  } else if (this->isHashed2(xyz)) {
2446  assert(mNode2);
2447  return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
2448  }
2449  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2450  } else if ((std::is_same<NodeT, NodeT2>::value)) {
2451  if (this->isHashed2(xyz)) {
2452  assert(mNode2);
2453  return reinterpret_cast<NodeT*>(const_cast<NodeT2*>(mNode2));
2454  }
2455  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2456  }
2457  return nullptr;
2459  }
2462  LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
2463 
2466  template<typename NodeT>
2467  const NodeT* probeConstNode(const Coord& xyz) const
2468  {
2469  assert(BaseT::mTree);
2471  if ((std::is_same<NodeT, NodeT0>::value)) {
2472  if (this->isHashed0(xyz)) {
2473  assert(mNode0);
2474  return reinterpret_cast<const NodeT*>(mNode0);
2475  } else if (this->isHashed1(xyz)) {
2476  assert(mNode1);
2477  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2478  } else if (this->isHashed2(xyz)) {
2479  assert(mNode2);
2480  return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2481  }
2482  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2483  } else if ((std::is_same<NodeT, NodeT1>::value)) {
2484  if (this->isHashed1(xyz)) {
2485  assert(mNode1);
2486  return reinterpret_cast<const NodeT*>(mNode1);
2487  } else if (this->isHashed2(xyz)) {
2488  assert(mNode2);
2489  return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2490  }
2491  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2492  } else if ((std::is_same<NodeT, NodeT2>::value)) {
2493  if (this->isHashed2(xyz)) {
2494  assert(mNode2);
2495  return reinterpret_cast<const NodeT*>(mNode2);
2496  }
2497  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2498  }
2499  return nullptr;
2501  }
2504  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
2505  {
2506  return this->template probeConstNode<LeafNodeT>(xyz);
2507  }
2508  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
2509 
2511  void clear() override
2512  {
2513  mKey0 = Coord::max();
2514  mNode0 = nullptr;
2515  mKey1 = Coord::max();
2516  mNode1 = nullptr;
2517  mKey2 = Coord::max();
2518  mNode2 = nullptr;
2519  }
2520 
2521 private:
2522  // Allow nodes to insert themselves into the cache.
2523  template<typename> friend class RootNode;
2524  template<typename, Index> friend class InternalNode;
2525  template<typename, Index> friend class LeafNode;
2526  // Allow trees to deregister themselves.
2527  template<typename> friend class Tree;
2528 
2529  // This private method is merely for convenience.
2530  inline ValueAccessor3& self() const { return const_cast<ValueAccessor3&>(*this); }
2531 
2533  inline void copy(const ValueAccessor3& other)
2534  {
2535  mKey0 = other.mKey0;
2536  mNode0 = other.mNode0;
2537  mKey1 = other.mKey1;
2538  mNode1 = other.mNode1;
2539  mKey2 = other.mKey2;
2540  mNode2 = other.mNode2;
2541  }
2542 
2545  void release() override
2546  {
2547  this->BaseT::release();
2548  this->clear();
2549  }
2550  void getNode(const NodeT0*& node) { node = mNode0; }
2551  void getNode(const NodeT1*& node) { node = mNode1; }
2552  void getNode(const NodeT2*& node) { node = mNode2; }
2553  void getNode(const RootNodeT*& node)
2554  {
2555  node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
2556  }
2557  template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
2558 
2559  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = nullptr; }
2560  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = nullptr; }
2561  void eraseNode(const NodeT2*) { mKey2 = Coord::max(); mNode2 = nullptr; }
2562  template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
2563 
2568  inline void insert(const Coord& xyz, const NodeT0* node)
2569  {
2570  assert(node);
2571  mKey0 = xyz & ~(NodeT0::DIM-1);
2572  mNode0 = node;
2573  }
2574  inline void insert(const Coord& xyz, const NodeT1* node)
2575  {
2576  assert(node);
2577  mKey1 = xyz & ~(NodeT1::DIM-1);
2578  mNode1 = node;
2579  }
2580  inline void insert(const Coord& xyz, const NodeT2* node)
2581  {
2582  assert(node);
2583  mKey2 = xyz & ~(NodeT2::DIM-1);
2584  mNode2 = node;
2585  }
2588  template<typename OtherNodeType>
2589  inline void insert(const Coord&, const OtherNodeType*)
2590  {
2591  }
2592  inline bool isHashed0(const Coord& xyz) const
2593  {
2594  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2595  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2596  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2597  }
2598  inline bool isHashed1(const Coord& xyz) const
2599  {
2600  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2601  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2602  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2603  }
2604  inline bool isHashed2(const Coord& xyz) const
2605  {
2606  return (xyz[0] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[0]
2607  && (xyz[1] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[1]
2608  && (xyz[2] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[2];
2609  }
2610  mutable Coord mKey0;
2611  mutable const NodeT0* mNode0;
2612  mutable Coord mKey1;
2613  mutable const NodeT1* mNode1;
2614  mutable Coord mKey2;
2615  mutable const NodeT2* mNode2;
2616 }; // ValueAccessor3
2617 
2618 } // namespace tree
2619 } // namespace OPENVDB_VERSION_NAME
2620 } // namespace openvdb
2621 
2622 #endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
void insert(const Coord &xyz, const OtherNodeType *node)
Forward the given node to another level of the cache.
Definition: ValueAccessor.h:569
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:285
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:226
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:1470
const NodeType * probeConstNode(const Coord &xyz)
Definition: ValueAccessor.h:905
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:1331
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:2467
ValueAccessor2(TreeType &tree)
Constructor from a tree.
Definition: ValueAccessor.h:1605
ValueAccessor2(const ValueAccessor2 &other)
Copy constructor.
Definition: ValueAccessor.h:1610
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:2122
friend class LeafNode
Definition: ValueAccessor.h:404
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:1681
ValueAccessor0(const ValueAccessor0 &other)
Definition: ValueAccessor.h:1012
CacheItem(TreeCacheT &parent)
Definition: ValueAccessor.h:528
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:1410
void insertNode(const Coord &xyz, NodeT &node)
Definition: ValueAccessor.h:1830
friend class LeafNode
Definition: ValueAccessor.h:1524
void getNode(OtherNodeType *&node)
Forward the request to another level of the cache.
Definition: ValueAccessor.h:592
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:276
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:1260
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
Definition: ValueAccessor.h:1816
ValueAccessor with no mutex and no node caching.
Definition: ValueAccessor.h:50
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:2146
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition: ValueAccessor.h:1979
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:1222
bool isValueOn(const Coord &xyz)
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:688
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition: ValueAccessor.h:1613
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:842
typename NodeType::LeafNodeType LeafNodeType
Definition: ValueAccessor.h:525
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:657
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:195
This accessor is thread-safe (at the cost of speed) for both reading and writing to a tree...
Definition: ValueAccessor.h:501
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:2281
void insertNode(const Coord &xyz, NodeT &node)
Definition: ValueAccessor.h:1420
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: ValueAccessor.h:298
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:2321
const LeafNodeType * probeConstLeaf(const Coord &xyz)
Definition: ValueAccessor.h:647
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:255
LeafNodeType * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:882
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:200
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:1598
ValueAccessorBase(const ValueAccessorBase &other)
Definition: ValueAccessor.h:112
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:1857
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:1954
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:1043
typename NodeType::ValueType ValueType
Definition: ValueAccessor.h:524
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:1348
TreeType * getTree() const
Return a pointer to the tree associated with this accessor.
Definition: ValueAccessor.h:108
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:2302
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:793
void setActiveState(const Coord &xyz, bool on)
Definition: ValueAccessor.h:976
void erase(const RootNodeType *)
Definition: ValueAccessor.h:850
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:769
const ValueType & getValue(const Coord &xyz)
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:595
void insert(const Coord &, const OtherNodeType *)
Definition: ValueAccessor.h:848
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:219
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
Definition: ValueAccessor.h:2341
ValueAccessorBase & operator=(const ValueAccessorBase &other)
Definition: ValueAccessor.h:117
friend class Tree
Definition: ValueAccessor.h:1198
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1511
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition: ValueAccessor.h:2511
CacheItem(TreeCacheT &parent)
Definition: ValueAccessor.h:832
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:1052
friend class RootNode
Definition: ValueAccessor.h:1989
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:358
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:1696
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1183
ValueAccessor1(const ValueAccessor1 &other)
Copy constructor.
Definition: ValueAccessor.h:1233
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:1006
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:448
ValueAccessorBase(TreeType &tree)
Definition: ValueAccessor.h:97
Definition: Tree.h:174
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: ValueAccessor.h:1124
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:2086
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:266
typename RootNodeT::NodeChainType InvTreeT
Definition: ValueAccessor.h:1600
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:729
friend class RootNode
Definition: ValueAccessor.h:1522
TreeType TreeType
Definition: ValueAccessor.h:1219
typename RootNodeType::ValueType ValueType
Definition: ValueAccessor.h:829
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
Definition: ValueAccessor.h:1015
bool isVoxel(const Coord &xyz)
Definition: ValueAccessor.h:927
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:1307
LeafNodeType * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:637
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:1493
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:364
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:1730
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1156
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:1746
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:1637
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:1783
ValueAccessor0 & operator=(const ValueAccessor0 &other)
Definition: ValueAccessor.h:1017
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:1036
friend class InternalNode
Definition: ValueAccessor.h:2524
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:2508
void insertNode(const Coord &xyz, NodeType &node)
Definition: ValueAccessor.h:315
void insertNode(const Coord &, NodeT &)
Definition: ValueAccessor.h:1131
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:1335
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:1115
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:1379
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:460
void eraseNode()
Definition: ValueAccessor.h:1426
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:189
void eraseNode()
Definition: ValueAccessor.h:325
static bool isSafe()
Return true if this accessor is safe, i.e. registered by the tree from which it is constructed...
Definition: ValueAccessor.h:95
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:1443
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:1364
ValueAccessor(const ValueAccessor &other)
Definition: ValueAccessor.h:472
ValueAccessor3(TreeType &tree)
Constructor from a tree.
Definition: ValueAccessor.h:2096
void insertNode(const Coord &xyz, NodeT &node)
Definition: ValueAccessor.h:2355
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:1596
friend class Tree
Definition: ValueAccessor.h:1993
typename NodeVecT::Front RootNodeType
Definition: ValueAccessor.h:828
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1485
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:1890
void clear()
Erase the nodes at this and lower levels of the cache.
Definition: ValueAccessor.h:578
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
Definition: ValueAccessor.h:1814
void clear() override
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:393
int getValueDepth(const Coord &xyz)
Definition: ValueAccessor.h:911
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:1074
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:246
Definition: ValueAccessor.h:57
ValueAccessor2 & operator=(const ValueAccessor2 &other)
Asignment operator.
Definition: ValueAccessor.h:1616
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:1765
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:238
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:2259
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
void getNode(const NodeType *&node)
Definition: ValueAccessor.h:582
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:1220
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1949
const NodeT * probeConstNode(const Coord &xyz)
Definition: ValueAccessor.h:673
void eraseNode()
Definition: ValueAccessor.h:2361
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
Definition: ValueAccessor.h:84
bool probeValue(const Coord &xyz, ValueType &value)
Definition: ValueAccessor.h:922
Definition: ValueAccessor.h:182
void erase(const NodeType *)
Erase the node at this level.
Definition: ValueAccessor.h:572
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1874
virtual ~ValueAccessorBase()
Definition: ValueAccessor.h:102
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:1029
LeafNodeType * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:627
typename RootNodeT::NodeChainType InvTreeT
Definition: ValueAccessor.h:1224
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:1135
void setValueOff(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:969
ValueAccessorRW(TreeType &tree)
Definition: ValueAccessor.h:504
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:1253
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:556
ValueAccessor3 & operator=(const ValueAccessor3 &other)
Asignment operator.
Definition: ValueAccessor.h:2105
NodeType * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:896
friend class LeafNode
Definition: ValueAccessor.h:2525
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:459
ValueAccessor3(const ValueAccessor3 &other)
Copy constructor.
Definition: ValueAccessor.h:2102
friend class Tree
Definition: ValueAccessor.h:2527
std::numeric_limits< Int32 > CoordLimits
Definition: ValueAccessor.h:526
TreeType * mTree
Definition: ValueAccessor.h:135
void clear() override
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:1194
friend class RootNode
Definition: ValueAccessor.h:2523
typename tbb::null_mutex::scoped_lock LockT
Definition: ValueAccessor.h:192
Definition: openvdb/Exceptions.h:13
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:337
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:2424
ValueAccessor0(TreeType &tree)
Definition: ValueAccessor.h:1010
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: ValueAccessor.h:1404
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:389
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:2200
void getNode(RootNodeType *&node)
Definition: ValueAccessor.h:854
bool isCached(const Coord &) const
Return true if nodes along the path to the given voxel have been cached.
Definition: ValueAccessor.h:1026
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:188
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:92
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:2087
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:384
void erase(const OtherNodeType *node)
Erase the node at another level of the cache.
Definition: ValueAccessor.h:575
NodeT * probeNode(const Coord &xyz)
Definition: ValueAccessor.h:1164
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:781
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:471
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:1726
typename RootNodeT::ValueType ValueType
Definition: ValueAccessor.h:190
void modifyValue(const Coord &xyz, const ModifyOp &op)
Definition: ValueAccessor.h:954
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:2240
const LeafNodeType * probeConstLeaf(const Coord &xyz)
Definition: ValueAccessor.h:889
bool isValueOn(const Coord &xyz)
Definition: ValueAccessor.h:916
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:2129
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: ValueAccessor.h:300
friend class Tree
Definition: ValueAccessor.h:1526
friend class InternalNode
Definition: ValueAccessor.h:1990
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1188
bool probeValue(const Coord &xyz, ValueType &value)
Return the active state and value of the voxel at the given coordinates.
Definition: ValueAccessor.h:698
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:2369
bool isCached(const Coord &xyz) const
Return true if nodes along the path to the given voxel have been cached.
Definition: ValueAccessor.h:216
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1916
typename SubtreeT::Front NodeType
Definition: ValueAccessor.h:523
Value accessor with two levels of node caching.
Definition: ValueAccessor.h:54
Library and file format version numbers.
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1507
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:1127
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:447
typename InvTreeT::template Get< L1 > NodeT1
Definition: ValueAccessor.h:1602
friend class RootNode
Definition: ValueAccessor.h:402
friend class LeafNode
Definition: ValueAccessor.h:1991
void addLeaf(LeafNodeType *leaf)
Definition: ValueAccessor.h:604
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: ValueAccessor.h:1406
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:1007
TreeType TreeType
Definition: ValueAccessor.h:1004
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:110
bool isVoxel(const Coord &xyz) const
Definition: ValueAccessor.h:1060
const NodeT * probeConstNode(const Coord &xyz) const
Definition: ValueAccessor.h:1172
bool isVoxel(const Coord &xyz)
Definition: ValueAccessor.h:718
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:1597
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Definition: ValueAccessor.h:962
Value accessor with three levels of node caching.
Definition: ValueAccessor.h:56
LeafNodeType * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:875
friend class Tree
Definition: ValueAccessor.h:406
const NodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1921
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:93
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:348
bool isCached(const Coord &xyz) const
Definition: ValueAccessor.h:1630
void setValueOnly(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:945
TreeType TreeType
Definition: ValueAccessor.h:2085
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
Definition: ValueAccessor.h:2339
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:749
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:1078
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:1282
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:951
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:1086
Definition: Coord.h:16
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: ValueAccessor.h:1107
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:1651
void getNode(NodeType *&node)
Definition: ValueAccessor.h:583
ValueAccessor & operator=(const ValueAccessor &other)
Definition: ValueAccessor.h:202
void eraseNode()
Definition: ValueAccessor.h:1836
ValueAccessor(TreeType &tree)
Definition: ValueAccessor.h:482
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:1945
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:2405
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:1799
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Definition: ValueAccessor.h:868
typename RootNodeType::LeafNodeType LeafNodeType
Definition: ValueAccessor.h:830
typename TreeType::LeafNodeType LeafNodeT
Definition: ValueAccessor.h:2088
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:1295
const ValueType & getValue(const Coord &xyz)
Definition: ValueAccessor.h:933
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1178
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:229
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:2385
CacheItem(TreeCacheT &parent, const CacheItem &other)
Definition: ValueAccessor.h:833
typename TreeType::RootNodeType RootNodeT
Definition: ValueAccessor.h:1221
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:1820
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
Definition: ValueAccessor.h:835
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Definition: ValueAccessor.h:615
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:259
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:546
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:2163
typename TreeType::ValueType ValueType
Definition: ValueAccessor.h:1005
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:329
friend class InternalNode
Definition: ValueAccessor.h:1523
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153
void setValueOnly(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:739
Value accessor with one level of node caching.
Definition: ValueAccessor.h:52
TreeType TreeType
Definition: ValueAccessor.h:1595
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition: ValueAccessor.h:1236
void insert(const Coord &xyz, const NodeType *node)
Cache the given node at this level.
Definition: ValueAccessor.h:562
LeafNodeT * touchLeaf(const Coord &xyz)
Definition: ValueAccessor.h:1456
void setValue(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:939
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:1271
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:1434
ValueAccessor1 & operator=(const ValueAccessor1 &other)
Asignment operator.
Definition: ValueAccessor.h:1239
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:2182
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:2504
void insert(const Coord &, const RootNodeType *root)
Definition: ValueAccessor.h:844
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:2236
ValueAccessor1(TreeType &tree)
Constructor from a tree.
Definition: ValueAccessor.h:1228
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:1392
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
Definition: ValueAccessor.h:213
void getNode(const RootNodeType *&node) const
Definition: ValueAccessor.h:859
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:370
typename RootNodeT::NodeChainType InvTreeT
Definition: ValueAccessor.h:2090
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:1844
void getNode(const NodeType *&node) const
Return the cached node (if any) at this level.
Definition: ValueAccessor.h:581
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition: ValueAccessor.h:1514
void eraseNode()
Definition: ValueAccessor.h:1154
int getValueDepth(const Coord &xyz)
Definition: ValueAccessor.h:707
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:292
NodeType * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:304
LeafNodeT * probeLeaf(const Coord &xyz)
Definition: ValueAccessor.h:2462
virtual void release()
Definition: ValueAccessor.h:133
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: ValueAccessor.h:1122
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition: ValueAccessor.h:2115
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:1144
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:755
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:1097
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:2345
friend class InternalNode
Definition: ValueAccessor.h:403
TreeType TreeType
Definition: ValueAccessor.h:187
Index32 Index
Definition: openvdb/Types.h:32
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:1665
void addLeaf(LeafNodeType *leaf)
Definition: ValueAccessor.h:861