Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | // | ||
4 | /// @file Activate.h | ||
5 | /// | ||
6 | /// @brief Implementation of topological activation/deactivation | ||
7 | /// | ||
8 | /// @author Ken Museth | ||
9 | /// | ||
10 | |||
11 | #ifndef OPENVDB_TOOLS_ACTIVATE_HAS_BEEN_INCLUDED | ||
12 | #define OPENVDB_TOOLS_ACTIVATE_HAS_BEEN_INCLUDED | ||
13 | |||
14 | #include <openvdb/Types.h> | ||
15 | #include <openvdb/Grid.h> | ||
16 | #include <openvdb/math/Math.h> // for isApproxEqual() | ||
17 | #include <openvdb/tree/NodeManager.h> | ||
18 | #include <openvdb/openvdb.h> | ||
19 | #include <openvdb/points/PointDataGrid.h> | ||
20 | |||
21 | |||
22 | namespace openvdb { | ||
23 | OPENVDB_USE_VERSION_NAMESPACE | ||
24 | namespace OPENVDB_VERSION_NAME { | ||
25 | namespace tools { | ||
26 | |||
27 | /// @brief Mark as active any inactive tiles or voxels in the given grid or tree | ||
28 | /// whose values are equal to @a value (optionally to within the given @a tolerance). | ||
29 | template<typename GridOrTree> | ||
30 | void activate( | ||
31 | GridOrTree&, | ||
32 | const typename GridOrTree::ValueType& value, | ||
33 |
2/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
3 | const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>(), |
34 | const bool threaded = true | ||
35 | ); | ||
36 | |||
37 | |||
38 | /// @brief Mark as inactive any active tiles or voxels in the given grid or tree | ||
39 | /// whose values are equal to @a value (optionally to within the given @a tolerance). | ||
40 | template<typename GridOrTree> | ||
41 | void deactivate( | ||
42 | GridOrTree&, | ||
43 | const typename GridOrTree::ValueType& value, | ||
44 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>(), |
45 | const bool threaded = true | ||
46 | ); | ||
47 | |||
48 | |||
49 | //////////////////////////////////////// | ||
50 | |||
51 | |||
52 | /// @cond OPENVDB_DOCS_INTERNAL | ||
53 | |||
54 | namespace activate_internal { | ||
55 | |||
56 | template<typename TreeT, bool IgnoreTolerance = false> | ||
57 | struct ActivateOp | ||
58 | { | ||
59 | public: | ||
60 | using RootT = typename TreeT::RootNodeType; | ||
61 | using LeafT = typename TreeT::LeafNodeType; | ||
62 | using ValueT = typename TreeT::ValueType; | ||
63 | |||
64 | 21 | explicit ActivateOp(const ValueT& value, | |
65 | 3 | const ValueT& tolerance = zeroVal<ValueT>()) | |
66 | : mValue(value) | ||
67 | 21 | , mTolerance(tolerance) { } | |
68 | |||
69 | inline bool check(const ValueT& value) const { | ||
70 | // math::isApproxEqual is marginally more expensive, | ||
71 | // so opt to do direct comparison if tolerance is ignored | ||
72 | 335867 | if (IgnoreTolerance) return value == mValue; | |
73 | return math::isApproxEqual(value, mValue, mTolerance); | ||
74 | } | ||
75 | |||
76 | 42 | bool operator()(RootT& root, size_t) const | |
77 | { | ||
78 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 21 times.
|
94 | for (auto it = root.beginValueOff(); it; ++it) { |
79 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
8 | if (check(*it)) it.setValueOn(/*on=*/true); |
80 | } | ||
81 | 42 | return true; | |
82 | } | ||
83 | |||
84 | template<typename NodeT> | ||
85 | 118 | bool operator()(NodeT& node, size_t) const | |
86 | { | ||
87 | // only iterate if there are inactive tiles | ||
88 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
118 | if (!node.isValueMaskOn()) { |
89 |
2/2✓ Branch 0 taken 729080 times.
✓ Branch 1 taken 59 times.
|
1458278 | for (auto it = node.beginValueOff(); it; ++it) { |
90 |
2/2✓ Branch 0 taken 36863 times.
✓ Branch 1 taken 405505 times.
|
995184 | if (check(*it)) it.setValueOn(/*on=*/true); |
91 | } | ||
92 | } | ||
93 | // return false if there are no child nodes below this node | ||
94 | 118 | return !node.isChildMaskOff(); | |
95 | } | ||
96 | |||
97 | 19270 | bool operator()(LeafT& leaf, size_t) const | |
98 | { | ||
99 | // early-exit if there are no inactive values | ||
100 |
1/2✓ Branch 0 taken 9635 times.
✗ Branch 1 not taken.
|
19270 | if (leaf.isValueMaskOn()) return true; |
101 |
2/2✓ Branch 0 taken 4929207 times.
✓ Branch 1 taken 9635 times.
|
9877684 | for (auto it = leaf.beginValueOff(); it; ++it) { |
102 |
2/2✓ Branch 0 taken 516 times.
✓ Branch 1 taken 5108 times.
|
6665130 | if (check(*it)) it.setValueOn(/*on=*/true); |
103 | } | ||
104 | 19270 | return true; | |
105 | } | ||
106 | |||
107 | private: | ||
108 | const ValueT mValue; | ||
109 | const ValueT mTolerance; | ||
110 | };// ActivateOp | ||
111 | |||
112 | template<typename TreeT, bool IgnoreTolerance = false> | ||
113 | struct DeactivateOp | ||
114 | { | ||
115 | public: | ||
116 | using RootT = typename TreeT::RootNodeType; | ||
117 | using LeafT = typename TreeT::LeafNodeType; | ||
118 | using ValueT = typename TreeT::ValueType; | ||
119 | |||
120 | 21 | explicit DeactivateOp(const ValueT& value, | |
121 | 2 | const ValueT& tolerance = zeroVal<ValueT>()) | |
122 | : mValue(value) | ||
123 | 21 | , mTolerance(tolerance) { } | |
124 | |||
125 | inline bool check(const ValueT& value) const { | ||
126 | 15 | if (IgnoreTolerance) return value == mValue; | |
127 | return math::isApproxEqual(value, mValue, mTolerance); | ||
128 | } | ||
129 | |||
130 | 42 | bool operator()(RootT& root, size_t) const | |
131 | { | ||
132 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 21 times.
|
94 | for (auto it = root.beginValueOn(); it; ++it) { |
133 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
8 | if (check(*it)) it.setValueOn(/*on=*/false); |
134 | } | ||
135 | 42 | return true; | |
136 | } | ||
137 | |||
138 | template<typename NodeT> | ||
139 | 118 | bool operator()(NodeT& node, size_t) const | |
140 | { | ||
141 | // only iterate if there are active tiles | ||
142 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 30 times.
|
118 | if (!node.isValueMaskOff()) { |
143 |
2/2✓ Branch 0 taken 55233 times.
✓ Branch 1 taken 29 times.
|
110524 | for (auto it = node.beginValueOn(); it; ++it) { |
144 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
110450 | if (check(*it)) it.setValueOn(/*on=*/false); |
145 | } | ||
146 | } | ||
147 | // return false if there are no child nodes below this node | ||
148 | 118 | return !node.isChildMaskOff(); | |
149 | } | ||
150 | |||
151 | 19270 | bool operator()(LeafT& leaf, size_t) const | |
152 | { | ||
153 | // early-exit if there are no active values | ||
154 |
2/2✓ Branch 0 taken 9634 times.
✓ Branch 1 taken 1 times.
|
19270 | if (leaf.isValueMaskOff()) return true; |
155 |
2/2✓ Branch 0 taken 3330863 times.
✓ Branch 1 taken 9634 times.
|
6680994 | for (auto it = leaf.beginValueOn(); it; ++it) { |
156 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
|
6653912 | if (check(*it)) it.setValueOn(/*on=*/false); |
157 | } | ||
158 | 19268 | return true; | |
159 | } | ||
160 | |||
161 | private: | ||
162 | const ValueT mValue; | ||
163 | const ValueT mTolerance; | ||
164 | };// DeactivateOp | ||
165 | |||
166 | } // namespace activate_internal | ||
167 | |||
168 | /// @endcond | ||
169 | |||
170 | |||
171 | //////////////////////////////////////// | ||
172 | |||
173 | |||
174 | template<typename GridOrTree> | ||
175 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9 times.
|
42 | void activate(GridOrTree& gridOrTree, |
176 | const typename GridOrTree::ValueType& value, | ||
177 | const typename GridOrTree::ValueType& tolerance, | ||
178 | const bool threaded) | ||
179 | { | ||
180 | using Adapter = TreeAdapter<GridOrTree>; | ||
181 | using TreeType = typename Adapter::TreeType; | ||
182 | using ValueType = typename TreeType::ValueType; | ||
183 | |||
184 | TreeType& tree = Adapter::tree(gridOrTree); | ||
185 | |||
186 | 42 | tree::DynamicNodeManager<TreeType> nodeManager(tree); | |
187 | |||
188 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
|
32 | if (tolerance == zeroVal<ValueType>()) { |
189 | 6 | activate_internal::ActivateOp<TreeType, /*IgnoreTolerance=*/true> op(value); | |
190 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
28 | nodeManager.foreachTopDown(op, threaded); |
191 | } else { | ||
192 | activate_internal::ActivateOp<TreeType> op(value, tolerance); | ||
193 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
14 | nodeManager.foreachTopDown(op, threaded); |
194 | } | ||
195 | } | ||
196 | |||
197 | |||
198 | template<typename GridOrTree> | ||
199 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 8 times.
|
42 | void deactivate(GridOrTree& gridOrTree, |
200 | const typename GridOrTree::ValueType& value, | ||
201 | const typename GridOrTree::ValueType& tolerance, | ||
202 | const bool threaded) | ||
203 | { | ||
204 | using Adapter = TreeAdapter<GridOrTree>; | ||
205 | using TreeType = typename Adapter::TreeType; | ||
206 | using ValueType = typename TreeType::ValueType; | ||
207 | |||
208 | TreeType& tree = Adapter::tree(gridOrTree); | ||
209 | |||
210 | 42 | tree::DynamicNodeManager<TreeType> nodeManager(tree); | |
211 | |||
212 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
|
32 | if (tolerance == zeroVal<ValueType>()) { |
213 | 4 | activate_internal::DeactivateOp<TreeType, /*IgnoreTolerance=*/true> op(value); | |
214 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
26 | nodeManager.foreachTopDown(op, threaded); |
215 | } else { | ||
216 | activate_internal::DeactivateOp<TreeType> op(value, tolerance); | ||
217 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | nodeManager.foreachTopDown(op, threaded); |
218 | } | ||
219 | } | ||
220 | |||
221 | |||
222 | //////////////////////////////////////// | ||
223 | |||
224 | |||
225 | // Explicit Template Instantiation | ||
226 | |||
227 | #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION | ||
228 | |||
229 | #ifdef OPENVDB_INSTANTIATE_ACTIVATE | ||
230 | #include <openvdb/util/ExplicitInstantiation.h> | ||
231 | #endif | ||
232 | |||
233 | #define _FUNCTION(TreeT) \ | ||
234 | void activate(TreeT&, const TreeT::ValueType&, const TreeT::ValueType&, const bool) | ||
235 | OPENVDB_ALL_TREE_INSTANTIATE(_FUNCTION) | ||
236 | #undef _FUNCTION | ||
237 | |||
238 | #define _FUNCTION(TreeT) \ | ||
239 | void activate(Grid<TreeT>&, const TreeT::ValueType&, const TreeT::ValueType&, const bool) | ||
240 | OPENVDB_ALL_TREE_INSTANTIATE(_FUNCTION) | ||
241 | #undef _FUNCTION | ||
242 | |||
243 | #define _FUNCTION(TreeT) \ | ||
244 | void deactivate(TreeT&, const TreeT::ValueType&, const TreeT::ValueType&, const bool) | ||
245 | OPENVDB_ALL_TREE_INSTANTIATE(_FUNCTION) | ||
246 | #undef _FUNCTION | ||
247 | |||
248 | #define _FUNCTION(TreeT) \ | ||
249 | void deactivate(Grid<TreeT>&, const TreeT::ValueType&, const TreeT::ValueType&, const bool) | ||
250 | OPENVDB_ALL_TREE_INSTANTIATE(_FUNCTION) | ||
251 | #undef _FUNCTION | ||
252 | |||
253 | #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION | ||
254 | |||
255 | |||
256 | } // namespace tools | ||
257 | } // namespace OPENVDB_VERSION_NAME | ||
258 | } // namespace openvdb | ||
259 | |||
260 | #endif // OPENVDB_TOOLS_ACTIVATE_HAS_BEEN_INCLUDED | ||
261 |