GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/points/PointStatistics.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 169 186 90.9%
Functions: 40 44 90.9%
Branches: 374 708 52.8%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
4 /// @author Nick Avramoussis
5 ///
6 /// @file PointStatistics.h
7 ///
8 /// @brief Functions to perform multi threaded reductions and analysis of
9 /// arbitrary point attribute types. Each function imposes various
10 /// requirements on the point ValueType (such as expected operators) and
11 /// supports arbitrary point filters.
12 ///
13
14 #ifndef OPENVDB_POINTS_STATISTICS_HAS_BEEN_INCLUDED
15 #define OPENVDB_POINTS_STATISTICS_HAS_BEEN_INCLUDED
16
17 #include "PointDataGrid.h"
18
19 #include <openvdb/openvdb.h>
20 #include <openvdb/Types.h>
21 #include <openvdb/math/Math.h>
22 #include <openvdb/tree/LeafManager.h>
23
24 #include <tbb/parallel_reduce.h>
25 #include <tbb/parallel_for.h>
26
27 namespace openvdb {
28 OPENVDB_USE_VERSION_NAMESPACE
29 namespace OPENVDB_VERSION_NAME {
30 namespace points {
31
32 /// @brief Evaluates the minimum and maximum values of a point attribute.
33 /// @details Performs parallel reduction by comparing values using their less
34 /// than and greater than operators. If the PointDataGrid is empty or the
35 /// filter evalutes to empty, zeroVal<ValueT>() is returned for both values.
36 /// @note The ValueT of the attribute must be copy constructible. This method
37 /// will throw if the templated ValueT does not match the given attribute.
38 /// For vectors and matrices, this results in per component comparisons.
39 /// See evalExtents for magnitudes or more custom control.
40 /// @warning if "P" is provided, the result is undefined.
41 /// @param points the point tree
42 /// @param attribute the attribute to reduce
43 /// @param filter a filter to apply to points
44 /// @return min,max value pair
45 template <typename ValueT,
46 typename CodecT = UnknownCodec,
47 typename FilterT = NullFilter,
48 typename PointDataTreeT>
49 std::pair<ValueT, ValueT>
50 evalMinMax(const PointDataTreeT& points,
51 const std::string& attribute,
52 const FilterT& filter = NullFilter());
53
54 /// @brief Evaluates the average value of a point attribute.
55 /// @details Performs parallel reduction by cumulative moving average. The
56 /// reduction arithmetic and return value precision evaluates to:
57 /// ConvertElementType<ValueT, double>::Type
58 /// which, for POD and VDB math types, is ValueT at double precision. If the
59 /// PointDataGrid is empty or the filter evalutes to empty, zeroVal<ValueT>()
60 /// is returned.
61 /// @note The ConvertElementType of the attribute must be copy constructible,
62 /// support the same type + - * operators and * / operators from a double.
63 /// This method will throw if ValueT does not match the given attribute. The
64 /// function is deterministic.
65 /// @warning if "P" is provided, the result is undefined.
66 /// @param points the point tree
67 /// @param attribute the attribute to reduce
68 /// @param filter a filter to apply to points
69 /// @return the average value
70 template <typename ValueT,
71 typename CodecT = UnknownCodec,
72 typename FilterT = NullFilter,
73 typename PointDataTreeT>
74 typename ConvertElementType<ValueT, double>::Type
75 evalAverage(const PointDataTreeT& points,
76 const std::string& attribute,
77 const FilterT& filter = NullFilter());
78
79 /// @brief Evaluates the total value of a point attribute.
80 /// @details Performs parallel reduction by summing all values. The reduction
81 /// arithmetic and return value precision evaluates to:
82 /// PromoteType<ValueT>::Highest
83 /// which, for POD and VDB math types, is ValueT at its highest bit precision.
84 /// If the PointDataGrid is empty or the filter evalutes to empty,
85 /// zeroVal<ValueT>() is returned.
86 /// @note The PromoteType of the attribute must be copy constructible, support
87 /// the same type + operator. This method will throw if ValueT does not match
88 /// the given attribute. The function is deterministic.
89 /// @warning if "P" is provided, the result is undefined.
90 /// @param points the point tree
91 /// @param attribute the attribute to reduce
92 /// @param filter a filter to apply to points
93 /// @return the total value
94 template <typename ValueT,
95 typename CodecT = UnknownCodec,
96 typename FilterT = NullFilter,
97 typename PointDataTreeT>
98 typename PromoteType<ValueT>::Highest
99 accumulate(const PointDataTreeT& points,
100 const std::string& attribute,
101 const FilterT& filter = NullFilter());
102
103 /// @brief Evaluates the minimum and maximum values of a point attribute and
104 /// returns whether the values are valid. Optionally constructs localised
105 /// min and max value trees.
106 /// @details Performs parallel reduction by comparing values using their less
107 /// than and greater than operators. This method will return true if min and
108 /// max have been set, false otherwise (when no points existed or a filter
109 /// evaluated to empty).
110 /// @note The ValueT of the attribute must also be copy constructible. This
111 /// method will throw if the templated ValueT does not match the given
112 /// attribute. For vectors and matrices, this results in per component
113 /// comparisons. See evalExtents for magnitudes or more custom control.
114 /// @warning if "P" is provided, the result is undefined.
115 /// @param points the point tree
116 /// @param attribute the attribute to reduce
117 /// @param min the computed min value
118 /// @param max the computed max value
119 /// @param filter a filter to apply to points
120 /// @param minTree if provided, builds a tiled tree of localised min results
121 /// @param maxTree if provided, builds a tiled tree of localised max results
122 /// @return true if min and max have been set, false otherwise. Can be false if
123 /// no points were processed or if the tree was empty.
124 template <typename ValueT,
125 typename CodecT = UnknownCodec,
126 typename FilterT = NullFilter,
127 typename PointDataTreeT>
128 bool evalMinMax(const PointDataTreeT& points,
129 const std::string& attribute,
130 ValueT& min,
131 ValueT& max,
132 const FilterT& filter = NullFilter(),
133 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree = nullptr,
134 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree = nullptr);
135
136 /// @brief Evaluates the average value of a point attribute and returns whether
137 /// the value is valid. Optionally constructs localised average value trees.
138 /// @details Performs parallel reduction by cumulative moving average. The
139 /// reduction arithmetic and return value precision evaluates to:
140 /// ConvertElementType<ValueT, double>::Type
141 /// which, for POD and VDB math types, is ValueT at double precision. This
142 /// method will return true average has been set, false otherwise (when no
143 /// points existed or a filter evaluated to empty).
144 /// @note The ConvertElementType of the attribute must be copy constructible,
145 /// support the same type + - * operators and * / operators from a double.
146 /// This method will throw if ValueT does not match the given attribute. The
147 /// function is deterministic.
148 /// @warning if "P" is provided, the result is undefined.
149 /// @param points the point tree
150 /// @param attribute the attribute to reduce
151 /// @param average the computed averaged value at double precision
152 /// @param filter a filter to apply to points
153 /// @param averageTree if provided, builds a tiled tree of localised avg results.
154 /// @return true if average has been set, false otherwise. Can be false if
155 /// no points were processed or if the tree was empty.
156 /// @par Example:
157 /// @code
158 /// using namespace openvdb;
159 /// using namespace openvdb::points
160 ///
161 /// // average and store per leaf values in a new tree
162 /// ConvertElementType<uint8_t, double>::Type avg; // evaluates to double
163 /// PointDataTree::ValueConverter<decltype(avg)>::Type avgTree; // double tree of averages
164 /// bool success = evalAverage<uint8_t>(tree, "attrib", avg, NullFilter(), &avgTree);
165 /// @endcode
166 template <typename ValueT,
167 typename CodecT = UnknownCodec,
168 typename FilterT = NullFilter,
169 typename PointDataTreeT,
170 typename ResultTreeT = typename ConvertElementType<ValueT, double>::Type>
171 bool evalAverage(const PointDataTreeT& points,
172 const std::string& attribute,
173 typename ConvertElementType<ValueT, double>::Type& average,
174 const FilterT& filter = NullFilter(),
175 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* averageTree = nullptr);
176
177 /// @brief Evaluates the total value of a point attribute and returns whether
178 /// the value is valid. Optionally constructs localised total value trees.
179 /// @details Performs parallel reduction by summing all values. The reduction
180 /// arithmetic and return value precision evaluates to:
181 /// PromoteType<ValueT>::Highest
182 /// which, for POD and VDB math types, is ValueT at its highest bit precision.
183 /// This method will return true total has been set, false otherwise (when no
184 /// points existed or a filter evaluated to empty).
185 /// @note The PromoteType of the attribute must be copy constructible, support
186 /// the same type + operator. This method will throw if ValueT does not match
187 /// the given attribute. The function is deterministic.
188 /// @warning if "P" is provided, the result is undefined.
189 /// @param points the point tree
190 /// @param attribute the attribute to reduce
191 /// @param total the computed total value
192 /// @param filter a filter to apply to points
193 /// @param totalTree if provided, builds a tiled tree of localised total results.
194 /// @return true if total has been set, false otherwise. Can be false if
195 /// no points were processed or if the tree was empty.
196 /// @par Example:
197 /// @code
198 /// using namespace openvdb;
199 /// using namespace openvdb::points;
200 ///
201 /// // accumulate and store per leaf values in a new tree
202 /// PromoteType<uint8_t>::Highest total; // evaluates to uint64_t
203 /// PointDataTree::ValueConverter<decltype(total)>::Type totalTree; // uint64_t tree of totals
204 /// bool success = accumulate<uint8_t>(tree, "attrib", total, NullFilter(), &totalTree);
205 /// @endcode
206 template <typename ValueT,
207 typename CodecT = UnknownCodec,
208 typename FilterT = NullFilter,
209 typename PointDataTreeT,
210 typename ResultTreeT = typename PromoteType<ValueT>::Highest>
211 bool accumulate(const PointDataTreeT& points,
212 const std::string& attribute,
213 typename PromoteType<ValueT>::Highest& total,
214 const FilterT& filter = NullFilter(),
215 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* totalTree = nullptr);
216
217 ///////////////////////////////////////////////////
218 ///////////////////////////////////////////////////
219
220 namespace statistics_internal
221 {
222
223 /// @brief Scalar extent op to evaluate the min/max values of a
224 /// single integral or floating point attribute type
225 template <typename ValueT>
226 struct ScalarMinMax
227 {
228 using ExtentT = std::pair<ValueT, ValueT>;
229 ScalarMinMax(const ValueT& init) : mMinMax(init, init) {}
230 13 ScalarMinMax(const ExtentT& init) : mMinMax(init) {}
231 inline void operator()(const ValueT& b)
232 {
233
5/10
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
59 mMinMax.first = std::min(mMinMax.first, b);
234 59 mMinMax.second = std::max(mMinMax.second, b);
235 }
236 inline void operator()(const ExtentT& b)
237 {
238
11/20
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 5 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
82 mMinMax.first = std::min(mMinMax.first, b.first);
239
5/10
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
20 mMinMax.second = std::max(mMinMax.second, b.second);
240 69 }
241 inline const ExtentT& get() const { return mMinMax; }
242 ExtentT mMinMax;
243 };
244
245 /// @brief Vector squared magnitude op to evaluate the min/max of a
246 /// vector attribute and return the result as a scalar of the
247 /// appropriate precision
248 template <typename VecT, bool MagResult = true>
249 struct MagnitudeExtent
250 : public ScalarMinMax<typename ValueTraits<VecT>::ElementType>
251 {
252 using ElementT = typename ValueTraits<VecT>::ElementType;
253 using ExtentT = typename ScalarMinMax<ElementT>::ExtentT;
254 using BaseT = ScalarMinMax<ElementT>;
255 MagnitudeExtent(const VecT& init) : BaseT(init.lengthSqr()) {}
256 MagnitudeExtent(const ExtentT& init) : BaseT(init) {}
257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 inline void operator()(const VecT& b) { this->BaseT::operator()(b.lengthSqr()); }
258 inline void operator()(const ExtentT& b) { this->BaseT::operator()(b); }
259 };
260
261 /// @brief Vector squared magnitude op to evaluate the min/max of a
262 /// vector attribute and return the result as the original vector
263 template <typename VecT>
264 struct MagnitudeExtent<VecT, false>
265 {
266 using ElementT = typename ValueTraits<VecT>::ElementType;
267 using ExtentT = std::pair<VecT, VecT>;
268 MagnitudeExtent(const VecT& init)
269 : mLengths(), mMinMax(init, init) {
270 1 mLengths.first = init.lengthSqr();
271 1 mLengths.second = mLengths.first;
272 }
273 MagnitudeExtent(const ExtentT& init)
274 : mLengths(), mMinMax(init) {
275 mLengths.first = init.first.lengthSqr();
276 mLengths.second = init.second.lengthSqr();
277 }
278 inline const ExtentT& get() const { return mMinMax; }
279 inline void operator()(const VecT& b)
280 {
281 const ElementT l = b.lengthSqr();
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (l < mLengths.first) {
283 mLengths.first = l;
284 mMinMax.first = b;
285 }
286
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 else if (l > mLengths.second) {
287 2 mLengths.second = l;
288 2 mMinMax.second = b;
289 }
290 }
291 inline void operator()(const ExtentT& b)
292 {
293 ElementT l = b.first.lengthSqr();
294 if (l < mLengths.first) {
295 mLengths.first = l;
296 mMinMax.first = b.first;
297 }
298 l = b.second.lengthSqr();
299 if (l > mLengths.second) {
300 mLengths.second = l;
301 mMinMax.second = b.second;
302 }
303 }
304
305 std::pair<ElementT, ElementT> mLengths;
306 ExtentT mMinMax;
307 };
308
309 /// @brief Vector component-wise op to evaluate the min/max of
310 /// vector components and return the result as a vector of
311 /// equal size and precision
312 template <typename VecT>
313 struct ComponentExtent
314 {
315 using ExtentT = std::pair<VecT, VecT>;
316 ComponentExtent(const VecT& init) : mMinMax(init, init) {}
317 3 ComponentExtent(const ExtentT& init) : mMinMax(init) {}
318 inline const ExtentT& get() const { return mMinMax; }
319 inline void operator()(const VecT& b)
320 {
321 mMinMax.first = math::minComponent(mMinMax.first, b);
322 mMinMax.second = math::maxComponent(mMinMax.second, b);
323 }
324 17 inline void operator()(const ExtentT& b)
325 {
326 17 mMinMax.first = math::minComponent(mMinMax.first, b.first);
327 17 mMinMax.second = math::maxComponent(mMinMax.second, b.second);
328 17 }
329
330 ExtentT mMinMax;
331 };
332
333 template <typename ValueT,
334 typename CodecT,
335 typename FilterT,
336 typename ExtentOp,
337 typename PointDataTreeT>
338 94 bool evalExtents(const PointDataTreeT& points,
339 const std::string& attribute,
340 typename ExtentOp::ExtentT& ext,
341 const FilterT& filter,
342 typename PointDataTreeT::template ValueConverter
343 <typename ExtentOp::ExtentT::first_type>::Type* const minTree = nullptr,
344 typename PointDataTreeT::template ValueConverter
345 <typename ExtentOp::ExtentT::second_type>::Type* const maxTree = nullptr)
346 {
347 static_assert(std::is_base_of<TreeBase, PointDataTreeT>::value,
348 "PointDataTreeT in instantiation of evalExtents is not an openvdb Tree type");
349
350
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
25 struct ResultType {
351 typename ExtentOp::ExtentT ext;
352 bool data = false;
353 };
354
355 188 tree::LeafManager<const PointDataTreeT> manager(points);
356
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
94 if (manager.leafCount() == 0) return false;
357
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
82 const size_t idx = manager.leaf(0).attributeSet().find(attribute);
358
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 1 times.
82 if (idx == AttributeSet::INVALID_POS) return false;
359
360 // track results per leaf for min/max trees
361 78 std::vector<std::unique_ptr<typename ExtentOp::ExtentT>> values;
362
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
80 if (minTree || maxTree) values.resize(manager.leafCount());
363
364
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 1 times.
90 const ResultType result = tbb::parallel_reduce(manager.leafRange(),
365 ResultType(),
366 367 [idx, &filter, &values]
367 (const auto& range, ResultType in) -> ResultType
368 {
369
14/18
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 62 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 25 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 34 times.
✓ Branch 14 taken 33 times.
✓ Branch 16 taken 16 times.
✓ Branch 17 taken 16 times.
✓ Branch 19 taken 27 times.
✓ Branch 20 taken 27 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 25 taken 8 times.
✓ Branch 26 taken 8 times.
345 for (auto leaf = range.begin(); leaf; ++leaf) {
370 308 AttributeHandle<ValueT, CodecT> handle(leaf->constAttributeArray(idx));
371
7/18
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 33 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 16 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 27 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 8 times.
209 if (handle.size() == 0) continue;
372 if (filter.state() == index::ALL) {
373
12/24
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 55 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 33 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 24 taken 32 times.
✓ Branch 26 taken 16 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 16 times.
113 const size_t size = handle.isUniform() ? 1 : handle.size();
374
3/8
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
113 ExtentOp op(handle.get(0));
375
9/12
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 33 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 16 times.
183 for (size_t i = 1; i < size; ++i) {
376
4/12
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
70 assert(i < size_t(std::numeric_limits<Index>::max()));
377
4/14
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
133 op(handle.get(Index(i)));
378 }
379
7/12
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✓ Branch 9 taken 24 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 16 times.
113 if (!values.empty()) {
380
4/12
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 9 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
57 values[leaf.pos()].reset(new typename ExtentOp::ExtentT(op.get()));
381 }
382
8/12
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 23 times.
✓ Branch 11 taken 10 times.
✓ Branch 12 taken 12 times.
✓ Branch 13 taken 4 times.
113 if (in.data) op(in.ext);
383 113 in.data = true;
384 in.ext = op.get();
385 }
386 else {
387 auto iter = leaf->beginIndexOn(filter);
388
6/12
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
59 if (!iter) continue;
389
2/6
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
22 ExtentOp op(handle.get(*iter));
390
2/6
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
22 ++iter;
391
7/22
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 4 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
28 for (; iter; ++iter) op(handle.get(*iter));
392
3/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
22 if (!values.empty()) {
393
1/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
6 values[leaf.pos()].reset(new typename ExtentOp::ExtentT(op.get()));
394 }
395
4/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
22 if (in.data) op(in.ext);
396
2/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
22 in.data = true;
397 in.ext = op.get();
398 }
399 }
400
401 172 return in;
402 },
403 18 [](const ResultType& a, const ResultType& b) -> ResultType {
404
7/18
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
18 if (!b.data) return a;
405
5/18
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
16 if (!a.data) return b;
406 3 ExtentOp op(a.ext); op(b.ext);
407 3 ResultType t;
408 t.ext = op.get();
409 16 t.data = true;
410 16 return t;
411 });
412
413 // set minmax trees only if a new value was set - if the value
414 // hasn't changed, leave it as inactive background (this is
415 // only possible if a point leaf exists with no points or if a
416 // filter is provided but is not hit for a given leaf)
417
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 13 times.
78 if (minTree || maxTree) {
418
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
129 manager.foreach([minTree, maxTree, &values]
419 (const auto& leaf, const size_t idx) {
420 const auto& v = values[idx];
421
9/18
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
75 if (v == nullptr) return;
422 const Coord& origin = leaf.origin();
423
7/18
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 45 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
63 if (minTree) minTree->addTile(1, origin, v->first, true);
424
7/18
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 45 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
63 if (maxTree) maxTree->addTile(1, origin, v->second, true);
425 }, false);
426 }
427
428
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 3 times.
78 if (result.data) ext = result.ext;
429 return result.data;
430 }
431
432 template <typename ValueT,
433 typename CodecT,
434 typename FilterT,
435 typename PointDataTreeT,
436 typename std::enable_if<ValueTraits<ValueT>::IsVec, int>::type = 0>
437 6 bool evalExtents(const PointDataTreeT& points,
438 const std::string& attribute,
439 ValueT& min,
440 ValueT& max,
441 const FilterT& filter,
442 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree,
443 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree)
444 {
445
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
36 typename ComponentExtent<ValueT>::ExtentT ext;
446 const bool s = evalExtents<ValueT, CodecT, FilterT,
447 ComponentExtent<ValueT>, PointDataTreeT>
448 6 (points, attribute, ext, filter, minTree, maxTree);
449
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 if (s) min = ext.first, max = ext.second;
450 6 return s;
451 }
452
453 template <typename ValueT,
454 typename CodecT,
455 typename FilterT,
456 typename PointDataTreeT,
457 typename std::enable_if<!ValueTraits<ValueT>::IsVec, int>::type = 0>
458 82 bool evalExtents(const PointDataTreeT& points,
459 const std::string& attribute,
460 ValueT& min,
461 ValueT& max,
462 const FilterT& filter,
463 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree,
464 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree)
465 {
466 82 typename ScalarMinMax<ValueT>::ExtentT ext;
467 const bool s = evalExtents<ValueT, CodecT, FilterT,
468 ScalarMinMax<ValueT>, PointDataTreeT>
469 82 (points, attribute, ext, filter, minTree, maxTree);
470
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
80 if (s) min = ext.first, max = ext.second;
471 80 return s;
472 }
473
474 } // namespace statistics_internal
475
476 template <typename ValueT,
477 typename CodecT,
478 typename FilterT,
479 typename PointDataTreeT>
480 60 bool evalMinMax(const PointDataTreeT& points,
481 const std::string& attribute,
482 ValueT& min,
483 ValueT& max,
484 const FilterT& filter,
485 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree,
486 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree)
487 {
488 return statistics_internal::evalExtents<ValueT, CodecT, FilterT, PointDataTreeT>
489 60 (points, attribute, min, max, filter, minTree, maxTree);
490 }
491
492 template <typename ValueT,
493 typename CodecT,
494 typename FilterT,
495 typename PointDataTreeT,
496 typename ResultTreeT>
497 46 bool evalAverage(const PointDataTreeT& points,
498 const std::string& attribute,
499 typename ConvertElementType<ValueT, double>::Type& average,
500 const FilterT& filter,
501 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* averageTree)
502 {
503 using ResultT = typename ConvertElementType<ValueT, double>::Type;
504
505 struct Sample
506 {
507 40 Sample(const ResultT& _avg, size_t _size) : avg(_avg), size(_size) {}
508
509 11 void add(const ResultT& val)
510 {
511 54 ++size;
512 43 const ResultT delta = val - avg;
513 54 avg = avg + (delta / static_cast<double>(size));
514 }
515
516 24 void add(const Sample& other)
517 {
518 24 assert(other.size > 0);
519 24 const double denom = 1.0 / static_cast<double>(size + other.size);
520 18 const ResultT delta = other.avg - avg;
521 24 avg = avg + (denom * delta * static_cast<double>(other.size));
522 24 size += other.size;
523 }
524
525 ResultT avg; size_t size;
526 };
527
528 static_assert(std::is_base_of<TreeBase, PointDataTreeT>::value,
529 "PointDataTreeT in instantiation of evalAverage is not an openvdb Tree type");
530 static_assert(std::is_constructible<ResultT, ValueT>::value,
531 "Target value in points::evalAverage is not constructible from the source value type.");
532
533 92 tree::LeafManager<const PointDataTreeT> manager(points);
534
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2 times.
46 if (manager.leafCount() == 0) return false;
535
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
42 const size_t idx = manager.leaf(0).attributeSet().find(attribute);
536
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1 times.
42 if (idx == AttributeSet::INVALID_POS) return false;
537
538 38 std::vector<std::unique_ptr<Sample>> values;
539
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
40 values.resize(manager.leafCount());
540
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 1 times.
40 tbb::parallel_for(manager.leafRange(),
541 149 [idx, &filter, &values] (const auto& range) {
542
12/12
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 13 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 6 times.
✓ Branch 10 taken 9 times.
✓ Branch 11 taken 9 times.
✓ Branch 13 taken 6 times.
✓ Branch 14 taken 6 times.
✓ Branch 16 taken 3 times.
✓ Branch 17 taken 3 times.
91 for (auto leaf = range.begin(); leaf; ++leaf) {
543 86 AttributeHandle<ValueT, CodecT> handle(leaf->constAttributeArray(idx));
544 45 size_t size = handle.size();
545
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
50 if (size == 0) continue;
546 if (filter.state() == index::ALL) {
547
6/12
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
27 std::unique_ptr<Sample> S(new Sample(ResultT(handle.get(0)), 1));
548
9/12
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 5 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 8 times.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 4 times.
27 if (handle.isUniform()) {
549 2 S->avg = S->avg / static_cast<double>(size);
550 10 S->size = size;
551 }
552 else {
553
6/6
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 4 times.
64 for (size_t i = 1; i < size; ++i) {
554
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
47 assert(i < size_t(std::numeric_limits<Index>::max()));
555
3/6
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
47 S->add(ResultT(handle.get(Index(i))));
556 }
557 }
558 values[leaf.pos()] = std::move(S);
559 }
560 else {
561 auto iter = leaf->beginIndexOn(filter);
562
7/12
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
18 if (!iter) continue;
563
6/14
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
13 std::unique_ptr<Sample> S(new Sample(ResultT(handle.get(*iter)), 1));
564
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
13 ++iter;
565
6/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
20 for (; iter; ++iter, ++size) {
566
6/12
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
7 S->add(ResultT(handle.get(*iter)));
567 }
568 values[leaf.pos()] = std::move(S);
569 }
570 }
571 });
572
573 38 auto iter = values.cbegin();
574
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 16 times.
48 while (iter != values.cend() && !(*iter)) ++iter;
575
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 3 times.
38 if (iter == values.cend()) return false;
576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
32 assert(*iter);
577
578 // serial deterministic reduction of floating point samples
579 32 Sample S = **iter;
580 ++iter;
581
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
80 for (; iter != values.cend(); ++iter) {
582
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 if (*iter) S.add(**iter);
583 }
584 32 average = S.avg;
585
586 // set average tree only if a new value was set - if the value
587 // hasn't changed, leave it as inactive background (this is
588 // only possible if a point leaf exists with no points or if a
589 // filter is provided but is not hit for a given leaf)
590
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
32 if (averageTree) {
591
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
13 manager.foreach([averageTree, &values]
592 (const auto& leaf, const size_t idx) {
593 const auto& S = values[idx];
594
3/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
5 if (S == nullptr) return;
595 const Coord& origin = leaf.origin();
596 5 averageTree->addTile(1, origin, S->avg, true);
597 }, false);
598 }
599
600 return true;
601 }
602
603 template <typename ValueT,
604 typename CodecT,
605 typename FilterT,
606 typename PointDataTreeT,
607 typename ResultTreeT>
608 46 bool accumulate(const PointDataTreeT& points,
609 const std::string& attribute,
610 typename PromoteType<ValueT>::Highest& total,
611 const FilterT& filter,
612 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* totalTree)
613 {
614 using ResultT = typename PromoteType<ValueT>::Highest;
615 using ElementT = typename ValueTraits<ResultT>::ElementType;
616
617 static_assert(std::is_base_of<TreeBase, PointDataTreeT>::value,
618 "PointDataTreeT in instantiation of accumulate is not an openvdb Tree type");
619 static_assert(std::is_constructible<ResultT, ValueT>::value,
620 "Target value in points::accumulate is not constructible from the source value type.");
621
622 92 tree::LeafManager<const PointDataTreeT> manager(points);
623
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2 times.
46 if (manager.leafCount() == 0) return false;
624
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
42 const size_t idx = manager.leaf(0).attributeSet().find(attribute);
625
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 2 times.
42 if (idx == AttributeSet::INVALID_POS) return false;
626
627 36 std::vector<std::unique_ptr<ResultT>> values;
628
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
38 values.resize(manager.leafCount());
629
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 1 times.
38 tbb::parallel_for(manager.leafRange(),
630 387 [idx, &filter, &values](const auto& range) {
631
12/12
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 17 times.
✓ Branch 4 taken 49 times.
✓ Branch 5 taken 48 times.
✓ Branch 7 taken 16 times.
✓ Branch 8 taken 16 times.
✓ Branch 10 taken 24 times.
✓ Branch 11 taken 24 times.
✓ Branch 13 taken 10 times.
✓ Branch 14 taken 10 times.
✓ Branch 16 taken 8 times.
✓ Branch 17 taken 8 times.
247 for (auto leaf = range.begin(); leaf; ++leaf) {
632 222 AttributeHandle<ValueT, CodecT> handle(leaf->constAttributeArray(idx));
633
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
148 if (handle.size() == 0) continue;
634 if (filter.state() == index::ALL) {
635
7/12
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 16 times.
✓ Branch 6 taken 48 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 48 times.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 16 times.
81 const size_t size = handle.isUniform() ? 1 : handle.size();
636
3/6
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
81 auto total = ResultT(handle.get(0));
637
4/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 16 times.
88 for (size_t i = 1; i < size; ++i) {
638
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 assert(i < size_t(std::numeric_limits<Index>::max()));
639
1/6
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
7 total += ResultT(handle.get(Index(i)));
640 }
641
3/6
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
81 values[leaf.pos()].reset(new ResultT(total));
642 }
643 else {
644 auto iter = leaf->beginIndexOn(filter);
645
9/12
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
42 if (!iter) continue;
646
3/6
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
17 auto total = ResultT(handle.get(*iter));
647
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
17 ++iter;
648
6/18
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 5 times.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
20 for (; iter; ++iter) total += ResultT(handle.get(*iter));
649
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
17 values[leaf.pos()].reset(new ResultT(total));
650 }
651 }
652 });
653
654 36 auto iter = values.cbegin();
655
4/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 16 times.
62 while (iter != values.cend() && !(*iter)) ++iter;
656
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
36 if (iter == values.cend()) return false;
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
32 assert(*iter);
658
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
32 total = **iter; ++iter;
659
660 if (std::is_integral<ElementT>::value) {
661 using RangeT = tbb::blocked_range<const std::unique_ptr<ResultT>*>;
662 // reasonable grain size for accumulation of single to matrix types
663
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 total = tbb::parallel_reduce(RangeT(&(*iter), (&values.back())+1, 32), total,
664 [](const RangeT& range, ResultT p) -> ResultT {
665
7/16
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 6 times.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
62 for (const auto& r : range) if (r) p += *r;
666 return p;
667 }, std::plus<ResultT>());
668 }
669 else {
670
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 8 times.
96 for (; iter != values.cend(); ++iter) {
671
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
80 if (*iter) total += (**iter);
672 }
673 }
674
675 // set total tree only if a new value was set - if the value
676 // hasn't changed, leave it as inactive background (this is
677 // only possible if a point leaf exists with no points or if a
678 // filter is provided but is not hit for a given leaf)
679
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
32 if (totalTree) {
680
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
18 manager.foreach([totalTree, &values]
681 (const auto& leaf, const size_t idx) {
682 const auto& v = values[idx];
683
3/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
10 if (v == nullptr) return;
684 const Coord& origin = leaf.origin();
685 totalTree->addTile(1, origin, *v, true);
686 }, false);
687 }
688
689 return true;
690 }
691
692 template <typename ValueT,
693 typename CodecT,
694 typename FilterT,
695 typename PointDataTreeT>
696 std::pair<ValueT, ValueT>
697 10 evalMinMax(const PointDataTreeT& points,
698 const std::string& attribute,
699 const FilterT& filter)
700 {
701 std::pair<ValueT, ValueT> results {
702 2 zeroVal<ValueT>(), zeroVal<ValueT>()
703 };
704 evalMinMax<ValueT, CodecT, FilterT, PointDataTreeT>
705 10 (points, attribute, results.first, results.second, filter);
706 10 return results;
707 }
708
709 template <typename ValueT,
710 typename CodecT,
711 typename FilterT,
712 typename PointDataTreeT>
713 typename ConvertElementType<ValueT, double>::Type
714 10 evalAverage(const PointDataTreeT& points,
715 const std::string& attribute,
716 const FilterT& filter)
717 {
718 using ConvertedT = typename ConvertElementType<ValueT, double>::Type;
719 8 ConvertedT result = zeroVal<ConvertedT>();
720 10 evalAverage<ValueT, CodecT, FilterT, PointDataTreeT>(points, attribute, result, filter);
721 10 return result;
722 }
723
724 template <typename ValueT,
725 typename CodecT,
726 typename FilterT,
727 typename PointDataTreeT>
728 typename PromoteType<ValueT>::Highest
729 5 accumulate(const PointDataTreeT& points,
730 const std::string& attribute,
731 const FilterT& filter)
732 {
733 using PromotedT = typename PromoteType<ValueT>::Highest;
734 4 PromotedT result = zeroVal<PromotedT>();
735 5 accumulate<ValueT, CodecT, FilterT, PointDataTreeT>(points, attribute, result, filter);
736 5 return result;
737 }
738
739 } // namespace points
740 } // namespace OPENVDB_VERSION_NAME
741 } // namespace openvdb
742
743 #endif // OPENVDB_POINTS_STATISTICS_HAS_BEEN_INCLUDED
744