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 |