Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | // | ||
4 | /// @file ChangeBackground.h | ||
5 | /// | ||
6 | /// @brief Efficient multi-threaded replacement of the background | ||
7 | /// values in tree. | ||
8 | /// | ||
9 | /// @author Ken Museth | ||
10 | |||
11 | #ifndef OPENVDB_TOOLS_ChangeBACKGROUND_HAS_BEEN_INCLUDED | ||
12 | #define OPENVDB_TOOLS_ChangeBACKGROUND_HAS_BEEN_INCLUDED | ||
13 | |||
14 | #include <openvdb/math/Math.h> // for isNegative and negative | ||
15 | #include <openvdb/Types.h> // for Index typedef | ||
16 | #include <openvdb/tree/NodeManager.h> | ||
17 | #include <openvdb/openvdb.h> | ||
18 | |||
19 | |||
20 | namespace openvdb { | ||
21 | OPENVDB_USE_VERSION_NAMESPACE | ||
22 | namespace OPENVDB_VERSION_NAME { | ||
23 | namespace tools { | ||
24 | |||
25 | /// @brief Replace the background value in all the nodes of a tree. | ||
26 | /// @details The sign of the background value is preserved, and only | ||
27 | /// inactive values equal to the old background value are replaced. | ||
28 | /// | ||
29 | /// @note If a LeafManager is used the cached leaf nodes are reused, | ||
30 | /// resulting in slightly better overall performance. | ||
31 | /// | ||
32 | /// @param tree Tree (or LeafManager) that will have its background value changed | ||
33 | /// @param background the new background value | ||
34 | /// @param threaded enable or disable threading (threading is enabled by default) | ||
35 | /// @param grainSize used to control the threading granularity (default is 32) | ||
36 | template<typename TreeOrLeafManagerT> | ||
37 | void | ||
38 | changeBackground( | ||
39 | TreeOrLeafManagerT& tree, | ||
40 | const typename TreeOrLeafManagerT::ValueType& background, | ||
41 | bool threaded = true, | ||
42 | size_t grainSize = 32); | ||
43 | |||
44 | |||
45 | /// @brief Replace the background value in all the nodes of a floating-point tree | ||
46 | /// containing a symmetric narrow-band level set. | ||
47 | /// @details All inactive values will be set to +| @a halfWidth | if outside | ||
48 | /// and -| @a halfWidth | if inside, where @a halfWidth is half the width | ||
49 | /// of the symmetric narrow band. | ||
50 | /// | ||
51 | /// @note This method is faster than changeBackground since it does not | ||
52 | /// perform tests to see if inactive values are equal to the old background value. | ||
53 | /// @note If a LeafManager is used the cached leaf nodes are reused, | ||
54 | /// resulting in slightly better overall performance. | ||
55 | /// | ||
56 | /// @param tree Tree (or LeafManager) that will have its background value changed | ||
57 | /// @param halfWidth half of the width of the symmetric narrow band | ||
58 | /// @param threaded enable or disable threading (threading is enabled by default) | ||
59 | /// @param grainSize used to control the threading granularity (default is 32) | ||
60 | /// | ||
61 | /// @throw ValueError if @a halfWidth is negative (as defined by math::isNegative) | ||
62 | template<typename TreeOrLeafManagerT> | ||
63 | void | ||
64 | changeLevelSetBackground( | ||
65 | TreeOrLeafManagerT& tree, | ||
66 | const typename TreeOrLeafManagerT::ValueType& halfWidth, | ||
67 | bool threaded = true, | ||
68 | size_t grainSize = 32); | ||
69 | |||
70 | |||
71 | /// @brief Replace the background values in all the nodes of a floating-point tree | ||
72 | /// containing a possibly asymmetric narrow-band level set. | ||
73 | /// @details All inactive values will be set to +| @a outsideWidth | if outside | ||
74 | /// and -| @a insideWidth | if inside, where @a outsideWidth is the outside | ||
75 | /// width of the narrow band and @a insideWidth is its inside width. | ||
76 | /// | ||
77 | /// @note This method is faster than changeBackground since it does not | ||
78 | /// perform tests to see if inactive values are equal to the old background value. | ||
79 | /// @note If a LeafManager is used the cached leaf nodes are reused, | ||
80 | /// resulting in slightly better overall performance. | ||
81 | /// | ||
82 | /// @param tree Tree (or LeafManager) that will have its background value changed | ||
83 | /// @param outsideWidth The width of the outside of the narrow band | ||
84 | /// @param insideWidth The width of the inside of the narrow band | ||
85 | /// @param threaded enable or disable threading (threading is enabled by default) | ||
86 | /// @param grainSize used to control the threading granularity (default is 32) | ||
87 | /// | ||
88 | /// @throw ValueError if @a outsideWidth is negative or @a insideWidth is | ||
89 | /// not negative (as defined by math::isNegative) | ||
90 | template<typename TreeOrLeafManagerT> | ||
91 | void | ||
92 | changeAsymmetricLevelSetBackground( | ||
93 | TreeOrLeafManagerT& tree, | ||
94 | const typename TreeOrLeafManagerT::ValueType& outsideWidth, | ||
95 | const typename TreeOrLeafManagerT::ValueType& insideWidth, | ||
96 | bool threaded = true, | ||
97 | size_t grainSize = 32); | ||
98 | |||
99 | |||
100 | ////////////////////////////////////////////////////// | ||
101 | |||
102 | |||
103 | // Replaces the background value in a Tree of any type. | ||
104 | template<typename TreeOrLeafManagerT> | ||
105 | class ChangeBackgroundOp | ||
106 | { | ||
107 | public: | ||
108 | typedef typename TreeOrLeafManagerT::ValueType ValueT; | ||
109 | typedef typename TreeOrLeafManagerT::RootNodeType RootT; | ||
110 | typedef typename TreeOrLeafManagerT::LeafNodeType LeafT; | ||
111 | |||
112 | |||
113 | ✗ | ChangeBackgroundOp(const TreeOrLeafManagerT& tree, const ValueT& newValue) | |
114 | : mOldValue(tree.root().background()) | ||
115 | 74 | , mNewValue(newValue) | |
116 | { | ||
117 | } | ||
118 | 148 | void operator()(RootT& root) const | |
119 | { | ||
120 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
|
296 | for (typename RootT::ValueOffIter it = root.beginValueOff(); it; ++it) this->set(it); |
121 | 148 | root.setBackground(mNewValue, false); | |
122 | } | ||
123 | 366 | void operator()(LeafT& node) const | |
124 | { | ||
125 |
2/2✓ Branch 0 taken 56659 times.
✓ Branch 1 taken 183 times.
|
113684 | for (typename LeafT::ValueOffIter it = node.beginValueOff(); it; ++it) this->set(it); |
126 | } | ||
127 | template<typename NodeT> | ||
128 | 4 | void operator()(NodeT& node) const | |
129 | { | ||
130 | 4 | typename NodeT::NodeMaskType mask = node.getValueOffMask(); | |
131 |
2/2✓ Branch 1 taken 36680 times.
✓ Branch 2 taken 2 times.
|
73368 | for (typename NodeT::ValueOnIter it(mask.beginOn(), &node); it; ++it) this->set(it); |
132 | } | ||
133 | private: | ||
134 | |||
135 | template<typename IterT> | ||
136 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
186678 | inline void set(IterT& iter) const |
137 | { | ||
138 |
3/3✓ Branch 0 taken 36673 times.
✓ Branch 1 taken 45934 times.
✓ Branch 2 taken 10732 times.
|
186678 | if (math::isApproxEqual(*iter, mOldValue)) { |
139 | 91854 | iter.setValue(mNewValue); | |
140 |
1/3✓ Branch 0 taken 10739 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
21478 | } else if (math::isApproxEqual(*iter, math::negative(mOldValue))) { |
141 | 21464 | iter.setValue(math::negative(mNewValue)); | |
142 | } | ||
143 | } | ||
144 | const ValueT mOldValue, mNewValue; | ||
145 | };// ChangeBackgroundOp | ||
146 | |||
147 | |||
148 | // Replaces the background value in a Tree assumed to represent a | ||
149 | // level set. It is generally faster than ChangeBackgroundOp. | ||
150 | // Note that is follows the sign-convention that outside is positive | ||
151 | // and inside is negative! | ||
152 | template<typename TreeOrLeafManagerT> | ||
153 | class ChangeLevelSetBackgroundOp | ||
154 | { | ||
155 | public: | ||
156 | typedef typename TreeOrLeafManagerT::ValueType ValueT; | ||
157 | typedef typename TreeOrLeafManagerT::RootNodeType RootT; | ||
158 | typedef typename TreeOrLeafManagerT::LeafNodeType LeafT; | ||
159 | |||
160 | /// @brief Constructor for asymmetric narrow-bands | ||
161 | 28 | ChangeLevelSetBackgroundOp(const ValueT& outside, const ValueT& inside) | |
162 | : mOutside(outside) | ||
163 | 28 | , mInside(inside) | |
164 | { | ||
165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
28 | if (math::isNegative(mOutside)) { |
166 | ✗ | OPENVDB_THROW(ValueError, | |
167 | "ChangeLevelSetBackgroundOp: the outside value cannot be negative!"); | ||
168 | } | ||
169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
28 | if (!math::isNegative(mInside)) { |
170 | ✗ | OPENVDB_THROW(ValueError, | |
171 | "ChangeLevelSetBackgroundOp: the inside value must be negative!"); | ||
172 | } | ||
173 | } | ||
174 | 28 | void operator()(RootT& root) const | |
175 | { | ||
176 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
|
56 | for (typename RootT::ValueOffIter it = root.beginValueOff(); it; ++it) this->set(it); |
177 | 28 | root.setBackground(mOutside, false); | |
178 | } | ||
179 | 52576 | void operator()(LeafT& node) const | |
180 | { | ||
181 |
2/2✓ Branch 0 taken 6798795 times.
✓ Branch 1 taken 26288 times.
|
13650166 | for(typename LeafT::ValueOffIter it = node.beginValueOff(); it; ++it) this->set(it); |
182 | } | ||
183 | template<typename NodeT> | ||
184 | 392 | void operator()(NodeT& node) const | |
185 | { | ||
186 | typedef typename NodeT::ValueOffIter IterT; | ||
187 |
2/2✓ Branch 1 taken 3586286 times.
✓ Branch 2 taken 196 times.
|
7173356 | for (IterT it(node.getChildMask().beginOff(), &node); it; ++it) this->set(it); |
188 | } | ||
189 | private: | ||
190 | |||
191 | template<typename IterT> | ||
192 | inline void set(IterT& iter) const | ||
193 | { | ||
194 | //this is safe since we know ValueType is_floating_point | ||
195 | ValueT& v = const_cast<ValueT&>(*iter); | ||
196 |
10/32✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 9 taken 214577 times.
✓ Branch 10 taken 312934 times.
✓ Branch 12 taken 1125 times.
✓ Branch 13 taken 34111 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 294903 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 27 taken 2362868 times.
✓ Branch 28 taken 3908416 times.
✓ Branch 30 taken 18689 times.
✓ Branch 31 taken 321195 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 2916263 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
|
10385081 | v = v < 0 ? mInside : mOutside; |
197 | } | ||
198 | const ValueT mOutside, mInside; | ||
199 | };// ChangeLevelSetBackgroundOp | ||
200 | |||
201 | |||
202 | template<typename TreeOrLeafManagerT> | ||
203 | void | ||
204 | 148 | changeBackground( | |
205 | TreeOrLeafManagerT& tree, | ||
206 | const typename TreeOrLeafManagerT::ValueType& background, | ||
207 | bool threaded, | ||
208 | size_t grainSize) | ||
209 | { | ||
210 | 296 | tree::NodeManager<TreeOrLeafManagerT> linearTree(tree); | |
211 | ChangeBackgroundOp<TreeOrLeafManagerT> op(tree, background); | ||
212 |
1/2✓ Branch 1 taken 74 times.
✗ Branch 2 not taken.
|
148 | linearTree.foreachTopDown(op, threaded, grainSize); |
213 | } | ||
214 | |||
215 | |||
216 | template<typename TreeOrLeafManagerT> | ||
217 | void | ||
218 | 28 | changeAsymmetricLevelSetBackground( | |
219 | TreeOrLeafManagerT& tree, | ||
220 | const typename TreeOrLeafManagerT::ValueType& outsideValue, | ||
221 | const typename TreeOrLeafManagerT::ValueType& insideValue, | ||
222 | bool threaded, | ||
223 | size_t grainSize) | ||
224 | { | ||
225 | 56 | tree::NodeManager<TreeOrLeafManagerT> linearTree(tree); | |
226 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
28 | ChangeLevelSetBackgroundOp<TreeOrLeafManagerT> op(outsideValue, insideValue); |
227 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
28 | linearTree.foreachTopDown(op, threaded, grainSize); |
228 | } | ||
229 | |||
230 | |||
231 | // If the narrow-band is symmetric only one background value is required | ||
232 | template<typename TreeOrLeafManagerT> | ||
233 | void | ||
234 | 10 | changeLevelSetBackground( | |
235 | TreeOrLeafManagerT& tree, | ||
236 | const typename TreeOrLeafManagerT::ValueType& background, | ||
237 | bool threaded, | ||
238 | size_t grainSize) | ||
239 | { | ||
240 | 10 | changeAsymmetricLevelSetBackground( | |
241 | 10 | tree, background, math::negative(background), threaded, grainSize); | |
242 | } | ||
243 | |||
244 | |||
245 | //////////////////////////////////////// | ||
246 | |||
247 | |||
248 | // Explicit Template Instantiation | ||
249 | |||
250 | #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION | ||
251 | |||
252 | #ifdef OPENVDB_INSTANTIATE_CHANGEBACKGROUND | ||
253 | #include <openvdb/util/ExplicitInstantiation.h> | ||
254 | #endif | ||
255 | |||
256 | #define _FUNCTION(TreeT) \ | ||
257 | void changeBackground(TreeT&, const TreeT::ValueType&, bool, size_t) | ||
258 | OPENVDB_VOLUME_TREE_INSTANTIATE(_FUNCTION) | ||
259 | #undef _FUNCTION | ||
260 | |||
261 | #define _FUNCTION(TreeT) \ | ||
262 | void changeBackground(tree::LeafManager<TreeT>&, const TreeT::ValueType&, bool, size_t) | ||
263 | OPENVDB_VOLUME_TREE_INSTANTIATE(_FUNCTION) | ||
264 | #undef _FUNCTION | ||
265 | |||
266 | #define _FUNCTION(TreeT) \ | ||
267 | void changeLevelSetBackground(TreeT&, const TreeT::ValueType&, bool, size_t) | ||
268 | OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION) | ||
269 | #undef _FUNCTION | ||
270 | |||
271 | #define _FUNCTION(TreeT) \ | ||
272 | void changeLevelSetBackground(tree::LeafManager<TreeT>&, const TreeT::ValueType&, bool, size_t) | ||
273 | OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION) | ||
274 | #undef _FUNCTION | ||
275 | |||
276 | #define _FUNCTION(TreeT) \ | ||
277 | void changeAsymmetricLevelSetBackground(TreeT&, const TreeT::ValueType&, const TreeT::ValueType&, bool, size_t) | ||
278 | OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION) | ||
279 | #undef _FUNCTION | ||
280 | |||
281 | #define _FUNCTION(TreeT) \ | ||
282 | void changeAsymmetricLevelSetBackground(tree::LeafManager<TreeT>&, const TreeT::ValueType&, const TreeT::ValueType&, bool, size_t) | ||
283 | OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION) | ||
284 | #undef _FUNCTION | ||
285 | |||
286 | #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION | ||
287 | |||
288 | |||
289 | } // namespace tools | ||
290 | } // namespace OPENVDB_VERSION_NAME | ||
291 | } // namespace openvdb | ||
292 | |||
293 | #endif // OPENVDB_TOOLS_CHANGEBACKGROUND_HAS_BEEN_INCLUDED | ||
294 |