| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | #ifndef OPENVDB_UTIL_UTIL_HAS_BEEN_INCLUDED | ||
| 5 | #define OPENVDB_UTIL_UTIL_HAS_BEEN_INCLUDED | ||
| 6 | |||
| 7 | #include <openvdb/Types.h> | ||
| 8 | #include <openvdb/tree/Tree.h> | ||
| 9 | #include <openvdb/tools/ValueTransformer.h> | ||
| 10 | #include <openvdb/tools/Prune.h>// for tree::pruneInactive | ||
| 11 | |||
| 12 | |||
| 13 | namespace openvdb { | ||
| 14 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 15 | namespace OPENVDB_VERSION_NAME { | ||
| 16 | namespace util { | ||
| 17 | |||
| 18 | OPENVDB_API extern const Index32 INVALID_IDX; | ||
| 19 | |||
| 20 | /// @brief coordinate offset table for neighboring voxels | ||
| 21 | OPENVDB_API extern const Coord COORD_OFFSETS[26]; | ||
| 22 | |||
| 23 | |||
| 24 | //////////////////////////////////////// | ||
| 25 | |||
| 26 | |||
| 27 | /// Return @a voxelCoord rounded to the closest integer coordinates. | ||
| 28 | inline Coord | ||
| 29 | 2 | nearestCoord(const Vec3d& voxelCoord) | |
| 30 | { | ||
| 31 | Coord ijk; | ||
| 32 | 2 | ijk[0] = int(std::floor(voxelCoord[0])); | |
| 33 | 2 | ijk[1] = int(std::floor(voxelCoord[1])); | |
| 34 | 2 | ijk[2] = int(std::floor(voxelCoord[2])); | |
| 35 | 2 | return ijk; | |
| 36 | } | ||
| 37 | |||
| 38 | |||
| 39 | //////////////////////////////////////// | ||
| 40 | |||
| 41 | |||
| 42 | /// @brief Functor for use with tools::foreach() to compute the boolean intersection | ||
| 43 | /// between the value masks of corresponding leaf nodes in two trees | ||
| 44 | template<class TreeType1, class TreeType2> | ||
| 45 | class LeafTopologyIntOp | ||
| 46 | { | ||
| 47 | public: | ||
| 48 | 2 | LeafTopologyIntOp(const TreeType2& tree): mOtherTree(&tree) {} | |
| 49 | |||
| 50 | 189 | inline void operator()(const typename TreeType1::LeafIter& lIter) const | |
| 51 | { | ||
| 52 | 189 | const Coord xyz = lIter->origin(); | |
| 53 | 189 | const typename TreeType2::LeafNodeType* leaf = mOtherTree->probeConstLeaf(xyz); | |
| 54 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 61 times.
|
189 | if (leaf) {//leaf node |
| 55 | lIter->topologyIntersection(*leaf, zeroVal<typename TreeType1::ValueType>()); | ||
| 56 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | } else if (!mOtherTree->isValueOn(xyz)) {//inactive tile |
| 57 | lIter->setValuesOff(); | ||
| 58 | } | ||
| 59 | 189 | } | |
| 60 | |||
| 61 | private: | ||
| 62 | const TreeType2* mOtherTree; | ||
| 63 | }; | ||
| 64 | |||
| 65 | |||
| 66 | /// @brief Functor for use with tools::foreach() to compute the boolean difference | ||
| 67 | /// between the value masks of corresponding leaf nodes in two trees | ||
| 68 | template<class TreeType1, class TreeType2> | ||
| 69 | class LeafTopologyDiffOp | ||
| 70 | { | ||
| 71 | public: | ||
| 72 | 2 | LeafTopologyDiffOp(const TreeType2& tree): mOtherTree(&tree) {} | |
| 73 | |||
| 74 | 189 | inline void operator()(const typename TreeType1::LeafIter& lIter) const | |
| 75 | { | ||
| 76 | 189 | const Coord xyz = lIter->origin(); | |
| 77 | 189 | const typename TreeType2::LeafNodeType* leaf = mOtherTree->probeConstLeaf(xyz); | |
| 78 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 61 times.
|
189 | if (leaf) {//leaf node |
| 79 | 128 | lIter->topologyDifference(*leaf, zeroVal<typename TreeType1::ValueType>()); | |
| 80 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
|
61 | } else if (mOtherTree->isValueOn(xyz)) {//active tile |
| 81 | lIter->setValuesOff(); | ||
| 82 | } | ||
| 83 | 189 | } | |
| 84 | |||
| 85 | private: | ||
| 86 | const TreeType2* mOtherTree; | ||
| 87 | }; | ||
| 88 | |||
| 89 | |||
| 90 | //////////////////////////////////////// | ||
| 91 | |||
| 92 | |||
| 93 | /// @brief Perform a boolean intersection between two leaf nodes' topology masks. | ||
| 94 | /// @return a pointer to a new, boolean-valued tree containing the overlapping voxels. | ||
| 95 | template<class TreeType1, class TreeType2> | ||
| 96 | inline typename TreeType1::template ValueConverter<bool>::Type::Ptr | ||
| 97 | 2 | leafTopologyIntersection(const TreeType1& lhs, const TreeType2& rhs, bool threaded = true) | |
| 98 | { | ||
| 99 | typedef typename TreeType1::template ValueConverter<bool>::Type BoolTreeType; | ||
| 100 | |||
| 101 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | typename BoolTreeType::Ptr topologyTree(new BoolTreeType( |
| 102 | lhs, /*inactiveValue=*/false, /*activeValue=*/true, TopologyCopy())); | ||
| 103 | |||
| 104 |
3/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
2 | tools::foreach(topologyTree->beginLeaf(), |
| 105 | LeafTopologyIntOp<BoolTreeType, TreeType2>(rhs), threaded); | ||
| 106 | |||
| 107 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | tools::pruneInactive(*topologyTree, threaded); |
| 108 | 2 | return topologyTree; | |
| 109 | } | ||
| 110 | |||
| 111 | |||
| 112 | /// @brief Perform a boolean difference between two leaf nodes' topology masks. | ||
| 113 | /// @return a pointer to a new, boolean-valued tree containing the non-overlapping | ||
| 114 | /// voxels from the lhs. | ||
| 115 | template<class TreeType1, class TreeType2> | ||
| 116 | inline typename TreeType1::template ValueConverter<bool>::Type::Ptr | ||
| 117 | 2 | leafTopologyDifference(const TreeType1& lhs, const TreeType2& rhs, bool threaded = true) | |
| 118 | { | ||
| 119 | typedef typename TreeType1::template ValueConverter<bool>::Type BoolTreeType; | ||
| 120 | |||
| 121 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | typename BoolTreeType::Ptr topologyTree(new BoolTreeType( |
| 122 | lhs, /*inactiveValue=*/false, /*activeValue=*/true, TopologyCopy())); | ||
| 123 | |||
| 124 |
3/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
2 | tools::foreach(topologyTree->beginLeaf(), |
| 125 | LeafTopologyDiffOp<BoolTreeType, TreeType2>(rhs), threaded); | ||
| 126 | |||
| 127 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | tools::pruneInactive(*topologyTree, threaded); |
| 128 | 2 | return topologyTree; | |
| 129 | } | ||
| 130 | |||
| 131 | } // namespace util | ||
| 132 | } // namespace OPENVDB_VERSION_NAME | ||
| 133 | } // namespace openvdb | ||
| 134 | |||
| 135 | #endif // OPENVDB_UTIL_UTIL_HAS_BEEN_INCLUDED | ||
| 136 |