GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/unittest/TestNodeVisitor.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 81 83 97.6%
Functions: 17 17 100.0%
Branches: 82 301 27.2%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 #include <openvdb/openvdb.h>
5 #include <openvdb/tools/LevelSetPlatonic.h>
6 #include <openvdb/tools/NodeVisitor.h>
7 #include <openvdb/tools/Prune.h>
8 #include "gtest/gtest.h"
9
10 6 class TestNodeVisitor: public ::testing::Test
11 {
12 };
13
14
15
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 struct NodeCountOp
16 {
17 template <typename NodeT>
18 34 void operator()(const NodeT&, size_t)
19 {
20 const openvdb::Index level = NodeT::LEVEL;
21
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1430 times.
1455 while (level >= counts.size()) counts.emplace_back(0);
22 1447 counts[level]++;
23 34 }
24
25 std::vector<openvdb::Index32> counts;
26 }; // struct NodeCountOp
27
28
29
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 TEST_F(TestNodeVisitor, testNodeCount)
30 {
31 using namespace openvdb;
32
33
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 auto grid = tools::createLevelSetCube<FloatGrid>(/*scale=*/10.0f);
34
35 NodeCountOp nodeCountOp;
36
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::visitNodesDepthFirst(grid->tree(), nodeCountOp);
37
38
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<Index32> nodeCount1 = nodeCountOp.counts;
39
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<Index32> nodeCount2 = grid->tree().nodeCount();
40
41
2/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
1 EXPECT_EQ(nodeCount1.size(), nodeCount2.size());
42
43
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (size_t i = 0; i < nodeCount1.size(); i++) {
44
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
4 EXPECT_EQ(nodeCount1[i], nodeCount2[i]);
45 }
46 1 }
47
48
49 template <typename TreeT>
50 struct LeafCountOp
51 {
52 using LeafT = typename TreeT::LeafNodeType;
53
54 template <typename NodeT>
55 void operator()(const NodeT&, size_t) { }
56 2826 void operator()(const LeafT&, size_t) { count++; }
57
58 openvdb::Index32 count{0};
59 }; // struct LeafCountOp
60
61
62
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 TEST_F(TestNodeVisitor, testLeafCount)
63 {
64 using namespace openvdb;
65
66 1 FloatGrid::Ptr grid = tools::createLevelSetCube<FloatGrid>(/*scale=*/10.0f);
67
68 { // non-const tree
69
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 LeafCountOp<FloatTree> leafCountOp;
70
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::visitNodesDepthFirst(grid->tree(), leafCountOp);
71
72
3/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
1 EXPECT_EQ(grid->tree().leafCount(), leafCountOp.count);
73 }
74
75 { // const tree
76
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 LeafCountOp<FloatTree> leafCountOp;
77
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::visitNodesDepthFirst(grid->constTree(), leafCountOp);
78
79
3/20
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
1 EXPECT_EQ(grid->tree().leafCount(), leafCountOp.count);
80 }
81 1 }
82
83
84 struct DescendOp
85 {
86 template <typename NodeT>
87 void operator()(const NodeT&, size_t)
88 {
89 const openvdb::Index level = NodeT::LEVEL;
90 // count the number of times the operator descends
91 // from a higher-level node to a lower-level node
92
6/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1405 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1430 if (NodeT::LEVEL < previousLevel) count++;
93 1430 previousLevel = level;
94 }
95
96 openvdb::Index32 previousLevel{0};
97 openvdb::Index32 count{0};
98 }; // struct DescendOp
99
100
101
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 TEST_F(TestNodeVisitor, testDepthFirst)
102 {
103 using namespace openvdb;
104
105 1 FloatGrid::Ptr grid = tools::createLevelSetCube<FloatGrid>(/*scale=*/10.0f);
106
107
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 DescendOp descendOp;
108
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::visitNodesDepthFirst(grid->tree(), descendOp);
109
110 // this confirms that the visit pattern is depth-first
111
3/20
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
1 EXPECT_EQ(descendOp.count, grid->tree().nonLeafCount());
112 1 }
113
114
115 template <typename TreeT>
116 struct StoreOriginsOp
117 {
118 using RootT = typename TreeT::RootNodeType;
119
120 1 StoreOriginsOp(std::vector<openvdb::Coord>& _origins)
121
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 : origins(_origins) { }
122
123 void operator()(const RootT&, size_t idx)
124 {
125 // root node has no origin
126 1 origins[idx] = openvdb::Coord::max();
127 }
128
129 template <typename NodeT>
130 void operator()(const NodeT& node, size_t idx)
131 {
132 1429 origins[idx] = node.origin();
133 }
134
135 std::vector<openvdb::Coord>& origins;
136 }; // struct StoreOriginsOp
137
138
139
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 TEST_F(TestNodeVisitor, testOriginArray)
140 {
141 using namespace openvdb;
142
143
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 FloatGrid::Ptr grid = tools::createLevelSetCube<FloatGrid>(/*scale=*/10.0f);
144
145
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<Index32> nodeCount = grid->tree().nodeCount();
146 Index32 totalNodeCount(0);
147
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (Index32 count : nodeCount) totalNodeCount += count;
148
149 // use an offset
150 size_t offset = 10;
151
152 std::vector<Coord> origins;
153
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 origins.resize(totalNodeCount + offset);
154
155 StoreOriginsOp<FloatTree> storeOriginsOp(origins);
156
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::visitNodesDepthFirst(grid->tree(), storeOriginsOp, offset);
157
158 size_t idx = offset;
159
160 // root node
161
2/16
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1 EXPECT_EQ(origins[idx++], Coord::max());
162
163 const auto& root = grid->tree().root();
164
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
10 for (auto internal1Iter = root.cbeginChildOn(); internal1Iter; ++internal1Iter) {
165
2/16
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
8 EXPECT_EQ(origins[idx++], internal1Iter->origin());
166
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 for (auto internal2Iter = internal1Iter->cbeginChildOn(); internal2Iter; ++internal2Iter) {
167
2/16
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
8 EXPECT_EQ(origins[idx++], internal2Iter->origin());
168
2/2
✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 8 times.
1421 for (auto leafIter = internal2Iter->cbeginChildOn(); leafIter; ++leafIter) {
169
2/16
✓ Branch 1 taken 1413 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1413 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1413 EXPECT_EQ(origins[idx++], leafIter->origin());
170 }
171 }
172 }
173
174
2/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
1 EXPECT_EQ(idx, origins.size());
175 1 }
176
177
178 template <typename TreeType>
179 struct DeactivateOp
180 {
181 using LeafT = typename TreeType::LeafNodeType;
182
183 template <typename NodeT>
184 void operator()(NodeT&, size_t) { }
185
186 void operator()(LeafT& leaf, size_t)
187 {
188 leaf.setValuesOff();
189 }
190 }; // struct DeactivateOp
191
192
193
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 TEST_F(TestNodeVisitor, testPartialDeactivate)
194 {
195 using namespace openvdb;
196
197 1 FloatGrid::Ptr grid = tools::createLevelSetCube<FloatGrid>(/*scale=*/10.0f);
198
199 using NodeT = FloatTree::RootNodeType::ChildNodeType::ChildNodeType;
200
201
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto iter = grid->tree().root().beginChildOn()->beginChildOn();
202
203 DeactivateOp<FloatTree> deactivateOp;
204
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::DepthFirstNodeVisitor<NodeT>::visit(*iter, deactivateOp);
205
206
3/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
1 EXPECT_EQ(Index32(1413), grid->tree().leafCount());
207
208
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::pruneInactive(grid->tree());
209
210 // a subset of the leaf nodes have now been deactivated and removed
211
3/20
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
1 EXPECT_EQ(Index32(1195), grid->tree().leafCount());
212 1 }
213
214
215 // Functor to offset all the active values of a tree.
216 struct OffsetOp
217 {
218 1 OffsetOp(float v): mOffset(v) { }
219
220 template<typename NodeT>
221 2860 void operator()(NodeT& node, size_t) const
222 {
223
3/3
✓ Branch 0 taken 299006 times.
✓ Branch 1 taken 1429 times.
✓ Branch 2 taken 1 times.
600874 for (auto iter = node.beginValueOn(); iter; ++iter) {
224
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
598012 iter.setValue(iter.getValue() + mOffset);
225 }
226 2860 }
227 private:
228 const float mOffset;
229 };
230
231 // Functor to offset all the active values of a tree. Note
232 // this implementation also illustrates how different
233 // computation can be applied to the different node types.
234 template<typename TreeT>
235 struct OffsetByLevelOp
236 {
237 using ValueT = typename TreeT::ValueType;
238 using RootT = typename TreeT::RootNodeType;
239 using LeafT = typename TreeT::LeafNodeType;
240
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 OffsetByLevelOp(const ValueT& v) : mOffset(v) {}
241 // Processes the root node.
242 1 void operator()(RootT& root, size_t) const
243 {
244
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
2 for (auto iter = root.beginValueOn(); iter; ++iter) {
245 iter.setValue(iter.getValue() + mOffset);
246 }
247 1 }
248 // Processes the leaf nodes.
249 1413 void operator()(LeafT& leaf, size_t) const
250 {
251
2/2
✓ Branch 0 taken 299006 times.
✓ Branch 1 taken 1413 times.
300419 for (auto iter = leaf.beginValueOn(); iter; ++iter) {
252 299006 iter.setValue(iter.getValue() + mOffset);
253 }
254 1413 }
255 // Processes the internal nodes.
256 template<typename NodeT>
257 32 void operator()(NodeT& node, size_t) const
258 {
259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
32 for (auto iter = node.beginValueOn(); iter; ++iter) {
260 iter.setValue(iter.getValue() + mOffset);
261 }
262 32 }
263 private:
264 const ValueT mOffset;
265 };
266
267 // this is the example from the documentation
268
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 TEST_F(TestNodeVisitor, testOffset)
269 {
270 using namespace openvdb;
271
272
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 FloatGrid::Ptr grid = tools::createLevelSetCube<FloatGrid>(/*scale=*/10.0f);
273
274 OffsetOp op(3.0f);
275
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::visitNodesDepthFirst(grid->tree(), op);
276
277 OffsetByLevelOp<FloatTree> byLevelOp(3.0f);
278
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tools::visitNodesDepthFirst(grid->tree(), byLevelOp);
279 1 }
280