| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | // | ||
| 4 | /// @file InternalNode.h | ||
| 5 | /// | ||
| 6 | /// @brief Internal table nodes for OpenVDB trees | ||
| 7 | |||
| 8 | #ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED | ||
| 9 | #define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED | ||
| 10 | |||
| 11 | #include <openvdb/Platform.h> | ||
| 12 | #include <openvdb/util/NodeMasks.h> | ||
| 13 | #include <openvdb/io/Compression.h> // for io::readCompressedValues(), etc. | ||
| 14 | #include <openvdb/math/Math.h> // for math::isExactlyEqual(), etc. | ||
| 15 | #include <openvdb/version.h> | ||
| 16 | #include <openvdb/Types.h> | ||
| 17 | #include "Iterator.h" | ||
| 18 | #include "NodeUnion.h" | ||
| 19 | #include <tbb/parallel_for.h> | ||
| 20 | #include <memory> | ||
| 21 | #include <type_traits> | ||
| 22 | |||
| 23 | |||
| 24 | namespace openvdb { | ||
| 25 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 26 | namespace OPENVDB_VERSION_NAME { | ||
| 27 | namespace tree { | ||
| 28 | |||
| 29 | template<typename, Index, typename> struct SameInternalConfig; // forward declaration | ||
| 30 | |||
| 31 | |||
| 32 | template<typename _ChildNodeType, Index Log2Dim> | ||
| 33 | class InternalNode | ||
| 34 | { | ||
| 35 | public: | ||
| 36 | using ChildNodeType = _ChildNodeType; | ||
| 37 | using LeafNodeType = typename ChildNodeType::LeafNodeType; | ||
| 38 | using ValueType = typename ChildNodeType::ValueType; | ||
| 39 | using BuildType = typename ChildNodeType::BuildType; | ||
| 40 | using UnionType = NodeUnion<ValueType, ChildNodeType>; | ||
| 41 | using NodeMaskType = util::NodeMask<Log2Dim>; | ||
| 42 | |||
| 43 | static const Index | ||
| 44 | LOG2DIM = Log2Dim, // log2 of tile count in one dimension | ||
| 45 | TOTAL = Log2Dim + ChildNodeType::TOTAL, // log2 of voxel count in one dimension | ||
| 46 | DIM = 1 << TOTAL, // total voxel count in one dimension | ||
| 47 | NUM_VALUES = 1 << (3 * Log2Dim), // total voxel count represented by this node | ||
| 48 | LEVEL = 1 + ChildNodeType::LEVEL; // level 0 = leaf | ||
| 49 | static const Index64 | ||
| 50 | NUM_VOXELS = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node | ||
| 51 | |||
| 52 | /// @brief ValueConverter<T>::Type is the type of an InternalNode having the same | ||
| 53 | /// child hierarchy and dimensions as this node but a different value type, T. | ||
| 54 | template<typename OtherValueType> | ||
| 55 | struct ValueConverter { | ||
| 56 | using Type = InternalNode<typename ChildNodeType::template ValueConverter< | ||
| 57 | OtherValueType>::Type, Log2Dim>; | ||
| 58 | }; | ||
| 59 | |||
| 60 | /// @brief SameConfiguration<OtherNodeType>::value is @c true if and only if OtherNodeType | ||
| 61 | /// is the type of an InternalNode with the same dimensions as this node and whose | ||
| 62 | /// ChildNodeType has the same configuration as this node's ChildNodeType. | ||
| 63 | template<typename OtherNodeType> | ||
| 64 | struct SameConfiguration { | ||
| 65 | static const bool value = | ||
| 66 | SameInternalConfig<ChildNodeType, Log2Dim, OtherNodeType>::value; | ||
| 67 | }; | ||
| 68 | |||
| 69 | |||
| 70 | /// @brief Default constructor | ||
| 71 | /// @warning The resulting InternalNode is uninitialized | ||
| 72 | InternalNode() {} | ||
| 73 | |||
| 74 | /// @brief Constructor of an InternalNode with dense inactive tiles of the specified value. | ||
| 75 | /// @param offValue Background value used for inactive values | ||
| 76 | explicit InternalNode(const ValueType& offValue); | ||
| 77 | |||
| 78 | /// @brief Constructs an InternalNode with dense tiles | ||
| 79 | /// @param origin The location in index space of the fist tile value | ||
| 80 | /// @param fillValue Value assigned to all the tiles | ||
| 81 | /// @param active State assigned to all the tiles | ||
| 82 | InternalNode(const Coord& origin, const ValueType& fillValue, bool active = false); | ||
| 83 | |||
| 84 | InternalNode(PartialCreate, const Coord&, const ValueType& fillValue, bool active = false); | ||
| 85 | |||
| 86 | /// @brief Deep copy constructor | ||
| 87 | /// | ||
| 88 | /// @note This method is multi-threaded! | ||
| 89 | InternalNode(const InternalNode&); | ||
| 90 | |||
| 91 | /// @brief Value conversion copy constructor | ||
| 92 | /// | ||
| 93 | /// @note This method is multi-threaded! | ||
| 94 | template<typename OtherChildNodeType> | ||
| 95 | explicit InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other); | ||
| 96 | |||
| 97 | /// @brief Topology copy constructor | ||
| 98 | /// | ||
| 99 | /// @note This method is multi-threaded! | ||
| 100 | template<typename OtherChildNodeType> | ||
| 101 | InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
| 102 | const ValueType& background, TopologyCopy); | ||
| 103 | |||
| 104 | /// @brief Topology copy constructor | ||
| 105 | /// | ||
| 106 | /// @note This method is multi-threaded! | ||
| 107 | template<typename OtherChildNodeType> | ||
| 108 | InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
| 109 | const ValueType& offValue, const ValueType& onValue, TopologyCopy); | ||
| 110 | |||
| 111 | ~InternalNode(); | ||
| 112 | |||
| 113 | protected: | ||
| 114 | using MaskOnIterator = typename NodeMaskType::OnIterator; | ||
| 115 | using MaskOffIterator = typename NodeMaskType::OffIterator; | ||
| 116 | using MaskDenseIterator = typename NodeMaskType::DenseIterator; | ||
| 117 | |||
| 118 | // Type tags to disambiguate template instantiations | ||
| 119 | struct ValueOn {}; struct ValueOff {}; struct ValueAll {}; | ||
| 120 | struct ChildOn {}; struct ChildOff {}; struct ChildAll {}; | ||
| 121 | |||
| 122 | // The following class templates implement the iterator interfaces specified in Iterator.h | ||
| 123 | // by providing getItem(), setItem() and/or modifyItem() methods. | ||
| 124 | |||
| 125 | // Sparse iterator that visits child nodes of an InternalNode | ||
| 126 | template<typename NodeT, typename ChildT, typename MaskIterT, typename TagT> | ||
| 127 | struct ChildIter: public SparseIteratorBase< | ||
| 128 | MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT> | ||
| 129 | { | ||
| 130 | ChildIter() {} | ||
| 131 | ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase< | ||
| 132 | MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {} | ||
| 133 | |||
| 134 | 137723072 | ChildT& getItem(Index pos) const | |
| 135 | { | ||
| 136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 68861536 times.
|
275446144 | assert(this->parent().isChildMaskOn(pos)); |
| 137 | 137723072 | return *(this->parent().getChildNode(pos)); | |
| 138 | } | ||
| 139 | |||
| 140 | // Note: setItem() can't be called on const iterators. | ||
| 141 | void setItem(Index pos, const ChildT& c) const { this->parent().resetChildNode(pos, &c); } | ||
| 142 | |||
| 143 | // Note: modifyItem() isn't implemented, since it's not useful for child node pointers. | ||
| 144 | };// ChildIter | ||
| 145 | |||
| 146 | // Sparse iterator that visits tile values of an InternalNode | ||
| 147 | template<typename NodeT, typename ValueT, typename MaskIterT, typename TagT> | ||
| 148 | struct ValueIter: public SparseIteratorBase< | ||
| 149 | MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT> | ||
| 150 | { | ||
| 151 | ✗ | ValueIter() {} | |
| 152 | ValueIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase< | ||
| 153 | MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {} | ||
| 154 | |||
| 155 |
9/34✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✓ Branch 81 taken 1 times.
✗ Branch 82 not taken.
✓ Branch 84 taken 1 times.
✗ Branch 85 not taken.
✓ Branch 87 taken 1 times.
✗ Branch 88 not taken.
✓ Branch 90 taken 1 times.
✗ Branch 91 not taken.
✓ Branch 93 taken 1 times.
✗ Branch 94 not taken.
✓ Branch 96 taken 1 times.
✗ Branch 97 not taken.
✓ Branch 99 taken 1 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 1 times.
✗ Branch 103 not taken.
✓ Branch 105 taken 1 times.
✗ Branch 106 not taken.
|
2073830124 | const ValueT& getItem(Index pos) const { return this->parent().mNodes[pos].getValue(); } |
| 156 | |||
| 157 | // Note: setItem() can't be called on const iterators. | ||
| 158 |
4/15✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 23 taken 99214 times.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 29 taken 2174 times.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 35 taken 12 times.
✗ Branch 36 not taken.
|
84793180 | void setItem(Index pos, const ValueT& v) const { this->parent().mNodes[pos].setValue(v); } |
| 159 | |||
| 160 | // Note: modifyItem() can't be called on const iterators. | ||
| 161 | template<typename ModifyOp> | ||
| 162 | void modifyItem(Index pos, const ModifyOp& op) const | ||
| 163 | { | ||
| 164 | 1188 | op(this->parent().mNodes[pos].getValue()); | |
| 165 | } | ||
| 166 | };// ValueIter | ||
| 167 | |||
| 168 | // Dense iterator that visits both tiles and child nodes of an InternalNode | ||
| 169 | template<typename NodeT, typename ChildT, typename ValueT, typename TagT> | ||
| 170 | struct DenseIter: public DenseIteratorBase< | ||
| 171 | MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT> | ||
| 172 | { | ||
| 173 | using BaseT = DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>; | ||
| 174 | using NonConstValueT = typename BaseT::NonConstValueType; | ||
| 175 | |||
| 176 | DenseIter() {} | ||
| 177 | DenseIter(const MaskDenseIterator& iter, NodeT* parent): | ||
| 178 | DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>(iter, parent) {} | ||
| 179 | |||
| 180 | 4743176 | bool getItem(Index pos, ChildT*& child, NonConstValueT& value) const | |
| 181 | { | ||
| 182 |
2/2✓ Branch 1 taken 555 times.
✓ Branch 2 taken 2371033 times.
|
9486352 | if (this->parent().isChildMaskOn(pos)) { |
| 183 | 1110 | child = this->parent().getChildNode(pos); | |
| 184 | 1110 | return true; | |
| 185 | } | ||
| 186 | 4742066 | child = nullptr; | |
| 187 | 4742066 | value = this->parent().mNodes[pos].getValue(); | |
| 188 | 4742066 | return false; | |
| 189 | } | ||
| 190 | |||
| 191 | // Note: setItem() can't be called on const iterators. | ||
| 192 | void setItem(Index pos, ChildT* child) const | ||
| 193 | { | ||
| 194 | this->parent().resetChildNode(pos, child); | ||
| 195 | } | ||
| 196 | |||
| 197 | // Note: unsetItem() can't be called on const iterators. | ||
| 198 | void unsetItem(Index pos, const ValueT& value) const | ||
| 199 | { | ||
| 200 | this->parent().unsetChildNode(pos, value); | ||
| 201 | } | ||
| 202 | };// DenseIter | ||
| 203 | |||
| 204 | public: | ||
| 205 | // Iterators (see Iterator.h for usage) | ||
| 206 | using ChildOnIter = ChildIter<InternalNode, ChildNodeType, MaskOnIterator, ChildOn>; | ||
| 207 | using ChildOnCIter = ChildIter<const InternalNode,const ChildNodeType,MaskOnIterator,ChildOn>; | ||
| 208 | using ChildOffIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ChildOff>; | ||
| 209 | using ChildOffCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ChildOff>; | ||
| 210 | using ChildAllIter = DenseIter<InternalNode, ChildNodeType, ValueType, ChildAll>; | ||
| 211 | using ChildAllCIter = DenseIter<const InternalNode,const ChildNodeType, ValueType, ChildAll>; | ||
| 212 | |||
| 213 | using ValueOnIter = ValueIter<InternalNode, const ValueType, MaskOnIterator, ValueOn>; | ||
| 214 | using ValueOnCIter = ValueIter<const InternalNode, const ValueType, MaskOnIterator, ValueOn>; | ||
| 215 | using ValueOffIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueOff>; | ||
| 216 | using ValueOffCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueOff>; | ||
| 217 | using ValueAllIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueAll>; | ||
| 218 | using ValueAllCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueAll>; | ||
| 219 | |||
| 220 |
12/24✓ Branch 110 taken 1 times.
✗ Branch 111 not taken.
✓ Branch 114 taken 1 times.
✗ Branch 115 not taken.
✓ Branch 118 taken 1 times.
✗ Branch 119 not taken.
✓ Branch 122 taken 1 times.
✗ Branch 123 not taken.
✓ Branch 126 taken 1 times.
✗ Branch 127 not taken.
✓ Branch 130 taken 1 times.
✗ Branch 131 not taken.
✓ Branch 134 taken 1 times.
✗ Branch 135 not taken.
✓ Branch 325 taken 1 times.
✗ Branch 326 not taken.
✓ Branch 329 taken 1 times.
✗ Branch 330 not taken.
✓ Branch 333 taken 1 times.
✗ Branch 334 not taken.
✓ Branch 337 taken 1 times.
✗ Branch 338 not taken.
✓ Branch 341 taken 1 times.
✗ Branch 342 not taken.
|
524713 | ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mChildMask.beginOn(), this); } |
| 221 | 64 | ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mChildMask.beginOff(), this); } | |
| 222 | 180 | ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mChildMask.beginDense(), this); } | |
| 223 | 76956 | ChildOnCIter beginChildOn() const { return cbeginChildOn(); } | |
| 224 | ChildOffCIter beginChildOff() const { return cbeginChildOff(); } | ||
| 225 | 90 | ChildAllCIter beginChildAll() const { return cbeginChildAll(); } | |
| 226 |
1/2✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
|
817281 | ChildOnIter beginChildOn() { return ChildOnIter(mChildMask.beginOn(), this); } |
| 227 | ChildOffIter beginChildOff() { return ChildOffIter(mChildMask.beginOff(), this); } | ||
| 228 | 294 | ChildAllIter beginChildAll() { return ChildAllIter(mChildMask.beginDense(), this); } | |
| 229 | |||
| 230 |
12/138✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 6 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 8 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 6 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 8 times.
✓ Branch 28 taken 5 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 5 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 3 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 3 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
|
375138 | ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); } |
| 231 | /// @warning This iterator will also visit child nodes so use isChildMaskOn to skip them! | ||
| 232 | 1088 | ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); } | |
| 233 |
13/26✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1 times.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 1 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 1 times.
✓ Branch 54 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 62 taken 1 times.
✗ Branch 63 not taken.
|
1872 | ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mChildMask.beginOff(), this); } |
| 234 | ValueOnCIter beginValueOn() const { return cbeginValueOn(); } | ||
| 235 | /// @warning This iterator will also visit child nodes so use isChildMaskOn to skip them! | ||
| 236 | ValueOffCIter beginValueOff() const { return cbeginValueOff(); } | ||
| 237 | 182 | ValueAllCIter beginValueAll() const { return cbeginValueAll(); } | |
| 238 |
40/80✗ Branch 4 not taken.
✓ Branch 5 taken 102 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 68 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 156 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 104 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 171 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 114 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 150 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 100 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 153 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 102 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 162 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 108 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 165 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 110 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 174 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 116 times.
✗ Branch 68 not taken.
✓ Branch 69 taken 186 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 124 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 306 times.
✗ Branch 79 not taken.
✓ Branch 80 taken 204 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 357 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 238 times.
✗ Branch 92 not taken.
✓ Branch 93 taken 105 times.
✗ Branch 95 not taken.
✓ Branch 96 taken 70 times.
✗ Branch 100 not taken.
✓ Branch 101 taken 105 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 70 times.
✗ Branch 108 not taken.
✓ Branch 109 taken 105 times.
✗ Branch 111 not taken.
✓ Branch 112 taken 70 times.
✗ Branch 116 not taken.
✓ Branch 117 taken 1302 times.
✗ Branch 119 not taken.
✓ Branch 120 taken 868 times.
✗ Branch 124 not taken.
✓ Branch 125 taken 78 times.
✗ Branch 127 not taken.
✓ Branch 128 taken 52 times.
✗ Branch 132 not taken.
✓ Branch 133 taken 765 times.
✗ Branch 135 not taken.
✓ Branch 136 taken 510 times.
✗ Branch 140 not taken.
✓ Branch 141 taken 231 times.
✗ Branch 143 not taken.
✓ Branch 144 taken 154 times.
✗ Branch 148 not taken.
✓ Branch 149 taken 757 times.
✗ Branch 151 not taken.
✓ Branch 152 taken 510 times.
✗ Branch 155 not taken.
✓ Branch 156 taken 1092 times.
✗ Branch 158 not taken.
✓ Branch 159 taken 728 times.
|
56615 | ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); } |
| 239 | /// @warning This iterator will also visit child nodes so use isChildMaskOn to skip them! | ||
| 240 |
4/160✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 208 not taken.
✗ Branch 209 not taken.
✗ Branch 211 not taken.
✗ Branch 212 not taken.
✗ Branch 214 not taken.
✗ Branch 215 not taken.
✗ Branch 217 not taken.
✓ Branch 218 taken 1 times.
✗ Branch 220 not taken.
✓ Branch 221 taken 1 times.
✗ Branch 223 not taken.
✓ Branch 224 taken 1 times.
✗ Branch 226 not taken.
✓ Branch 227 taken 1 times.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 232 not taken.
✗ Branch 233 not taken.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
|
931 | ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); } |
| 241 |
0/80✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 168 not taken.
✗ Branch 169 not taken.
✗ Branch 171 not taken.
✗ Branch 172 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 192 not taken.
✗ Branch 193 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
|
12248 | ValueAllIter beginValueAll() { return ValueAllIter(mChildMask.beginOff(), this); } |
| 242 | |||
| 243 | |||
| 244 | /// @return The dimension of this InternalNode | ||
| 245 | /// @details The number of voxels in one coordinate direction covered by this node | ||
| 246 | static Index dim() { return DIM; } | ||
| 247 | /// @return The level of this node | ||
| 248 | /// @details Level 0 is by definition the level of the leaf nodes | ||
| 249 | static Index getLevel() { return LEVEL; } | ||
| 250 | /// @brief Populated an std::vector with the dimension of all the | ||
| 251 | /// nodes in the branch starting with this node. | ||
| 252 | static void getNodeLog2Dims(std::vector<Index>& dims); | ||
| 253 | /// @return The dimension of the child nodes of this node. | ||
| 254 | /// @details The number of voxels in one coordinate direction | ||
| 255 | /// covered by a child node of this node. | ||
| 256 | static Index getChildDim() { return ChildNodeType::DIM; } | ||
| 257 | |||
| 258 | /// Return the linear table offset of the given global or local coordinates. | ||
| 259 | static Index coordToOffset(const Coord& xyz); | ||
| 260 | /// @brief Return the local coordinates for a linear table offset, | ||
| 261 | /// where offset 0 has coordinates (0, 0, 0). | ||
| 262 | static void offsetToLocalCoord(Index n, Coord& xyz); | ||
| 263 | /// Return the global coordinates for a linear table offset. | ||
| 264 | Coord offsetToGlobalCoord(Index n) const; | ||
| 265 | |||
| 266 | /// Return the grid index coordinates of this node's local origin. | ||
| 267 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
5637 | const Coord& origin() const { return mOrigin; } |
| 268 | /// Set the grid index coordinates of this node's local origin. | ||
| 269 |
1/18✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
|
8 | void setOrigin(const Coord& origin) { mOrigin = origin; } |
| 270 | |||
| 271 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 272 | /// Return the transient data value. | ||
| 273 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
3 | Index32 transientData() const { return mTransientData; } |
| 274 | /// Set the transient data value. | ||
| 275 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | void setTransientData(Index32 transientData) { mTransientData = transientData; } |
| 276 | #endif | ||
| 277 | |||
| 278 | Index32 leafCount() const; | ||
| 279 | void nodeCount(std::vector<Index32> &vec) const; | ||
| 280 | Index32 nonLeafCount() const; | ||
| 281 | Index32 childCount() const; | ||
| 282 | Index64 onVoxelCount() const; | ||
| 283 | Index64 offVoxelCount() const; | ||
| 284 | Index64 onLeafVoxelCount() const; | ||
| 285 | Index64 offLeafVoxelCount() const; | ||
| 286 | Index64 onTileCount() const; | ||
| 287 | |||
| 288 | /// Return the total amount of memory in bytes occupied by this node and its children. | ||
| 289 | Index64 memUsage() const; | ||
| 290 | |||
| 291 | /// @brief Expand the specified bounding box so that it includes the active tiles | ||
| 292 | /// of this internal node as well as all the active values in its child nodes. | ||
| 293 | /// If visitVoxels is false LeafNodes will be approximated as dense, i.e. with all | ||
| 294 | /// voxels active. Else the individual active voxels are visited to produce a tight bbox. | ||
| 295 | void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const; | ||
| 296 | |||
| 297 | /// @brief Return the bounding box of this node, i.e., the full index space | ||
| 298 | /// spanned by the node regardless of its content. | ||
| 299 | 43662 | CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); } | |
| 300 | |||
| 301 | /// @return True if this node contains no child nodes. | ||
| 302 | bool isEmpty() const { return mChildMask.isOff(); } | ||
| 303 | |||
| 304 | /// Return @c true if all of this node's table entries have the same active state | ||
| 305 | /// and the same constant value to within the given tolerance, | ||
| 306 | /// and return that value in @a firstValue and the active state in @a state. | ||
| 307 | /// | ||
| 308 | /// @note This method also returns @c false if this node contains any child nodes. | ||
| 309 | bool isConstant(ValueType& firstValue, bool& state, | ||
| 310 |
13/52✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 10 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 16 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 9 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 9 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 9 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 9 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 9 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 9 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✓ Branch 43 taken 12 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✓ Branch 47 taken 12 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 12 times.
|
136 | const ValueType& tolerance = zeroVal<ValueType>()) const; |
| 311 | |||
| 312 | /// Return @c true if all of this node's tables entries have | ||
| 313 | /// the same active @a state and the range of its values satisfy | ||
| 314 | /// (@a maxValue - @a minValue) <= @a tolerance. | ||
| 315 | /// | ||
| 316 | /// @param minValue Is updated with the minimum of all values IF method | ||
| 317 | /// returns @c true. Else the value is undefined! | ||
| 318 | /// @param maxValue Is updated with the maximum of all values IF method | ||
| 319 | /// returns @c true. Else the value is undefined! | ||
| 320 | /// @param state Is updated with the state of all values IF method | ||
| 321 | /// returns @c true. Else the value is undefined! | ||
| 322 | /// @param tolerance The tolerance used to determine if values are | ||
| 323 | /// approximately constant. | ||
| 324 | /// | ||
| 325 | /// @note This method also returns @c false if this node contains any child nodes. | ||
| 326 | bool isConstant(ValueType& minValue, ValueType& maxValue, | ||
| 327 | bool& state, const ValueType& tolerance = zeroVal<ValueType>()) const; | ||
| 328 | |||
| 329 | /// Return @c true if this node has no children and only contains inactive values. | ||
| 330 |
7/8✓ Branch 0 taken 2942 times.
✓ Branch 1 taken 12468 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 2931 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 23 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
|
67483 | bool isInactive() const { return this->isChildMaskOff() && this->isValueMaskOff(); } |
| 331 | |||
| 332 | /// Return @c true if the voxel at the given coordinates is active. | ||
| 333 | bool isValueOn(const Coord& xyz) const; | ||
| 334 | /// Return @c true if the voxel at the given offset is active. | ||
| 335 | 19 | bool isValueOn(Index offset) const { return mValueMask.isOn(offset); } | |
| 336 | |||
| 337 | /// Return @c true if this node or any of its child nodes have any active tiles. | ||
| 338 | bool hasActiveTiles() const; | ||
| 339 | |||
| 340 | const ValueType& getValue(const Coord& xyz) const; | ||
| 341 | bool probeValue(const Coord& xyz, ValueType& value) const; | ||
| 342 | |||
| 343 | /// @brief Return the level of the tree (0 = leaf) at which the value | ||
| 344 | /// at the given coordinates resides. | ||
| 345 | Index getValueLevel(const Coord& xyz) const; | ||
| 346 | |||
| 347 | /// @brief If the first entry in this node's table is a tile, return the tile's value. | ||
| 348 | /// Otherwise, return the result of calling getFirstValue() on the child. | ||
| 349 | const ValueType& getFirstValue() const; | ||
| 350 | /// @brief If the last entry in this node's table is a tile, return the tile's value. | ||
| 351 | /// Otherwise, return the result of calling getLastValue() on the child. | ||
| 352 | const ValueType& getLastValue() const; | ||
| 353 | |||
| 354 | /// Set the active state of the voxel at the given coordinates but don't change its value. | ||
| 355 | void setActiveState(const Coord& xyz, bool on); | ||
| 356 | /// Set the value of the voxel at the given coordinates but don't change its active state. | ||
| 357 | void setValueOnly(const Coord& xyz, const ValueType& value); | ||
| 358 | /// Mark the voxel at the given coordinates as active but don't change its value. | ||
| 359 | void setValueOn(const Coord& xyz); | ||
| 360 | /// Set the value of the voxel at the given coordinates and mark the voxel as active. | ||
| 361 | void setValueOn(const Coord& xyz, const ValueType& value); | ||
| 362 | /// Mark the voxel at the given coordinates as inactive but don't change its value. | ||
| 363 | void setValueOff(const Coord& xyz); | ||
| 364 | /// Set the value of the voxel at the given coordinates and mark the voxel as inactive. | ||
| 365 | void setValueOff(const Coord& xyz, const ValueType& value); | ||
| 366 | |||
| 367 | /// @brief Apply a functor to the value of the voxel at the given coordinates | ||
| 368 | /// and mark the voxel as active. | ||
| 369 | template<typename ModifyOp> | ||
| 370 | void modifyValue(const Coord& xyz, const ModifyOp& op); | ||
| 371 | /// Apply a functor to the voxel at the given coordinates. | ||
| 372 | template<typename ModifyOp> | ||
| 373 | void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op); | ||
| 374 | |||
| 375 | /// Return the value of the voxel at the given coordinates and, if necessary, update | ||
| 376 | /// the accessor with pointers to the nodes along the path from the root node to | ||
| 377 | /// the node containing the voxel. | ||
| 378 | /// @note Used internally by ValueAccessor. | ||
| 379 | template<typename AccessorT> | ||
| 380 | const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const; | ||
| 381 | |||
| 382 | /// Return @c true if the voxel at the given coordinates is active and, if necessary, | ||
| 383 | /// update the accessor with pointers to the nodes along the path from the root node | ||
| 384 | /// to the node containing the voxel. | ||
| 385 | /// @note Used internally by ValueAccessor. | ||
| 386 | template<typename AccessorT> | ||
| 387 | bool isValueOnAndCache(const Coord& xyz, AccessorT&) const; | ||
| 388 | |||
| 389 | /// Change the value of the voxel at the given coordinates and mark it as active. | ||
| 390 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
| 391 | /// from the root node to the node containing the voxel. | ||
| 392 | /// @note Used internally by ValueAccessor. | ||
| 393 | template<typename AccessorT> | ||
| 394 | void setValueAndCache(const Coord& xyz, const ValueType& value, AccessorT&); | ||
| 395 | |||
| 396 | /// Set the value of the voxel at the given coordinate but preserves its active state. | ||
| 397 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
| 398 | /// from the root node to the node containing the voxel. | ||
| 399 | /// @note Used internally by ValueAccessor. | ||
| 400 | template<typename AccessorT> | ||
| 401 | void setValueOnlyAndCache(const Coord& xyz, const ValueType& value, AccessorT&); | ||
| 402 | |||
| 403 | /// @brief Apply a functor to the value of the voxel at the given coordinates | ||
| 404 | /// and mark the voxel as active. | ||
| 405 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
| 406 | /// from the root node to the node containing the voxel. | ||
| 407 | /// @note Used internally by ValueAccessor. | ||
| 408 | template<typename ModifyOp, typename AccessorT> | ||
| 409 | void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&); | ||
| 410 | |||
| 411 | /// Apply a functor to the voxel at the given coordinates. | ||
| 412 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
| 413 | /// from the root node to the node containing the voxel. | ||
| 414 | /// @note Used internally by ValueAccessor. | ||
| 415 | template<typename ModifyOp, typename AccessorT> | ||
| 416 | void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&); | ||
| 417 | |||
| 418 | /// Change the value of the voxel at the given coordinates and mark it as inactive. | ||
| 419 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
| 420 | /// from the root node to the node containing the voxel. | ||
| 421 | /// @note Used internally by ValueAccessor. | ||
| 422 | template<typename AccessorT> | ||
| 423 | void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&); | ||
| 424 | |||
| 425 | /// Set the active state of the voxel at the given coordinates without changing its value. | ||
| 426 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
| 427 | /// from the root node to the node containing the voxel. | ||
| 428 | /// @note Used internally by ValueAccessor. | ||
| 429 | template<typename AccessorT> | ||
| 430 | void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&); | ||
| 431 | |||
| 432 | /// Return, in @a value, the value of the voxel at the given coordinates and, | ||
| 433 | /// if necessary, update the accessor with pointers to the nodes along | ||
| 434 | /// the path from the root node to the node containing the voxel. | ||
| 435 | /// @return @c true if the voxel at the given coordinates is active | ||
| 436 | /// @note Used internally by ValueAccessor. | ||
| 437 | template<typename AccessorT> | ||
| 438 | bool probeValueAndCache(const Coord& xyz, ValueType& value, AccessorT&) const; | ||
| 439 | |||
| 440 | /// @brief Return the level of the tree (0 = leaf) at which the value | ||
| 441 | /// at the given coordinates resides. | ||
| 442 | /// | ||
| 443 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
| 444 | /// from the root node to the node containing the voxel. | ||
| 445 | /// @note Used internally by ValueAccessor. | ||
| 446 | template<typename AccessorT> | ||
| 447 | Index getValueLevelAndCache(const Coord& xyz, AccessorT&) const; | ||
| 448 | |||
| 449 | /// Mark all values (both tiles and voxels) as active. | ||
| 450 | void setValuesOn(); | ||
| 451 | |||
| 452 | // | ||
| 453 | // I/O | ||
| 454 | // | ||
| 455 | void writeTopology(std::ostream&, bool toHalf = false) const; | ||
| 456 | void readTopology(std::istream&, bool fromHalf = false); | ||
| 457 | void writeBuffers(std::ostream&, bool toHalf = false) const; | ||
| 458 | void readBuffers(std::istream&, bool fromHalf = false); | ||
| 459 | void readBuffers(std::istream&, const CoordBBox&, bool fromHalf = false); | ||
| 460 | |||
| 461 | |||
| 462 | // | ||
| 463 | // Aux methods | ||
| 464 | // | ||
| 465 | |||
| 466 | /// Change the sign of all the values represented in this node and its child nodes. | ||
| 467 | void negate(); | ||
| 468 | |||
| 469 | /// @brief Set all voxels within a given axis-aligned box to a constant value. | ||
| 470 | /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box | ||
| 471 | /// @param value the value to which to set voxels within the box | ||
| 472 | /// @param active if true, mark voxels within the box as active, | ||
| 473 | /// otherwise mark them as inactive | ||
| 474 | /// @note This operation generates a sparse, but not always optimally sparse, | ||
| 475 | /// representation of the filled box. Follow fill operations with a prune() | ||
| 476 | /// operation for optimal sparseness. | ||
| 477 | void fill(const CoordBBox& bbox, const ValueType& value, bool active = true); | ||
| 478 | |||
| 479 | /// @brief Set all voxels within a given axis-aligned box to a constant value | ||
| 480 | /// and ensure that those voxels are all represented at the leaf level. | ||
| 481 | /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box. | ||
| 482 | /// @param value the value to which to set voxels within the box. | ||
| 483 | /// @param active if true, mark voxels within the box as active, | ||
| 484 | /// otherwise mark them as inactive. | ||
| 485 | /// @sa voxelizeActiveTiles() | ||
| 486 | void denseFill(const CoordBBox& bbox, const ValueType& value, bool active = true); | ||
| 487 | |||
| 488 | /// @brief Densify active tiles, i.e., replace them with leaf-level active voxels. | ||
| 489 | /// @param threaded if true, this operation is multi-threaded (over the internal nodes). | ||
| 490 | /// @sa denseFill() | ||
| 491 | void voxelizeActiveTiles(bool threaded = true); | ||
| 492 | |||
| 493 | /// @brief Copy into a dense grid the values of the voxels that lie within | ||
| 494 | /// a given bounding box. | ||
| 495 | /// @param bbox inclusive bounding box of the voxels to be copied into the dense grid | ||
| 496 | /// @param dense dense grid with a stride in @e z of one (see tools::Dense | ||
| 497 | /// in tools/Dense.h for the required API) | ||
| 498 | /// @note @a bbox is assumed to be identical to or contained in the coordinate domains | ||
| 499 | /// of both the dense grid and this node, i.e., no bounds checking is performed. | ||
| 500 | template<typename DenseT> | ||
| 501 | void copyToDense(const CoordBBox& bbox, DenseT& dense) const; | ||
| 502 | |||
| 503 | /// @brief Efficiently merge another tree into this tree using one of several schemes. | ||
| 504 | /// @warning This operation cannibalizes the other tree. | ||
| 505 | template<MergePolicy Policy> | ||
| 506 | void merge(InternalNode& other, const ValueType& background, const ValueType& otherBackground); | ||
| 507 | |||
| 508 | /// @brief Merge, using one of several schemes, this node (and its descendants) | ||
| 509 | /// with a tile of the same dimensions and the given value and active state. | ||
| 510 | template<MergePolicy Policy> void merge(const ValueType& tileValue, bool tileActive); | ||
| 511 | |||
| 512 | /// @brief Union this branch's set of active values with the other branch's | ||
| 513 | /// active values. The value type of the other branch can be different. | ||
| 514 | /// @details The resulting state of a value is active if the corresponding value | ||
| 515 | /// was already active OR if it is active in the other tree. Also, a resulting | ||
| 516 | /// value maps to a voxel if the corresponding value already mapped to a voxel | ||
| 517 | /// OR if it is a voxel in the other tree. Thus, a resulting value can only | ||
| 518 | /// map to a tile if the corresponding value already mapped to a tile | ||
| 519 | /// AND if it is a tile value in other tree. | ||
| 520 | /// | ||
| 521 | /// Specifically, active tiles and voxels in this branch are not changed, and | ||
| 522 | /// tiles or voxels that were inactive in this branch but active in the other branch | ||
| 523 | /// are marked as active in this branch but left with their original values. | ||
| 524 | template<typename OtherChildNodeType> | ||
| 525 | void topologyUnion(const InternalNode<OtherChildNodeType, Log2Dim>& other, const bool preserveTiles = false); | ||
| 526 | |||
| 527 | /// @brief Intersects this tree's set of active values with the active values | ||
| 528 | /// of the other tree, whose @c ValueType may be different. | ||
| 529 | /// @details The resulting state of a value is active only if the corresponding | ||
| 530 | /// value was already active AND if it is active in the other tree. Also, a | ||
| 531 | /// resulting value maps to a voxel if the corresponding value | ||
| 532 | /// already mapped to an active voxel in either of the two grids | ||
| 533 | /// and it maps to an active tile or voxel in the other grid. | ||
| 534 | /// | ||
| 535 | /// @note This operation can delete branches in this grid if they | ||
| 536 | /// overlap with inactive tiles in the other grid. Likewise active | ||
| 537 | /// voxels can be turned into inactive voxels resulting in leaf | ||
| 538 | /// nodes with no active values. Thus, it is recommended to | ||
| 539 | /// subsequently call prune. | ||
| 540 | template<typename OtherChildNodeType> | ||
| 541 | void topologyIntersection(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
| 542 | const ValueType& background); | ||
| 543 | |||
| 544 | /// @brief Difference this node's set of active values with the active values | ||
| 545 | /// of the other node, whose @c ValueType may be different. So a | ||
| 546 | /// resulting voxel will be active only if the original voxel is | ||
| 547 | /// active in this node and inactive in the other node. | ||
| 548 | /// | ||
| 549 | /// @details The last dummy argument is required to match the signature | ||
| 550 | /// for InternalNode::topologyDifference. | ||
| 551 | /// | ||
| 552 | /// @note This operation modifies only active states, not | ||
| 553 | /// values. Also note that this operation can result in all voxels | ||
| 554 | /// being inactive so consider subsequently calling prune. | ||
| 555 | template<typename OtherChildNodeType> | ||
| 556 | void topologyDifference(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
| 557 | const ValueType& background); | ||
| 558 | |||
| 559 | template<typename CombineOp> | ||
| 560 | void combine(InternalNode& other, CombineOp&); | ||
| 561 | template<typename CombineOp> | ||
| 562 | void combine(const ValueType& value, bool valueIsActive, CombineOp&); | ||
| 563 | |||
| 564 | template<typename CombineOp, typename OtherNodeType /*= InternalNode*/> | ||
| 565 | void combine2(const InternalNode& other0, const OtherNodeType& other1, CombineOp&); | ||
| 566 | template<typename CombineOp, typename OtherNodeType /*= InternalNode*/> | ||
| 567 | void combine2(const ValueType& value, const OtherNodeType& other, bool valIsActive, CombineOp&); | ||
| 568 | template<typename CombineOp, typename OtherValueType> | ||
| 569 | void combine2(const InternalNode& other, const OtherValueType&, bool valIsActive, CombineOp&); | ||
| 570 | |||
| 571 | /// @brief Calls the templated functor BBoxOp with bounding box | ||
| 572 | /// information for all active tiles and leaf nodes in this node. | ||
| 573 | /// An additional level argument is provided for each callback. | ||
| 574 | /// | ||
| 575 | /// @note The bounding boxes are guaranteed to be non-overlapping. | ||
| 576 | template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const; | ||
| 577 | |||
| 578 | template<typename VisitorOp> void visit(VisitorOp&); | ||
| 579 | template<typename VisitorOp> void visit(VisitorOp&) const; | ||
| 580 | |||
| 581 | template<typename OtherNodeType, typename VisitorOp> | ||
| 582 | void visit2Node(OtherNodeType& other, VisitorOp&); | ||
| 583 | template<typename OtherNodeType, typename VisitorOp> | ||
| 584 | void visit2Node(OtherNodeType& other, VisitorOp&) const; | ||
| 585 | template<typename IterT, typename VisitorOp> | ||
| 586 | void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false); | ||
| 587 | template<typename IterT, typename VisitorOp> | ||
| 588 | void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const; | ||
| 589 | |||
| 590 | /// Set all voxels that lie outside the given axis-aligned box to the background. | ||
| 591 | void clip(const CoordBBox&, const ValueType& background); | ||
| 592 | |||
| 593 | /// @brief Reduce the memory footprint of this tree by replacing with tiles | ||
| 594 | /// any nodes whose values are all the same (optionally to within a tolerance) | ||
| 595 | /// and have the same active state. | ||
| 596 | ✗ | void prune(const ValueType& tolerance = zeroVal<ValueType>()); | |
| 597 | |||
| 598 | /// @brief Add the specified leaf to this node, possibly creating a child branch | ||
| 599 | /// in the process. If the leaf node already exists, replace it. | ||
| 600 | void addLeaf(LeafNodeType* leaf); | ||
| 601 | |||
| 602 | /// @brief Same as addLeaf() except, if necessary, update the accessor with pointers | ||
| 603 | /// to the nodes along the path from the root node to the node containing the coordinate. | ||
| 604 | template<typename AccessorT> | ||
| 605 | void addLeafAndCache(LeafNodeType* leaf, AccessorT&); | ||
| 606 | |||
| 607 | /// @brief Return a pointer to the node of type @c NodeT that contains voxel (x, y, z) | ||
| 608 | /// and replace it with a tile of the specified value and state. | ||
| 609 | /// If no such node exists, leave the tree unchanged and return @c nullptr. | ||
| 610 | /// | ||
| 611 | /// @note The caller takes ownership of the node and is responsible for deleting it. | ||
| 612 | /// | ||
| 613 | /// @warning Since this method potentially removes nodes and branches of the tree, | ||
| 614 | /// it is important to clear the caches of all ValueAccessors associated with this tree. | ||
| 615 | template<typename NodeT> | ||
| 616 | NodeT* stealNode(const Coord& xyz, const ValueType& value, bool state); | ||
| 617 | |||
| 618 | /// @brief Add the given child node at this level deducing the offset from it's origin. | ||
| 619 | /// If a child node with this offset already exists, delete the old node and add the | ||
| 620 | /// new node in its place (i.e. ownership of the new child node is transferred to | ||
| 621 | /// this InternalNode) | ||
| 622 | /// @return @c true if inserting the child has been successful, otherwise the caller | ||
| 623 | /// retains ownership of the node and is responsible for deleting it. | ||
| 624 | bool addChild(ChildNodeType* child); | ||
| 625 | |||
| 626 | /// @brief Add a tile at the specified tree level that contains voxel (x, y, z), | ||
| 627 | /// possibly creating a parent branch or deleting a child branch in the process. | ||
| 628 | void addTile(Index level, const Coord& xyz, const ValueType& value, bool state); | ||
| 629 | |||
| 630 | /// @brief Delete any existing child branch at the specified offset and add a tile. | ||
| 631 | void addTile(Index offset, const ValueType& value, bool state); | ||
| 632 | |||
| 633 | /// @brief Same as addTile() except, if necessary, update the accessor with pointers | ||
| 634 | /// to the nodes along the path from the root node to the node containing (x, y, z). | ||
| 635 | template<typename AccessorT> | ||
| 636 | void addTileAndCache(Index level, const Coord& xyz, const ValueType&, bool state, AccessorT&); | ||
| 637 | |||
| 638 | //@{ | ||
| 639 | /// @brief Return a pointer to the node that contains voxel (x, y, z). | ||
| 640 | /// If no such node exists, return nullptr. | ||
| 641 | template<typename NodeType> NodeType* probeNode(const Coord& xyz); | ||
| 642 | template<typename NodeType> const NodeType* probeConstNode(const Coord& xyz) const; | ||
| 643 | //@} | ||
| 644 | |||
| 645 | //@{ | ||
| 646 | /// @brief Same as probeNode() except, if necessary, update the accessor with pointers | ||
| 647 | /// to the nodes along the path from the root node to the node containing (x, y, z). | ||
| 648 | template<typename NodeType, typename AccessorT> | ||
| 649 | NodeType* probeNodeAndCache(const Coord& xyz, AccessorT&); | ||
| 650 | template<typename NodeType, typename AccessorT> | ||
| 651 | const NodeType* probeConstNodeAndCache(const Coord& xyz, AccessorT&) const; | ||
| 652 | //@} | ||
| 653 | |||
| 654 | //@{ | ||
| 655 | /// @brief Return a pointer to the leaf node that contains voxel (x, y, z). | ||
| 656 | /// If no such node exists, return @c nullptr. | ||
| 657 | LeafNodeType* probeLeaf(const Coord& xyz); | ||
| 658 | const LeafNodeType* probeConstLeaf(const Coord& xyz) const; | ||
| 659 | const LeafNodeType* probeLeaf(const Coord& xyz) const; | ||
| 660 | //@} | ||
| 661 | |||
| 662 | //@{ | ||
| 663 | /// @brief Same as probeLeaf() except, if necessary, update the accessor with pointers | ||
| 664 | /// to the nodes along the path from the root node to the node containing (x, y, z). | ||
| 665 | template<typename AccessorT> | ||
| 666 | LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc); | ||
| 667 | template<typename AccessorT> | ||
| 668 | const LeafNodeType* probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const; | ||
| 669 | template<typename AccessorT> | ||
| 670 | const LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc) const; | ||
| 671 | //@} | ||
| 672 | |||
| 673 | /// @brief Return the leaf node that contains voxel (x, y, z). | ||
| 674 | /// If no such node exists, create one, but preserve the values and | ||
| 675 | /// active states of all voxels. | ||
| 676 | /// | ||
| 677 | /// @details Use this method to preallocate a static tree topology | ||
| 678 | /// over which to safely perform multithreaded processing. | ||
| 679 | LeafNodeType* touchLeaf(const Coord& xyz); | ||
| 680 | |||
| 681 | /// @brief Same as touchLeaf() except, if necessary, update the accessor with pointers | ||
| 682 | /// to the nodes along the path from the root node to the node containing the coordinate. | ||
| 683 | template<typename AccessorT> | ||
| 684 | LeafNodeType* touchLeafAndCache(const Coord& xyz, AccessorT&); | ||
| 685 | |||
| 686 | //@{ | ||
| 687 | /// @brief Adds all nodes of a certain type to a container with the following API: | ||
| 688 | /// @code | ||
| 689 | /// struct ArrayT { | ||
| 690 | /// using value_type = ...;// defines the type of nodes to be added to the array | ||
| 691 | /// void push_back(value_type nodePtr);// method that add nodes to the array | ||
| 692 | /// }; | ||
| 693 | /// @endcode | ||
| 694 | /// @details An example of a wrapper around a c-style array is: | ||
| 695 | /// @code | ||
| 696 | /// struct MyArray { | ||
| 697 | /// using value_type = LeafType*; | ||
| 698 | /// value_type* ptr; | ||
| 699 | /// MyArray(value_type* array) : ptr(array) {} | ||
| 700 | /// void push_back(value_type leaf) { *ptr++ = leaf; } | ||
| 701 | ///}; | ||
| 702 | /// @endcode | ||
| 703 | /// @details An example that constructs a list of pointer to all leaf nodes is: | ||
| 704 | /// @code | ||
| 705 | /// std::vector<const LeafNodeType*> array;//most std contains have the required API | ||
| 706 | /// array.reserve(tree.leafCount());//this is a fast preallocation. | ||
| 707 | /// tree.getNodes(array); | ||
| 708 | /// @endcode | ||
| 709 | template<typename ArrayT> | ||
| 710 | void getNodes(ArrayT& array); | ||
| 711 | template<typename ArrayT> | ||
| 712 | void getNodes(ArrayT& array) const; | ||
| 713 | //@} | ||
| 714 | |||
| 715 | /// @brief Steals all nodes of a certain type from the tree and | ||
| 716 | /// adds them to a container with the following API: | ||
| 717 | /// @code | ||
| 718 | /// struct ArrayT { | ||
| 719 | /// using value_type = ...;// defines the type of nodes to be added to the array | ||
| 720 | /// void push_back(value_type nodePtr);// method that add nodes to the array | ||
| 721 | /// }; | ||
| 722 | /// @endcode | ||
| 723 | /// @details An example of a wrapper around a c-style array is: | ||
| 724 | /// @code | ||
| 725 | /// struct MyArray { | ||
| 726 | /// using value_type = LeafType*; | ||
| 727 | /// value_type* ptr; | ||
| 728 | /// MyArray(value_type* array) : ptr(array) {} | ||
| 729 | /// void push_back(value_type leaf) { *ptr++ = leaf; } | ||
| 730 | ///}; | ||
| 731 | /// @endcode | ||
| 732 | /// @details An example that constructs a list of pointer to all leaf nodes is: | ||
| 733 | /// @code | ||
| 734 | /// std::vector<const LeafNodeType*> array;//most std contains have the required API | ||
| 735 | /// array.reserve(tree.leafCount());//this is a fast preallocation. | ||
| 736 | /// tree.stealNodes(array); | ||
| 737 | /// @endcode | ||
| 738 | template<typename ArrayT> | ||
| 739 | void stealNodes(ArrayT& array, const ValueType& value, bool state); | ||
| 740 | |||
| 741 | /// @brief Change inactive tiles or voxels with value oldBackground to newBackground | ||
| 742 | /// or -oldBackground to -newBackground. Active values are unchanged. | ||
| 743 | void resetBackground(const ValueType& oldBackground, const ValueType& newBackground); | ||
| 744 | |||
| 745 | /// @brief Return @c true if the given tree branch has the same node and active value | ||
| 746 | /// topology as this tree branch (but possibly a different @c ValueType). | ||
| 747 | template<typename OtherChildNodeType, Index OtherLog2Dim> | ||
| 748 | bool hasSameTopology(const InternalNode<OtherChildNodeType, OtherLog2Dim>* other) const; | ||
| 749 | |||
| 750 | protected: | ||
| 751 | //@{ | ||
| 752 | /// Allow iterators to call mask accessor methods (setValueMask(), setChildMask(), etc.). | ||
| 753 | /// @todo Make mask accessors public? | ||
| 754 | friend class IteratorBase<MaskOnIterator, InternalNode>; | ||
| 755 | friend class IteratorBase<MaskOffIterator, InternalNode>; | ||
| 756 | friend class IteratorBase<MaskDenseIterator, InternalNode>; | ||
| 757 | //@} | ||
| 758 | |||
| 759 | /// @brief During topology-only construction, access is needed | ||
| 760 | /// to protected/private members of other template instances. | ||
| 761 | template<typename, Index> friend class InternalNode; | ||
| 762 | |||
| 763 | // Mask accessors | ||
| 764 | public: | ||
| 765 | 497658246 | bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); } | |
| 766 | bool isValueMaskOn() const { return mValueMask.isOn(); } | ||
| 767 | 462844 | bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); } | |
| 768 | bool isValueMaskOff() const { return mValueMask.isOff(); } | ||
| 769 | 4492402214 | bool isChildMaskOn(Index n) const { return mChildMask.isOn(n); } | |
| 770 | 6348730 | bool isChildMaskOff(Index n) const { return mChildMask.isOff(n); } | |
| 771 | bool isChildMaskOff() const { return mChildMask.isOff(); } | ||
| 772 | 4265256 | const NodeMaskType& getValueMask() const { return mValueMask; } | |
| 773 | 178580 | const NodeMaskType& getChildMask() const { return mChildMask; } | |
| 774 | 4 | NodeMaskType getValueOffMask() const | |
| 775 | { | ||
| 776 | NodeMaskType mask = mValueMask; | ||
| 777 | mask |= mChildMask; | ||
| 778 | mask.toggle(); | ||
| 779 | 4 | return mask; | |
| 780 | } | ||
| 781 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
4268657 | const UnionType* getTable() const { return mNodes; } |
| 782 | protected: | ||
| 783 | //@{ | ||
| 784 | /// Use a mask accessor to ensure consistency between the child and value masks; | ||
| 785 | /// i.e., the value mask should always be off wherever the child mask is on. | ||
| 786 |
1/2✓ Branch 1 taken 351119 times.
✗ Branch 2 not taken.
|
702238 | void setValueMask(Index n, bool on) { mValueMask.set(n, mChildMask.isOn(n) ? false : on); } |
| 787 | //@} | ||
| 788 | |||
| 789 | void makeChildNodeEmpty(Index n, const ValueType& value); | ||
| 790 | void setChildNode( Index i, ChildNodeType* child);//assumes a tile | ||
| 791 | void resetChildNode(Index i, ChildNodeType* child);//checks for an existing child | ||
| 792 | ChildNodeType* unsetChildNode(Index i, const ValueType& value); | ||
| 793 | |||
| 794 | template<typename NodeT, typename VisitorOp, typename ChildAllIterT> | ||
| 795 | static inline void doVisit(NodeT&, VisitorOp&); | ||
| 796 | |||
| 797 | template<typename NodeT, typename OtherNodeT, typename VisitorOp, | ||
| 798 | typename ChildAllIterT, typename OtherChildAllIterT> | ||
| 799 | static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&); | ||
| 800 | |||
| 801 | template<typename NodeT, typename VisitorOp, | ||
| 802 | typename ChildAllIterT, typename OtherChildAllIterT> | ||
| 803 | static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS); | ||
| 804 | |||
| 805 | ///@{ | ||
| 806 | /// @brief Returns a pointer to the child node at the linear offset n. | ||
| 807 | /// @warning This protected method assumes that a child node exists at | ||
| 808 | /// the specified linear offset! | ||
| 809 | ChildNodeType* getChildNode(Index n); | ||
| 810 | const ChildNodeType* getChildNode(Index n) const; | ||
| 811 | ///@} | ||
| 812 | |||
| 813 | ///@{ | ||
| 814 | /// @brief Protected member classes for recursive multi-threading | ||
| 815 | struct VoxelizeActiveTiles; | ||
| 816 | template<typename OtherInternalNode> struct DeepCopy; | ||
| 817 | template<typename OtherInternalNode> struct TopologyCopy1; | ||
| 818 | template<typename OtherInternalNode> struct TopologyCopy2; | ||
| 819 | template<typename OtherInternalNode> struct TopologyUnion; | ||
| 820 | template<typename OtherInternalNode> struct TopologyDifference; | ||
| 821 | template<typename OtherInternalNode> struct TopologyIntersection; | ||
| 822 | ///@} | ||
| 823 | |||
| 824 | UnionType mNodes[NUM_VALUES]; | ||
| 825 | NodeMaskType mChildMask, mValueMask; | ||
| 826 | /// Global grid index coordinates (x,y,z) of the local origin of this node | ||
| 827 | Coord mOrigin; | ||
| 828 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 829 | /// Transient data (not serialized) | ||
| 830 | Index32 mTransientData = 0; | ||
| 831 | #endif | ||
| 832 | }; // class InternalNode | ||
| 833 | |||
| 834 | |||
| 835 | //////////////////////////////////////// | ||
| 836 | |||
| 837 | |||
| 838 | //@{ | ||
| 839 | /// Helper metafunction used to implement InternalNode::SameConfiguration | ||
| 840 | /// (which, as an inner class, can't be independently specialized) | ||
| 841 | template<typename ChildT1, Index Dim1, typename NodeT2> | ||
| 842 | struct SameInternalConfig { | ||
| 843 | static const bool value = false; | ||
| 844 | }; | ||
| 845 | |||
| 846 | template<typename ChildT1, Index Dim1, typename ChildT2> | ||
| 847 | struct SameInternalConfig<ChildT1, Dim1, InternalNode<ChildT2, Dim1> > { | ||
| 848 | static const bool value = ChildT1::template SameConfiguration<ChildT2>::value; | ||
| 849 | }; | ||
| 850 | //@} | ||
| 851 | |||
| 852 | |||
| 853 | //////////////////////////////////////// | ||
| 854 | |||
| 855 | |||
| 856 | template<typename ChildT, Index Log2Dim> | ||
| 857 | inline | ||
| 858 | InternalNode<ChildT, Log2Dim>::InternalNode(const ValueType& background) | ||
| 859 | { | ||
| 860 | for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background); | ||
| 861 | } | ||
| 862 | |||
| 863 | |||
| 864 | template<typename ChildT, Index Log2Dim> | ||
| 865 | inline | ||
| 866 | 477391 | InternalNode<ChildT, Log2Dim>::InternalNode(const Coord& origin, const ValueType& val, bool active): | |
| 867 | mOrigin(origin[0] & ~(DIM - 1), // zero out the low-order bits | ||
| 868 | origin[1] & ~(DIM - 1), | ||
| 869 |
40/56✓ Branch 0 taken 3005841216 times.
✓ Branch 1 taken 214417 times.
✓ Branch 2 taken 37449 times.
✓ Branch 3 taken 176838 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1536 times.
✓ Branch 9 taken 24 times.
✓ Branch 10 taken 132 times.
✓ Branch 11 taken 22 times.
✓ Branch 12 taken 20480 times.
✓ Branch 13 taken 42 times.
✓ Branch 14 taken 2000000 times.
✓ Branch 15 taken 31290 times.
✓ Branch 16 taken 128 times.
✓ Branch 17 taken 31252 times.
✓ Branch 18 taken 1281 times.
✓ Branch 19 taken 21 times.
✓ Branch 20 taken 128 times.
✓ Branch 21 taken 22 times.
✓ Branch 22 taken 513 times.
✓ Branch 23 taken 9 times.
✓ Branch 24 taken 64 times.
✓ Branch 25 taken 1 times.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1108224 times.
✓ Branch 29 taken 17316 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 15625 times.
✓ Branch 32 taken 8320 times.
✓ Branch 33 taken 130 times.
✓ Branch 34 taken 256 times.
✓ Branch 35 taken 4 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 4 times.
✓ Branch 38 taken 1664 times.
✓ Branch 39 taken 26 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 25600 times.
✓ Branch 45 taken 400 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 400 times.
✓ Branch 48 taken 256 times.
✓ Branch 49 taken 4 times.
✓ Branch 50 taken 256 times.
✓ Branch 51 taken 4 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
|
6015712911 | origin[2] & ~(DIM - 1)) |
| 870 | { | ||
| 871 |
12/20✓ Branch 0 taken 37449 times.
✓ Branch 1 taken 176838 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 31294 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 17 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 15629 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 400 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
475398 | if (active) mValueMask.setOn(); |
| 872 |
30/40✓ Branch 0 taken 3005841216 times.
✓ Branch 1 taken 214417 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1536 times.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 20608 times.
✓ Branch 7 taken 42 times.
✓ Branch 8 taken 2000128 times.
✓ Branch 9 taken 31252 times.
✓ Branch 10 taken 1152 times.
✓ Branch 11 taken 18 times.
✓ Branch 12 taken 320 times.
✓ Branch 13 taken 5 times.
✓ Branch 14 taken 576 times.
✓ Branch 15 taken 9 times.
✓ Branch 16 taken 1000000 times.
✓ Branch 17 taken 15625 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 108160 times.
✓ Branch 21 taken 1690 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 8320 times.
✓ Branch 25 taken 130 times.
✓ Branch 26 taken 256 times.
✓ Branch 27 taken 4 times.
✓ Branch 28 taken 1664 times.
✓ Branch 29 taken 26 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 25600 times.
✓ Branch 33 taken 400 times.
✓ Branch 34 taken 256 times.
✓ Branch 35 taken 4 times.
✓ Branch 36 taken 256 times.
✓ Branch 37 taken 4 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
|
6015285391 | for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val); |
| 873 | 427522 | } | |
| 874 | |||
| 875 | |||
| 876 | // For InternalNodes, the PartialCreate constructor is identical to its | ||
| 877 | // non-PartialCreate counterpart. | ||
| 878 | template<typename ChildT, Index Log2Dim> | ||
| 879 | inline | ||
| 880 | 1010 | InternalNode<ChildT, Log2Dim>::InternalNode(PartialCreate, | |
| 881 | const Coord& origin, const ValueType& val, bool active) | ||
| 882 |
3/12✓ Branch 0 taken 9222144 times.
✓ Branch 1 taken 505 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 505 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
18446308 | : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1)) |
| 883 | { | ||
| 884 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
1010 | if (active) mValueMask.setOn(); |
| 885 |
2/12✓ Branch 0 taken 9222144 times.
✓ Branch 1 taken 505 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
18445298 | for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val); |
| 886 | } | ||
| 887 | |||
| 888 | template<typename ChildT, Index Log2Dim> | ||
| 889 | template<typename OtherInternalNode> | ||
| 890 | struct InternalNode<ChildT, Log2Dim>::DeepCopy | ||
| 891 | { | ||
| 892 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
7997 | DeepCopy(const OtherInternalNode* source, InternalNode* target) : s(source), t(target) { |
| 893 |
2/12✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
|
7997 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); |
| 894 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//serial | ||
| 895 | } | ||
| 896 | 2351522 | void operator()(const tbb::blocked_range<Index> &r) const { | |
| 897 |
2/2✓ Branch 0 taken 129753088 times.
✓ Branch 1 taken 1175761 times.
|
261857698 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
| 898 |
2/2✓ Branch 1 taken 129671652 times.
✓ Branch 2 taken 81436 times.
|
259506176 | if (s->mChildMask.isOff(i)) { |
| 899 | 260195248 | t->mNodes[i].setValue(ValueType(s->mNodes[i].getValue())); | |
| 900 | } else { | ||
| 901 |
1/2✓ Branch 2 taken 79303 times.
✗ Branch 3 not taken.
|
162872 | t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()))); |
| 902 | } | ||
| 903 | } | ||
| 904 | 2351522 | } | |
| 905 | const OtherInternalNode* s; | ||
| 906 | InternalNode* t; | ||
| 907 | };// DeepCopy | ||
| 908 | |||
| 909 | template<typename ChildT, Index Log2Dim> | ||
| 910 | inline | ||
| 911 | 9094 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode& other) | |
| 912 | : mChildMask(other.mChildMask) | ||
| 913 | , mValueMask(other.mValueMask) | ||
| 914 | , mOrigin(other.mOrigin) | ||
| 915 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 916 |
3/4✓ Branch 0 taken 85803008 times.
✓ Branch 1 taken 4547 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
|
171624204 | , mTransientData(other.mTransientData) |
| 917 | #endif | ||
| 918 | { | ||
| 919 | DeepCopy<InternalNode<ChildT, Log2Dim> > tmp(&other, this); | ||
| 920 | 9094 | } | |
| 921 | |||
| 922 | |||
| 923 | // Copy-construct from a node with the same configuration but a different ValueType. | ||
| 924 | template<typename ChildT, Index Log2Dim> | ||
| 925 | template<typename OtherChildNodeType> | ||
| 926 | inline | ||
| 927 | 6900 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other) | |
| 928 | : mChildMask(other.mChildMask) | ||
| 929 | , mValueMask(other.mValueMask) | ||
| 930 | , mOrigin(other.mOrigin) | ||
| 931 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 932 |
2/2✓ Branch 0 taken 43950080 times.
✓ Branch 1 taken 3450 times.
|
87913960 | , mTransientData(other.mTransientData) |
| 933 | #endif | ||
| 934 | { | ||
| 935 | DeepCopy<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this); | ||
| 936 | 6900 | } | |
| 937 | |||
| 938 | template<typename ChildT, Index Log2Dim> | ||
| 939 | template<typename OtherInternalNode> | ||
| 940 | struct InternalNode<ChildT, Log2Dim>::TopologyCopy1 | ||
| 941 | { | ||
| 942 | 44950 | TopologyCopy1(const OtherInternalNode* source, InternalNode* target, | |
| 943 | 44950 | const ValueType& background) : s(source), t(target), b(background) { | |
| 944 | 44950 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
| 945 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//serial | ||
| 946 | } | ||
| 947 | 12655502 | void operator()(const tbb::blocked_range<Index> &r) const { | |
| 948 |
2/2✓ Branch 0 taken 622682112 times.
✓ Branch 1 taken 6327751 times.
|
1258019726 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
| 949 |
2/2✓ Branch 1 taken 1185679 times.
✓ Branch 2 taken 621496433 times.
|
1245364224 | if (s->isChildMaskOn(i)) { |
| 950 |
1/2✓ Branch 1 taken 108558 times.
✗ Branch 2 not taken.
|
2435382 | t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()), |
| 951 |
1/2✓ Branch 1 taken 108558 times.
✗ Branch 2 not taken.
|
797056 | b, TopologyCopy())); |
| 952 | } else { | ||
| 953 | 1242992866 | t->mNodes[i].setValue(b); | |
| 954 | } | ||
| 955 | } | ||
| 956 | 12655502 | } | |
| 957 | const OtherInternalNode* s; | ||
| 958 | InternalNode* t; | ||
| 959 | const ValueType &b; | ||
| 960 | };// TopologyCopy1 | ||
| 961 | |||
| 962 | template<typename ChildT, Index Log2Dim> | ||
| 963 | template<typename OtherChildNodeType> | ||
| 964 | inline | ||
| 965 | 89900 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | |
| 966 | const ValueType& background, TopologyCopy) | ||
| 967 | : mChildMask(other.mChildMask) | ||
| 968 | , mValueMask(other.mValueMask) | ||
| 969 | , mOrigin(other.mOrigin) | ||
| 970 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 971 |
2/2✓ Branch 0 taken 622682112 times.
✓ Branch 1 taken 44950 times.
|
1245544024 | , mTransientData(other.mTransientData) |
| 972 | #endif | ||
| 973 | { | ||
| 974 | TopologyCopy1<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this, background); | ||
| 975 | 89900 | } | |
| 976 | |||
| 977 | template<typename ChildT, Index Log2Dim> | ||
| 978 | template<typename OtherInternalNode> | ||
| 979 | struct InternalNode<ChildT, Log2Dim>::TopologyCopy2 | ||
| 980 | { | ||
| 981 | 172 | TopologyCopy2(const OtherInternalNode* source, InternalNode* target, | |
| 982 | const ValueType& offValue, const ValueType& onValue) | ||
| 983 | 172 | : s(source), t(target), offV(offValue), onV(onValue) { | |
| 984 | 172 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
| 985 | } | ||
| 986 | 43682 | void operator()(const tbb::blocked_range<Index> &r) const { | |
| 987 |
2/2✓ Branch 0 taken 1894400 times.
✓ Branch 1 taken 21841 times.
|
3832482 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
| 988 |
2/2✓ Branch 1 taken 14460 times.
✓ Branch 2 taken 1879940 times.
|
3788800 | if (s->isChildMaskOn(i)) { |
| 989 |
1/2✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
|
57840 | t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()), |
| 990 |
1/2✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
|
28920 | offV, onV, TopologyCopy())); |
| 991 | } else { | ||
| 992 |
2/2✓ Branch 1 taken 164 times.
✓ Branch 2 taken 1879776 times.
|
3759880 | t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV); |
| 993 | } | ||
| 994 | } | ||
| 995 | 43682 | } | |
| 996 | const OtherInternalNode* s; | ||
| 997 | InternalNode* t; | ||
| 998 | const ValueType &offV, &onV; | ||
| 999 | };// TopologyCopy2 | ||
| 1000 | |||
| 1001 | template<typename ChildT, Index Log2Dim> | ||
| 1002 | template<typename OtherChildNodeType> | ||
| 1003 | inline | ||
| 1004 | 344 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | |
| 1005 | const ValueType& offValue, | ||
| 1006 | const ValueType& onValue, TopologyCopy) | ||
| 1007 | : mChildMask(other.mChildMask) | ||
| 1008 | , mValueMask(other.mValueMask) | ||
| 1009 | , mOrigin(other.mOrigin) | ||
| 1010 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 1011 |
2/2✓ Branch 0 taken 1894400 times.
✓ Branch 1 taken 172 times.
|
3789424 | , mTransientData(other.mTransientData) |
| 1012 | #endif | ||
| 1013 | { | ||
| 1014 | TopologyCopy2<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this, offValue, onValue); | ||
| 1015 | 344 | } | |
| 1016 | |||
| 1017 | |||
| 1018 | template<typename ChildT, Index Log2Dim> | ||
| 1019 | inline | ||
| 1020 | 634548 | InternalNode<ChildT, Log2Dim>::~InternalNode() | |
| 1021 | { | ||
| 1022 |
2/2✓ Branch 0 taken 297102 times.
✓ Branch 1 taken 317274 times.
|
1228752 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 1023 |
1/2✓ Branch 0 taken 297102 times.
✗ Branch 1 not taken.
|
641680 | delete mNodes[iter.pos()].getChild(); |
| 1024 | } | ||
| 1025 |
3/4✓ Branch 0 taken 487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10129984 times.
✓ Branch 3 taken 487 times.
|
20895490 | } |
| 1026 | |||
| 1027 | |||
| 1028 | //////////////////////////////////////// | ||
| 1029 | |||
| 1030 | |||
| 1031 | template<typename ChildT, Index Log2Dim> | ||
| 1032 | inline Index32 | ||
| 1033 | 214937 | InternalNode<ChildT, Log2Dim>::leafCount() const | |
| 1034 | { | ||
| 1035 |
7/14✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 21 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 155 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 174 times.
✗ Branch 20 not taken.
|
217684 | if (ChildNodeType::getLevel() == 0) return mChildMask.countOn(); |
| 1036 | Index32 sum = 0; | ||
| 1037 |
2/2✓ Branch 0 taken 108674 times.
✓ Branch 1 taken 107475 times.
|
432262 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
| 1038 | 217325 | sum += iter->leafCount(); | |
| 1039 | } | ||
| 1040 | return sum; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | template<typename ChildT, Index Log2Dim> | ||
| 1044 | inline void | ||
| 1045 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
|
672 | InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index32> &vec) const |
| 1046 | { | ||
| 1047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
|
672 | assert(vec.size() > ChildNodeType::LEVEL); |
| 1048 | 672 | const auto count = mChildMask.countOn(); | |
| 1049 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
48 | if (ChildNodeType::LEVEL > 0 && count > 0) { |
| 1050 |
2/2✓ Branch 0 taken 312 times.
✓ Branch 1 taken 24 times.
|
1296 | for (auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec); |
| 1051 | } | ||
| 1052 | 672 | vec[ChildNodeType::LEVEL] += count; | |
| 1053 | } | ||
| 1054 | |||
| 1055 | |||
| 1056 | template<typename ChildT, Index Log2Dim> | ||
| 1057 | inline Index32 | ||
| 1058 | 2405 | InternalNode<ChildT, Log2Dim>::nonLeafCount() const | |
| 1059 | { | ||
| 1060 | Index32 sum = 1; | ||
| 1061 | if (ChildNodeType::getLevel() == 0) return sum; | ||
| 1062 |
2/2✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 1209 times.
|
5170 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
| 1063 | 2765 | sum += iter->nonLeafCount(); | |
| 1064 | } | ||
| 1065 | return sum; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | |||
| 1069 | template<typename ChildT, Index Log2Dim> | ||
| 1070 | inline Index32 | ||
| 1071 | InternalNode<ChildT, Log2Dim>::childCount() const | ||
| 1072 | { | ||
| 1073 |
20/511✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 3 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✓ Branch 124 taken 1 times.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✓ Branch 166 taken 8 times.
✗ Branch 167 not taken.
✗ Branch 168 not taken.
✓ Branch 169 taken 8 times.
✗ Branch 170 not taken.
✓ Branch 171 taken 1 times.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✓ Branch 174 taken 1 times.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✓ Branch 177 taken 1 times.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✓ Branch 180 taken 1 times.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✓ Branch 183 taken 1 times.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✓ Branch 186 taken 1 times.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✓ Branch 189 taken 1 times.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 208 not taken.
✗ Branch 209 not taken.
✗ Branch 211 not taken.
✗ Branch 212 not taken.
✗ Branch 214 not taken.
✗ Branch 215 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 220 not taken.
✗ Branch 221 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 232 not taken.
✗ Branch 233 not taken.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 244 not taken.
✗ Branch 245 not taken.
✗ Branch 247 not taken.
✗ Branch 248 not taken.
✗ Branch 250 not taken.
✗ Branch 251 not taken.
✗ Branch 253 not taken.
✗ Branch 254 not taken.
✗ Branch 256 not taken.
✗ Branch 257 not taken.
✗ Branch 259 not taken.
✗ Branch 260 not taken.
✗ Branch 262 not taken.
✗ Branch 263 not taken.
✗ Branch 265 not taken.
✗ Branch 266 not taken.
✗ Branch 268 not taken.
✗ Branch 269 not taken.
✗ Branch 271 not taken.
✗ Branch 272 not taken.
✗ Branch 274 not taken.
✗ Branch 275 not taken.
✗ Branch 277 not taken.
✗ Branch 278 not taken.
✗ Branch 280 not taken.
✗ Branch 281 not taken.
✗ Branch 283 not taken.
✗ Branch 284 not taken.
✗ Branch 286 not taken.
✗ Branch 287 not taken.
✗ Branch 289 not taken.
✗ Branch 290 not taken.
✗ Branch 292 not taken.
✗ Branch 293 not taken.
✗ Branch 295 not taken.
✗ Branch 296 not taken.
✗ Branch 298 not taken.
✗ Branch 299 not taken.
✗ Branch 301 not taken.
✗ Branch 302 not taken.
✗ Branch 304 not taken.
✗ Branch 305 not taken.
✗ Branch 307 not taken.
✗ Branch 308 not taken.
✗ Branch 310 not taken.
✗ Branch 311 not taken.
✗ Branch 313 not taken.
✗ Branch 314 not taken.
✗ Branch 316 not taken.
✗ Branch 317 not taken.
✓ Branch 319 taken 1 times.
✗ Branch 320 not taken.
✓ Branch 322 taken 1 times.
✗ Branch 323 not taken.
✓ Branch 325 taken 1 times.
✗ Branch 326 not taken.
✓ Branch 328 taken 1 times.
✗ Branch 329 not taken.
✓ Branch 331 taken 1 times.
✗ Branch 332 not taken.
✓ Branch 334 taken 1 times.
✗ Branch 335 not taken.
✗ Branch 337 not taken.
✗ Branch 338 not taken.
✗ Branch 340 not taken.
✗ Branch 341 not taken.
✗ Branch 343 not taken.
✗ Branch 344 not taken.
✗ Branch 346 not taken.
✗ Branch 347 not taken.
✗ Branch 349 not taken.
✗ Branch 350 not taken.
✗ Branch 352 not taken.
✗ Branch 353 not taken.
✗ Branch 355 not taken.
✗ Branch 356 not taken.
✗ Branch 358 not taken.
✗ Branch 359 not taken.
✗ Branch 361 not taken.
✗ Branch 362 not taken.
✗ Branch 364 not taken.
✗ Branch 365 not taken.
✗ Branch 367 not taken.
✗ Branch 368 not taken.
✗ Branch 370 not taken.
✗ Branch 371 not taken.
✗ Branch 373 not taken.
✗ Branch 374 not taken.
✗ Branch 376 not taken.
✗ Branch 377 not taken.
✗ Branch 379 not taken.
✗ Branch 380 not taken.
✗ Branch 382 not taken.
✗ Branch 383 not taken.
✗ Branch 385 not taken.
✗ Branch 386 not taken.
✗ Branch 388 not taken.
✗ Branch 389 not taken.
✗ Branch 391 not taken.
✗ Branch 392 not taken.
✗ Branch 394 not taken.
✗ Branch 395 not taken.
✗ Branch 397 not taken.
✗ Branch 398 not taken.
✗ Branch 400 not taken.
✗ Branch 401 not taken.
✗ Branch 403 not taken.
✗ Branch 404 not taken.
✗ Branch 406 not taken.
✗ Branch 407 not taken.
✗ Branch 409 not taken.
✗ Branch 410 not taken.
✗ Branch 412 not taken.
✗ Branch 413 not taken.
✗ Branch 415 not taken.
✗ Branch 416 not taken.
✗ Branch 418 not taken.
✗ Branch 419 not taken.
✗ Branch 421 not taken.
✗ Branch 422 not taken.
✗ Branch 424 not taken.
✗ Branch 425 not taken.
✗ Branch 427 not taken.
✗ Branch 428 not taken.
✗ Branch 430 not taken.
✗ Branch 431 not taken.
✗ Branch 433 not taken.
✗ Branch 434 not taken.
✗ Branch 436 not taken.
✗ Branch 437 not taken.
✗ Branch 439 not taken.
✗ Branch 440 not taken.
✗ Branch 442 not taken.
✗ Branch 443 not taken.
✗ Branch 445 not taken.
✗ Branch 446 not taken.
✗ Branch 448 not taken.
✗ Branch 449 not taken.
✗ Branch 451 not taken.
✗ Branch 452 not taken.
✗ Branch 454 not taken.
✗ Branch 455 not taken.
✗ Branch 457 not taken.
✗ Branch 458 not taken.
✗ Branch 460 not taken.
✗ Branch 461 not taken.
✗ Branch 463 not taken.
✗ Branch 464 not taken.
✗ Branch 466 not taken.
✗ Branch 467 not taken.
✗ Branch 469 not taken.
✗ Branch 470 not taken.
✗ Branch 472 not taken.
✗ Branch 473 not taken.
✗ Branch 475 not taken.
✗ Branch 476 not taken.
✗ Branch 478 not taken.
✗ Branch 479 not taken.
✗ Branch 481 not taken.
✗ Branch 482 not taken.
✗ Branch 484 not taken.
✗ Branch 485 not taken.
✗ Branch 487 not taken.
✗ Branch 488 not taken.
✗ Branch 490 not taken.
✗ Branch 491 not taken.
✗ Branch 493 not taken.
✗ Branch 494 not taken.
✗ Branch 496 not taken.
✗ Branch 497 not taken.
✗ Branch 499 not taken.
✗ Branch 500 not taken.
✗ Branch 502 not taken.
✗ Branch 503 not taken.
✗ Branch 505 not taken.
✗ Branch 506 not taken.
✗ Branch 508 not taken.
✗ Branch 509 not taken.
✗ Branch 511 not taken.
✗ Branch 512 not taken.
✗ Branch 514 not taken.
✗ Branch 515 not taken.
✗ Branch 517 not taken.
✗ Branch 518 not taken.
✗ Branch 520 not taken.
✗ Branch 521 not taken.
✗ Branch 523 not taken.
✗ Branch 524 not taken.
✗ Branch 526 not taken.
✗ Branch 527 not taken.
✗ Branch 529 not taken.
✗ Branch 530 not taken.
✗ Branch 532 not taken.
✗ Branch 533 not taken.
✗ Branch 535 not taken.
✗ Branch 536 not taken.
✗ Branch 538 not taken.
✗ Branch 539 not taken.
✗ Branch 541 not taken.
✗ Branch 542 not taken.
✗ Branch 544 not taken.
✗ Branch 545 not taken.
✗ Branch 547 not taken.
✗ Branch 548 not taken.
✗ Branch 550 not taken.
✗ Branch 551 not taken.
✗ Branch 553 not taken.
✗ Branch 554 not taken.
✗ Branch 556 not taken.
✗ Branch 557 not taken.
✗ Branch 559 not taken.
✗ Branch 560 not taken.
✗ Branch 562 not taken.
✗ Branch 563 not taken.
✗ Branch 565 not taken.
✗ Branch 566 not taken.
✗ Branch 568 not taken.
✗ Branch 569 not taken.
✗ Branch 571 not taken.
✗ Branch 572 not taken.
✗ Branch 574 not taken.
✗ Branch 575 not taken.
✗ Branch 577 not taken.
✗ Branch 578 not taken.
✗ Branch 580 not taken.
✗ Branch 581 not taken.
✗ Branch 583 not taken.
✗ Branch 584 not taken.
✗ Branch 586 not taken.
✗ Branch 587 not taken.
✗ Branch 589 not taken.
✗ Branch 590 not taken.
✗ Branch 592 not taken.
✗ Branch 593 not taken.
✗ Branch 595 not taken.
✗ Branch 596 not taken.
✗ Branch 598 not taken.
✗ Branch 599 not taken.
✗ Branch 601 not taken.
✗ Branch 602 not taken.
✗ Branch 604 not taken.
✗ Branch 605 not taken.
✗ Branch 607 not taken.
✗ Branch 608 not taken.
✗ Branch 610 not taken.
✗ Branch 611 not taken.
✗ Branch 613 not taken.
✗ Branch 614 not taken.
✗ Branch 616 not taken.
✗ Branch 617 not taken.
✗ Branch 619 not taken.
✗ Branch 620 not taken.
✗ Branch 622 not taken.
✗ Branch 623 not taken.
✗ Branch 625 not taken.
✗ Branch 626 not taken.
✗ Branch 628 not taken.
✗ Branch 629 not taken.
✗ Branch 631 not taken.
✗ Branch 632 not taken.
✗ Branch 634 not taken.
✗ Branch 635 not taken.
✗ Branch 637 not taken.
✗ Branch 638 not taken.
✗ Branch 640 not taken.
✗ Branch 641 not taken.
✗ Branch 643 not taken.
✗ Branch 644 not taken.
✗ Branch 646 not taken.
✗ Branch 647 not taken.
✗ Branch 649 not taken.
✗ Branch 650 not taken.
✗ Branch 652 not taken.
✗ Branch 653 not taken.
✗ Branch 655 not taken.
✗ Branch 656 not taken.
✗ Branch 658 not taken.
✗ Branch 659 not taken.
✗ Branch 661 not taken.
✗ Branch 662 not taken.
✗ Branch 664 not taken.
✗ Branch 665 not taken.
✗ Branch 667 not taken.
✗ Branch 668 not taken.
✗ Branch 670 not taken.
✗ Branch 671 not taken.
✗ Branch 673 not taken.
✗ Branch 674 not taken.
✗ Branch 676 not taken.
✗ Branch 677 not taken.
✗ Branch 679 not taken.
✗ Branch 680 not taken.
✗ Branch 682 not taken.
✗ Branch 683 not taken.
✗ Branch 685 not taken.
✗ Branch 686 not taken.
✗ Branch 688 not taken.
✗ Branch 689 not taken.
✗ Branch 691 not taken.
✗ Branch 692 not taken.
✗ Branch 694 not taken.
✗ Branch 695 not taken.
✗ Branch 697 not taken.
✗ Branch 698 not taken.
✗ Branch 700 not taken.
✗ Branch 701 not taken.
✗ Branch 703 not taken.
✗ Branch 704 not taken.
✗ Branch 706 not taken.
✗ Branch 707 not taken.
✗ Branch 709 not taken.
✗ Branch 710 not taken.
✗ Branch 712 not taken.
✗ Branch 713 not taken.
✗ Branch 715 not taken.
✗ Branch 716 not taken.
✗ Branch 718 not taken.
✗ Branch 719 not taken.
|
171188 | return this->getChildMask().countOn(); |
| 1074 | } | ||
| 1075 | |||
| 1076 | |||
| 1077 | template<typename ChildT, Index Log2Dim> | ||
| 1078 | inline Index64 | ||
| 1079 | InternalNode<ChildT, Log2Dim>::onVoxelCount() const | ||
| 1080 | { | ||
| 1081 | Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn(); | ||
| 1082 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { | ||
| 1083 | sum += iter->onVoxelCount(); | ||
| 1084 | } | ||
| 1085 | return sum; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | |||
| 1089 | template<typename ChildT, Index Log2Dim> | ||
| 1090 | inline Index64 | ||
| 1091 | InternalNode<ChildT, Log2Dim>::offVoxelCount() const | ||
| 1092 | { | ||
| 1093 | Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn()); | ||
| 1094 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { | ||
| 1095 | sum += iter->offVoxelCount(); | ||
| 1096 | } | ||
| 1097 | return sum; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | |||
| 1101 | template<typename ChildT, Index Log2Dim> | ||
| 1102 | inline Index64 | ||
| 1103 | InternalNode<ChildT, Log2Dim>::onLeafVoxelCount() const | ||
| 1104 | { | ||
| 1105 | Index64 sum = 0; | ||
| 1106 | for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) { | ||
| 1107 | sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount(); | ||
| 1108 | } | ||
| 1109 | return sum; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | |||
| 1113 | template<typename ChildT, Index Log2Dim> | ||
| 1114 | inline Index64 | ||
| 1115 | InternalNode<ChildT, Log2Dim>::offLeafVoxelCount() const | ||
| 1116 | { | ||
| 1117 | Index64 sum = 0; | ||
| 1118 | for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) { | ||
| 1119 | sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount(); | ||
| 1120 | } | ||
| 1121 | return sum; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | template<typename ChildT, Index Log2Dim> | ||
| 1125 | inline Index64 | ||
| 1126 | 1 | InternalNode<ChildT, Log2Dim>::onTileCount() const | |
| 1127 | { | ||
| 1128 | 3 | Index64 sum = mValueMask.countOn(); | |
| 1129 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) { |
| 1130 | 2 | sum += iter->onTileCount(); | |
| 1131 | } | ||
| 1132 | 1 | return sum; | |
| 1133 | } | ||
| 1134 | |||
| 1135 | template<typename ChildT, Index Log2Dim> | ||
| 1136 | inline Index64 | ||
| 1137 | InternalNode<ChildT, Log2Dim>::memUsage() const | ||
| 1138 | { | ||
| 1139 | Index64 sum = NUM_VALUES * sizeof(UnionType) + mChildMask.memUsage() | ||
| 1140 | + mValueMask.memUsage() + sizeof(mOrigin); | ||
| 1141 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { | ||
| 1142 | sum += iter->memUsage(); | ||
| 1143 | } | ||
| 1144 | return sum; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | |||
| 1148 | template<typename ChildT, Index Log2Dim> | ||
| 1149 | inline void | ||
| 1150 | 5828 | InternalNode<ChildT, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const | |
| 1151 | { | ||
| 1152 | 11656 | if (bbox.isInside(this->getNodeBoundingBox())) return; | |
| 1153 | |||
| 1154 |
2/2✓ Branch 0 taken 13628 times.
✓ Branch 1 taken 2761 times.
|
32778 | for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) { |
| 1155 | 27256 | bbox.expand(i.getCoord(), ChildT::DIM); | |
| 1156 | } | ||
| 1157 |
2/2✓ Branch 0 taken 120649 times.
✓ Branch 1 taken 2761 times.
|
246820 | for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) { |
| 1158 | 241298 | i->evalActiveBoundingBox(bbox, visitVoxels); | |
| 1159 | } | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | |||
| 1163 | //////////////////////////////////////// | ||
| 1164 | |||
| 1165 | |||
| 1166 | template<typename ChildT, Index Log2Dim> | ||
| 1167 | inline void | ||
| 1168 | 864 | InternalNode<ChildT, Log2Dim>::prune(const ValueType& tolerance) | |
| 1169 | { | ||
| 1170 | 864 | bool state = false; | |
| 1171 | 736 | ValueType value = zeroVal<ValueType>(); | |
| 1172 |
2/2✓ Branch 0 taken 22128 times.
✓ Branch 1 taken 432 times.
|
45120 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 1173 | const Index i = iter.pos(); | ||
| 1174 | ChildT* child = mNodes[i].getChild(); | ||
| 1175 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
434 | child->prune(tolerance); |
| 1176 |
2/5✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✓ Branch 2 taken 21938 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
44256 | if (child->isConstant(value, state, tolerance)) { |
| 1177 |
1/2✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
|
734 | delete child; |
| 1178 | 380 | mChildMask.setOff(i); | |
| 1179 |
2/2✓ Branch 0 taken 58 times.
✓ Branch 1 taken 132 times.
|
380 | mValueMask.set(i, state); |
| 1180 | mNodes[i].setValue(value); | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | |||
| 1186 | //////////////////////////////////////// | ||
| 1187 | |||
| 1188 | |||
| 1189 | template<typename ChildT, Index Log2Dim> | ||
| 1190 | template<typename NodeT> | ||
| 1191 | inline NodeT* | ||
| 1192 | 126866 | InternalNode<ChildT, Log2Dim>::stealNode(const Coord& xyz, const ValueType& value, bool state) | |
| 1193 | { | ||
| 1194 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
| 1195 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
| 1196 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 1197 | const Index n = this->coordToOffset(xyz); | ||
| 1198 |
2/2✓ Branch 0 taken 63431 times.
✓ Branch 1 taken 2 times.
|
126866 | if (mChildMask.isOff(n)) return nullptr; |
| 1199 | ChildT* child = mNodes[n].getChild(); | ||
| 1200 | if (std::is_same<NodeT, ChildT>::value) { | ||
| 1201 | 63498 | mChildMask.setOff(n); | |
| 1202 |
2/2✓ Branch 0 taken 3174 times.
✓ Branch 1 taken 28575 times.
|
63498 | mValueMask.set(n, state); |
| 1203 | mNodes[n].setValue(value); | ||
| 1204 | } | ||
| 1205 | return (std::is_same<NodeT, ChildT>::value) | ||
| 1206 | 63364 | ? reinterpret_cast<NodeT*>(child) | |
| 1207 | 126862 | : child->template stealNode<NodeT>(xyz, value, state); | |
| 1208 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | |||
| 1212 | //////////////////////////////////////// | ||
| 1213 | |||
| 1214 | |||
| 1215 | template<typename ChildT, Index Log2Dim> | ||
| 1216 | template<typename NodeT> | ||
| 1217 | inline NodeT* | ||
| 1218 | 156456 | InternalNode<ChildT, Log2Dim>::probeNode(const Coord& xyz) | |
| 1219 | { | ||
| 1220 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
| 1221 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
| 1222 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 1223 | const Index n = this->coordToOffset(xyz); | ||
| 1224 |
2/2✓ Branch 0 taken 60650 times.
✓ Branch 1 taken 19306 times.
|
156456 | if (mChildMask.isOff(n)) return nullptr; |
| 1225 | ChildT* child = mNodes[n].getChild(); | ||
| 1226 | return (std::is_same<NodeT, ChildT>::value) | ||
| 1227 | 76382 | ? reinterpret_cast<NodeT*>(child) | |
| 1228 | 117844 | : child->template probeNode<NodeT>(xyz); | |
| 1229 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | |||
| 1233 | template<typename ChildT, Index Log2Dim> | ||
| 1234 | template<typename NodeT, typename AccessorT> | ||
| 1235 | inline NodeT* | ||
| 1236 | 7144828 | InternalNode<ChildT, Log2Dim>::probeNodeAndCache(const Coord& xyz, AccessorT& acc) | |
| 1237 | { | ||
| 1238 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
| 1239 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
| 1240 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 1241 | const Index n = this->coordToOffset(xyz); | ||
| 1242 |
2/2✓ Branch 0 taken 3063946 times.
✓ Branch 1 taken 508468 times.
|
7144828 | if (mChildMask.isOff(n)) return nullptr; |
| 1243 | ChildT* child = mNodes[n].getChild(); | ||
| 1244 | 6127892 | acc.insert(xyz, child); | |
| 1245 | return (std::is_same<NodeT, ChildT>::value) | ||
| 1246 | 1690896 | ? reinterpret_cast<NodeT*>(child) | |
| 1247 | 6127892 | : child->template probeNodeAndCache<NodeT>(xyz, acc); | |
| 1248 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | |||
| 1252 | template<typename ChildT, Index Log2Dim> | ||
| 1253 | template<typename NodeT> | ||
| 1254 | inline const NodeT* | ||
| 1255 | 358846 | InternalNode<ChildT, Log2Dim>::probeConstNode(const Coord& xyz) const | |
| 1256 | { | ||
| 1257 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
| 1258 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
| 1259 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 1260 | const Index n = this->coordToOffset(xyz); | ||
| 1261 |
2/2✓ Branch 0 taken 166101 times.
✓ Branch 1 taken 13322 times.
|
358846 | if (mChildMask.isOff(n)) return nullptr; |
| 1262 | const ChildT* child = mNodes[n].getChild(); | ||
| 1263 | return (std::is_same<NodeT, ChildT>::value) | ||
| 1264 | 179202 | ? reinterpret_cast<const NodeT*>(child) | |
| 1265 | 332202 | : child->template probeConstNode<NodeT>(xyz); | |
| 1266 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | |||
| 1270 | template<typename ChildT, Index Log2Dim> | ||
| 1271 | template<typename NodeT, typename AccessorT> | ||
| 1272 | inline const NodeT* | ||
| 1273 | 806133010 | InternalNode<ChildT, Log2Dim>::probeConstNodeAndCache(const Coord& xyz, AccessorT& acc) const | |
| 1274 | { | ||
| 1275 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
| 1276 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
| 1277 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 1278 | const Index n = this->coordToOffset(xyz); | ||
| 1279 |
2/2✓ Branch 0 taken 1273827 times.
✓ Branch 1 taken 401792678 times.
|
806133010 | if (mChildMask.isOff(n)) return nullptr; |
| 1280 | const ChildT* child = mNodes[n].getChild(); | ||
| 1281 | 2547654 | acc.insert(xyz, child); | |
| 1282 | return (std::is_same<NodeT, ChildT>::value) | ||
| 1283 | 1541734 | ? reinterpret_cast<const NodeT*>(child) | |
| 1284 | 2547654 | : child->template probeConstNodeAndCache<NodeT>(xyz, acc); | |
| 1285 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | |||
| 1289 | //////////////////////////////////////// | ||
| 1290 | |||
| 1291 | |||
| 1292 | template<typename ChildT, Index Log2Dim> | ||
| 1293 | inline typename ChildT::LeafNodeType* | ||
| 1294 | InternalNode<ChildT, Log2Dim>::probeLeaf(const Coord& xyz) | ||
| 1295 | { | ||
| 1296 | 1 | return this->template probeNode<LeafNodeType>(xyz); | |
| 1297 | } | ||
| 1298 | |||
| 1299 | |||
| 1300 | template<typename ChildT, Index Log2Dim> | ||
| 1301 | template<typename AccessorT> | ||
| 1302 | inline typename ChildT::LeafNodeType* | ||
| 1303 | InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc) | ||
| 1304 | { | ||
| 1305 | return this->template probeNodeAndCache<LeafNodeType>(xyz, acc); | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | |||
| 1309 | template<typename ChildT, Index Log2Dim> | ||
| 1310 | template<typename AccessorT> | ||
| 1311 | inline const typename ChildT::LeafNodeType* | ||
| 1312 | InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc) const | ||
| 1313 | { | ||
| 1314 | return this->probeConstLeafAndCache(xyz, acc); | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | |||
| 1318 | template<typename ChildT, Index Log2Dim> | ||
| 1319 | inline const typename ChildT::LeafNodeType* | ||
| 1320 | InternalNode<ChildT, Log2Dim>::probeConstLeaf(const Coord& xyz) const | ||
| 1321 | { | ||
| 1322 | return this->template probeConstNode<LeafNodeType>(xyz); | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | |||
| 1326 | template<typename ChildT, Index Log2Dim> | ||
| 1327 | template<typename AccessorT> | ||
| 1328 | inline const typename ChildT::LeafNodeType* | ||
| 1329 | InternalNode<ChildT, Log2Dim>::probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const | ||
| 1330 | { | ||
| 1331 | return this->template probeConstNodeAndCache<LeafNodeType>(xyz, acc); | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | |||
| 1335 | //////////////////////////////////////// | ||
| 1336 | |||
| 1337 | |||
| 1338 | template<typename ChildT, Index Log2Dim> | ||
| 1339 | inline void | ||
| 1340 | 773192 | InternalNode<ChildT, Log2Dim>::addLeaf(LeafNodeType* leaf) | |
| 1341 | { | ||
| 1342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 386596 times.
|
773192 | assert(leaf != nullptr); |
| 1343 | const Coord& xyz = leaf->origin(); | ||
| 1344 | const Index n = this->coordToOffset(xyz); | ||
| 1345 | ChildT* child = nullptr; | ||
| 1346 |
2/2✓ Branch 0 taken 349129 times.
✓ Branch 1 taken 37467 times.
|
773192 | if (mChildMask.isOff(n)) { |
| 1347 | if (ChildT::LEVEL>0) { | ||
| 1348 | 40814 | child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); | |
| 1349 | } else { | ||
| 1350 | child = reinterpret_cast<ChildT*>(leaf); | ||
| 1351 | } | ||
| 1352 | 698258 | this->setChildNode(n, child); | |
| 1353 | } else { | ||
| 1354 | if (ChildT::LEVEL>0) { | ||
| 1355 | child = mNodes[n].getChild(); | ||
| 1356 | } else { | ||
| 1357 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
4 | delete mNodes[n].getChild(); |
| 1358 | child = reinterpret_cast<ChildT*>(leaf); | ||
| 1359 | mNodes[n].setChild(child); | ||
| 1360 | } | ||
| 1361 | } | ||
| 1362 | 115746 | child->addLeaf(leaf); | |
| 1363 | 773192 | } | |
| 1364 | |||
| 1365 | |||
| 1366 | template<typename ChildT, Index Log2Dim> | ||
| 1367 | template<typename AccessorT> | ||
| 1368 | inline void | ||
| 1369 | 247342 | InternalNode<ChildT, Log2Dim>::addLeafAndCache(LeafNodeType* leaf, AccessorT& acc) | |
| 1370 | { | ||
| 1371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 123671 times.
|
247342 | assert(leaf != nullptr); |
| 1372 | const Coord& xyz = leaf->origin(); | ||
| 1373 | const Index n = this->coordToOffset(xyz); | ||
| 1374 | ChildT* child = nullptr; | ||
| 1375 |
2/2✓ Branch 0 taken 122423 times.
✓ Branch 1 taken 1248 times.
|
247342 | if (mChildMask.isOff(n)) { |
| 1376 | if (ChildT::LEVEL>0) { | ||
| 1377 | 6408 | child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); | |
| 1378 | 6408 | acc.insert(xyz, child);//we only cache internal nodes | |
| 1379 | } else { | ||
| 1380 | child = reinterpret_cast<ChildT*>(leaf); | ||
| 1381 | } | ||
| 1382 | 244846 | this->setChildNode(n, child); | |
| 1383 | } else { | ||
| 1384 | if (ChildT::LEVEL>0) { | ||
| 1385 | child = mNodes[n].getChild(); | ||
| 1386 | 2464 | acc.insert(xyz, child);//we only cache internal nodes | |
| 1387 | } else { | ||
| 1388 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
64 | delete mNodes[n].getChild(); |
| 1389 | child = reinterpret_cast<ChildT*>(leaf); | ||
| 1390 | mNodes[n].setChild(child); | ||
| 1391 | } | ||
| 1392 | } | ||
| 1393 | 8872 | child->addLeafAndCache(leaf, acc); | |
| 1394 | 247342 | } | |
| 1395 | |||
| 1396 | |||
| 1397 | //////////////////////////////////////// | ||
| 1398 | |||
| 1399 | |||
| 1400 | template<typename ChildT, Index Log2Dim> | ||
| 1401 | inline bool | ||
| 1402 | 151160 | InternalNode<ChildT, Log2Dim>::addChild(ChildT* child) | |
| 1403 | { | ||
| 1404 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75580 times.
|
151160 | assert(child); |
| 1405 | const Coord& xyz = child->origin(); | ||
| 1406 | // verify that the child belongs in this internal node | ||
| 1407 | 2 | if (Coord((xyz & ~(DIM-1))) != this->origin()) return false; | |
| 1408 | // compute the offset and insert the child node | ||
| 1409 | const Index n = this->coordToOffset(xyz); | ||
| 1410 | // this also deletes an existing child node | ||
| 1411 | 151158 | this->resetChildNode(n, child); | |
| 1412 | 151158 | return true; | |
| 1413 | } | ||
| 1414 | |||
| 1415 | |||
| 1416 | template<typename ChildT, Index Log2Dim> | ||
| 1417 | inline void | ||
| 1418 | 646716 | InternalNode<ChildT, Log2Dim>::addTile(Index n, const ValueType& value, bool state) | |
| 1419 | { | ||
| 1420 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 323358 times.
|
646716 | assert(n < NUM_VALUES); |
| 1421 | 646716 | this->makeChildNodeEmpty(n, value); | |
| 1422 |
2/2✓ Branch 0 taken 51040 times.
✓ Branch 1 taken 272318 times.
|
646716 | mValueMask.set(n, state); |
| 1423 | 646716 | } | |
| 1424 | |||
| 1425 | |||
| 1426 | template<typename ChildT, Index Log2Dim> | ||
| 1427 | inline void | ||
| 1428 | 35504 | InternalNode<ChildT, Log2Dim>::addTile(Index level, const Coord& xyz, | |
| 1429 | const ValueType& value, bool state) | ||
| 1430 | { | ||
| 1431 |
1/2✓ Branch 0 taken 17752 times.
✗ Branch 1 not taken.
|
35504 | if (LEVEL >= level) { |
| 1432 | const Index n = this->coordToOffset(xyz); | ||
| 1433 |
2/2✓ Branch 0 taken 14292 times.
✓ Branch 1 taken 3460 times.
|
35504 | if (mChildMask.isOff(n)) {// tile case |
| 1434 |
2/2✓ Branch 0 taken 3673 times.
✓ Branch 1 taken 10619 times.
|
28584 | if (LEVEL > level) { |
| 1435 |
1/2✓ Branch 3 taken 94 times.
✗ Branch 4 not taken.
|
7346 | ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); |
| 1436 | 7346 | this->setChildNode(n, child); | |
| 1437 | 7346 | child->addTile(level, xyz, value, state); | |
| 1438 | } else { | ||
| 1439 |
2/2✓ Branch 0 taken 10605 times.
✓ Branch 1 taken 14 times.
|
21238 | mValueMask.set(n, state); |
| 1440 | mNodes[n].setValue(value); | ||
| 1441 | } | ||
| 1442 | } else {// child branch case | ||
| 1443 | ChildT* child = mNodes[n].getChild(); | ||
| 1444 |
2/2✓ Branch 0 taken 3459 times.
✓ Branch 1 taken 1 times.
|
6920 | if (LEVEL > level) { |
| 1445 | 6918 | child->addTile(level, xyz, value, state); | |
| 1446 | } else { | ||
| 1447 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | delete child; |
| 1448 | 2 | mChildMask.setOff(n); | |
| 1449 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | mValueMask.set(n, state); |
| 1450 | mNodes[n].setValue(value); | ||
| 1451 | } | ||
| 1452 | } | ||
| 1453 | } | ||
| 1454 | 35504 | } | |
| 1455 | |||
| 1456 | |||
| 1457 | template<typename ChildT, Index Log2Dim> | ||
| 1458 | template<typename AccessorT> | ||
| 1459 | inline void | ||
| 1460 | 14654 | InternalNode<ChildT, Log2Dim>::addTileAndCache(Index level, const Coord& xyz, | |
| 1461 | const ValueType& value, bool state, AccessorT& acc) | ||
| 1462 | { | ||
| 1463 |
1/2✓ Branch 0 taken 7327 times.
✗ Branch 1 not taken.
|
14654 | if (LEVEL >= level) { |
| 1464 | const Index n = this->coordToOffset(xyz); | ||
| 1465 |
2/2✓ Branch 0 taken 353 times.
✓ Branch 1 taken 6974 times.
|
14654 | if (mChildMask.isOff(n)) {// tile case |
| 1466 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 342 times.
|
706 | if (LEVEL > level) { |
| 1467 |
0/2✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
22 | ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); |
| 1468 | 22 | this->setChildNode(n, child); | |
| 1469 | 22 | acc.insert(xyz, child); | |
| 1470 | 22 | child->addTileAndCache(level, xyz, value, state, acc); | |
| 1471 | } else { | ||
| 1472 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
684 | mValueMask.set(n, state); |
| 1473 | mNodes[n].setValue(value); | ||
| 1474 | } | ||
| 1475 | } else {// child branch case | ||
| 1476 | ChildT* child = mNodes[n].getChild(); | ||
| 1477 |
2/2✓ Branch 0 taken 1238 times.
✓ Branch 1 taken 5736 times.
|
13948 | if (LEVEL > level) { |
| 1478 | 2476 | acc.insert(xyz, child); | |
| 1479 | 2476 | child->addTileAndCache(level, xyz, value, state, acc); | |
| 1480 | } else { | ||
| 1481 |
1/2✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
|
11472 | delete child; |
| 1482 | 11472 | mChildMask.setOff(n); | |
| 1483 |
1/2✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
|
11472 | mValueMask.set(n, state); |
| 1484 | mNodes[n].setValue(value); | ||
| 1485 | } | ||
| 1486 | } | ||
| 1487 | } | ||
| 1488 | 14654 | } | |
| 1489 | |||
| 1490 | |||
| 1491 | //////////////////////////////////////// | ||
| 1492 | |||
| 1493 | |||
| 1494 | template<typename ChildT, Index Log2Dim> | ||
| 1495 | inline typename ChildT::LeafNodeType* | ||
| 1496 | 15760 | InternalNode<ChildT, Log2Dim>::touchLeaf(const Coord& xyz) | |
| 1497 | { | ||
| 1498 | const Index n = this->coordToOffset(xyz); | ||
| 1499 | ChildT* child = nullptr; | ||
| 1500 |
2/2✓ Branch 0 taken 3507 times.
✓ Branch 1 taken 4373 times.
|
15760 | if (mChildMask.isOff(n)) { |
| 1501 |
1/2✓ Branch 3 taken 83 times.
✗ Branch 4 not taken.
|
7014 | child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); |
| 1502 | 7014 | this->setChildNode(n, child); | |
| 1503 | } else { | ||
| 1504 | child = mNodes[n].getChild(); | ||
| 1505 | } | ||
| 1506 | 15760 | return child->touchLeaf(xyz); | |
| 1507 | } | ||
| 1508 | |||
| 1509 | |||
| 1510 | template<typename ChildT, Index Log2Dim> | ||
| 1511 | template<typename AccessorT> | ||
| 1512 | inline typename ChildT::LeafNodeType* | ||
| 1513 | 1027698 | InternalNode<ChildT, Log2Dim>::touchLeafAndCache(const Coord& xyz, AccessorT& acc) | |
| 1514 | { | ||
| 1515 | const Index n = this->coordToOffset(xyz); | ||
| 1516 |
2/2✓ Branch 0 taken 170184 times.
✓ Branch 1 taken 343665 times.
|
1027698 | if (mChildMask.isOff(n)) { |
| 1517 |
1/2✓ Branch 3 taken 7674 times.
✗ Branch 4 not taken.
|
340368 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n))); |
| 1518 | } | ||
| 1519 | 1027698 | acc.insert(xyz, mNodes[n].getChild()); | |
| 1520 | 1027698 | return mNodes[n].getChild()->touchLeafAndCache(xyz, acc); | |
| 1521 | } | ||
| 1522 | |||
| 1523 | |||
| 1524 | //////////////////////////////////////// | ||
| 1525 | |||
| 1526 | |||
| 1527 | template<typename ChildT, Index Log2Dim> | ||
| 1528 | inline bool | ||
| 1529 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
68606 | InternalNode<ChildT, Log2Dim>::isConstant(ValueType& firstValue, bool& state, |
| 1530 | const ValueType& tolerance) const | ||
| 1531 | { | ||
| 1532 |
3/6✓ Branch 0 taken 32155 times.
✓ Branch 1 taken 2148 times.
✓ Branch 2 taken 32147 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
132916 | if (!mChildMask.isOff() || !mValueMask.isConstant(state)) return false;// early termination |
| 1533 | |||
| 1534 | 64272 | firstValue = mNodes[0].getValue(); | |
| 1535 |
2/6✓ Branch 0 taken 133849709 times.
✓ Branch 1 taken 32147 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
267763712 | for (Index i = 1; i < NUM_VALUES; ++i) { |
| 1536 |
2/6✓ Branch 0 taken 133403354 times.
✓ Branch 1 taken 188370 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
267183448 | if (!math::isApproxEqual(mNodes[i].getValue(), firstValue, tolerance)) { |
| 1537 | return false; // early termination | ||
| 1538 | } | ||
| 1539 | } | ||
| 1540 | return true; | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | |||
| 1544 | //////////////////////////////////////// | ||
| 1545 | |||
| 1546 | |||
| 1547 | template<typename ChildT, Index Log2Dim> | ||
| 1548 | inline bool | ||
| 1549 |
1/2✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
|
3146 | InternalNode<ChildT, Log2Dim>::isConstant(ValueType& minValue, |
| 1550 | ValueType& maxValue, | ||
| 1551 | bool& state, | ||
| 1552 | const ValueType& tolerance) const | ||
| 1553 | { | ||
| 1554 | |||
| 1555 |
3/4✓ Branch 0 taken 316 times.
✓ Branch 1 taken 1257 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
3186 | if (!mChildMask.isOff() || !mValueMask.isConstant(state)) return false;// early termination |
| 1556 | 630 | minValue = maxValue = mNodes[0].getValue(); | |
| 1557 |
2/2✓ Branch 0 taken 350917 times.
✓ Branch 1 taken 315 times.
|
702464 | for (Index i = 1; i < NUM_VALUES; ++i) { |
| 1558 | const ValueType& v = mNodes[i].getValue(); | ||
| 1559 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 350917 times.
✗ Branch 2 not taken.
|
701834 | if (v < minValue) { |
| 1560 | ✗ | if ((maxValue - v) > tolerance) return false;// early termination | |
| 1561 | ✗ | minValue = v; | |
| 1562 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 350917 times.
✗ Branch 2 not taken.
|
701834 | } else if (v > maxValue) { |
| 1563 | ✗ | if ((v - minValue) > tolerance) return false;// early termination | |
| 1564 | ✗ | maxValue = v; | |
| 1565 | } | ||
| 1566 | } | ||
| 1567 | return true; | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | |||
| 1571 | //////////////////////////////////////// | ||
| 1572 | |||
| 1573 | |||
| 1574 | template<typename ChildT, Index Log2Dim> | ||
| 1575 | inline bool | ||
| 1576 | 18422 | InternalNode<ChildT, Log2Dim>::hasActiveTiles() const | |
| 1577 | { | ||
| 1578 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 1579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
18949 | const bool anyActiveTiles = !mValueMask.isOff(); |
| 1580 |
2/2✓ Branch 0 taken 9361 times.
✓ Branch 1 taken 5 times.
|
18422 | if (LEVEL==1 || anyActiveTiles) return anyActiveTiles; |
| 1581 |
2/2✓ Branch 0 taken 9383 times.
✓ Branch 1 taken 6816 times.
|
31792 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
| 1582 |
2/2✓ Branch 0 taken 2545 times.
✓ Branch 1 taken 6838 times.
|
18453 | if (iter->hasActiveTiles()) return true; |
| 1583 | } | ||
| 1584 | 13339 | return false; | |
| 1585 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | |||
| 1589 | template<typename ChildT, Index Log2Dim> | ||
| 1590 | inline bool | ||
| 1591 | 126779646 | InternalNode<ChildT, Log2Dim>::isValueOn(const Coord& xyz) const | |
| 1592 | { | ||
| 1593 | const Index n = this->coordToOffset(xyz); | ||
| 1594 |
2/2✓ Branch 0 taken 2554922 times.
✓ Branch 1 taken 60834901 times.
|
131889490 | if (this->isChildMaskOff(n)) return this->isValueMaskOn(n); |
| 1595 | 121669802 | return mNodes[n].getChild()->isValueOn(xyz); | |
| 1596 | } | ||
| 1597 | |||
| 1598 | template<typename ChildT, Index Log2Dim> | ||
| 1599 | template<typename AccessorT> | ||
| 1600 | inline bool | ||
| 1601 | 501093166 | InternalNode<ChildT, Log2Dim>::isValueOnAndCache(const Coord& xyz, AccessorT& acc) const | |
| 1602 | { | ||
| 1603 | const Index n = this->coordToOffset(xyz); | ||
| 1604 |
2/2✓ Branch 0 taken 246271400 times.
✓ Branch 1 taken 4275183 times.
|
993635966 | if (this->isChildMaskOff(n)) return this->isValueMaskOn(n); |
| 1605 | 8550240 | acc.insert(xyz, mNodes[n].getChild()); | |
| 1606 | 8550366 | return mNodes[n].getChild()->isValueOnAndCache(xyz, acc); | |
| 1607 | } | ||
| 1608 | |||
| 1609 | |||
| 1610 | template<typename ChildT, Index Log2Dim> | ||
| 1611 | inline const typename ChildT::ValueType& | ||
| 1612 | 114326376 | InternalNode<ChildT, Log2Dim>::getValue(const Coord& xyz) const | |
| 1613 | { | ||
| 1614 | const Index n = this->coordToOffset(xyz); | ||
| 1615 |
2/2✓ Branch 0 taken 17301502 times.
✓ Branch 1 taken 19461938 times.
|
105703538 | return this->isChildMaskOff(n) ? mNodes[n].getValue() |
| 1616 |
2/2✓ Branch 0 taken 4311419 times.
✓ Branch 1 taken 16088329 times.
|
114326376 | : mNodes[n].getChild()->getValue(xyz); |
| 1617 | } | ||
| 1618 | |||
| 1619 | template<typename ChildT, Index Log2Dim> | ||
| 1620 | template<typename AccessorT> | ||
| 1621 | inline const typename ChildT::ValueType& | ||
| 1622 | 10331632662 | InternalNode<ChildT, Log2Dim>::getValueAndCache(const Coord& xyz, AccessorT& acc) const | |
| 1623 | { | ||
| 1624 | const Index n = this->coordToOffset(xyz); | ||
| 1625 |
2/2✓ Branch 0 taken 196770741 times.
✓ Branch 1 taken 4969045590 times.
|
10331632662 | if (this->isChildMaskOn(n)) { |
| 1626 | 393486194 | acc.insert(xyz, mNodes[n].getChild()); | |
| 1627 | 393541482 | return mNodes[n].getChild()->getValueAndCache(xyz, acc); | |
| 1628 | } | ||
| 1629 | 9938091180 | return mNodes[n].getValue(); | |
| 1630 | } | ||
| 1631 | |||
| 1632 | |||
| 1633 | template<typename ChildT, Index Log2Dim> | ||
| 1634 | inline Index | ||
| 1635 | 620218 | InternalNode<ChildT, Log2Dim>::getValueLevel(const Coord& xyz) const | |
| 1636 | { | ||
| 1637 | const Index n = this->coordToOffset(xyz); | ||
| 1638 |
2/2✓ Branch 0 taken 310030 times.
✓ Branch 1 taken 79 times.
|
620218 | return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz); |
| 1639 | } | ||
| 1640 | |||
| 1641 | template<typename ChildT, Index Log2Dim> | ||
| 1642 | template<typename AccessorT> | ||
| 1643 | inline Index | ||
| 1644 | 12770174 | InternalNode<ChildT, Log2Dim>::getValueLevelAndCache(const Coord& xyz, AccessorT& acc) const | |
| 1645 | { | ||
| 1646 | const Index n = this->coordToOffset(xyz); | ||
| 1647 |
2/2✓ Branch 0 taken 234 times.
✓ Branch 1 taken 6384853 times.
|
12770174 | if (this->isChildMaskOn(n)) { |
| 1648 | 234 | acc.insert(xyz, mNodes[n].getChild()); | |
| 1649 | 468 | return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc); | |
| 1650 | } | ||
| 1651 | return LEVEL; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | |||
| 1655 | template<typename ChildT, Index Log2Dim> | ||
| 1656 | inline bool | ||
| 1657 | 639002 | InternalNode<ChildT, Log2Dim>::probeValue(const Coord& xyz, ValueType& value) const | |
| 1658 | { | ||
| 1659 | const Index n = this->coordToOffset(xyz); | ||
| 1660 |
2/2✓ Branch 0 taken 311415 times.
✓ Branch 1 taken 8086 times.
|
639002 | if (this->isChildMaskOff(n)) { |
| 1661 | 622830 | value = mNodes[n].getValue(); | |
| 1662 | 622830 | return this->isValueMaskOn(n); | |
| 1663 | } | ||
| 1664 | 16172 | return mNodes[n].getChild()->probeValue(xyz, value); | |
| 1665 | } | ||
| 1666 | |||
| 1667 | template<typename ChildT, Index Log2Dim> | ||
| 1668 | template<typename AccessorT> | ||
| 1669 | inline bool | ||
| 1670 | 2617807248 | InternalNode<ChildT, Log2Dim>::probeValueAndCache(const Coord& xyz, | |
| 1671 | ValueType& value, AccessorT& acc) const | ||
| 1672 | { | ||
| 1673 | const Index n = this->coordToOffset(xyz); | ||
| 1674 |
2/2✓ Branch 0 taken 148297750 times.
✓ Branch 1 taken 1160605874 times.
|
2617807248 | if (this->isChildMaskOn(n)) { |
| 1675 | 296595500 | acc.insert(xyz, mNodes[n].getChild()); | |
| 1676 | 296595500 | return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc); | |
| 1677 | } | ||
| 1678 | 2321211544 | value = mNodes[n].getValue(); | |
| 1679 | 2321211748 | return this->isValueMaskOn(n); | |
| 1680 | } | ||
| 1681 | |||
| 1682 | |||
| 1683 | template<typename ChildT, Index Log2Dim> | ||
| 1684 | inline void | ||
| 1685 | 136 | InternalNode<ChildT, Log2Dim>::setValueOff(const Coord& xyz) | |
| 1686 | { | ||
| 1687 | const Index n = this->coordToOffset(xyz); | ||
| 1688 | bool hasChild = this->isChildMaskOn(n); | ||
| 1689 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
140 | if (!hasChild && this->isValueMaskOn(n)) { |
| 1690 | // If the voxel belongs to a constant tile that is active, | ||
| 1691 | // a child subtree must be constructed. | ||
| 1692 | hasChild = true; | ||
| 1693 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
6 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/true)); |
| 1694 | } | ||
| 1695 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
136 | if (hasChild) mNodes[n].getChild()->setValueOff(xyz); |
| 1696 | 136 | } | |
| 1697 | |||
| 1698 | |||
| 1699 | template<typename ChildT, Index Log2Dim> | ||
| 1700 | inline void | ||
| 1701 | InternalNode<ChildT, Log2Dim>::setValueOn(const Coord& xyz) | ||
| 1702 | { | ||
| 1703 | const Index n = this->coordToOffset(xyz); | ||
| 1704 | bool hasChild = this->isChildMaskOn(n); | ||
| 1705 | if (!hasChild && !this->isValueMaskOn(n)) { | ||
| 1706 | // If the voxel belongs to a constant tile that is inactive, | ||
| 1707 | // a child subtree must be constructed. | ||
| 1708 | hasChild = true; | ||
| 1709 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/false)); | ||
| 1710 | } | ||
| 1711 | if (hasChild) mNodes[n].getChild()->setValueOn(xyz); | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | |||
| 1715 | template<typename ChildT, Index Log2Dim> | ||
| 1716 | inline void | ||
| 1717 | 648 | InternalNode<ChildT, Log2Dim>::setValueOff(const Coord& xyz, const ValueType& value) | |
| 1718 | { | ||
| 1719 | const Index n = InternalNode::coordToOffset(xyz); | ||
| 1720 | bool hasChild = this->isChildMaskOn(n); | ||
| 1721 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 284 times.
|
648 | if (!hasChild) { |
| 1722 | const bool active = this->isValueMaskOn(n); | ||
| 1723 |
3/4✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
80 | if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
| 1724 | // If the voxel belongs to a tile that is either active or that | ||
| 1725 | // has a constant value that is different from the one provided, | ||
| 1726 | // a child subtree must be constructed. | ||
| 1727 | hasChild = true; | ||
| 1728 |
1/2✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
82 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1729 | } | ||
| 1730 | } | ||
| 1731 |
1/2✓ Branch 0 taken 284 times.
✗ Branch 1 not taken.
|
648 | if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value); |
| 1732 | 648 | } | |
| 1733 | |||
| 1734 | template<typename ChildT, Index Log2Dim> | ||
| 1735 | template<typename AccessorT> | ||
| 1736 | inline void | ||
| 1737 | 478163502 | InternalNode<ChildT, Log2Dim>::setValueOffAndCache(const Coord& xyz, | |
| 1738 | const ValueType& value, AccessorT& acc) | ||
| 1739 | { | ||
| 1740 | const Index n = InternalNode::coordToOffset(xyz); | ||
| 1741 | bool hasChild = this->isChildMaskOn(n); | ||
| 1742 |
2/2✓ Branch 0 taken 239017631 times.
✓ Branch 1 taken 64120 times.
|
478163502 | if (!hasChild) { |
| 1743 | const bool active = this->isValueMaskOn(n); | ||
| 1744 |
3/4✓ Branch 0 taken 239017631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 188264252 times.
|
478035262 | if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
| 1745 | // If the voxel belongs to a tile that is either active or that | ||
| 1746 | // has a constant value that is different from the one provided, | ||
| 1747 | // a child subtree must be constructed. | ||
| 1748 | hasChild = true; | ||
| 1749 |
1/2✓ Branch 2 taken 925 times.
✗ Branch 3 not taken.
|
1982 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1750 | } | ||
| 1751 | } | ||
| 1752 |
2/2✓ Branch 0 taken 64120 times.
✓ Branch 1 taken 239016640 times.
|
478161520 | if (hasChild) { |
| 1753 | ChildT* child = mNodes[n].getChild(); | ||
| 1754 | 130222 | acc.insert(xyz, child); | |
| 1755 | 132 | child->setValueOffAndCache(xyz, value, acc); | |
| 1756 | } | ||
| 1757 | 478163502 | } | |
| 1758 | |||
| 1759 | |||
| 1760 | template<typename ChildT, Index Log2Dim> | ||
| 1761 | inline void | ||
| 1762 | 1266024 | InternalNode<ChildT, Log2Dim>::setValueOn(const Coord& xyz, const ValueType& value) | |
| 1763 | { | ||
| 1764 | const Index n = this->coordToOffset(xyz); | ||
| 1765 | bool hasChild = this->isChildMaskOn(n); | ||
| 1766 |
2/2✓ Branch 0 taken 127912 times.
✓ Branch 1 taken 505100 times.
|
1266024 | if (!hasChild) { |
| 1767 | const bool active = this->isValueMaskOn(n); // tile's active state | ||
| 1768 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 127900 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
255824 | if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
| 1769 | // If the voxel belongs to a tile that is either inactive or that | ||
| 1770 | // has a constant value that is different from the one provided, | ||
| 1771 | // a child subtree must be constructed. | ||
| 1772 | hasChild = true; | ||
| 1773 |
1/2✓ Branch 2 taken 98467 times.
✗ Branch 3 not taken.
|
287128 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1774 | } | ||
| 1775 | } | ||
| 1776 |
1/2✓ Branch 0 taken 505100 times.
✗ Branch 1 not taken.
|
1266024 | if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value); |
| 1777 | 1266024 | } | |
| 1778 | |||
| 1779 | template<typename ChildT, Index Log2Dim> | ||
| 1780 | template<typename AccessorT> | ||
| 1781 | inline void | ||
| 1782 | 43143130 | InternalNode<ChildT, Log2Dim>::setValueAndCache(const Coord& xyz, | |
| 1783 | const ValueType& value, AccessorT& acc) | ||
| 1784 | { | ||
| 1785 | const Index n = this->coordToOffset(xyz); | ||
| 1786 | bool hasChild = this->isChildMaskOn(n); | ||
| 1787 |
2/2✓ Branch 0 taken 478865 times.
✓ Branch 1 taken 21092700 times.
|
43143130 | if (!hasChild) { |
| 1788 | const bool active = this->isValueMaskOn(n); | ||
| 1789 |
3/4✓ Branch 0 taken 246 times.
✓ Branch 1 taken 478619 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 246 times.
|
957730 | if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
| 1790 | // If the voxel belongs to a tile that is either inactive or that | ||
| 1791 | // has a constant value that is different from the one provided, | ||
| 1792 | // a child subtree must be constructed. | ||
| 1793 | hasChild = true; | ||
| 1794 |
1/2✓ Branch 2 taken 439025 times.
✗ Branch 3 not taken.
|
1019738 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1795 | } | ||
| 1796 | } | ||
| 1797 |
2/2✓ Branch 0 taken 21092700 times.
✓ Branch 1 taken 246 times.
|
42185892 | if (hasChild) { |
| 1798 | 43127900 | acc.insert(xyz, mNodes[n].getChild()); | |
| 1799 | 11704886 | mNodes[n].getChild()->setValueAndCache(xyz, value, acc); | |
| 1800 | } | ||
| 1801 | 43143130 | } | |
| 1802 | |||
| 1803 | |||
| 1804 | template<typename ChildT, Index Log2Dim> | ||
| 1805 | inline void | ||
| 1806 | 64 | InternalNode<ChildT, Log2Dim>::setValueOnly(const Coord& xyz, const ValueType& value) | |
| 1807 | { | ||
| 1808 | const Index n = this->coordToOffset(xyz); | ||
| 1809 | bool hasChild = this->isChildMaskOn(n); | ||
| 1810 |
3/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
64 | if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
| 1811 | // If the voxel has a tile value that is different from the one provided, | ||
| 1812 | // a child subtree must be constructed. | ||
| 1813 | const bool active = this->isValueMaskOn(n); | ||
| 1814 | hasChild = true; | ||
| 1815 |
1/2✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
40 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1816 | } | ||
| 1817 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
64 | if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value); |
| 1818 | 64 | } | |
| 1819 | |||
| 1820 | template<typename ChildT, Index Log2Dim> | ||
| 1821 | template<typename AccessorT> | ||
| 1822 | inline void | ||
| 1823 | 89196 | InternalNode<ChildT, Log2Dim>::setValueOnlyAndCache(const Coord& xyz, | |
| 1824 | const ValueType& value, AccessorT& acc) | ||
| 1825 | { | ||
| 1826 | const Index n = this->coordToOffset(xyz); | ||
| 1827 | bool hasChild = this->isChildMaskOn(n); | ||
| 1828 |
3/4✓ Branch 0 taken 25129 times.
✓ Branch 1 taken 19469 times.
✓ Branch 2 taken 25129 times.
✗ Branch 3 not taken.
|
89196 | if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
| 1829 | // If the voxel has a tile value that is different from the one provided, | ||
| 1830 | // a child subtree must be constructed. | ||
| 1831 | const bool active = this->isValueMaskOn(n); | ||
| 1832 | hasChild = true; | ||
| 1833 |
1/2✓ Branch 2 taken 23815 times.
✗ Branch 3 not taken.
|
50258 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1834 | } | ||
| 1835 |
1/2✓ Branch 0 taken 19469 times.
✗ Branch 1 not taken.
|
38938 | if (hasChild) { |
| 1836 | 89196 | acc.insert(xyz, mNodes[n].getChild()); | |
| 1837 | 6984 | mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc); | |
| 1838 | } | ||
| 1839 | } | ||
| 1840 | |||
| 1841 | |||
| 1842 | template<typename ChildT, Index Log2Dim> | ||
| 1843 | inline void | ||
| 1844 | 132 | InternalNode<ChildT, Log2Dim>::setActiveState(const Coord& xyz, bool on) | |
| 1845 | { | ||
| 1846 | const Index n = this->coordToOffset(xyz); | ||
| 1847 | bool hasChild = this->isChildMaskOn(n); | ||
| 1848 |
2/2✓ Branch 0 taken 50 times.
✓ Branch 1 taken 16 times.
|
132 | if (!hasChild) { |
| 1849 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
|
100 | if (on != this->isValueMaskOn(n)) { |
| 1850 | // If the voxel belongs to a tile with the wrong active state, | ||
| 1851 | // then a child subtree must be constructed. | ||
| 1852 | // 'on' is the voxel's new state, therefore '!on' is the tile's current state | ||
| 1853 | hasChild = true; | ||
| 1854 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
98 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on)); |
| 1855 | } | ||
| 1856 | } | ||
| 1857 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
|
132 | if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on); |
| 1858 | 132 | } | |
| 1859 | |||
| 1860 | template<typename ChildT, Index Log2Dim> | ||
| 1861 | template<typename AccessorT> | ||
| 1862 | inline void | ||
| 1863 | 23142398 | InternalNode<ChildT, Log2Dim>::setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& acc) | |
| 1864 | { | ||
| 1865 | const Index n = this->coordToOffset(xyz); | ||
| 1866 | bool hasChild = this->isChildMaskOn(n); | ||
| 1867 |
2/2✓ Branch 0 taken 1340532 times.
✓ Branch 1 taken 10230667 times.
|
23142398 | if (!hasChild) { |
| 1868 |
1/2✓ Branch 0 taken 1340532 times.
✗ Branch 1 not taken.
|
2681064 | if (on != this->isValueMaskOn(n)) { |
| 1869 | // If the voxel belongs to a tile with the wrong active state, | ||
| 1870 | // then a child subtree must be constructed. | ||
| 1871 | // 'on' is the voxel's new state, therefore '!on' is the tile's current state | ||
| 1872 | hasChild = true; | ||
| 1873 |
1/2✓ Branch 2 taken 1269 times.
✗ Branch 3 not taken.
|
2681064 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on)); |
| 1874 | } | ||
| 1875 | } | ||
| 1876 |
1/2✓ Branch 0 taken 10230667 times.
✗ Branch 1 not taken.
|
20461334 | if (hasChild) { |
| 1877 | ChildT* child = mNodes[n].getChild(); | ||
| 1878 | 23142398 | acc.insert(xyz, child); | |
| 1879 | 23142398 | child->setActiveStateAndCache(xyz, on, acc); | |
| 1880 | } | ||
| 1881 | 23142398 | } | |
| 1882 | |||
| 1883 | |||
| 1884 | template<typename ChildT, Index Log2Dim> | ||
| 1885 | inline void | ||
| 1886 | 20 | InternalNode<ChildT, Log2Dim>::setValuesOn() | |
| 1887 | { | ||
| 1888 | 20 | mValueMask = !mChildMask; | |
| 1889 |
2/2✓ Branch 0 taken 2729 times.
✓ Branch 1 taken 10 times.
|
5478 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 1890 | 4 | mNodes[iter.pos()].getChild()->setValuesOn(); | |
| 1891 | } | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | |||
| 1895 | template<typename ChildT, Index Log2Dim> | ||
| 1896 | template<typename ModifyOp> | ||
| 1897 | inline void | ||
| 1898 | 26 | InternalNode<ChildT, Log2Dim>::modifyValue(const Coord& xyz, const ModifyOp& op) | |
| 1899 | { | ||
| 1900 | const Index n = InternalNode::coordToOffset(xyz); | ||
| 1901 | bool hasChild = this->isChildMaskOn(n); | ||
| 1902 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
|
26 | if (!hasChild) { |
| 1903 | // Need to create a child if the tile is inactive, | ||
| 1904 | // in order to activate voxel (x, y, z). | ||
| 1905 | const bool active = this->isValueMaskOn(n); | ||
| 1906 | 10 | bool createChild = !active; | |
| 1907 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
10 | if (!createChild) { |
| 1908 | // Need to create a child if applying the functor | ||
| 1909 | // to the tile value produces a different value. | ||
| 1910 | const ValueType& tileVal = mNodes[n].getValue(); | ||
| 1911 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
10 | ValueType modifiedVal = tileVal; |
| 1912 | op(modifiedVal); | ||
| 1913 | 10 | createChild = !math::isExactlyEqual(tileVal, modifiedVal); | |
| 1914 | } | ||
| 1915 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
10 | if (createChild) { |
| 1916 | hasChild = true; | ||
| 1917 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
12 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1918 | } | ||
| 1919 | } | ||
| 1920 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
26 | if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op); |
| 1921 | 26 | } | |
| 1922 | |||
| 1923 | template<typename ChildT, Index Log2Dim> | ||
| 1924 | template<typename ModifyOp, typename AccessorT> | ||
| 1925 | inline void | ||
| 1926 | 266527302 | InternalNode<ChildT, Log2Dim>::modifyValueAndCache(const Coord& xyz, const ModifyOp& op, | |
| 1927 | AccessorT& acc) | ||
| 1928 | { | ||
| 1929 | const Index n = InternalNode::coordToOffset(xyz); | ||
| 1930 | bool hasChild = this->isChildMaskOn(n); | ||
| 1931 |
2/2✓ Branch 0 taken 16868 times.
✓ Branch 1 taken 133246783 times.
|
266527302 | if (!hasChild) { |
| 1932 | // Need to create a child if the tile is inactive, | ||
| 1933 | // in order to activate voxel (x, y, z). | ||
| 1934 | const bool active = this->isValueMaskOn(n); | ||
| 1935 | 33736 | bool createChild = !active; | |
| 1936 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16868 times.
|
33736 | if (!createChild) { |
| 1937 | // Need to create a child if applying the functor | ||
| 1938 | // to the tile value produces a different value. | ||
| 1939 | const ValueType& tileVal = mNodes[n].getValue(); | ||
| 1940 | ✗ | ValueType modifiedVal = tileVal; | |
| 1941 | op(modifiedVal); | ||
| 1942 | ✗ | createChild = !math::isExactlyEqual(tileVal, modifiedVal); | |
| 1943 | } | ||
| 1944 |
1/2✓ Branch 0 taken 16868 times.
✗ Branch 1 not taken.
|
33736 | if (createChild) { |
| 1945 | hasChild = true; | ||
| 1946 |
1/2✓ Branch 2 taken 16489 times.
✗ Branch 3 not taken.
|
33736 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
| 1947 | } | ||
| 1948 | } | ||
| 1949 |
1/2✓ Branch 0 taken 133246783 times.
✗ Branch 1 not taken.
|
266493566 | if (hasChild) { |
| 1950 | ChildNodeType* child = mNodes[n].getChild(); | ||
| 1951 | 266527302 | acc.insert(xyz, child); | |
| 1952 | 34772582 | child->modifyValueAndCache(xyz, op, acc); | |
| 1953 | } | ||
| 1954 | } | ||
| 1955 | |||
| 1956 | |||
| 1957 | template<typename ChildT, Index Log2Dim> | ||
| 1958 | template<typename ModifyOp> | ||
| 1959 | inline void | ||
| 1960 | 16 | InternalNode<ChildT, Log2Dim>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op) | |
| 1961 | { | ||
| 1962 | const Index n = InternalNode::coordToOffset(xyz); | ||
| 1963 | bool hasChild = this->isChildMaskOn(n); | ||
| 1964 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | if (!hasChild) { |
| 1965 | const bool tileState = this->isValueMaskOn(n); | ||
| 1966 | const ValueType& tileVal = mNodes[n].getValue(); | ||
| 1967 | ✗ | bool modifiedState = !tileState; | |
| 1968 | ✗ | ValueType modifiedVal = tileVal; | |
| 1969 | ✗ | op(modifiedVal, modifiedState); | |
| 1970 | // Need to create a child if applying the functor to the tile | ||
| 1971 | // produces a different value or active state. | ||
| 1972 | ✗ | if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) { | |
| 1973 | hasChild = true; | ||
| 1974 | ✗ | this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState)); | |
| 1975 | } | ||
| 1976 | } | ||
| 1977 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op); |
| 1978 | 16 | } | |
| 1979 | |||
| 1980 | template<typename ChildT, Index Log2Dim> | ||
| 1981 | template<typename ModifyOp, typename AccessorT> | ||
| 1982 | inline void | ||
| 1983 | ✗ | InternalNode<ChildT, Log2Dim>::modifyValueAndActiveStateAndCache( | |
| 1984 | const Coord& xyz, const ModifyOp& op, AccessorT& acc) | ||
| 1985 | { | ||
| 1986 | const Index n = InternalNode::coordToOffset(xyz); | ||
| 1987 | bool hasChild = this->isChildMaskOn(n); | ||
| 1988 | ✗ | if (!hasChild) { | |
| 1989 | const bool tileState = this->isValueMaskOn(n); | ||
| 1990 | const ValueType& tileVal = mNodes[n].getValue(); | ||
| 1991 | bool modifiedState = !tileState; | ||
| 1992 | ✗ | ValueType modifiedVal = tileVal; | |
| 1993 | op(modifiedVal, modifiedState); | ||
| 1994 | // Need to create a child if applying the functor to the tile | ||
| 1995 | // produces a different value or active state. | ||
| 1996 | ✗ | if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) { | |
| 1997 | hasChild = true; | ||
| 1998 | ✗ | this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState)); | |
| 1999 | } | ||
| 2000 | } | ||
| 2001 | ✗ | if (hasChild) { | |
| 2002 | ChildNodeType* child = mNodes[n].getChild(); | ||
| 2003 | ✗ | acc.insert(xyz, child); | |
| 2004 | ✗ | child->modifyValueAndActiveStateAndCache(xyz, op, acc); | |
| 2005 | } | ||
| 2006 | } | ||
| 2007 | |||
| 2008 | |||
| 2009 | //////////////////////////////////////// | ||
| 2010 | |||
| 2011 | |||
| 2012 | template<typename ChildT, Index Log2Dim> | ||
| 2013 | inline void | ||
| 2014 | 194 | InternalNode<ChildT, Log2Dim>::clip(const CoordBBox& clipBBox, const ValueType& background) | |
| 2015 | { | ||
| 2016 | 194 | CoordBBox nodeBBox = this->getNodeBoundingBox(); | |
| 2017 | if (!clipBBox.hasOverlap(nodeBBox)) { | ||
| 2018 | // This node lies completely outside the clipping region. Fill it with background tiles. | ||
| 2019 | 72 | this->fill(nodeBBox, background, /*active=*/false); | |
| 2020 | } else if (clipBBox.isInside(nodeBBox)) { | ||
| 2021 | // This node lies completely inside the clipping region. Leave it intact. | ||
| 2022 | ✗ | return; | |
| 2023 | } | ||
| 2024 | |||
| 2025 | // This node isn't completely contained inside the clipping region. | ||
| 2026 | // Clip tiles and children, and replace any that lie outside the region | ||
| 2027 | // with background tiles. | ||
| 2028 | |||
| 2029 |
2/2✓ Branch 0 taken 1687552 times.
✓ Branch 1 taken 97 times.
|
3375298 | for (Index pos = 0; pos < NUM_VALUES; ++pos) { |
| 2030 | 3375104 | const Coord xyz = this->offsetToGlobalCoord(pos); // tile or child origin | |
| 2031 |
2/2✓ Branch 0 taken 487168 times.
✓ Branch 1 taken 1200384 times.
|
3375104 | CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1)); // tile or child bounds |
| 2032 | if (!clipBBox.hasOverlap(tileBBox)) { | ||
| 2033 | // This table entry lies completely outside the clipping region. | ||
| 2034 | // Replace it with a background tile. | ||
| 2035 | 3374940 | this->makeChildNodeEmpty(pos, background); | |
| 2036 | 3374940 | mValueMask.setOff(pos); | |
| 2037 | } else if (!clipBBox.isInside(tileBBox)) { | ||
| 2038 | // This table entry does not lie completely inside the clipping region | ||
| 2039 | // and must be clipped. | ||
| 2040 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 25 times.
|
158 | if (this->isChildMaskOn(pos)) { |
| 2041 | 108 | mNodes[pos].getChild()->clip(clipBBox, background); | |
| 2042 | } else { | ||
| 2043 | // Replace this tile with a background tile, then fill the clip region | ||
| 2044 | // with the tile's original value. (This might create a child branch.) | ||
| 2045 | 50 | tileBBox.intersect(clipBBox); | |
| 2046 | 50 | const ValueType val = mNodes[pos].getValue(); | |
| 2047 | const bool on = this->isValueMaskOn(pos); | ||
| 2048 | mNodes[pos].setValue(background); | ||
| 2049 | 50 | mValueMask.setOff(pos); | |
| 2050 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
50 | this->fill(tileBBox, val, on); |
| 2051 | } | ||
| 2052 | } else { | ||
| 2053 | // This table entry lies completely inside the clipping region. Leave it intact. | ||
| 2054 | } | ||
| 2055 | } | ||
| 2056 | } | ||
| 2057 | |||
| 2058 | |||
| 2059 | //////////////////////////////////////// | ||
| 2060 | |||
| 2061 | |||
| 2062 | template<typename ChildT, Index Log2Dim> | ||
| 2063 | inline void | ||
| 2064 | 30036 | InternalNode<ChildT, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active) | |
| 2065 | { | ||
| 2066 | 30036 | auto clippedBBox = this->getNodeBoundingBox(); | |
| 2067 | 30036 | clippedBBox.intersect(bbox); | |
| 2068 | ✗ | if (!clippedBBox) return; | |
| 2069 | |||
| 2070 | // Iterate over the fill region in axis-aligned, tile-sized chunks. | ||
| 2071 | // (The first and last chunks along each axis might be smaller than a tile.) | ||
| 2072 | Coord xyz, tileMin, tileMax; | ||
| 2073 |
2/2✓ Branch 0 taken 40090 times.
✓ Branch 1 taken 15018 times.
|
110216 | for (int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.x() + 1) { |
| 2074 | xyz.setX(x); | ||
| 2075 |
2/2✓ Branch 0 taken 318163 times.
✓ Branch 1 taken 40090 times.
|
716506 | for (int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.y() + 1) { |
| 2076 | xyz.setY(y); | ||
| 2077 |
2/2✓ Branch 0 taken 4160096 times.
✓ Branch 1 taken 318163 times.
|
8956518 | for (int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.z() + 1) { |
| 2078 | xyz.setZ(z); | ||
| 2079 | |||
| 2080 | // Get the bounds of the tile that contains voxel (x, y, z). | ||
| 2081 | const Index n = this->coordToOffset(xyz); | ||
| 2082 | 8320192 | tileMin = this->offsetToGlobalCoord(n); | |
| 2083 |
2/2✓ Branch 0 taken 4146735 times.
✓ Branch 1 taken 13361 times.
|
8320192 | tileMax = tileMin.offsetBy(ChildT::DIM - 1); |
| 2084 | |||
| 2085 | if (xyz != tileMin || Coord::lessThan(clippedBBox.max(), tileMax)) { | ||
| 2086 | // If the box defined by (xyz, clippedBBox.max()) doesn't completely enclose | ||
| 2087 | // the tile to which xyz belongs, create a child node (or retrieve | ||
| 2088 | // the existing one). | ||
| 2089 | ChildT* child = nullptr; | ||
| 2090 |
2/2✓ Branch 0 taken 400627 times.
✓ Branch 1 taken 14087 times.
|
829428 | if (this->isChildMaskOff(n)) { |
| 2091 | // Replace the tile with a newly-created child that is initialized | ||
| 2092 | // with the tile's value and active state. | ||
| 2093 |
1/2✓ Branch 2 taken 146660 times.
✗ Branch 3 not taken.
|
801254 | child = new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)}; |
| 2094 | 801254 | this->setChildNode(n, child); | |
| 2095 | } else { | ||
| 2096 | child = mNodes[n].getChild(); | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | // Forward the fill request to the child. | ||
| 2100 |
1/2✓ Branch 0 taken 414714 times.
✗ Branch 1 not taken.
|
829428 | if (child) { |
| 2101 | 829428 | const Coord tmp = Coord::minComponent(clippedBBox.max(), tileMax); | |
| 2102 | 829428 | child->fill(CoordBBox(xyz, tmp), value, active); | |
| 2103 | } | ||
| 2104 | |||
| 2105 | } else { | ||
| 2106 | // If the box given by (xyz, clippedBBox.max()) completely encloses | ||
| 2107 | // the tile to which xyz belongs, create the tile (if it | ||
| 2108 | // doesn't already exist) and give it the fill value. | ||
| 2109 | 7490764 | this->makeChildNodeEmpty(n, value); | |
| 2110 |
2/2✓ Branch 0 taken 3019088 times.
✓ Branch 1 taken 726294 times.
|
7490764 | mValueMask.set(n, active); |
| 2111 | } | ||
| 2112 | } | ||
| 2113 | } | ||
| 2114 | } | ||
| 2115 | } | ||
| 2116 | |||
| 2117 | |||
| 2118 | template<typename ChildT, Index Log2Dim> | ||
| 2119 | inline void | ||
| 2120 | 416 | InternalNode<ChildT, Log2Dim>::denseFill(const CoordBBox& bbox, const ValueType& value, bool active) | |
| 2121 | { | ||
| 2122 | 416 | auto clippedBBox = this->getNodeBoundingBox(); | |
| 2123 | 416 | clippedBBox.intersect(bbox); | |
| 2124 | ✗ | if (!clippedBBox) return; | |
| 2125 | |||
| 2126 | // Iterate over the fill region in axis-aligned, tile-sized chunks. | ||
| 2127 | // (The first and last chunks along each axis might be smaller than a tile.) | ||
| 2128 | Coord xyz, tileMin, tileMax; | ||
| 2129 |
2/2✓ Branch 0 taken 1012 times.
✓ Branch 1 taken 408 times.
|
1440 | for (int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.x() + 1) { |
| 2130 | xyz.setX(x); | ||
| 2131 |
2/2✓ Branch 0 taken 3224 times.
✓ Branch 1 taken 1012 times.
|
4272 | for (int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.y() + 1) { |
| 2132 | xyz.setY(y); | ||
| 2133 |
2/2✓ Branch 0 taken 11924 times.
✓ Branch 1 taken 3224 times.
|
15256 | for (int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.z() + 1) { |
| 2134 | xyz.setZ(z); | ||
| 2135 | |||
| 2136 | // Get the table index of the tile that contains voxel (x, y, z). | ||
| 2137 | const auto n = this->coordToOffset(xyz); | ||
| 2138 | |||
| 2139 | // Retrieve the child node at index n, or replace the tile at index n with a child. | ||
| 2140 | ChildT* child = nullptr; | ||
| 2141 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 11858 times.
|
12008 | if (this->isChildMaskOn(n)) { |
| 2142 | child = mNodes[n].getChild(); | ||
| 2143 | } else { | ||
| 2144 | // Replace the tile with a newly-created child that is filled | ||
| 2145 | // with the tile's value and active state. | ||
| 2146 |
1/2✓ Branch 2 taken 11858 times.
✗ Branch 3 not taken.
|
11876 | child = new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)}; |
| 2147 | 11876 | this->setChildNode(n, child); | |
| 2148 | } | ||
| 2149 | |||
| 2150 | // Get the bounds of the tile that contains voxel (x, y, z). | ||
| 2151 | 12008 | tileMin = this->offsetToGlobalCoord(n); | |
| 2152 | 12008 | tileMax = tileMin.offsetBy(ChildT::DIM - 1); | |
| 2153 | |||
| 2154 | // Forward the fill request to the child. | ||
| 2155 | 12008 | child->denseFill(CoordBBox{xyz, clippedBBox.max()}, value, active); | |
| 2156 | } | ||
| 2157 | } | ||
| 2158 | } | ||
| 2159 | } | ||
| 2160 | |||
| 2161 | |||
| 2162 | //////////////////////////////////////// | ||
| 2163 | |||
| 2164 | |||
| 2165 | template<typename ChildT, Index Log2Dim> | ||
| 2166 | template<typename DenseT> | ||
| 2167 | inline void | ||
| 2168 | 4956 | InternalNode<ChildT, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const | |
| 2169 | { | ||
| 2170 | using DenseValueType = typename DenseT::ValueType; | ||
| 2171 | |||
| 2172 | const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride(); | ||
| 2173 | const Coord& min = dense.bbox().min(); | ||
| 2174 |
2/2✓ Branch 0 taken 3040 times.
✓ Branch 1 taken 2478 times.
|
11036 | for (Coord xyz = bbox.min(), max; xyz[0] <= bbox.max()[0]; xyz[0] = max[0] + 1) { |
| 2175 |
2/2✓ Branch 0 taken 4137 times.
✓ Branch 1 taken 3040 times.
|
14354 | for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = max[1] + 1) { |
| 2176 |
2/2✓ Branch 0 taken 5443 times.
✓ Branch 1 taken 4137 times.
|
19160 | for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = max[2] + 1) { |
| 2177 | const Index n = this->coordToOffset(xyz); | ||
| 2178 | // Get max coordinates of the child node that contains voxel xyz. | ||
| 2179 | 10886 | max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1); | |
| 2180 | |||
| 2181 | // Get the bbox of the interection of bbox and the child node | ||
| 2182 | 10886 | CoordBBox sub(xyz, Coord::minComponent(bbox.max(), max)); | |
| 2183 | |||
| 2184 |
2/2✓ Branch 0 taken 4306 times.
✓ Branch 1 taken 1137 times.
|
10886 | if (this->isChildMaskOn(n)) {//is a child |
| 2185 | 8612 | mNodes[n].getChild()->copyToDense(sub, dense); | |
| 2186 | } else {//a tile value | ||
| 2187 | 2274 | const ValueType value = mNodes[n].getValue(); | |
| 2188 | sub.translate(-min); | ||
| 2189 | 2274 | DenseValueType* a0 = dense.data() + zStride*sub.min()[2]; | |
| 2190 |
2/2✓ Branch 0 taken 4023 times.
✓ Branch 1 taken 1137 times.
|
10320 | for (Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) { |
| 2191 | 8046 | DenseValueType* a1 = a0 + x*xStride; | |
| 2192 |
2/2✓ Branch 0 taken 14253 times.
✓ Branch 1 taken 4023 times.
|
36552 | for (Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) { |
| 2193 | 28506 | DenseValueType* a2 = a1 + y*yStride; | |
| 2194 | 28506 | for (Int32 z = sub.min()[2], ez = sub.max()[2]+1; | |
| 2195 |
2/2✓ Branch 0 taken 42274 times.
✓ Branch 1 taken 14253 times.
|
113054 | z < ez; ++z, a2 += zStride) |
| 2196 | { | ||
| 2197 | 84548 | *a2 = DenseValueType(value); | |
| 2198 | } | ||
| 2199 | } | ||
| 2200 | } | ||
| 2201 | } | ||
| 2202 | } | ||
| 2203 | } | ||
| 2204 | } | ||
| 2205 | 4956 | } | |
| 2206 | |||
| 2207 | |||
| 2208 | //////////////////////////////////////// | ||
| 2209 | |||
| 2210 | |||
| 2211 | template<typename ChildT, Index Log2Dim> | ||
| 2212 | inline void | ||
| 2213 | 1012 | InternalNode<ChildT, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const | |
| 2214 | { | ||
| 2215 | mChildMask.save(os); | ||
| 2216 | mValueMask.save(os); | ||
| 2217 | |||
| 2218 | { | ||
| 2219 | // Copy all of this node's values into an array. | ||
| 2220 |
2/2✓ Branch 1 taken 1806336 times.
✓ Branch 2 taken 98 times.
|
3613684 | std::unique_ptr<ValueType[]> valuePtr(new ValueType[NUM_VALUES]); |
| 2221 | ValueType* values = valuePtr.get(); | ||
| 2222 | 196 | const ValueType zero = zeroVal<ValueType>(); | |
| 2223 |
2/2✓ Branch 0 taken 9226240 times.
✓ Branch 1 taken 506 times.
|
18453492 | for (Index i = 0; i < NUM_VALUES; ++i) { |
| 2224 |
2/4✓ Branch 1 taken 9198097 times.
✓ Branch 2 taken 28143 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
22056398 | values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero); |
| 2225 | } | ||
| 2226 | // Compress (optionally) and write out the contents of the array. | ||
| 2227 |
1/2✓ Branch 1 taken 506 times.
✗ Branch 2 not taken.
|
1012 | io::writeCompressedValues(os, values, NUM_VALUES, mValueMask, mChildMask, toHalf); |
| 2228 | } | ||
| 2229 | // Write out the child nodes in order. | ||
| 2230 |
2/2✓ Branch 0 taken 28143 times.
✓ Branch 1 taken 506 times.
|
57298 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
| 2231 | 512 | iter->writeTopology(os, toHalf); | |
| 2232 | } | ||
| 2233 | } | ||
| 2234 | |||
| 2235 | |||
| 2236 | template<typename ChildT, Index Log2Dim> | ||
| 2237 | inline void | ||
| 2238 | 1010 | InternalNode<ChildT, Log2Dim>::readTopology(std::istream& is, bool fromHalf) | |
| 2239 | { | ||
| 2240 |
2/2✓ Branch 1 taken 303 times.
✓ Branch 2 taken 202 times.
|
2020 | const ValueType background = (!io::getGridBackgroundValuePtr(is) ? zeroVal<ValueType>() |
| 2241 | 1010 | : *static_cast<const ValueType*>(io::getGridBackgroundValuePtr(is))); | |
| 2242 | |||
| 2243 | mChildMask.load(is); | ||
| 2244 | mValueMask.load(is); | ||
| 2245 | |||
| 2246 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 505 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1010 | if (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION) { |
| 2247 | ✗ | for (Index i = 0; i < NUM_VALUES; ++i) { | |
| 2248 | ✗ | if (this->isChildMaskOn(i)) { | |
| 2249 | ✗ | ChildNodeType* child = | |
| 2250 | ✗ | new ChildNodeType(PartialCreate(), offsetToGlobalCoord(i), background); | |
| 2251 | mNodes[i].setChild(child); | ||
| 2252 | ✗ | child->readTopology(is); | |
| 2253 | } else { | ||
| 2254 | ✗ | ValueType value; | |
| 2255 | ✗ | is.read(reinterpret_cast<char*>(&value), sizeof(ValueType)); | |
| 2256 | mNodes[i].setValue(value); | ||
| 2257 | } | ||
| 2258 | } | ||
| 2259 | } else { | ||
| 2260 | const bool oldVersion = | ||
| 2261 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1010 | (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION); |
| 2262 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
1010 | const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES); |
| 2263 | { | ||
| 2264 | // Read in (and uncompress, if necessary) all of this node's values | ||
| 2265 | // into a contiguous array. | ||
| 2266 |
2/4✓ Branch 1 taken 3723264 times.
✓ Branch 2 taken 202 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
7447538 | std::unique_ptr<ValueType[]> valuePtr(new ValueType[numValues]); |
| 2267 | ValueType* values = valuePtr.get(); | ||
| 2268 |
1/2✓ Branch 1 taken 505 times.
✗ Branch 2 not taken.
|
1010 | io::readCompressedValues(is, values, numValues, mValueMask, fromHalf); |
| 2269 | |||
| 2270 | // Copy values from the array into this node's table. | ||
| 2271 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
1010 | if (oldVersion) { |
| 2272 | Index n = 0; | ||
| 2273 | ✗ | for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) { | |
| 2274 | ✗ | mNodes[iter.pos()].setValue(values[n++]); | |
| 2275 | } | ||
| 2276 | ✗ | assert(n == numValues); | |
| 2277 | } else { | ||
| 2278 |
2/2✓ Branch 0 taken 9198703 times.
✓ Branch 1 taken 505 times.
|
18398416 | for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) { |
| 2279 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
18397406 | mNodes[iter.pos()].setValue(values[iter.pos()]); |
| 2280 | } | ||
| 2281 | } | ||
| 2282 | } | ||
| 2283 | // Read in all child nodes and insert them into the table at their proper locations. | ||
| 2284 |
2/2✓ Branch 0 taken 23441 times.
✓ Branch 1 taken 505 times.
|
47892 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 2285 |
3/9✓ Branch 1 taken 23441 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23441 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10219 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
46894 | ChildNodeType* child = new ChildNodeType(PartialCreate(), iter.getCoord(), background); |
| 2286 | mNodes[iter.pos()].setChild(child); | ||
| 2287 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
510 | child->readTopology(is, fromHalf); |
| 2288 | } | ||
| 2289 | } | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | |||
| 2293 | //////////////////////////////////////// | ||
| 2294 | |||
| 2295 | |||
| 2296 | template<typename ChildT, Index Log2Dim> | ||
| 2297 | inline const typename ChildT::ValueType& | ||
| 2298 | 1554 | InternalNode<ChildT, Log2Dim>::getFirstValue() const | |
| 2299 | { | ||
| 2300 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 743 times.
|
1554 | return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue()); |
| 2301 | } | ||
| 2302 | |||
| 2303 | |||
| 2304 | template<typename ChildT, Index Log2Dim> | ||
| 2305 | inline const typename ChildT::ValueType& | ||
| 2306 | 4295 | InternalNode<ChildT, Log2Dim>::getLastValue() const | |
| 2307 | { | ||
| 2308 | const Index n = NUM_VALUES - 1; | ||
| 2309 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 2078 times.
|
4295 | return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue()); |
| 2310 | } | ||
| 2311 | |||
| 2312 | |||
| 2313 | //////////////////////////////////////// | ||
| 2314 | |||
| 2315 | |||
| 2316 | template<typename ChildT, Index Log2Dim> | ||
| 2317 | inline void | ||
| 2318 | 7 | InternalNode<ChildT, Log2Dim>::negate() | |
| 2319 | { | ||
| 2320 |
2/2✓ Branch 0 taken 102400 times.
✓ Branch 1 taken 4 times.
|
200711 | for (Index i = 0; i < NUM_VALUES; ++i) { |
| 2321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 102400 times.
|
200704 | if (this->isChildMaskOn(i)) { |
| 2322 | ✗ | mNodes[i].getChild()->negate(); | |
| 2323 | } else { | ||
| 2324 | mNodes[i].setValue(math::negative(mNodes[i].getValue())); | ||
| 2325 | } | ||
| 2326 | } | ||
| 2327 | |||
| 2328 | 7 | } | |
| 2329 | |||
| 2330 | |||
| 2331 | //////////////////////////////////////// | ||
| 2332 | |||
| 2333 | |||
| 2334 | template<typename ChildT, Index Log2Dim> | ||
| 2335 | struct InternalNode<ChildT, Log2Dim>::VoxelizeActiveTiles | ||
| 2336 | { | ||
| 2337 | 32326 | VoxelizeActiveTiles(InternalNode &node) : mNode(&node) { | |
| 2338 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
| 2339 | 32326 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
| 2340 | |||
| 2341 | node.mChildMask |= node.mValueMask; | ||
| 2342 | node.mValueMask.setOff(); | ||
| 2343 | 32160 | } | |
| 2344 | 4626874 | void operator()(const tbb::blocked_range<Index> &r) const | |
| 2345 | { | ||
| 2346 |
2/2✓ Branch 0 taken 219318656 times.
✓ Branch 1 taken 2313437 times.
|
443264186 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
| 2347 |
2/2✓ Branch 1 taken 43559920 times.
✓ Branch 2 taken 175758736 times.
|
438637312 | if (mNode->mChildMask.isOn(i)) {// Loop over node's child nodes |
| 2348 | 12754 | mNode->mNodes[i].getChild()->voxelizeActiveTiles(true); | |
| 2349 |
2/2✓ Branch 1 taken 20730988 times.
✓ Branch 2 taken 198236082 times.
|
437934140 | } else if (mNode->mValueMask.isOn(i)) {// Loop over node's active tiles |
| 2350 | 41461976 | const Coord &ijk = mNode->offsetToGlobalCoord(i); | |
| 2351 |
1/2✓ Branch 2 taken 574236 times.
✗ Branch 3 not taken.
|
41461976 | ChildNodeType *child = new ChildNodeType(ijk, mNode->mNodes[i].getValue(), true); |
| 2352 | 8992 | child->voxelizeActiveTiles(true); | |
| 2353 | 41461976 | mNode->mNodes[i].setChild(child); | |
| 2354 | } | ||
| 2355 | } | ||
| 2356 | 4626874 | } | |
| 2357 | InternalNode* mNode; | ||
| 2358 | };// VoxelizeActiveTiles | ||
| 2359 | |||
| 2360 | template<typename ChildT, Index Log2Dim> | ||
| 2361 | inline void | ||
| 2362 | 32800 | InternalNode<ChildT, Log2Dim>::voxelizeActiveTiles(bool threaded) | |
| 2363 | { | ||
| 2364 |
2/2✓ Branch 0 taken 16258 times.
✓ Branch 1 taken 142 times.
|
32800 | if (threaded) { |
| 2365 | 32184 | VoxelizeActiveTiles tmp(*this); | |
| 2366 | } else { | ||
| 2367 |
2/2✓ Branch 0 taken 8452 times.
✓ Branch 1 taken 142 times.
|
17188 | for (ValueOnIter iter = this->beginValueOn(); iter; ++iter) { |
| 2368 | 16904 | this->setChildNode(iter.pos(), | |
| 2369 |
1/2✓ Branch 3 taken 8322 times.
✗ Branch 4 not taken.
|
50712 | new ChildNodeType(iter.getCoord(), iter.getValue(), true)); |
| 2370 | } | ||
| 2371 |
2/2✓ Branch 0 taken 8458 times.
✓ Branch 1 taken 142 times.
|
17200 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) |
| 2372 | 268 | iter->voxelizeActiveTiles(false); | |
| 2373 | } | ||
| 2374 | 32800 | } | |
| 2375 | |||
| 2376 | |||
| 2377 | //////////////////////////////////////// | ||
| 2378 | |||
| 2379 | |||
| 2380 | template<typename ChildT, Index Log2Dim> | ||
| 2381 | template<MergePolicy Policy> | ||
| 2382 | inline void | ||
| 2383 | 170264 | InternalNode<ChildT, Log2Dim>::merge(InternalNode& other, | |
| 2384 | const ValueType& background, const ValueType& otherBackground) | ||
| 2385 | { | ||
| 2386 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 2387 | |||
| 2388 | switch (Policy) { | ||
| 2389 | |||
| 2390 | case MERGE_ACTIVE_STATES: | ||
| 2391 | default: | ||
| 2392 | { | ||
| 2393 |
2/2✓ Branch 0 taken 212294 times.
✓ Branch 1 taken 85108 times.
|
594804 | for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) { |
| 2394 | const Index n = iter.pos(); | ||
| 2395 |
2/2✓ Branch 1 taken 129694 times.
✓ Branch 2 taken 82600 times.
|
424588 | if (mChildMask.isOn(n)) { |
| 2396 | // Merge this node's child with the other node's child. | ||
| 2397 | 88452 | mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter, | |
| 2398 | background, otherBackground); | ||
| 2399 |
2/2✓ Branch 1 taken 82403 times.
✓ Branch 2 taken 197 times.
|
165200 | } else if (mValueMask.isOff(n)) { |
| 2400 | // Replace this node's inactive tile with the other node's child | ||
| 2401 | // and replace the other node's child with a tile of undefined value | ||
| 2402 | // (which is okay since the other tree is assumed to be cannibalized | ||
| 2403 | // in the process of merging). | ||
| 2404 | ChildNodeType* child = other.mNodes[n].getChild(); | ||
| 2405 | 164806 | other.mChildMask.setOff(n); | |
| 2406 | 35174 | child->resetBackground(otherBackground, background); | |
| 2407 | 164806 | this->setChildNode(n, child); | |
| 2408 | } | ||
| 2409 | } | ||
| 2410 | |||
| 2411 | // Copy active tile values. | ||
| 2412 |
2/2✓ Branch 0 taken 5799 times.
✓ Branch 1 taken 85108 times.
|
181814 | for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) { |
| 2413 | const Index n = iter.pos(); | ||
| 2414 |
2/2✓ Branch 1 taken 1539 times.
✓ Branch 2 taken 4260 times.
|
11598 | if (mValueMask.isOff(n)) { |
| 2415 | // Replace this node's child or inactive tile with the other node's active tile. | ||
| 2416 | 3078 | this->makeChildNodeEmpty(n, iter.getValue()); | |
| 2417 | 3078 | mValueMask.setOn(n); | |
| 2418 | } | ||
| 2419 | } | ||
| 2420 | break; | ||
| 2421 | } | ||
| 2422 | |||
| 2423 | case MERGE_NODES: | ||
| 2424 | { | ||
| 2425 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
|
28 | for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) { |
| 2426 | const Index n = iter.pos(); | ||
| 2427 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | if (mChildMask.isOn(n)) { |
| 2428 | // Merge this node's child with the other node's child. | ||
| 2429 | 8 | mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground); | |
| 2430 | } else { | ||
| 2431 | // Replace this node's tile (regardless of its active state) with | ||
| 2432 | // the other node's child and replace the other node's child with | ||
| 2433 | // a tile of undefined value (which is okay since the other tree | ||
| 2434 | // is assumed to be cannibalized in the process of merging). | ||
| 2435 | ChildNodeType* child = other.mNodes[n].getChild(); | ||
| 2436 | ✗ | other.mChildMask.setOff(n); | |
| 2437 | ✗ | child->resetBackground(otherBackground, background); | |
| 2438 | ✗ | this->setChildNode(n, child); | |
| 2439 | } | ||
| 2440 | } | ||
| 2441 | break; | ||
| 2442 | } | ||
| 2443 | |||
| 2444 | case MERGE_ACTIVE_STATES_AND_NODES: | ||
| 2445 | { | ||
| 2446 | // Transfer children from the other tree to this tree. | ||
| 2447 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
|
118 | for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) { |
| 2448 | const Index n = iter.pos(); | ||
| 2449 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 33 times.
|
86 | if (mChildMask.isOn(n)) { |
| 2450 | // Merge this node's child with the other node's child. | ||
| 2451 | 18 | mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground); | |
| 2452 | } else { | ||
| 2453 | // Replace this node's tile with the other node's child, leaving the other | ||
| 2454 | // node with an inactive tile of undefined value (which is okay since | ||
| 2455 | // the other tree is assumed to be cannibalized in the process of merging). | ||
| 2456 | ChildNodeType* child = other.mNodes[n].getChild(); | ||
| 2457 | 66 | other.mChildMask.setOff(n); | |
| 2458 | 66 | child->resetBackground(otherBackground, background); | |
| 2459 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
|
66 | if (mValueMask.isOn(n)) { |
| 2460 | // Merge the child with this node's active tile. | ||
| 2461 | ✗ | child->template merge<Policy>(mNodes[n].getValue(), /*on=*/true); | |
| 2462 | ✗ | mValueMask.setOff(n); | |
| 2463 | } | ||
| 2464 | 66 | mChildMask.setOn(n); | |
| 2465 | mNodes[n].setChild(child); | ||
| 2466 | } | ||
| 2467 | } | ||
| 2468 | |||
| 2469 | // Merge active tiles into this tree. | ||
| 2470 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
|
36 | for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) { |
| 2471 | const Index n = iter.pos(); | ||
| 2472 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | if (mChildMask.isOn(n)) { |
| 2473 | // Merge the other node's active tile into this node's child. | ||
| 2474 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
4 | mNodes[n].getChild()->template merge<Policy>(iter.getValue(), /*on=*/true); |
| 2475 | ✗ | } else if (mValueMask.isOff(n)) { | |
| 2476 | // Replace this node's inactive tile with the other node's active tile. | ||
| 2477 | mNodes[n].setValue(iter.getValue()); | ||
| 2478 | ✗ | mValueMask.setOn(n); | |
| 2479 | } | ||
| 2480 | } | ||
| 2481 | break; | ||
| 2482 | } | ||
| 2483 | |||
| 2484 | } | ||
| 2485 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 2486 | } | ||
| 2487 | |||
| 2488 | |||
| 2489 | template<typename ChildT, Index Log2Dim> | ||
| 2490 | template<MergePolicy Policy> | ||
| 2491 | inline void | ||
| 2492 | ✗ | InternalNode<ChildT, Log2Dim>::merge(const ValueType& tileValue, bool tileActive) | |
| 2493 | { | ||
| 2494 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 2495 | |||
| 2496 | if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return; | ||
| 2497 | |||
| 2498 | // For MERGE_ACTIVE_STATES_AND_NODES, inactive tiles in the other tree are ignored. | ||
| 2499 | ✗ | if (!tileActive) return; | |
| 2500 | |||
| 2501 | // Iterate over this node's children and inactive tiles. | ||
| 2502 | ✗ | for (ValueOffIter iter = this->beginValueOff(); iter; ++iter) { | |
| 2503 | const Index n = iter.pos(); | ||
| 2504 | ✗ | if (mChildMask.isOn(n)) { | |
| 2505 | // Merge the other node's active tile into this node's child. | ||
| 2506 | ✗ | mNodes[n].getChild()->template merge<Policy>(tileValue, /*on=*/true); | |
| 2507 | } else { | ||
| 2508 | // Replace this node's inactive tile with the other node's active tile. | ||
| 2509 | iter.setValue(tileValue); | ||
| 2510 | ✗ | mValueMask.setOn(n); | |
| 2511 | } | ||
| 2512 | } | ||
| 2513 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | |||
| 2517 | //////////////////////////////////////// | ||
| 2518 | |||
| 2519 | |||
| 2520 | template<typename ChildT, Index Log2Dim> | ||
| 2521 | template<typename OtherInternalNode> | ||
| 2522 | struct InternalNode<ChildT, Log2Dim>::TopologyUnion | ||
| 2523 | { | ||
| 2524 | using W = typename NodeMaskType::Word; | ||
| 2525 | struct A { inline void operator()(W &tV, const W& sV, const W& tC) const | ||
| 2526 | 3997568 | { tV = (tV | sV) & ~tC; } | |
| 2527 | }; | ||
| 2528 | 29752 | TopologyUnion(const OtherInternalNode* source, InternalNode* target, const bool preserveTiles) | |
| 2529 | 29752 | : s(source), t(target), mPreserveTiles(preserveTiles) { | |
| 2530 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
| 2531 | 29752 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
| 2532 | |||
| 2533 | // Bit processing is done in a single thread! | ||
| 2534 |
2/2✓ Branch 0 taken 9609 times.
✓ Branch 1 taken 5267 times.
|
29752 | if (!mPreserveTiles) t->mChildMask |= s->mChildMask;//serial but very fast bitwise post-process |
| 2535 | 42136 | else t->mChildMask |= (s->mChildMask & !t->mValueMask); | |
| 2536 | |||
| 2537 | A op; | ||
| 2538 | 29752 | t->mValueMask.foreach(s->mValueMask, t->mChildMask, op); | |
| 2539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14876 times.
|
59504 | assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles or child nodes |
| 2540 | 29752 | } | |
| 2541 | 4363708 | void operator()(const tbb::blocked_range<Index> &r) const { | |
| 2542 |
2/2✓ Branch 0 taken 255844352 times.
✓ Branch 1 taken 2181854 times.
|
516052412 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
| 2543 |
2/2✓ Branch 1 taken 68381 times.
✓ Branch 2 taken 255775971 times.
|
511688704 | if (s->mChildMask.isOn(i)) {// Loop over other node's child nodes |
| 2544 | const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild()); | ||
| 2545 |
2/2✓ Branch 1 taken 37219 times.
✓ Branch 2 taken 31162 times.
|
136762 | if (t->mChildMask.isOn(i)) {//this has a child node |
| 2546 | 16156 | t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles); | |
| 2547 | } else {// this is a tile so replace it with a child branch with identical topology | ||
| 2548 |
4/4✓ Branch 0 taken 3265 times.
✓ Branch 1 taken 27897 times.
✓ Branch 3 taken 3232 times.
✓ Branch 4 taken 33 times.
|
62324 | if (!mPreserveTiles || t->mValueMask.isOff(i)) { // force child topology |
| 2549 |
2/4✓ Branch 1 taken 6915 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1698 times.
✗ Branch 5 not taken.
|
62258 | ChildT* child = new ChildT(other, t->mNodes[i].getValue(), TopologyCopy()); |
| 2550 |
2/2✓ Branch 1 taken 91 times.
✓ Branch 2 taken 31038 times.
|
62258 | if (t->mValueMask.isOn(i)) child->setValuesOn();//activate all values |
| 2551 | 62258 | t->mNodes[i].setChild(child); | |
| 2552 | } | ||
| 2553 | } | ||
| 2554 |
4/4✓ Branch 1 taken 41175 times.
✓ Branch 2 taken 255734796 times.
✓ Branch 4 taken 178 times.
✓ Branch 5 taken 40997 times.
|
511551942 | } else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) { |
| 2555 | 2 | t->mNodes[i].getChild()->setValuesOn(); | |
| 2556 | } | ||
| 2557 | } | ||
| 2558 | 4363708 | } | |
| 2559 | const OtherInternalNode* s; | ||
| 2560 | InternalNode* t; | ||
| 2561 | const bool mPreserveTiles; | ||
| 2562 | };// TopologyUnion | ||
| 2563 | |||
| 2564 | template<typename ChildT, Index Log2Dim> | ||
| 2565 | template<typename OtherChildT> | ||
| 2566 | inline void | ||
| 2567 | InternalNode<ChildT, Log2Dim>::topologyUnion(const InternalNode<OtherChildT, Log2Dim>& other, const bool preserveTiles) | ||
| 2568 | { | ||
| 2569 |
27/68✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 250 times.
✓ Branch 10 taken 623 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2619 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 14 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 45 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 75 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 69 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 65 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 69 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 66 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 66 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 69 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 75 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 116 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 130 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 49 times.
✗ Branch 57 not taken.
✓ Branch 59 taken 49 times.
✗ Branch 60 not taken.
✓ Branch 62 taken 67 times.
✗ Branch 63 not taken.
✓ Branch 65 taken 449 times.
✗ Branch 66 not taken.
✓ Branch 68 taken 34 times.
✗ Branch 69 not taken.
✓ Branch 71 taken 286 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 99 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 273 times.
✗ Branch 78 not taken.
✓ Branch 80 taken 398 times.
✗ Branch 81 not taken.
✓ Branch 83 taken 720 times.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
|
14876 | TopologyUnion<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, preserveTiles); |
| 2570 | 14876 | } | |
| 2571 | |||
| 2572 | template<typename ChildT, Index Log2Dim> | ||
| 2573 | template<typename OtherInternalNode> | ||
| 2574 | struct InternalNode<ChildT, Log2Dim>::TopologyIntersection | ||
| 2575 | { | ||
| 2576 | using W = typename NodeMaskType::Word; | ||
| 2577 | struct A { inline void operator()(W &tC, const W& sC, const W& sV, const W& tV) const | ||
| 2578 | 214912 | { tC = (tC & (sC | sV)) | (tV & sC); } | |
| 2579 | }; | ||
| 2580 | 1494 | TopologyIntersection(const OtherInternalNode* source, InternalNode* target, | |
| 2581 | 1494 | const ValueType& background) : s(source), t(target), b(background) { | |
| 2582 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
| 2583 | 1494 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
| 2584 | |||
| 2585 | // Bit processing is done in a single thread! | ||
| 2586 | A op; | ||
| 2587 | 1494 | t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op); | |
| 2588 | |||
| 2589 | 1494 | t->mValueMask &= s->mValueMask; | |
| 2590 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 747 times.
|
2988 | assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles or child nodes |
| 2591 | 1494 | } | |
| 2592 | 216068 | void operator()(const tbb::blocked_range<Index> &r) const { | |
| 2593 |
2/2✓ Branch 0 taken 13754368 times.
✓ Branch 1 taken 108034 times.
|
27724804 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
| 2594 |
2/2✓ Branch 1 taken 13761 times.
✓ Branch 2 taken 13740607 times.
|
27508736 | if (t->mChildMask.isOn(i)) {// Loop over this node's child nodes |
| 2595 | ChildT* child = t->mNodes[i].getChild(); | ||
| 2596 |
2/2✓ Branch 1 taken 8426 times.
✓ Branch 2 taken 5335 times.
|
27522 | if (s->mChildMask.isOn(i)) {//other also has a child node |
| 2597 | 748 | child->topologyIntersection(*(s->mNodes[i].getChild()), b); | |
| 2598 |
2/2✓ Branch 1 taken 4884 times.
✓ Branch 2 taken 451 times.
|
10670 | } else if (s->mValueMask.isOff(i)) {//other is an inactive tile |
| 2599 |
1/2✓ Branch 0 taken 4884 times.
✗ Branch 1 not taken.
|
15856 | delete child;//convert child to an inactive tile |
| 2600 | 9768 | t->mNodes[i].setValue(b); | |
| 2601 | } | ||
| 2602 |
4/4✓ Branch 1 taken 3438 times.
✓ Branch 2 taken 13737169 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 3388 times.
|
27481214 | } else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {//active tile -> a branch |
| 2603 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
100 | t->mNodes[i].setChild(new ChildT(*(s->mNodes[i].getChild()), |
| 2604 | t->mNodes[i].getValue(), TopologyCopy())); | ||
| 2605 | } | ||
| 2606 | } | ||
| 2607 | 216068 | } | |
| 2608 | const OtherInternalNode* s; | ||
| 2609 | InternalNode* t; | ||
| 2610 | const ValueType& b; | ||
| 2611 | };// TopologyIntersection | ||
| 2612 | |||
| 2613 | template<typename ChildT, Index Log2Dim> | ||
| 2614 | template<typename OtherChildT> | ||
| 2615 | inline void | ||
| 2616 | InternalNode<ChildT, Log2Dim>::topologyIntersection( | ||
| 2617 | const InternalNode<OtherChildT, Log2Dim>& other, const ValueType& background) | ||
| 2618 | { | ||
| 2619 |
8/47✓ Branch 2 taken 279 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 40 times.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 8 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 9 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 21 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
|
747 | TopologyIntersection<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, background); |
| 2620 | 747 | } | |
| 2621 | |||
| 2622 | template<typename ChildT, Index Log2Dim> | ||
| 2623 | template<typename OtherInternalNode> | ||
| 2624 | struct InternalNode<ChildT, Log2Dim>::TopologyDifference | ||
| 2625 | { | ||
| 2626 | using W = typename NodeMaskType::Word; | ||
| 2627 | struct A {inline void operator()(W &tC, const W& sC, const W& sV, const W& tV) const | ||
| 2628 | 102912 | { tC = (tC & (sC | ~sV)) | (tV & sC); } | |
| 2629 | }; | ||
| 2630 | struct B {inline void operator()(W &tV, const W& sC, const W& sV, const W& tC) const | ||
| 2631 | 102912 | { tV &= ~((tC & sV) | (sC | sV)); } | |
| 2632 | }; | ||
| 2633 | 724 | TopologyDifference(const OtherInternalNode* source, InternalNode* target, | |
| 2634 | 724 | const ValueType& background) : s(source), t(target), b(background) { | |
| 2635 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
| 2636 | 724 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
| 2637 | |||
| 2638 | // Bit processing is done in a single thread! | ||
| 2639 | 724 | const NodeMaskType oldChildMask(t->mChildMask);//important to avoid cross pollution | |
| 2640 | A op1; | ||
| 2641 | 724 | t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1); | |
| 2642 | |||
| 2643 | B op2; | ||
| 2644 | 724 | t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2); | |
| 2645 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 362 times.
|
1448 | assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles or child nodes |
| 2646 | 724 | } | |
| 2647 | 109050 | void operator()(const tbb::blocked_range<Index> &r) const { | |
| 2648 |
2/2✓ Branch 0 taken 6586368 times.
✓ Branch 1 taken 54525 times.
|
13281786 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
| 2649 |
2/2✓ Branch 1 taken 18267 times.
✓ Branch 2 taken 6568101 times.
|
13172736 | if (t->mChildMask.isOn(i)) {// Loop over this node's child nodes |
| 2650 | ChildT* child = t->mNodes[i].getChild(); | ||
| 2651 |
2/2✓ Branch 1 taken 12108 times.
✓ Branch 2 taken 6159 times.
|
36534 | if (s->mChildMask.isOn(i)) { |
| 2652 | 24216 | child->topologyDifference(*(s->mNodes[i].getChild()), b); | |
| 2653 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6159 times.
|
12318 | } else if (s->mValueMask.isOn(i)) { |
| 2654 | ✗ | delete child;//convert child to an inactive tile | |
| 2655 | ✗ | t->mNodes[i].setValue(b); | |
| 2656 | } | ||
| 2657 |
2/2✓ Branch 1 taken 42765 times.
✓ Branch 2 taken 6525336 times.
|
13136202 | } else if (t->mValueMask.isOn(i)) {//this is an active tile |
| 2658 |
2/2✓ Branch 1 taken 40 times.
✓ Branch 2 taken 42725 times.
|
85530 | if (s->mChildMask.isOn(i)) { |
| 2659 | const typename OtherInternalNode::ChildNodeType& other = | ||
| 2660 | *(s->mNodes[i].getChild()); | ||
| 2661 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
80 | ChildT* child = new ChildT(other.origin(), t->mNodes[i].getValue(), true); |
| 2662 | 80 | child->topologyDifference(other, b); | |
| 2663 | 80 | t->mNodes[i].setChild(child);//replace the active tile with a child branch | |
| 2664 | } | ||
| 2665 | } | ||
| 2666 | } | ||
| 2667 | 109050 | } | |
| 2668 | const OtherInternalNode* s; | ||
| 2669 | InternalNode* t; | ||
| 2670 | const ValueType& b; | ||
| 2671 | };// TopologyDifference | ||
| 2672 | |||
| 2673 | template<typename ChildT, Index Log2Dim> | ||
| 2674 | template<typename OtherChildT> | ||
| 2675 | inline void | ||
| 2676 | InternalNode<ChildT, Log2Dim>::topologyDifference(const InternalNode<OtherChildT, Log2Dim>& other, | ||
| 2677 | const ValueType& background) | ||
| 2678 | { | ||
| 2679 |
3/11✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 11 taken 64 times.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
362 | TopologyDifference<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, background); |
| 2680 | 359 | } | |
| 2681 | |||
| 2682 | |||
| 2683 | //////////////////////////////////////// | ||
| 2684 | |||
| 2685 | |||
| 2686 | template<typename ChildT, Index Log2Dim> | ||
| 2687 | template<typename CombineOp> | ||
| 2688 | inline void | ||
| 2689 | 148 | InternalNode<ChildT, Log2Dim>::combine(InternalNode& other, CombineOp& op) | |
| 2690 | { | ||
| 2691 | 76 | const ValueType zero = zeroVal<ValueType>(); | |
| 2692 | |||
| 2693 | CombineArgs<ValueType> args; | ||
| 2694 | |||
| 2695 |
2/2✓ Branch 0 taken 1363968 times.
✓ Branch 1 taken 74 times.
|
2728084 | for (Index i = 0; i < NUM_VALUES; ++i) { |
| 2696 |
4/4✓ Branch 0 taken 1363566 times.
✓ Branch 1 taken 402 times.
✓ Branch 2 taken 1363208 times.
✓ Branch 3 taken 358 times.
|
5455068 | if (this->isChildMaskOff(i) && other.isChildMaskOff(i)) { |
| 2697 | // Both this node and the other node have constant values (tiles). | ||
| 2698 | // Combine the two values and store the result as this node's new tile value. | ||
| 2699 | 2431520 | op(args.setARef(mNodes[i].getValue()) | |
| 2700 | .setAIsActive(isValueMaskOn(i)) | ||
| 2701 | .setBRef(other.mNodes[i].getValue()) | ||
| 2702 | .setBIsActive(other.isValueMaskOn(i))); | ||
| 2703 | mNodes[i].setValue(args.result()); | ||
| 2704 | mValueMask.set(i, args.resultIsActive()); | ||
| 2705 |
4/4✓ Branch 0 taken 402 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 303 times.
|
2324 | } else if (this->isChildMaskOn(i) && other.isChildMaskOff(i)) { |
| 2706 | // Combine this node's child with the other node's constant value. | ||
| 2707 | ChildNodeType* child = mNodes[i].getChild(); | ||
| 2708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
606 | assert(child); |
| 2709 | if (child) { | ||
| 2710 | 606 | child->combine(other.mNodes[i].getValue(), other.isValueMaskOn(i), op); | |
| 2711 | } | ||
| 2712 |
3/4✓ Branch 0 taken 358 times.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
|
1630 | } else if (this->isChildMaskOff(i) && other.isChildMaskOn(i)) { |
| 2713 | // Combine this node's constant value with the other node's child. | ||
| 2714 | ChildNodeType* child = other.mNodes[i].getChild(); | ||
| 2715 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 358 times.
|
716 | assert(child); |
| 2716 | if (child) { | ||
| 2717 | // Combine this node's constant value with the other node's child, | ||
| 2718 | // but use a new functor in which the A and B values are swapped, | ||
| 2719 | // since the constant value is the A value, not the B value. | ||
| 2720 | SwappedCombineOp<ValueType, CombineOp> swappedOp(op); | ||
| 2721 | 716 | child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp); | |
| 2722 | |||
| 2723 | // Steal the other node's child. | ||
| 2724 | 716 | other.mChildMask.setOff(i); | |
| 2725 | other.mNodes[i].setValue(zero); | ||
| 2726 | 716 | this->setChildNode(i, child); | |
| 2727 | } | ||
| 2728 | |||
| 2729 | } else /*if (isChildMaskOn(i) && other.isChildMaskOn(i))*/ { | ||
| 2730 | // Combine this node's child with the other node's child. | ||
| 2731 | ChildNodeType | ||
| 2732 | *child = mNodes[i].getChild(), | ||
| 2733 | *otherChild = other.mNodes[i].getChild(); | ||
| 2734 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
198 | assert(child); |
| 2735 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
198 | assert(otherChild); |
| 2736 | if (child && otherChild) { | ||
| 2737 | 198 | child->combine(*otherChild, op); | |
| 2738 | } | ||
| 2739 | } | ||
| 2740 | } | ||
| 2741 | 148 | } | |
| 2742 | |||
| 2743 | |||
| 2744 | template<typename ChildT, Index Log2Dim> | ||
| 2745 | template<typename CombineOp> | ||
| 2746 | inline void | ||
| 2747 | 12 | InternalNode<ChildT, Log2Dim>::combine(const ValueType& value, bool valueIsActive, CombineOp& op) | |
| 2748 | { | ||
| 2749 | CombineArgs<ValueType> args; | ||
| 2750 | |||
| 2751 |
2/2✓ Branch 0 taken 110592 times.
✓ Branch 1 taken 6 times.
|
221196 | for (Index i = 0; i < NUM_VALUES; ++i) { |
| 2752 |
2/2✓ Branch 0 taken 110577 times.
✓ Branch 1 taken 15 times.
|
221184 | if (this->isChildMaskOff(i)) { |
| 2753 | // Combine this node's constant value with the given constant value. | ||
| 2754 | 221154 | op(args.setARef(mNodes[i].getValue()) | |
| 2755 | .setAIsActive(isValueMaskOn(i)) | ||
| 2756 | .setBRef(value) | ||
| 2757 | .setBIsActive(valueIsActive)); | ||
| 2758 | mNodes[i].setValue(args.result()); | ||
| 2759 | mValueMask.set(i, args.resultIsActive()); | ||
| 2760 | } else /*if (isChildMaskOn(i))*/ { | ||
| 2761 | // Combine this node's child with the given constant value. | ||
| 2762 | ChildNodeType* child = mNodes[i].getChild(); | ||
| 2763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
30 | assert(child); |
| 2764 | 30 | if (child) child->combine(value, valueIsActive, op); | |
| 2765 | } | ||
| 2766 | } | ||
| 2767 | } | ||
| 2768 | |||
| 2769 | |||
| 2770 | //////////////////////////////////////// | ||
| 2771 | |||
| 2772 | |||
| 2773 | template<typename ChildT, Index Log2Dim> | ||
| 2774 | template<typename CombineOp, typename OtherNodeType> | ||
| 2775 | inline void | ||
| 2776 | 16 | InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other0, const OtherNodeType& other1, | |
| 2777 | CombineOp& op) | ||
| 2778 | { | ||
| 2779 | CombineArgs<ValueType, typename OtherNodeType::ValueType> args; | ||
| 2780 | |||
| 2781 |
2/2✓ Branch 0 taken 147456 times.
✓ Branch 1 taken 8 times.
|
294928 | for (Index i = 0; i < NUM_VALUES; ++i) { |
| 2782 |
3/4✓ Branch 0 taken 147448 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 147448 times.
✗ Branch 3 not taken.
|
589808 | if (other0.isChildMaskOff(i) && other1.isChildMaskOff(i)) { |
| 2783 | op(args.setARef(other0.mNodes[i].getValue()) | ||
| 2784 | .setAIsActive(other0.isValueMaskOn(i)) | ||
| 2785 | .setBRef(other1.mNodes[i].getValue()) | ||
| 2786 | .setBIsActive(other1.isValueMaskOn(i))); | ||
| 2787 | // Replace child i with a constant value. | ||
| 2788 | 294896 | this->makeChildNodeEmpty(i, args.result()); | |
| 2789 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147448 times.
|
294896 | mValueMask.set(i, args.resultIsActive()); |
| 2790 | } else { | ||
| 2791 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | if (this->isChildMaskOff(i)) { |
| 2792 | // Add a new child with the same coordinates, etc. as the other node's child. | ||
| 2793 | const Coord& childOrigin = other0.isChildMaskOn(i) | ||
| 2794 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | ? other0.mNodes[i].getChild()->origin() |
| 2795 | : other1.mNodes[i].getChild()->origin(); | ||
| 2796 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
16 | this->setChildNode(i, new ChildNodeType(childOrigin, mNodes[i].getValue())); |
| 2797 | } | ||
| 2798 | |||
| 2799 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | if (other0.isChildMaskOff(i)) { |
| 2800 | // Combine node1's child with node0's constant value | ||
| 2801 | // and write the result into child i. | ||
| 2802 | ✗ | mNodes[i].getChild()->combine2(other0.mNodes[i].getValue(), | |
| 2803 | *other1.mNodes[i].getChild(), other0.isValueMaskOn(i), op); | ||
| 2804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | } else if (other1.isChildMaskOff(i)) { |
| 2805 | // Combine node0's child with node1's constant value | ||
| 2806 | // and write the result into child i. | ||
| 2807 | ✗ | mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(), | |
| 2808 | other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op); | ||
| 2809 | } else { | ||
| 2810 | // Combine node0's child with node1's child | ||
| 2811 | // and write the result into child i. | ||
| 2812 | 16 | mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(), | |
| 2813 | *other1.mNodes[i].getChild(), op); | ||
| 2814 | } | ||
| 2815 | } | ||
| 2816 | } | ||
| 2817 | 16 | } | |
| 2818 | |||
| 2819 | |||
| 2820 | template<typename ChildT, Index Log2Dim> | ||
| 2821 | template<typename CombineOp, typename OtherNodeType> | ||
| 2822 | inline void | ||
| 2823 | ✗ | InternalNode<ChildT, Log2Dim>::combine2(const ValueType& value, const OtherNodeType& other, | |
| 2824 | bool valueIsActive, CombineOp& op) | ||
| 2825 | { | ||
| 2826 | CombineArgs<ValueType, typename OtherNodeType::ValueType> args; | ||
| 2827 | |||
| 2828 | ✗ | for (Index i = 0; i < NUM_VALUES; ++i) { | |
| 2829 | ✗ | if (other.isChildMaskOff(i)) { | |
| 2830 | op(args.setARef(value) | ||
| 2831 | .setAIsActive(valueIsActive) | ||
| 2832 | .setBRef(other.mNodes[i].getValue()) | ||
| 2833 | .setBIsActive(other.isValueMaskOn(i))); | ||
| 2834 | // Replace child i with a constant value. | ||
| 2835 | ✗ | this->makeChildNodeEmpty(i, args.result()); | |
| 2836 | ✗ | mValueMask.set(i, args.resultIsActive()); | |
| 2837 | } else { | ||
| 2838 | typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild(); | ||
| 2839 | ✗ | assert(otherChild); | |
| 2840 | ✗ | if (this->isChildMaskOff(i)) { | |
| 2841 | // Add a new child with the same coordinates, etc. | ||
| 2842 | // as the other node's child. | ||
| 2843 | ✗ | this->setChildNode(i, new ChildNodeType(*otherChild)); | |
| 2844 | } | ||
| 2845 | // Combine the other node's child with a constant value | ||
| 2846 | // and write the result into child i. | ||
| 2847 | ✗ | mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op); | |
| 2848 | } | ||
| 2849 | } | ||
| 2850 | } | ||
| 2851 | |||
| 2852 | |||
| 2853 | template<typename ChildT, Index Log2Dim> | ||
| 2854 | template<typename CombineOp, typename OtherValueType> | ||
| 2855 | inline void | ||
| 2856 | ✗ | InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other, const OtherValueType& value, | |
| 2857 | bool valueIsActive, CombineOp& op) | ||
| 2858 | { | ||
| 2859 | CombineArgs<ValueType, OtherValueType> args; | ||
| 2860 | |||
| 2861 | ✗ | for (Index i = 0; i < NUM_VALUES; ++i) { | |
| 2862 | ✗ | if (other.isChildMaskOff(i)) { | |
| 2863 | op(args.setARef(other.mNodes[i].getValue()) | ||
| 2864 | .setAIsActive(other.isValueMaskOn(i)) | ||
| 2865 | .setBRef(value) | ||
| 2866 | .setBIsActive(valueIsActive)); | ||
| 2867 | // Replace child i with a constant value. | ||
| 2868 | ✗ | this->makeChildNodeEmpty(i, args.result()); | |
| 2869 | ✗ | mValueMask.set(i, args.resultIsActive()); | |
| 2870 | } else { | ||
| 2871 | ChildNodeType* otherChild = other.mNodes[i].getChild(); | ||
| 2872 | ✗ | assert(otherChild); | |
| 2873 | ✗ | if (this->isChildMaskOff(i)) { | |
| 2874 | // Add a new child with the same coordinates, etc. as the other node's child. | ||
| 2875 | ✗ | this->setChildNode(i, | |
| 2876 | ✗ | new ChildNodeType(otherChild->origin(), mNodes[i].getValue())); | |
| 2877 | } | ||
| 2878 | // Combine the other node's child with a constant value | ||
| 2879 | // and write the result into child i. | ||
| 2880 | ✗ | mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op); | |
| 2881 | } | ||
| 2882 | } | ||
| 2883 | } | ||
| 2884 | |||
| 2885 | |||
| 2886 | //////////////////////////////////////// | ||
| 2887 | |||
| 2888 | |||
| 2889 | template<typename ChildT, Index Log2Dim> | ||
| 2890 | template<typename BBoxOp> | ||
| 2891 | inline void | ||
| 2892 | 20 | InternalNode<ChildT, Log2Dim>::visitActiveBBox(BBoxOp& op) const | |
| 2893 | { | ||
| 2894 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
|
28 | for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) { |
| 2895 | 16 | op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), ChildNodeType::DIM)); | |
| 2896 | } | ||
| 2897 | if (op.template descent<LEVEL>()) { | ||
| 2898 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 10 times.
|
44 | for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) i->visitActiveBBox(op); |
| 2899 | } else { | ||
| 2900 | for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) { | ||
| 2901 | op.template operator()<LEVEL>(i->getNodeBoundingBox()); | ||
| 2902 | } | ||
| 2903 | } | ||
| 2904 | 20 | } | |
| 2905 | |||
| 2906 | |||
| 2907 | template<typename ChildT, Index Log2Dim> | ||
| 2908 | template<typename VisitorOp> | ||
| 2909 | inline void | ||
| 2910 | InternalNode<ChildT, Log2Dim>::visit(VisitorOp& op) | ||
| 2911 | { | ||
| 2912 |
10/20✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
|
45 | doVisit<InternalNode, VisitorOp, ChildAllIter>(*this, op); |
| 2913 | 45 | } | |
| 2914 | |||
| 2915 | |||
| 2916 | template<typename ChildT, Index Log2Dim> | ||
| 2917 | template<typename VisitorOp> | ||
| 2918 | inline void | ||
| 2919 | InternalNode<ChildT, Log2Dim>::visit(VisitorOp& op) const | ||
| 2920 | { | ||
| 2921 |
10/20✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 16 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
|
90 | doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*this, op); |
| 2922 | 90 | } | |
| 2923 | |||
| 2924 | |||
| 2925 | template<typename ChildT, Index Log2Dim> | ||
| 2926 | template<typename NodeT, typename VisitorOp, typename ChildAllIterT> | ||
| 2927 | inline void | ||
| 2928 | 270 | InternalNode<ChildT, Log2Dim>::doVisit(NodeT& self, VisitorOp& op) | |
| 2929 | { | ||
| 2930 | typename NodeT::ValueType val; | ||
| 2931 |
3/3✓ Branch 0 taken 655360 times.
✓ Branch 1 taken 327770 times.
✓ Branch 2 taken 45 times.
|
1966440 | for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) { |
| 2932 |
3/4✓ Branch 1 taken 983040 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 163840 times.
✓ Branch 4 taken 819200 times.
|
1966080 | if (op(iter)) continue; |
| 2933 |
2/2✓ Branch 0 taken 200 times.
✓ Branch 1 taken 819000 times.
|
1638400 | if (typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) { |
| 2934 | child->visit(op); | ||
| 2935 | } | ||
| 2936 | } | ||
| 2937 | 270 | } | |
| 2938 | |||
| 2939 | |||
| 2940 | //////////////////////////////////////// | ||
| 2941 | |||
| 2942 | |||
| 2943 | template<typename ChildT, Index Log2Dim> | ||
| 2944 | template<typename OtherNodeType, typename VisitorOp> | ||
| 2945 | inline void | ||
| 2946 | InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op) | ||
| 2947 | { | ||
| 2948 | doVisit2Node<InternalNode, OtherNodeType, VisitorOp, ChildAllIter, | ||
| 2949 |
2/4✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
45 | typename OtherNodeType::ChildAllIter>(*this, other, op); |
| 2950 | 45 | } | |
| 2951 | |||
| 2952 | |||
| 2953 | template<typename ChildT, Index Log2Dim> | ||
| 2954 | template<typename OtherNodeType, typename VisitorOp> | ||
| 2955 | inline void | ||
| 2956 | InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op) const | ||
| 2957 | { | ||
| 2958 | doVisit2Node<const InternalNode, OtherNodeType, VisitorOp, ChildAllCIter, | ||
| 2959 | typename OtherNodeType::ChildAllCIter>(*this, other, op); | ||
| 2960 | } | ||
| 2961 | |||
| 2962 | |||
| 2963 | template<typename ChildT, Index Log2Dim> | ||
| 2964 | template< | ||
| 2965 | typename NodeT, | ||
| 2966 | typename OtherNodeT, | ||
| 2967 | typename VisitorOp, | ||
| 2968 | typename ChildAllIterT, | ||
| 2969 | typename OtherChildAllIterT> | ||
| 2970 | inline void | ||
| 2971 | 90 | InternalNode<ChildT, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op) | |
| 2972 | { | ||
| 2973 | // Allow the two nodes to have different ValueTypes, but not different dimensions. | ||
| 2974 | static_assert(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES, | ||
| 2975 | "visit2() requires nodes to have the same dimensions"); | ||
| 2976 | static_assert(OtherNodeT::LEVEL == NodeT::LEVEL, | ||
| 2977 | "visit2() requires nodes to be at the same tree level"); | ||
| 2978 | |||
| 2979 | typename NodeT::ValueType val; | ||
| 2980 | typename OtherNodeT::ValueType otherVal; | ||
| 2981 | |||
| 2982 | 90 | ChildAllIterT iter = self.beginChildAll(); | |
| 2983 | 90 | OtherChildAllIterT otherIter = other.beginChildAll(); | |
| 2984 | |||
| 2985 |
3/4✓ Branch 0 taken 327680 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 327680 times.
✗ Branch 3 not taken.
|
1310810 | for ( ; iter && otherIter; ++iter, ++otherIter) |
| 2986 | { | ||
| 2987 | 655360 | const size_t skipBranch = static_cast<size_t>(op(iter, otherIter)); | |
| 2988 | |||
| 2989 | typename ChildAllIterT::ChildNodeType* child = | ||
| 2990 |
2/2✓ Branch 0 taken 294912 times.
✓ Branch 1 taken 32768 times.
|
655360 | (skipBranch & 1U) ? nullptr : iter.probeChild(val); |
| 2991 | typename OtherChildAllIterT::ChildNodeType* otherChild = | ||
| 2992 |
2/2✓ Branch 0 taken 294912 times.
✓ Branch 1 taken 32768 times.
|
655360 | (skipBranch & 2U) ? nullptr : otherIter.probeChild(otherVal); |
| 2993 | |||
| 2994 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 327616 times.
|
655360 | if (child != nullptr && otherChild != nullptr) { |
| 2995 | child->visit2Node(*otherChild, op); | ||
| 2996 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 327608 times.
|
655232 | } else if (child != nullptr) { |
| 2997 | child->visit2(otherIter, op); | ||
| 2998 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 327600 times.
|
655216 | } else if (otherChild != nullptr) { |
| 2999 | otherChild->visit2(iter, op, /*otherIsLHS=*/true); | ||
| 3000 | } | ||
| 3001 | } | ||
| 3002 | 90 | } | |
| 3003 | |||
| 3004 | |||
| 3005 | //////////////////////////////////////// | ||
| 3006 | |||
| 3007 | |||
| 3008 | template<typename ChildT, Index Log2Dim> | ||
| 3009 | template<typename OtherChildAllIterType, typename VisitorOp> | ||
| 3010 | inline void | ||
| 3011 | InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter, | ||
| 3012 | VisitorOp& op, bool otherIsLHS) | ||
| 3013 | { | ||
| 3014 |
2/8✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
4 | doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>( |
| 3015 | *this, otherIter, op, otherIsLHS); | ||
| 3016 | 8 | } | |
| 3017 | |||
| 3018 | |||
| 3019 | template<typename ChildT, Index Log2Dim> | ||
| 3020 | template<typename OtherChildAllIterType, typename VisitorOp> | ||
| 3021 | inline void | ||
| 3022 | InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter, | ||
| 3023 | VisitorOp& op, bool otherIsLHS) const | ||
| 3024 | { | ||
| 3025 | doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>( | ||
| 3026 | *this, otherIter, op, otherIsLHS); | ||
| 3027 | } | ||
| 3028 | |||
| 3029 | |||
| 3030 | template<typename ChildT, Index Log2Dim> | ||
| 3031 | template<typename NodeT, typename VisitorOp, typename ChildAllIterT, typename OtherChildAllIterT> | ||
| 3032 | inline void | ||
| 3033 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | InternalNode<ChildT, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter, |
| 3034 | VisitorOp& op, bool otherIsLHS) | ||
| 3035 | { | ||
| 3036 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | if (!otherIter) return; |
| 3037 | |||
| 3038 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
16 | const size_t skipBitMask = (otherIsLHS ? 2U : 1U); |
| 3039 | |||
| 3040 | typename NodeT::ValueType val; | ||
| 3041 |
2/2✓ Branch 1 taken 147456 times.
✓ Branch 2 taken 8 times.
|
294944 | for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) { |
| 3042 | const size_t skipBranch = static_cast<size_t>( | ||
| 3043 |
2/2✓ Branch 0 taken 110592 times.
✓ Branch 1 taken 36864 times.
|
294912 | otherIsLHS ? op(otherIter, iter) : op(iter, otherIter)); |
| 3044 | |||
| 3045 | typename ChildAllIterT::ChildNodeType* child = | ||
| 3046 |
2/2✓ Branch 0 taken 143360 times.
✓ Branch 1 taken 4096 times.
|
294912 | (skipBranch & skipBitMask) ? nullptr : iter.probeChild(val); |
| 3047 | |||
| 3048 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 143353 times.
|
286720 | if (child != nullptr) child->visit2(otherIter, op, otherIsLHS); |
| 3049 | } | ||
| 3050 | } | ||
| 3051 | |||
| 3052 | |||
| 3053 | //////////////////////////////////////// | ||
| 3054 | |||
| 3055 | |||
| 3056 | template<typename ChildT, Index Log2Dim> | ||
| 3057 | inline void | ||
| 3058 | 2168 | InternalNode<ChildT, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const | |
| 3059 | { | ||
| 3060 |
2/2✓ Branch 0 taken 91958 times.
✓ Branch 1 taken 1084 times.
|
186084 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
| 3061 | 183916 | iter->writeBuffers(os, toHalf); | |
| 3062 | } | ||
| 3063 | } | ||
| 3064 | |||
| 3065 | |||
| 3066 | template<typename ChildT, Index Log2Dim> | ||
| 3067 | inline void | ||
| 3068 | 3706 | InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is, bool fromHalf) | |
| 3069 | { | ||
| 3070 |
2/2✓ Branch 0 taken 131427 times.
✓ Branch 1 taken 1853 times.
|
266560 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 3071 | 262854 | iter->readBuffers(is, fromHalf); | |
| 3072 | } | ||
| 3073 | } | ||
| 3074 | |||
| 3075 | |||
| 3076 | template<typename ChildT, Index Log2Dim> | ||
| 3077 | inline void | ||
| 3078 | 100 | InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is, | |
| 3079 | const CoordBBox& clipBBox, bool fromHalf) | ||
| 3080 | { | ||
| 3081 |
2/2✓ Branch 0 taken 376 times.
✓ Branch 1 taken 50 times.
|
852 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 3082 | // Stream in the branch rooted at this child. | ||
| 3083 | // (We can't skip over children that lie outside the clipping region, | ||
| 3084 | // because buffers are serialized in depth-first order and need to be | ||
| 3085 | // unserialized in the same order.) | ||
| 3086 | 752 | iter->readBuffers(is, clipBBox, fromHalf); | |
| 3087 | } | ||
| 3088 | |||
| 3089 | // Get this tree's background value. | ||
| 3090 | 100 | ValueType background = zeroVal<ValueType>(); | |
| 3091 |
1/4✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
100 | if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) { |
| 3092 | 100 | background = *static_cast<const ValueType*>(bgPtr); | |
| 3093 | } | ||
| 3094 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
100 | this->clip(clipBBox, background); |
| 3095 | } | ||
| 3096 | |||
| 3097 | |||
| 3098 | //////////////////////////////////////// | ||
| 3099 | |||
| 3100 | |||
| 3101 | template<typename ChildT, Index Log2Dim> | ||
| 3102 | void | ||
| 3103 | 146844 | InternalNode<ChildT, Log2Dim>::getNodeLog2Dims(std::vector<Index>& dims) | |
| 3104 | { | ||
| 3105 | 146844 | dims.push_back(Log2Dim); | |
| 3106 | 73422 | ChildNodeType::getNodeLog2Dims(dims); | |
| 3107 | 146844 | } | |
| 3108 | |||
| 3109 | |||
| 3110 | template<typename ChildT, Index Log2Dim> | ||
| 3111 | inline void | ||
| 3112 | 446148910 | InternalNode<ChildT, Log2Dim>::offsetToLocalCoord(Index n, Coord &xyz) | |
| 3113 | { | ||
| 3114 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 223074455 times.
|
446148910 | assert(n<(1<<3*Log2Dim)); |
| 3115 | 446148910 | xyz.setX(n >> 2*Log2Dim); | |
| 3116 | 446148910 | n &= ((1<<2*Log2Dim)-1); | |
| 3117 | 446148910 | xyz.setY(n >> Log2Dim); | |
| 3118 | 446148910 | xyz.setZ(n & ((1<<Log2Dim)-1)); | |
| 3119 | 446148910 | } | |
| 3120 | |||
| 3121 | |||
| 3122 | template<typename ChildT, Index Log2Dim> | ||
| 3123 | inline Index | ||
| 3124 | InternalNode<ChildT, Log2Dim>::coordToOffset(const Coord& xyz) | ||
| 3125 | { | ||
| 3126 | 7671356178 | return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim) | |
| 3127 | 7671356178 | + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim) | |
| 3128 | 7671356178 | + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL); | |
| 3129 | } | ||
| 3130 | |||
| 3131 | |||
| 3132 | template<typename ChildT, Index Log2Dim> | ||
| 3133 | inline Coord | ||
| 3134 | 446083374 | InternalNode<ChildT, Log2Dim>::offsetToGlobalCoord(Index n) const | |
| 3135 | { | ||
| 3136 | Coord local; | ||
| 3137 | 446083374 | this->offsetToLocalCoord(n, local); | |
| 3138 | local <<= ChildT::TOTAL; | ||
| 3139 | 446083374 | return local + this->origin(); | |
| 3140 | } | ||
| 3141 | |||
| 3142 | |||
| 3143 | //////////////////////////////////////// | ||
| 3144 | |||
| 3145 | |||
| 3146 | template<typename ChildT, Index Log2Dim> | ||
| 3147 | template<typename ArrayT> | ||
| 3148 | inline void | ||
| 3149 | 139918 | InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array) | |
| 3150 | { | ||
| 3151 | using T = typename ArrayT::value_type; | ||
| 3152 | static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array"); | ||
| 3153 | using ArrayChildT = typename std::conditional< | ||
| 3154 | std::is_const<typename std::remove_pointer<T>::type>::value, const ChildT, ChildT>::type; | ||
| 3155 |
2/2✓ Branch 0 taken 182528 times.
✓ Branch 1 taken 77204 times.
|
488923 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 3156 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 3157 | if (std::is_same<T, ArrayChildT*>::value) { | ||
| 3158 | 346253 | array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild())); | |
| 3159 | } else { | ||
| 3160 | 2752 | iter->getNodes(array);//descent | |
| 3161 | } | ||
| 3162 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 3163 | } | ||
| 3164 | 139918 | } | |
| 3165 | |||
| 3166 | template<typename ChildT, Index Log2Dim> | ||
| 3167 | template<typename ArrayT> | ||
| 3168 | inline void | ||
| 3169 | 7110 | InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array) const | |
| 3170 | { | ||
| 3171 | using T = typename ArrayT::value_type; | ||
| 3172 | static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array"); | ||
| 3173 | static_assert(std::is_const<typename std::remove_pointer<T>::type>::value, | ||
| 3174 | "argument to getNodes() must be an array of const node pointers"); | ||
| 3175 |
2/2✓ Branch 0 taken 26603 times.
✓ Branch 1 taken 3555 times.
|
60316 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
| 3176 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 3177 | if (std::is_same<T, const ChildT*>::value) { | ||
| 3178 | 52844 | array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild())); | |
| 3179 | } else { | ||
| 3180 | 362 | iter->getNodes(array);//descent | |
| 3181 | } | ||
| 3182 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 3183 | } | ||
| 3184 | 7110 | } | |
| 3185 | |||
| 3186 | |||
| 3187 | //////////////////////////////////////// | ||
| 3188 | |||
| 3189 | |||
| 3190 | template<typename ChildT, Index Log2Dim> | ||
| 3191 | template<typename ArrayT> | ||
| 3192 | inline void | ||
| 3193 | 441638 | InternalNode<ChildT, Log2Dim>::stealNodes(ArrayT& array, const ValueType& value, bool state) | |
| 3194 | { | ||
| 3195 | using T = typename ArrayT::value_type; | ||
| 3196 | static_assert(std::is_pointer<T>::value, "argument to stealNodes() must be a pointer array"); | ||
| 3197 | using ArrayChildT = typename std::conditional< | ||
| 3198 | std::is_const<typename std::remove_pointer<T>::type>::value, const ChildT, ChildT>::type; | ||
| 3199 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
| 3200 |
2/2✓ Branch 0 taken 24981846 times.
✓ Branch 1 taken 220819 times.
|
50405330 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
| 3201 | const Index n = iter.pos(); | ||
| 3202 | if (std::is_same<T, ArrayChildT*>::value) { | ||
| 3203 | 49652608 | array.push_back(reinterpret_cast<T>(mNodes[n].getChild())); | |
| 3204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24826304 times.
|
49652608 | mValueMask.set(n, state); |
| 3205 | mNodes[n].setValue(value); | ||
| 3206 | } else { | ||
| 3207 | 311084 | iter->stealNodes(array, value, state);//descent | |
| 3208 | } | ||
| 3209 | } | ||
| 3210 | if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff(); | ||
| 3211 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
| 3212 | 441638 | } | |
| 3213 | |||
| 3214 | |||
| 3215 | //////////////////////////////////////// | ||
| 3216 | |||
| 3217 | |||
| 3218 | template<typename ChildT, Index Log2Dim> | ||
| 3219 | inline void | ||
| 3220 |
2/2✓ Branch 0 taken 732 times.
✓ Branch 1 taken 5763 times.
|
12990 | InternalNode<ChildT, Log2Dim>::resetBackground(const ValueType& oldBackground, |
| 3221 | const ValueType& newBackground) | ||
| 3222 | { | ||
| 3223 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5763 times.
|
11570 | if (math::isExactlyEqual(oldBackground, newBackground)) return; |
| 3224 |
2/2✓ Branch 0 taken 462848 times.
✓ Branch 1 taken 22 times.
|
925740 | for (Index i = 0; i < NUM_VALUES; ++i) { |
| 3225 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 462844 times.
|
925696 | if (this->isChildMaskOn(i)) { |
| 3226 | 8 | mNodes[i].getChild()->resetBackground(oldBackground, newBackground); | |
| 3227 |
2/2✓ Branch 0 taken 462843 times.
✓ Branch 1 taken 1 times.
|
925688 | } else if (this->isValueMaskOff(i)) { |
| 3228 |
2/2✓ Branch 0 taken 176123 times.
✓ Branch 1 taken 286720 times.
|
925686 | if (math::isApproxEqual(mNodes[i].getValue(), oldBackground)) { |
| 3229 | mNodes[i].setValue(newBackground); | ||
| 3230 |
2/2✓ Branch 0 taken 98304 times.
✓ Branch 1 taken 188416 times.
|
573440 | } else if (math::isApproxEqual(mNodes[i].getValue(), math::negative(oldBackground))) { |
| 3231 | ✗ | mNodes[i].setValue(math::negative(newBackground)); | |
| 3232 | } | ||
| 3233 | } | ||
| 3234 | } | ||
| 3235 | } | ||
| 3236 | |||
| 3237 | template<typename ChildT, Index Log2Dim> | ||
| 3238 | template<typename OtherChildNodeType, Index OtherLog2Dim> | ||
| 3239 | inline bool | ||
| 3240 | 14612 | InternalNode<ChildT, Log2Dim>::hasSameTopology( | |
| 3241 | const InternalNode<OtherChildNodeType, OtherLog2Dim>* other) const | ||
| 3242 | { | ||
| 3243 |
3/4✓ Branch 0 taken 7298 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 7298 times.
✗ Branch 3 not taken.
|
29208 | if (Log2Dim != OtherLog2Dim || mChildMask != other->mChildMask || |
| 3244 | mValueMask != other->mValueMask) return false; | ||
| 3245 |
2/2✓ Branch 0 taken 11843 times.
✓ Branch 1 taken 7298 times.
|
38282 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
| 3246 |
2/3✗ Branch 0 not taken.
✓ Branch 1 taken 1440 times.
✓ Branch 2 taken 10403 times.
|
23686 | if (!iter->hasSameTopology(other->mNodes[iter.pos()].getChild())) return false; |
| 3247 | } | ||
| 3248 | 14596 | return true; | |
| 3249 | } | ||
| 3250 | |||
| 3251 | |||
| 3252 | template<typename ChildT, Index Log2Dim> | ||
| 3253 | inline void | ||
| 3254 | 151158 | InternalNode<ChildT, Log2Dim>::resetChildNode(Index i, ChildNodeType* child) | |
| 3255 | { | ||
| 3256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75579 times.
|
151158 | assert(child); |
| 3257 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 75578 times.
|
151158 | if (this->isChildMaskOn(i)) { |
| 3258 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
4 | delete mNodes[i].getChild(); |
| 3259 | } else { | ||
| 3260 | 151156 | mChildMask.setOn(i); | |
| 3261 | 151156 | mValueMask.setOff(i); | |
| 3262 | } | ||
| 3263 | mNodes[i].setChild(child); | ||
| 3264 | 151158 | } | |
| 3265 | |||
| 3266 | template<typename ChildT, Index Log2Dim> | ||
| 3267 | inline void | ||
| 3268 | 6285596 | InternalNode<ChildT, Log2Dim>::setChildNode(Index i, ChildNodeType* child) | |
| 3269 | { | ||
| 3270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3142798 times.
|
6285596 | assert(child); |
| 3271 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3142798 times.
|
6285596 | assert(mChildMask.isOff(i)); |
| 3272 | 6285596 | mChildMask.setOn(i); | |
| 3273 | 6285596 | mValueMask.setOff(i); | |
| 3274 | mNodes[i].setChild(child); | ||
| 3275 | 6285596 | } | |
| 3276 | |||
| 3277 | |||
| 3278 | template<typename ChildT, Index Log2Dim> | ||
| 3279 | inline ChildT* | ||
| 3280 | 11810394 | InternalNode<ChildT, Log2Dim>::unsetChildNode(Index i, const ValueType& value) | |
| 3281 | { | ||
| 3282 |
2/2✓ Branch 0 taken 5868325 times.
✓ Branch 1 taken 36872 times.
|
11810394 | if (this->isChildMaskOff(i)) { |
| 3283 | mNodes[i].setValue(value); | ||
| 3284 | 11736650 | return nullptr; | |
| 3285 | } | ||
| 3286 | ChildNodeType* child = mNodes[i].getChild(); | ||
| 3287 | 73744 | mChildMask.setOff(i); | |
| 3288 | mNodes[i].setValue(value); | ||
| 3289 | 73744 | return child; | |
| 3290 | } | ||
| 3291 | |||
| 3292 | |||
| 3293 | template<typename ChildT, Index Log2Dim> | ||
| 3294 | inline void | ||
| 3295 | 11810394 | InternalNode<ChildT, Log2Dim>::makeChildNodeEmpty(Index n, const ValueType& value) | |
| 3296 | { | ||
| 3297 |
2/2✓ Branch 1 taken 36872 times.
✓ Branch 2 taken 5868325 times.
|
11869202 | delete this->unsetChildNode(n, value); |
| 3298 | 11810394 | } | |
| 3299 | |||
| 3300 | template<typename ChildT, Index Log2Dim> | ||
| 3301 | inline ChildT* | ||
| 3302 | 43990496 | InternalNode<ChildT, Log2Dim>::getChildNode(Index n) | |
| 3303 | { | ||
| 3304 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21905157 times.
|
43990496 | assert(this->isChildMaskOn(n)); |
| 3305 | 43990496 | return mNodes[n].getChild(); | |
| 3306 | } | ||
| 3307 | |||
| 3308 | |||
| 3309 | template<typename ChildT, Index Log2Dim> | ||
| 3310 | inline const ChildT* | ||
| 3311 | 46776752 | InternalNode<ChildT, Log2Dim>::getChildNode(Index n) const | |
| 3312 | { | ||
| 3313 | 46776752 | assert(this->isChildMaskOn(n)); | |
| 3314 | 46776752 | return mNodes[n].getChild(); | |
| 3315 | } | ||
| 3316 | |||
| 3317 | } // namespace tree | ||
| 3318 | } // namespace OPENVDB_VERSION_NAME | ||
| 3319 | } // namespace openvdb | ||
| 3320 | |||
| 3321 | #endif // OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED | ||
| 3322 |