GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/points/PointCount.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 34 35 97.1%
Functions: 11 13 84.6%
Branches: 44 92 47.8%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file points/PointCount.h
5 ///
6 /// @author Dan Bailey
7 ///
8 /// @brief Methods for counting points in VDB Point grids.
9
10 #ifndef OPENVDB_POINTS_POINT_COUNT_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_COUNT_HAS_BEEN_INCLUDED
12
13 #include <openvdb/openvdb.h>
14
15 #include "PointDataGrid.h"
16 #include "PointMask.h"
17 #include "IndexFilter.h"
18
19 #include <tbb/parallel_reduce.h>
20
21 #include <vector>
22
23
24 namespace openvdb {
25 OPENVDB_USE_VERSION_NAMESPACE
26 namespace OPENVDB_VERSION_NAME {
27 namespace points {
28
29
30 /// @brief Count the total number of points in a PointDataTree
31 /// @param tree the PointDataTree in which to count the points
32 /// @param filter an optional index filter
33 /// @param inCoreOnly if true, points in out-of-core leaf nodes are not counted
34 /// @param threaded enable or disable threading (threading is enabled by default)
35 template <typename PointDataTreeT, typename FilterT = NullFilter>
36 inline Index64 pointCount( const PointDataTreeT& tree,
37 const FilterT& filter = NullFilter(),
38 const bool inCoreOnly = false,
39 const bool threaded = true);
40
41
42 /// @brief Populate an array of cumulative point offsets per leaf node.
43 /// @param pointOffsets array of offsets to be populated
44 /// @param tree the PointDataTree from which to populate the offsets
45 /// @param filter an optional index filter
46 /// @param inCoreOnly if true, points in out-of-core leaf nodes are ignored
47 /// @param threaded enable or disable threading (threading is enabled by default)
48 /// @return The final cumulative point offset.
49 template <typename PointDataTreeT, typename FilterT = NullFilter>
50 inline Index64 pointOffsets(std::vector<Index64>& pointOffsets,
51 const PointDataTreeT& tree,
52 const FilterT& filter = NullFilter(),
53 const bool inCoreOnly = false,
54 const bool threaded = true);
55
56
57 /// @brief Generate a new grid with voxel values to store the number of points per voxel
58 /// @param grid the PointDataGrid to use to compute the count grid
59 /// @param filter an optional index filter
60 /// @note The return type of the grid must be an integer or floating-point scalar grid.
61 template <typename PointDataGridT,
62 typename GridT = typename PointDataGridT::template ValueConverter<Int32>::Type,
63 typename FilterT = NullFilter>
64 inline typename GridT::Ptr
65 pointCountGrid( const PointDataGridT& grid,
66 const FilterT& filter = NullFilter());
67
68
69 /// @brief Generate a new grid that uses the supplied transform with voxel values to store the
70 /// number of points per voxel.
71 /// @param grid the PointDataGrid to use to compute the count grid
72 /// @param transform the transform to use to compute the count grid
73 /// @param filter an optional index filter
74 /// @note The return type of the grid must be an integer or floating-point scalar grid.
75 template <typename PointDataGridT,
76 typename GridT = typename PointDataGridT::template ValueConverter<Int32>::Type,
77 typename FilterT = NullFilter>
78 inline typename GridT::Ptr
79 pointCountGrid( const PointDataGridT& grid,
80 const openvdb::math::Transform& transform,
81 const FilterT& filter = NullFilter());
82
83
84 ////////////////////////////////////////
85
86
87 template <typename PointDataTreeT, typename FilterT>
88 205 Index64 pointCount(const PointDataTreeT& tree,
89 const FilterT& filter,
90 const bool inCoreOnly,
91 const bool threaded)
92 {
93 using LeafManagerT = tree::LeafManager<const PointDataTreeT>;
94 using LeafRangeT = typename LeafManagerT::LeafRange;
95
96 205 auto countLambda =
97 11282 [&filter, &inCoreOnly] (const LeafRangeT& range, Index64 sum) -> Index64 {
98 11356 for (const auto& leaf : range) {
99
15/24
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9943 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 60 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 9 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 9 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
10031 if (inCoreOnly && leaf.buffer().isOutOfCore()) continue;
100 18 auto state = filter.state(leaf);
101
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7 times.
18 if (state == index::ALL) {
102 9941 sum += leaf.pointCount();
103
5/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
24 } else if (state != index::NONE) {
104
6/12
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 60 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 60 times.
✗ Branch 14 not taken.
150 sum += iterCount(leaf.beginIndexAll(filter));
105 }
106 }
107 1325 return sum;
108 };
109
110 410 LeafManagerT leafManager(tree);
111
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
205 if (threaded) {
112
1/2
✓ Branch 1 taken 147 times.
✗ Branch 2 not taken.
205 return tbb::parallel_reduce(leafManager.leafRange(), Index64(0), countLambda,
113 56 [] (Index64 n, Index64 m) -> Index64 { return n + m; });
114 }
115 else {
116 return countLambda(leafManager.leafRange(), Index64(0));
117 }
118 }
119
120
121 template <typename PointDataTreeT, typename FilterT>
122 71 Index64 pointOffsets( std::vector<Index64>& pointOffsets,
123 const PointDataTreeT& tree,
124 const FilterT& filter,
125 const bool inCoreOnly,
126 const bool threaded)
127 {
128 using LeafT = typename PointDataTreeT::LeafNodeType;
129 using LeafManagerT = typename tree::LeafManager<const PointDataTreeT>;
130
131 // allocate and zero values in point offsets array
132
133
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
71 pointOffsets.assign(tree.leafCount(), Index64(0));
134
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
71 if (pointOffsets.empty()) return 0;
135
136 // compute total points per-leaf
137
138 140 LeafManagerT leafManager(tree);
139
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
70 leafManager.foreach(
140 28611 [&pointOffsets, &filter, &inCoreOnly](const LeafT& leaf, size_t pos) {
141
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 22795 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 5816 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
28615 if (inCoreOnly && leaf.buffer().isOutOfCore()) return;
142 auto state = filter.state(leaf);
143 if (state == index::ALL) {
144 22795 pointOffsets[pos] = leaf.pointCount();
145 } else if (state != index::NONE) {
146
1/2
✓ Branch 1 taken 5816 times.
✗ Branch 2 not taken.
5816 pointOffsets[pos] = iterCount(leaf.beginIndexAll(filter));
147 }
148 },
149 threaded);
150
151 // turn per-leaf totals into cumulative leaf totals
152
153 70 Index64 pointOffset(pointOffsets[0]);
154
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
28615 for (size_t n = 1; n < pointOffsets.size(); n++) {
155 28545 pointOffset += pointOffsets[n];
156 28545 pointOffsets[n] = pointOffset;
157 }
158
159 return pointOffset;
160 }
161
162
163 template <typename PointDataGridT, typename GridT, typename FilterT>
164 typename GridT::Ptr
165 18 pointCountGrid( const PointDataGridT& points,
166 const FilterT& filter)
167 {
168 static_assert(std::is_integral<typename GridT::ValueType>::value ||
169 std::is_floating_point<typename GridT::ValueType>::value,
170 "openvdb::points::pointCountGrid must return an integer or floating-point scalar grid");
171
172 using PointDataTreeT = typename PointDataGridT::TreeType;
173 using TreeT = typename GridT::TreeType;
174
175 18 typename TreeT::Ptr tree =
176 point_mask_internal::convertPointsToScalar<TreeT, PointDataTreeT, FilterT>
177 (points.tree(), filter);
178
179
3/8
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
36 typename GridT::Ptr grid(new GridT(tree));
180
3/8
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
36 grid->setTransform(points.transform().copy());
181 18 return grid;
182 }
183
184
185 template <typename PointDataGridT, typename GridT, typename FilterT>
186 typename GridT::Ptr
187 pointCountGrid( const PointDataGridT& points,
188 const openvdb::math::Transform& transform,
189 const FilterT& filter)
190 {
191 static_assert( std::is_integral<typename GridT::ValueType>::value ||
192 std::is_floating_point<typename GridT::ValueType>::value,
193 "openvdb::points::pointCountGrid must return an integer or floating-point scalar grid");
194
195 // This is safe because the PointDataGrid can only be modified by the deformer
196 using AdapterT = TreeAdapter<typename PointDataGridT::TreeType>;
197 auto& nonConstPoints = const_cast<typename AdapterT::NonConstGridType&>(points);
198
199 NullDeformer deformer;
200 return point_mask_internal::convertPointsToScalar<GridT>(
201
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 nonConstPoints, transform, filter, deformer);
202 }
203
204
205 ////////////////////////////////////////
206
207
208 } // namespace points
209 } // namespace OPENVDB_VERSION_NAME
210 } // namespace openvdb
211
212 #endif // OPENVDB_POINTS_POINT_COUNT_HAS_BEEN_INCLUDED
213