GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/points/PointMask.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 71 71 100.0%
Functions: 52 87 59.8%
Branches: 99 226 43.8%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file points/PointMask.h
5 ///
6 /// @author Dan Bailey
7 ///
8 /// @brief Methods for extracting masks from VDB Point grids.
9
10 #ifndef OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
12
13 #include <openvdb/openvdb.h>
14 #include <openvdb/tools/ValueTransformer.h> // valxform::SumOp
15
16 #include "PointDataGrid.h"
17 #include "IndexFilter.h"
18
19 #include <tbb/combinable.h>
20
21 #include <type_traits>
22 #include <vector>
23
24
25 namespace openvdb {
26 OPENVDB_USE_VERSION_NAMESPACE
27 namespace OPENVDB_VERSION_NAME {
28 namespace points {
29
30 /// @brief Extract a Mask Tree from a Point Data Tree
31 /// @param tree the PointDataTree to extract the mask from.
32 /// @param filter an optional index filter
33 /// @param threaded enable or disable threading (threading is enabled by default)
34 template <typename PointDataTreeT,
35 typename MaskTreeT = typename PointDataTreeT::template ValueConverter<bool>::Type,
36 typename FilterT = NullFilter>
37 inline typename std::enable_if<std::is_base_of<TreeBase, PointDataTreeT>::value &&
38 std::is_same<typename MaskTreeT::ValueType, bool>::value, typename MaskTreeT::Ptr>::type
39 convertPointsToMask(const PointDataTreeT& tree,
40 const FilterT& filter = NullFilter(),
41 bool threaded = true);
42
43 /// @brief Extract a Mask Grid from a Point Data Grid
44 /// @param grid the PointDataGrid to extract the mask from.
45 /// @param filter an optional index filter
46 /// @param threaded enable or disable threading (threading is enabled by default)
47 /// @note this method is only available for Bool Grids and Mask Grids
48 template <typename PointDataGridT,
49 typename MaskGridT = typename PointDataGridT::template ValueConverter<bool>::Type,
50 typename FilterT = NullFilter>
51 inline typename std::enable_if<std::is_base_of<GridBase, PointDataGridT>::value &&
52 std::is_same<typename MaskGridT::ValueType, bool>::value, typename MaskGridT::Ptr>::type
53 convertPointsToMask(const PointDataGridT& grid,
54 const FilterT& filter = NullFilter(),
55 bool threaded = true);
56
57 /// @brief Extract a Mask Grid from a Point Data Grid using a new transform
58 /// @param grid the PointDataGrid to extract the mask from.
59 /// @param transform target transform for the mask.
60 /// @param filter an optional index filter
61 /// @param threaded enable or disable threading (threading is enabled by default)
62 /// @note this method is only available for Bool Grids and Mask Grids
63 template <typename PointDataGridT,
64 typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type,
65 typename FilterT = NullFilter>
66 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
67 typename MaskT::Ptr>::type
68 convertPointsToMask(const PointDataGridT& grid,
69 const openvdb::math::Transform& transform,
70 const FilterT& filter = NullFilter(),
71 bool threaded = true);
72
73 /// @brief No-op deformer (adheres to the deformer interface documented in PointMove.h)
74 struct NullDeformer
75 {
76 template <typename LeafT>
77 void reset(LeafT&, size_t /*idx*/ = 0) { }
78
79 template <typename IterT>
80 void apply(Vec3d&, IterT&) const { }
81 };
82
83 /// @brief Deformer Traits for optionally configuring deformers to be applied
84 /// in index-space. The default is world-space.
85 template <typename DeformerT>
86 struct DeformerTraits
87 {
88 static const bool IndexSpace = false;
89 };
90
91
92 ////////////////////////////////////////
93
94 /// @cond OPENVDB_DOCS_INTERNAL
95
96 namespace point_mask_internal {
97
98 template <typename LeafT>
99 82427 void voxelSum(LeafT& leaf, const Index offset, const typename LeafT::ValueType& value)
100 {
101 82427 leaf.modifyValue(offset, tools::valxform::SumOp<typename LeafT::ValueType>(value));
102 82427 }
103
104 // overload PointDataLeaf access to use setOffsetOn(), as modifyValue()
105 // is intentionally disabled to avoid accidental usage
106
107 template <typename T, Index Log2Dim>
108 5495149 void voxelSum(PointDataLeafNode<T, Log2Dim>& leaf, const Index offset,
109 const typename PointDataLeafNode<T, Log2Dim>::ValueType& value)
110 {
111 5495149 leaf.setOffsetOn(offset, leaf.getValue(offset) + value);
112 5495149 }
113
114
115 /// @brief Combines multiple grids into one by stealing leaf nodes and summing voxel values
116 /// This class is designed to work with thread local storage containers such as tbb::combinable
117 template<typename GridT>
118 struct GridCombinerOp
119 {
120 using CombinableT = typename tbb::combinable<GridT>;
121
122 using TreeT = typename GridT::TreeType;
123 using LeafT = typename TreeT::LeafNodeType;
124 using ValueType = typename TreeT::ValueType;
125 using SumOp = tools::valxform::SumOp<typename TreeT::ValueType>;
126
127 48 GridCombinerOp(GridT& grid)
128
12/52
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 5 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 49 taken 3 times.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✓ Branch 76 taken 9 times.
✗ Branch 77 not taken.
48 : mTree(grid.tree()) {}
129
130 100 void operator()(const GridT& grid)
131 {
132
2/2
✓ Branch 0 taken 5613 times.
✓ Branch 1 taken 84 times.
5733 for (auto leaf = grid.tree().beginLeaf(); leaf; ++leaf) {
133 5633 auto* newLeaf = mTree.probeLeaf(leaf->origin());
134
2/2
✓ Branch 0 taken 5328 times.
✓ Branch 1 taken 285 times.
5633 if (!newLeaf) {
135 // if the leaf doesn't yet exist in the new tree, steal it
136 auto& tree = const_cast<GridT&>(grid).tree();
137 7834 mTree.addLeaf(tree.template stealNode<LeafT>(leaf->origin(),
138 10690 zeroVal<ValueType>(), false));
139 }
140 else {
141 // otherwise increment existing values
142
2/2
✓ Branch 0 taken 6244 times.
✓ Branch 1 taken 285 times.
6536 for (auto iter = leaf->cbeginValueOn(); iter; ++iter) {
143 6248 voxelSum(*newLeaf, iter.offset(), ValueType(*iter));
144 }
145 }
146 }
147 100 }
148
149 private:
150 TreeT& mTree;
151 }; // struct GridCombinerOp
152
153
154 /// @brief Compute scalar grid from PointDataGrid while evaluating the point filter
155 template <typename TreeT, typename PointDataTreeT, typename FilterT>
156
10/24
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 5 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 5 times.
✗ Branch 35 not taken.
108 struct PointsToScalarOp
157 {
158 using LeafT = typename TreeT::LeafNodeType;
159 using ValueT = typename LeafT::ValueType;
160 // This method is also used by PointCount so ValueT may not be bool
161 static constexpr bool IsBool =
162 std::is_same<ValueT, bool>::value;
163
164
4/10
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
11 PointsToScalarOp(const PointDataTreeT& tree,
165 const FilterT& filter)
166 : mPointDataAccessor(tree)
167 11 , mFilter(filter) {}
168
169 5710 void operator()(LeafT& leaf, size_t /*idx*/) const
170 {
171 // assumes matching topology
172 5710 const auto* const pointLeaf =
173 mPointDataAccessor.probeConstLeaf(leaf.origin());
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2855 times.
5710 assert(pointLeaf);
175
176
2/2
✓ Branch 0 taken 41341 times.
✓ Branch 1 taken 2855 times.
88392 for (auto value = leaf.beginValueOn(); value; ++value) {
177
2/3
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
82682 const auto iter = pointLeaf->beginIndexVoxel(value.getCoord(), mFilter);
178 if (IsBool) {
179
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
16 if (!iter) value.setValueOn(false);
180 }
181 else {
182
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
82666 const Index64 count = points::iterCount(iter);
183
3/4
✓ Branch 0 taken 41330 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
82666 if (count > Index64(0)) value.setValue(ValueT(count));
184
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 else value.setValueOn(false);
185 }
186 }
187 5710 }
188
189 private:
190 const tree::ValueAccessor<const PointDataTreeT> mPointDataAccessor;
191 const FilterT& mFilter;
192 }; // struct PointsToScalarOp
193
194
195 /// @brief Compute scalar grid from PointDataGrid using a different transform
196 /// and while evaluating the point filter
197 template <typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
198 struct PointsToTransformedScalarOp
199 {
200 using PointDataLeafT = typename PointDataGridT::TreeType::LeafNodeType;
201 using ValueT = typename GridT::TreeType::ValueType;
202 using HandleT = AttributeHandle<Vec3f>;
203 using CombinableT = typename GridCombinerOp<GridT>::CombinableT;
204
205 48 PointsToTransformedScalarOp(const math::Transform& targetTransform,
206 const math::Transform& sourceTransform,
207 const FilterT& filter,
208 const DeformerT& deformer,
209 CombinableT& combinable)
210 : mTargetTransform(targetTransform)
211 , mSourceTransform(sourceTransform)
212 , mFilter(filter)
213 , mDeformer(deformer)
214 48 , mCombinable(combinable) { }
215
216 9010 void operator()(const PointDataLeafT& leaf, size_t idx) const
217 {
218
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
4874 DeformerT deformer(mDeformer);
219
220
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
9010 auto& grid = mCombinable.local();
221 auto& countTree = grid.tree();
222 tree::ValueAccessor<typename GridT::TreeType> accessor(countTree);
223
224
1/2
✓ Branch 1 taken 2366 times.
✗ Branch 2 not taken.
4732 deformer.reset(leaf, idx);
225
226
2/4
✓ Branch 1 taken 5916 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5916 times.
✗ Branch 5 not taken.
26954 auto handle = HandleT::create(leaf.constAttributeArray("P"));
227
228
4/5
✓ Branch 0 taken 5571281 times.
✓ Branch 1 taken 5916 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
✓ Branch 4 taken 38 times.
22134298 for (auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
229
230 // extract index-space position
231
232
3/9
✓ Branch 1 taken 5571303 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5571303 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
11062606 Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
233
234 // if deformer is designed to be used in index-space, perform deformation prior
235 // to transforming position to world-space, otherwise perform deformation afterwards
236
237 if (DeformerTraits<DeformerT>::IndexSpace) {
238 deformer.template apply<decltype(iter)>(position, iter);
239
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
26 position = mSourceTransform.indexToWorld(position);
240 }
241 else {
242
2/4
✓ Branch 1 taken 5571290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
11062580 position = mSourceTransform.indexToWorld(position);
243
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
7674268 deformer.template apply<decltype(iter)>(position, iter);
244 }
245
246 // determine coord of target grid
247
248
1/2
✓ Branch 1 taken 5571303 times.
✗ Branch 2 not taken.
11062606 const Coord ijk = mTargetTransform.worldToIndexCellCentered(position);
249
250 // increment count in target voxel
251
252
1/2
✓ Branch 1 taken 5571303 times.
✗ Branch 2 not taken.
11062606 auto* newLeaf = accessor.touchLeaf(ijk);
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5571303 times.
11062606 assert(newLeaf);
254
3/5
✓ Branch 1 taken 5571278 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
11062606 voxelSum(*newLeaf, newLeaf->coordToOffset(ijk), ValueT(1));
255 }
256 9010 }
257
258 private:
259 const openvdb::math::Transform& mTargetTransform;
260 const openvdb::math::Transform& mSourceTransform;
261 const FilterT& mFilter;
262 const DeformerT& mDeformer;
263 CombinableT& mCombinable;
264 }; // struct PointsToTransformedScalarOp
265
266
267 template<typename TreeT, typename PointDataTreeT, typename FilterT>
268
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
34 inline typename TreeT::Ptr convertPointsToScalar(
269 const PointDataTreeT& points,
270 const FilterT& filter,
271 bool threaded = true)
272 {
273 using point_mask_internal::PointsToScalarOp;
274
275 using ValueT = typename TreeT::ValueType;
276
277 // copy the topology from the points tree
278
279
2/4
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
68 typename TreeT::Ptr tree(new TreeT(/*background=*/false));
280 tree->topologyUnion(points);
281
282 // early exit if no leaves
283
284
2/4
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
34 if (points.leafCount() == 0) return tree;
285
286 // early exit if mask and no group logic
287
288 if (std::is_same<ValueT, bool>::value && filter.state() == index::ALL) return tree;
289
290 // evaluate point group filters to produce a subset of the generated mask
291
292
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
44 tree::LeafManager<TreeT> leafManager(*tree);
293
294 if (filter.state() == index::ALL) {
295 NullFilter nullFilter;
296 PointsToScalarOp<TreeT, PointDataTreeT, NullFilter> pointsToScalarOp(
297 points, nullFilter);
298
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
14 leafManager.foreach(pointsToScalarOp, threaded);
299 } else {
300 // build mask from points in parallel only where filter evaluates to true
301 PointsToScalarOp<TreeT, PointDataTreeT, FilterT> pointsToScalarOp(
302 points, filter);
303
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 leafManager.foreach(pointsToScalarOp, threaded);
304 }
305
306 return tree;
307 }
308
309
310 template<typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
311 60 inline typename GridT::Ptr convertPointsToScalar(
312 PointDataGridT& points,
313 const math::Transform& transform,
314 const FilterT& filter,
315 const DeformerT& deformer,
316 bool threaded = true)
317 {
318 using point_mask_internal::PointsToTransformedScalarOp;
319 using point_mask_internal::GridCombinerOp;
320
321 using CombinerOpT = GridCombinerOp<GridT>;
322 using CombinableT = typename GridCombinerOp<GridT>::CombinableT;
323
324 38 typename GridT::Ptr grid = GridT::create();
325
3/8
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
120 grid->setTransform(transform.copy());
326
327 // use the simpler method if the requested transform matches the existing one
328
329 const math::Transform& pointsTransform = points.constTransform();
330
331
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 5 times.
60 if (transform == pointsTransform && std::is_same<NullDeformer, DeformerT>()) {
332 using TreeT = typename GridT::TreeType;
333
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 typename TreeT::Ptr tree =
334 convertPointsToScalar<TreeT>(points.tree(), filter, threaded);
335
2/6
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 grid->setTree(tree);
336 return grid;
337 }
338
339 // early exit if no leaves
340
341
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
56 if (points.constTree().leafCount() == 0) return grid;
342
343 // compute mask grids in parallel using new transform
344
345 CombinableT combiner;
346
347
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
56 tree::LeafManager<typename PointDataGridT::TreeType> leafManager(points.tree());
348
349 if (filter.state() == index::ALL) {
350 NullFilter nullFilter;
351 PointsToTransformedScalarOp<GridT, PointDataGridT, NullFilter, DeformerT> pointsToScalarOp(
352 transform, pointsTransform, nullFilter, deformer, combiner);
353
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
41 leafManager.foreach(pointsToScalarOp, threaded);
354 } else {
355 PointsToTransformedScalarOp<GridT, PointDataGridT, FilterT, DeformerT> pointsToScalarOp(
356 transform, pointsTransform, filter, deformer, combiner);
357
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
15 leafManager.foreach(pointsToScalarOp, threaded);
358 }
359
360 // combine the mask grids into one
361
362 CombinerOpT combineOp(*grid);
363 56 combiner.combine_each(combineOp);
364
365 return grid;
366 }
367
368
369 } // namespace point_mask_internal
370
371 /// @endcond
372
373 ////////////////////////////////////////
374
375
376 template <typename PointDataTreeT, typename MaskTreeT, typename FilterT>
377 inline typename std::enable_if<std::is_base_of<TreeBase, PointDataTreeT>::value &&
378 std::is_same<typename MaskTreeT::ValueType, bool>::value, typename MaskTreeT::Ptr>::type
379 convertPointsToMask(const PointDataTreeT& tree,
380 const FilterT& filter,
381 bool threaded)
382 {
383 return point_mask_internal::convertPointsToScalar<MaskTreeT>(
384
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
6 tree, filter, threaded);
385 }
386
387
388 template<typename PointDataGridT, typename MaskGridT, typename FilterT>
389 inline typename std::enable_if<std::is_base_of<GridBase, PointDataGridT>::value &&
390 std::is_same<typename MaskGridT::ValueType, bool>::value, typename MaskGridT::Ptr>::type
391 10 convertPointsToMask(
392 const PointDataGridT& points,
393 const FilterT& filter,
394 bool threaded)
395 {
396 using PointDataTreeT = typename PointDataGridT::TreeType;
397 using MaskTreeT = typename MaskGridT::TreeType;
398
399 10 typename MaskTreeT::Ptr tree =
400 convertPointsToMask<PointDataTreeT, MaskTreeT, FilterT>
401 (points.tree(), filter, threaded);
402
403
3/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
20 typename MaskGridT::Ptr grid(new MaskGridT(tree));
404
3/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
20 grid->setTransform(points.transform().copy());
405 10 return grid;
406 }
407
408
409 template<typename PointDataGridT, typename MaskT, typename FilterT>
410 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
411 typename MaskT::Ptr>::type
412 convertPointsToMask(
413 const PointDataGridT& points,
414 const openvdb::math::Transform& transform,
415 const FilterT& filter,
416 bool threaded)
417 {
418 // This is safe because the PointDataGrid can only be modified by the deformer
419 using AdapterT = TreeAdapter<typename PointDataGridT::TreeType>;
420 auto& nonConstPoints = const_cast<typename AdapterT::NonConstGridType&>(points);
421
422 NullDeformer deformer;
423 return point_mask_internal::convertPointsToScalar<MaskT>(
424
4/8
✓ Branch 1 taken 1 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 taken 1 times.
✗ Branch 11 not taken.
4 nonConstPoints, transform, filter, deformer, threaded);
425 }
426
427
428 ////////////////////////////////////////
429
430
431 } // namespace points
432 } // namespace OPENVDB_VERSION_NAME
433 } // namespace openvdb
434
435 #endif // OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
436