GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/Grid.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 178 203 87.7%
Functions: 502 1710 29.4%
Branches: 270 686 39.4%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 #ifndef OPENVDB_GRID_HAS_BEEN_INCLUDED
5 #define OPENVDB_GRID_HAS_BEEN_INCLUDED
6
7 #include "Exceptions.h"
8 #include "MetaMap.h"
9 #include "Types.h"
10 #include "io/io.h"
11 #include "math/Transform.h"
12 #include "tree/Tree.h"
13 #include "util/logging.h"
14 #include "util/Name.h"
15 #include <cassert>
16 #include <iostream>
17 #include <set>
18 #include <type_traits>
19 #include <vector>
20
21
22 namespace openvdb {
23 OPENVDB_USE_VERSION_NAMESPACE
24 namespace OPENVDB_VERSION_NAME {
25
26 using TreeBase = tree::TreeBase;
27
28 template<typename> class Grid; // forward declaration
29
30
31 /// @brief Create a new grid of type @c GridType with a given background value.
32 ///
33 /// @note Calling createGrid<GridType>(background) is equivalent to calling
34 /// GridType::create(background).
35 template<typename GridType>
36 inline typename GridType::Ptr createGrid(const typename GridType::ValueType& background);
37
38
39 /// @brief Create a new grid of type @c GridType with background value zero.
40 ///
41 /// @note Calling createGrid<GridType>() is equivalent to calling GridType::create().
42 template<typename GridType>
43 inline typename GridType::Ptr createGrid();
44
45
46 /// @brief Create a new grid of the appropriate type that wraps the given tree.
47 ///
48 /// @note This function can be called without specifying the template argument,
49 /// i.e., as createGrid(tree).
50 template<typename TreePtrType>
51 inline typename Grid<typename TreePtrType::element_type>::Ptr createGrid(TreePtrType);
52
53
54 /// @brief Create a new grid of type @c GridType classified as a "Level Set",
55 /// i.e., a narrow-band level set.
56 ///
57 /// @note @c GridType::ValueType must be a floating-point scalar.
58 ///
59 /// @param voxelSize the size of a voxel in world units
60 /// @param halfWidth the half width of the narrow band in voxel units
61 ///
62 /// @details The voxel size and the narrow band half width define the grid's
63 /// background value as halfWidth*voxelWidth. The transform is linear
64 /// with a uniform scaling only corresponding to the specified voxel size.
65 ///
66 /// @note It is generally advisable to specify a half-width of the narrow band
67 /// that is larger than one voxel unit, otherwise zero crossings are not guaranteed.
68 template<typename GridType>
69 typename GridType::Ptr createLevelSet(
70 Real voxelSize = 1.0, Real halfWidth = LEVEL_SET_HALF_WIDTH);
71
72
73 ////////////////////////////////////////
74
75
76 /// @brief Abstract base class for typed grids
77 class OPENVDB_API GridBase: public MetaMap
78 {
79 public:
80 using Ptr = SharedPtr<GridBase>;
81 using ConstPtr = SharedPtr<const GridBase>;
82
83 using GridFactory = Ptr (*)();
84
85
86
1/2
✓ Branch 0 taken 26663 times.
✗ Branch 1 not taken.
53326 ~GridBase() override {}
87
88
89 /// @name Copying
90 /// @{
91
92 /// @brief Return a new grid of the same type as this grid whose metadata is a
93 /// deep copy of this grid's and whose tree and transform are shared with this grid.
94 virtual GridBase::Ptr copyGrid() = 0;
95 /// @brief Return a new grid of the same type as this grid whose metadata is a
96 /// deep copy of this grid's and whose tree and transform are shared with this grid.
97 virtual GridBase::ConstPtr copyGrid() const = 0;
98 /// @brief Return a new grid of the same type as this grid whose metadata and
99 /// transform are deep copies of this grid's and whose tree is default-constructed.
100 virtual GridBase::Ptr copyGridWithNewTree() const = 0;
101
102 /// @brief Return a new grid of the same type as this grid whose tree and transform
103 /// is shared with this grid and whose metadata is provided as an argument.
104 virtual GridBase::ConstPtr copyGridReplacingMetadata(const MetaMap& meta) const = 0;
105 /// @brief Return a new grid of the same type as this grid whose tree is shared with
106 /// this grid, whose metadata is a deep copy of this grid's and whose transform is
107 /// provided as an argument.
108 /// @throw ValueError if the transform pointer is null
109 virtual GridBase::ConstPtr copyGridReplacingTransform(math::Transform::Ptr xform) const = 0;
110 /// @brief Return a new grid of the same type as this grid whose tree is shared with
111 /// this grid and whose transform and metadata are provided as arguments.
112 /// @throw ValueError if the transform pointer is null
113 virtual GridBase::ConstPtr copyGridReplacingMetadataAndTransform(const MetaMap& meta,
114 math::Transform::Ptr xform) const = 0;
115
116 /// Return a new grid whose metadata, transform and tree are deep copies of this grid's.
117 virtual GridBase::Ptr deepCopyGrid() const = 0;
118
119 /// @}
120
121
122 /// @name Registry
123 /// @{
124
125 /// Create a new grid of the given (registered) type.
126 static Ptr createGrid(const Name& type);
127
128 /// Return @c true if the given grid type name is registered.
129 static bool isRegistered(const Name &type);
130
131 /// Clear the grid type registry.
132 static void clearRegistry();
133
134 /// @}
135
136 /// @name Type access
137 /// @{
138
139 /// Return the name of this grid's type.
140 virtual Name type() const = 0;
141 /// Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
142 virtual Name valueType() const = 0;
143
144 /// Return @c true if this grid is of the same type as the template parameter.
145 template<typename GridType>
146
1/2
✓ Branch 2 taken 144768 times.
✗ Branch 3 not taken.
289493 bool isType() const { return (this->type() == GridType::gridType()); }
147
148 /// @}
149
150 //@{
151 /// @brief Return the result of downcasting a GridBase pointer to a Grid pointer
152 /// of the specified type, or return a null pointer if the types are incompatible.
153 template<typename GridType>
154 static typename GridType::Ptr grid(const GridBase::Ptr&);
155 template<typename GridType>
156 static typename GridType::ConstPtr grid(const GridBase::ConstPtr&);
157 template<typename GridType>
158 static typename GridType::ConstPtr constGrid(const GridBase::Ptr&);
159 template<typename GridType>
160 static typename GridType::ConstPtr constGrid(const GridBase::ConstPtr&);
161 //@}
162
163 /// @name Tree
164 /// @{
165
166 /// @brief Return a pointer to this grid's tree, which might be
167 /// shared with other grids. The pointer is guaranteed to be non-null.
168 TreeBase::Ptr baseTreePtr();
169 /// @brief Return a pointer to this grid's tree, which might be
170 /// shared with other grids. The pointer is guaranteed to be non-null.
171
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 TreeBase::ConstPtr baseTreePtr() const { return this->constBaseTreePtr(); }
172 /// @brief Return a pointer to this grid's tree, which might be
173 /// shared with other grids. The pointer is guaranteed to be non-null.
174 virtual TreeBase::ConstPtr constBaseTreePtr() const = 0;
175
176 #if OPENVDB_ABI_VERSION_NUMBER >= 8
177 /// @brief Return true if tree is not shared with another grid.
178 virtual bool isTreeUnique() const = 0;
179 #endif
180
181 /// @brief Return a reference to this grid's tree, which might be
182 /// shared with other grids.
183 /// @note Calling @vdblink::GridBase::setTree() setTree@endlink
184 /// on this grid invalidates all references previously returned by this method.
185
24/48
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 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 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 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 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 1 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
28 TreeBase& baseTree() { return const_cast<TreeBase&>(this->constBaseTree()); }
186 /// @brief Return a reference to this grid's tree, which might be
187 /// shared with other grids.
188 /// @note Calling @vdblink::GridBase::setTree() setTree@endlink
189 /// on this grid invalidates all references previously returned by this method.
190
1/2
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
154 const TreeBase& baseTree() const { return this->constBaseTree(); }
191 /// @brief Return a reference to this grid's tree, which might be
192 /// shared with other grids.
193 /// @note Calling @vdblink::GridBase::setTree() setTree@endlink
194 /// on this grid invalidates all references previously returned by this method.
195 182 const TreeBase& constBaseTree() const { return *(this->constBaseTreePtr()); }
196
197 /// @brief Associate the given tree with this grid, in place of its existing tree.
198 /// @throw ValueError if the tree pointer is null
199 /// @throw TypeError if the tree is not of the appropriate type
200 /// @note Invalidates all references previously returned by
201 /// @vdblink::GridBase::baseTree() baseTree@endlink
202 /// or @vdblink::GridBase::constBaseTree() constBaseTree@endlink.
203 virtual void setTree(TreeBase::Ptr) = 0;
204
205 /// Set a new tree with the same background value as the previous tree.
206 virtual void newTree() = 0;
207
208 /// @}
209
210 /// Return @c true if this grid contains only background voxels.
211 virtual bool empty() const = 0;
212 /// Empty this grid, setting all voxels to the background.
213 virtual void clear() = 0;
214
215
216 /// @name Tools
217 /// @{
218
219 /// @brief Reduce the memory footprint of this grid by increasing its sparseness
220 /// either losslessly (@a tolerance = 0) or lossily (@a tolerance > 0).
221 /// @details With @a tolerance > 0, sparsify regions where voxels have the same
222 /// active state and have values that differ by no more than the tolerance
223 /// (converted to this grid's value type).
224 virtual void pruneGrid(float tolerance = 0.0) = 0;
225
226 /// @brief Clip this grid to the given world-space bounding box.
227 /// @details Voxels that lie outside the bounding box are set to the background.
228 /// @warning Clipping a level set will likely produce a grid that is
229 /// no longer a valid level set.
230 void clipGrid(const BBoxd&);
231
232 /// @brief Clip this grid to the given index-space bounding box.
233 /// @details Voxels that lie outside the bounding box are set to the background.
234 /// @warning Clipping a level set will likely produce a grid that is
235 /// no longer a valid level set.
236 virtual void clip(const CoordBBox&) = 0;
237
238 /// @}
239
240 /// @{
241 /// @brief If this grid resolves to one of the listed grid types,
242 /// invoke the given functor on the resolved grid.
243 /// @return @c false if this grid's type is not one of the listed types
244 ///
245 /// @par Example:
246 /// @code
247 /// using AllowedGridTypes = openvdb::TypeList<
248 /// openvdb::Int32Grid, openvdb::Int64Grid,
249 /// openvdb::FloatGrid, openvdb::DoubleGrid>;
250 ///
251 /// const openvdb::CoordBBox bbox{
252 /// openvdb::Coord{0,0,0}, openvdb::Coord{10,10,10}};
253 ///
254 /// // Fill the grid if it is one of the allowed types.
255 /// myGridBasePtr->apply<AllowedGridTypes>(
256 /// [&bbox](auto& grid) { // C++14
257 /// using GridType = typename std::decay<decltype(grid)>::type;
258 /// grid.fill(bbox, typename GridType::ValueType(1));
259 /// }
260 /// );
261 /// @endcode
262 ///
263 /// @see @vdblink::TypeList TypeList@endlink
264 template<typename GridTypeListT, typename OpT> inline bool apply(OpT&) const;
265 template<typename GridTypeListT, typename OpT> inline bool apply(OpT&);
266 template<typename GridTypeListT, typename OpT> inline bool apply(const OpT&) const;
267 template<typename GridTypeListT, typename OpT> inline bool apply(const OpT&);
268 /// @}
269
270 /// @name Metadata
271 /// @{
272
273 /// Return this grid's user-specified name.
274 std::string getName() const;
275 /// Specify a name for this grid.
276 void setName(const std::string&);
277
278 /// Return the user-specified description of this grid's creator.
279 std::string getCreator() const;
280 /// Provide a description of this grid's creator.
281 void setCreator(const std::string&);
282
283 /// @brief Return @c true if this grid should be written out with floating-point
284 /// voxel values (including components of vectors) quantized to 16 bits.
285 bool saveFloatAsHalf() const;
286 void setSaveFloatAsHalf(bool);
287
288 /// @brief Return the class of volumetric data (level set, fog volume, etc.)
289 /// that is stored in this grid.
290 /// @sa gridClassToString, gridClassToMenuName, stringToGridClass
291 GridClass getGridClass() const;
292 /// @brief Specify the class of volumetric data (level set, fog volume, etc.)
293 /// that is stored in this grid.
294 /// @sa gridClassToString, gridClassToMenuName, stringToGridClass
295 void setGridClass(GridClass);
296 /// Remove the setting specifying the class of this grid's volumetric data.
297 void clearGridClass();
298
299 /// @}
300
301 /// Return the metadata string value for the given class of volumetric data.
302 static std::string gridClassToString(GridClass);
303 /// Return a formatted string version of the grid class.
304 static std::string gridClassToMenuName(GridClass);
305 /// @brief Return the class of volumetric data specified by the given string.
306 /// @details If the string is not one of the ones returned by
307 /// @vdblink::GridBase::gridClassToString() gridClassToString@endlink,
308 /// return @c GRID_UNKNOWN.
309 static GridClass stringToGridClass(const std::string&);
310
311 /// @name Metadata
312 /// @{
313
314 /// @brief Return the type of vector data (invariant, covariant, etc.) stored
315 /// in this grid, assuming that this grid contains a vector-valued tree.
316 /// @sa vecTypeToString, vecTypeExamples, vecTypeDescription, stringToVecType
317 VecType getVectorType() const;
318 /// @brief Specify the type of vector data (invariant, covariant, etc.) stored
319 /// in this grid, assuming that this grid contains a vector-valued tree.
320 /// @sa vecTypeToString, vecTypeExamples, vecTypeDescription, stringToVecType
321 void setVectorType(VecType);
322 /// Remove the setting specifying the type of vector data stored in this grid.
323 void clearVectorType();
324
325 /// @}
326
327 /// Return the metadata string value for the given type of vector data.
328 static std::string vecTypeToString(VecType);
329 /// Return a string listing examples of the given type of vector data
330 /// (e.g., "Gradient/Normal", given VEC_COVARIANT).
331 static std::string vecTypeExamples(VecType);
332 /// @brief Return a string describing how the given type of vector data is affected
333 /// by transformations (e.g., "Does not transform", given VEC_INVARIANT).
334 static std::string vecTypeDescription(VecType);
335 static VecType stringToVecType(const std::string&);
336
337 /// @name Metadata
338 /// @{
339
340 /// Return @c true if this grid's voxel values are in world space and should be
341 /// affected by transformations, @c false if they are in local space and should
342 /// not be affected by transformations.
343 bool isInWorldSpace() const;
344 /// Specify whether this grid's voxel values are in world space or in local space.
345 void setIsInWorldSpace(bool);
346
347 /// @}
348
349 // Standard metadata field names
350 // (These fields should normally not be accessed directly, but rather
351 // via the accessor methods above, when available.)
352 // Note: Visual C++ requires these declarations to be separate statements.
353 static const char* const META_GRID_CLASS;
354 static const char* const META_GRID_CREATOR;
355 static const char* const META_GRID_NAME;
356 static const char* const META_SAVE_HALF_FLOAT;
357 static const char* const META_IS_LOCAL_SPACE;
358 static const char* const META_VECTOR_TYPE;
359 static const char* const META_FILE_BBOX_MIN;
360 static const char* const META_FILE_BBOX_MAX;
361 static const char* const META_FILE_COMPRESSION;
362 static const char* const META_FILE_MEM_BYTES;
363 static const char* const META_FILE_VOXEL_COUNT;
364 static const char* const META_FILE_DELAYED_LOAD;
365
366
367 /// @name Statistics
368 /// @{
369
370 /// Return the number of active voxels.
371 virtual Index64 activeVoxelCount() const = 0;
372
373 /// Return the axis-aligned bounding box of all active voxels. If
374 /// the grid is empty a default bbox is returned.
375 virtual CoordBBox evalActiveVoxelBoundingBox() const = 0;
376
377 /// Return the dimensions of the axis-aligned bounding box of all active voxels.
378 virtual Coord evalActiveVoxelDim() const = 0;
379
380 /// Return the number of bytes of memory used by this grid.
381 virtual Index64 memUsage() const = 0;
382
383 /// @brief Add metadata to this grid comprising the current values
384 /// of statistics like the active voxel count and bounding box.
385 /// @note This metadata is not automatically kept up-to-date with
386 /// changes to this grid.
387 void addStatsMetadata();
388 /// @brief Return a new MetaMap containing just the metadata that
389 /// was added to this grid with @vdblink::GridBase::addStatsMetadata()
390 /// addStatsMetadata@endlink.
391 /// @details If @vdblink::GridBase::addStatsMetadata() addStatsMetadata@endlink
392 /// was never called on this grid, return an empty MetaMap.
393 MetaMap::Ptr getStatsMetadata() const;
394
395 /// @}
396
397
398 /// @name Transform
399 /// @{
400
401 //@{
402 /// @brief Return a pointer to this grid's transform, which might be
403 /// shared with other grids.
404 math::Transform::Ptr transformPtr() { return mTransform; }
405 math::Transform::ConstPtr transformPtr() const { return mTransform; }
406 math::Transform::ConstPtr constTransformPtr() const { return mTransform; }
407 //@}
408 //@{
409 /// @brief Return a reference to this grid's transform, which might be
410 /// shared with other grids.
411 /// @note Calling @vdblink::GridBase::setTransform() setTransform@endlink
412 /// on this grid invalidates all references previously returned by this method.
413 math::Transform& transform() { return *mTransform; }
414 const math::Transform& transform() const { return *mTransform; }
415 const math::Transform& constTransform() const { return *mTransform; }
416 //@}
417
418 /// @}
419
420 /// @name Transform
421 /// @{
422
423 /// @brief Associate the given transform with this grid, in place of
424 /// its existing transform.
425 /// @throw ValueError if the transform pointer is null
426 /// @note Invalidates all references previously returned by
427 /// @vdblink::GridBase::transform() transform@endlink
428 /// or @vdblink::GridBase::constTransform() constTransform@endlink.
429 void setTransform(math::Transform::Ptr);
430
431 /// Return the size of this grid's voxels.
432 298886 Vec3d voxelSize() const { return transform().voxelSize(); }
433 /// @brief Return the size of this grid's voxel at position (x, y, z).
434 /// @note Frustum and perspective transforms have position-dependent voxel size.
435 1 Vec3d voxelSize(const Vec3d& xyz) const { return transform().voxelSize(xyz); }
436 /// Return true if the voxels in world space are uniformly sized cubes
437 bool hasUniformVoxels() const { return mTransform->hasUniformScale(); }
438 /// Apply this grid's transform to the given coordinates.
439 122169 Vec3d indexToWorld(const Vec3d& xyz) const { return transform().indexToWorld(xyz); }
440 /// Apply this grid's transform to the given coordinates.
441 Vec3d indexToWorld(const Coord& ijk) const { return transform().indexToWorld(ijk); }
442 /// Apply the inverse of this grid's transform to the given coordinates.
443 2 Vec3d worldToIndex(const Vec3d& xyz) const { return transform().worldToIndex(xyz); }
444
445 /// @}
446
447
448 /// @name I/O
449 /// @{
450
451 /// @brief Read the grid topology from a stream.
452 /// This will read only the grid structure, not the actual data buffers.
453 virtual void readTopology(std::istream&) = 0;
454 /// @brief Write the grid topology to a stream.
455 /// This will write only the grid structure, not the actual data buffers.
456 virtual void writeTopology(std::ostream&) const = 0;
457
458 /// Read all data buffers for this grid.
459 virtual void readBuffers(std::istream&) = 0;
460 /// Read all of this grid's data buffers that intersect the given index-space bounding box.
461 virtual void readBuffers(std::istream&, const CoordBBox&) = 0;
462 /// @brief Read all of this grid's data buffers that are not yet resident in memory
463 /// (because delayed loading is in effect).
464 /// @details If this grid was read from a memory-mapped file, this operation
465 /// disconnects the grid from the file.
466 /// @sa io::File::open, io::MappedFile
467 virtual void readNonresidentBuffers() const = 0;
468 /// Write out all data buffers for this grid.
469 virtual void writeBuffers(std::ostream&) const = 0;
470
471 /// Read in the transform for this grid.
472
5/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 121 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
134 void readTransform(std::istream& is) { transform().read(is); }
473 /// Write out the transform for this grid.
474
1/2
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
163 void writeTransform(std::ostream& os) const { transform().write(os); }
475
476 /// Output a human-readable description of this grid.
477 virtual void print(std::ostream& = std::cout, int verboseLevel = 1) const = 0;
478
479 /// @}
480
481
482 protected:
483 /// @brief Initialize with an identity linear transform.
484
1/2
✓ Branch 1 taken 24348 times.
✗ Branch 2 not taken.
24348 GridBase(): mTransform(math::Transform::createLinearTransform()) {}
485
486 /// @brief Initialize with metadata and a transform.
487 /// @throw ValueError if the transform pointer is null
488 GridBase(const MetaMap& meta, math::Transform::Ptr xform);
489
490 /// @brief Deep copy another grid's metadata and transform.
491
1/2
✓ Branch 2 taken 2314 times.
✗ Branch 3 not taken.
2314 GridBase(const GridBase& other): MetaMap(other), mTransform(other.mTransform->copy()) {}
492
493 /// @brief Copy another grid's metadata but share its transform.
494 GridBase(GridBase& other, ShallowCopy): MetaMap(other), mTransform(other.mTransform) {}
495
496 /// Register a grid type along with a factory function.
497 static void registerGrid(const Name& type, GridFactory);
498 /// Remove a grid type from the registry.
499 static void unregisterGrid(const Name& type);
500
501
502 private:
503 math::Transform::Ptr mTransform;
504 }; // class GridBase
505
506
507 ////////////////////////////////////////
508
509
510 using GridPtrVec = std::vector<GridBase::Ptr>;
511 using GridPtrVecIter = GridPtrVec::iterator;
512 using GridPtrVecCIter = GridPtrVec::const_iterator;
513 using GridPtrVecPtr = SharedPtr<GridPtrVec>;
514
515 using GridCPtrVec = std::vector<GridBase::ConstPtr>;
516 using GridCPtrVecIter = GridCPtrVec::iterator;
517 using GridCPtrVecCIter = GridCPtrVec::const_iterator;
518 using GridCPtrVecPtr = SharedPtr<GridCPtrVec>;
519
520 using GridPtrSet = std::set<GridBase::Ptr>;
521 using GridPtrSetIter = GridPtrSet::iterator;
522 using GridPtrSetCIter = GridPtrSet::const_iterator;
523 using GridPtrSetPtr = SharedPtr<GridPtrSet>;
524
525 using GridCPtrSet = std::set<GridBase::ConstPtr>;
526 using GridCPtrSetIter = GridCPtrSet::iterator;
527 using GridCPtrSetCIter = GridCPtrSet::const_iterator;
528 using GridCPtrSetPtr = SharedPtr<GridCPtrSet>;
529
530
531 /// @brief Predicate functor that returns @c true for grids that have a specified name
532 60 struct OPENVDB_API GridNamePred
533 {
534 30 GridNamePred(const Name& _name): name(_name) {}
535
4/6
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
60 bool operator()(const GridBase::ConstPtr& g) const { return g && g->getName() == name; }
536 Name name;
537 };
538
539 /// Return the first grid in the given container whose name is @a name.
540 template<typename GridPtrContainerT>
541 inline typename GridPtrContainerT::value_type
542 30 findGridByName(const GridPtrContainerT& container, const Name& name)
543 {
544 using GridPtrT = typename GridPtrContainerT::value_type;
545 typename GridPtrContainerT::const_iterator it =
546
2/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
60 std::find_if(container.begin(), container.end(), GridNamePred(name));
547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
60 return (it == container.end() ? GridPtrT() : *it);
548 }
549
550 /// Return the first grid in the given map whose name is @a name.
551 template<typename KeyT, typename GridPtrT>
552 inline GridPtrT
553 findGridByName(const std::map<KeyT, GridPtrT>& container, const Name& name)
554 {
555 using GridPtrMapT = std::map<KeyT, GridPtrT>;
556 for (typename GridPtrMapT::const_iterator it = container.begin(), end = container.end();
557 it != end; ++it)
558 {
559 const GridPtrT& grid = it->second;
560 if (grid && grid->getName() == name) return grid;
561 }
562 return GridPtrT();
563 }
564 //@}
565
566
567 ////////////////////////////////////////
568
569
570 /// @brief Container class that associates a tree with a transform and metadata
571 template<typename _TreeType>
572 class Grid: public GridBase
573 {
574 public:
575 using Ptr = SharedPtr<Grid>;
576 using ConstPtr = SharedPtr<const Grid>;
577
578 using TreeType = _TreeType;
579 using TreePtrType = typename _TreeType::Ptr;
580 using ConstTreePtrType = typename _TreeType::ConstPtr;
581 using ValueType = typename _TreeType::ValueType;
582 using BuildType = typename _TreeType::BuildType;
583
584 using ValueOnIter = typename _TreeType::ValueOnIter;
585 using ValueOnCIter = typename _TreeType::ValueOnCIter;
586 using ValueOffIter = typename _TreeType::ValueOffIter;
587 using ValueOffCIter = typename _TreeType::ValueOffCIter;
588 using ValueAllIter = typename _TreeType::ValueAllIter;
589 using ValueAllCIter = typename _TreeType::ValueAllCIter;
590
591 using Accessor = typename tree::ValueAccessor<_TreeType, true>;
592 using ConstAccessor = typename tree::ValueAccessor<const _TreeType, true>;
593 using UnsafeAccessor = typename tree::ValueAccessor<_TreeType, false>;
594 using ConstUnsafeAccessor = typename tree::ValueAccessor<const _TreeType, false>;
595
596 /// @brief ValueConverter<T>::Type is the type of a grid having the same
597 /// hierarchy as this grid but a different value type, T.
598 ///
599 /// For example, FloatGrid::ValueConverter<double>::Type is equivalent to DoubleGrid.
600 /// @note If the source grid type is a template argument, it might be necessary
601 /// to write "typename SourceGrid::template ValueConverter<T>::Type".
602 template<typename OtherValueType>
603 struct ValueConverter {
604 using Type = Grid<typename TreeType::template ValueConverter<OtherValueType>::Type>;
605 };
606
607 /// Return a new grid with the given background value.
608 static Ptr create(const ValueType& background);
609 /// Return a new grid with background value zero.
610 static Ptr create();
611 /// @brief Return a new grid that contains the given tree.
612 /// @throw ValueError if the tree pointer is null
613 static Ptr create(TreePtrType);
614 /// @brief Return a new, empty grid with the same transform and metadata as the
615 /// given grid and with background value zero.
616 static Ptr create(const GridBase& other);
617
618
619 /// Construct a new grid with background value zero.
620 Grid();
621 /// Construct a new grid with the given background value.
622 explicit Grid(const ValueType& background);
623 /// @brief Construct a new grid that shares the given tree and associates with it
624 /// an identity linear transform.
625 /// @throw ValueError if the tree pointer is null
626 explicit Grid(TreePtrType);
627 /// Deep copy another grid's metadata, transform and tree.
628 Grid(const Grid&);
629 /// @brief Deep copy the metadata, transform and tree of another grid whose tree
630 /// configuration is the same as this grid's but whose value type is different.
631 /// Cast the other grid's values to this grid's value type.
632 /// @throw TypeError if the other grid's tree configuration doesn't match this grid's
633 /// or if this grid's ValueType is not constructible from the other grid's ValueType.
634 template<typename OtherTreeType>
635 explicit Grid(const Grid<OtherTreeType>&);
636 /// Deep copy another grid's metadata and transform, but share its tree.
637 Grid(Grid&, ShallowCopy);
638 /// @brief Deep copy another grid's metadata and transform, but construct a new tree
639 /// with background value zero.
640 explicit Grid(const GridBase&);
641
642
1/2
✓ Branch 0 taken 26661 times.
✗ Branch 1 not taken.
158502 ~Grid() override {}
643
644 /// Disallow assignment, since it wouldn't be obvious whether the copy is deep or shallow.
645 Grid& operator=(const Grid&) = delete;
646
647 /// @name Copying
648 /// @{
649
650 /// @brief Return a new grid of the same type as this grid whose metadata and
651 /// transform are deep copies of this grid's and whose tree is shared with this grid.
652 Ptr copy();
653 /// @brief Return a new grid of the same type as this grid whose metadata and
654 /// transform are deep copies of this grid's and whose tree is shared with this grid.
655 ConstPtr copy() const;
656 /// @brief Return a new grid of the same type as this grid whose metadata and
657 /// transform are deep copies of this grid's and whose tree is default-constructed.
658 Ptr copyWithNewTree() const;
659
660 /// @brief Return a new grid of the same type as this grid whose metadata is a
661 /// deep copy of this grid's and whose tree and transform are shared with this grid.
662 GridBase::Ptr copyGrid() override;
663 /// @brief Return a new grid of the same type as this grid whose metadata is a
664 /// deep copy of this grid's and whose tree and transform are shared with this grid.
665 GridBase::ConstPtr copyGrid() const override;
666 /// @brief Return a new grid of the same type as this grid whose metadata and
667 /// transform are deep copies of this grid's and whose tree is default-constructed.
668 GridBase::Ptr copyGridWithNewTree() const override;
669 //@}
670
671 /// @name Copying
672 /// @{
673
674 /// @brief Return a new grid of the same type as this grid whose tree and transform
675 /// is shared with this grid and whose metadata is provided as an argument.
676 ConstPtr copyReplacingMetadata(const MetaMap& meta) const;
677 /// @brief Return a new grid of the same type as this grid whose tree is shared with
678 /// this grid, whose metadata is a deep copy of this grid's and whose transform is
679 /// provided as an argument.
680 /// @throw ValueError if the transform pointer is null
681 ConstPtr copyReplacingTransform(math::Transform::Ptr xform) const;
682 /// @brief Return a new grid of the same type as this grid whose tree is shared with
683 /// this grid and whose transform and metadata are provided as arguments.
684 /// @throw ValueError if the transform pointer is null
685 ConstPtr copyReplacingMetadataAndTransform(const MetaMap& meta,
686 math::Transform::Ptr xform) const;
687
688 /// @brief Return a new grid of the same type as this grid whose tree and transform
689 /// is shared with this grid and whose metadata is provided as an argument.
690 GridBase::ConstPtr copyGridReplacingMetadata(const MetaMap& meta) const override;
691 /// @brief Return a new grid of the same type as this grid whose tree is shared with
692 /// this grid, whose metadata is a deep copy of this grid's and whose transform is
693 /// provided as an argument.
694 /// @throw ValueError if the transform pointer is null
695 GridBase::ConstPtr copyGridReplacingTransform(math::Transform::Ptr xform) const override;
696 /// @brief Return a new grid of the same type as this grid whose tree is shared with
697 /// this grid and whose transform and metadata are provided as arguments.
698 /// @throw ValueError if the transform pointer is null
699 GridBase::ConstPtr copyGridReplacingMetadataAndTransform(const MetaMap& meta,
700 math::Transform::Ptr xform) const override;
701
702 /// @brief Return a new grid whose metadata, transform and tree are deep copies of this grid's.
703
1/2
✓ Branch 2 taken 1671 times.
✗ Branch 3 not taken.
6684 Ptr deepCopy() const { return Ptr(new Grid(*this)); }
704 /// @brief Return a new grid whose metadata, transform and tree are deep copies of this grid's.
705 674 GridBase::Ptr deepCopyGrid() const override { return this->deepCopy(); }
706
707 //@}
708
709
710 /// Return the name of this grid's type.
711 290148 Name type() const override { return this->gridType(); }
712 /// Return the name of this type of grid.
713 588055 static Name gridType() { return TreeType::treeType(); }
714
715 /// Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
716 19930 Name valueType() const override { return tree().valueType(); }
717
718
719 /// @name Voxel access
720 /// @{
721
722 /// @brief Return this grid's background value.
723 /// @note Use tools::changeBackground to efficiently modify the background value.
724 const ValueType& background() const { return mTree->background(); }
725
726 /// Return @c true if this grid contains only inactive background voxels.
727 298 bool empty() const override { return tree().empty(); }
728 /// Empty this grid, so that all voxels become inactive background voxels.
729
6/12
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 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 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
80 void clear() override { tree().clear(); }
730
731 /// @brief Return an accessor that provides random read and write access
732 /// to this grid's voxels.
733 /// @details The accessor is safe in the sense that it is registered with this grid's tree.
734 Accessor getAccessor() { return Accessor(tree()); }
735 /// @brief Return an unsafe accessor that provides random read and write access
736 /// to this grid's voxels.
737 /// @details The accessor is unsafe in the sense that it is not registered
738 /// with this grid's tree. In some rare cases this can give a performance advantage
739 /// over a registered accessor, but it is unsafe if the tree topology is modified.
740 /// @warning Only use this method if you're an expert and know the
741 /// risks of using an unregistered accessor (see tree/ValueAccessor.h)
742 UnsafeAccessor getUnsafeAccessor() { return UnsafeAccessor(tree()); }
743 /// Return an accessor that provides random read-only access to this grid's voxels.
744 ConstAccessor getAccessor() const { return ConstAccessor(tree()); }
745 /// Return an accessor that provides random read-only access to this grid's voxels.
746 11 ConstAccessor getConstAccessor() const { return ConstAccessor(tree()); }
747 /// @brief Return an unsafe accessor that provides random read-only access
748 /// to this grid's voxels.
749 /// @details The accessor is unsafe in the sense that it is not registered
750 /// with this grid's tree. In some rare cases this can give a performance advantage
751 /// over a registered accessor, but it is unsafe if the tree topology is modified.
752 /// @warning Only use this method if you're an expert and know the
753 /// risks of using an unregistered accessor (see tree/ValueAccessor.h)
754 ConstUnsafeAccessor getConstUnsafeAccessor() const { return ConstUnsafeAccessor(tree()); }
755
756 /// Return an iterator over all of this grid's active values (tile and voxel).
757 6 ValueOnIter beginValueOn() { return tree().beginValueOn(); }
758 /// Return an iterator over all of this grid's active values (tile and voxel).
759 ValueOnCIter beginValueOn() const { return tree().cbeginValueOn(); }
760 /// Return an iterator over all of this grid's active values (tile and voxel).
761 76 ValueOnCIter cbeginValueOn() const { return tree().cbeginValueOn(); }
762 /// Return an iterator over all of this grid's inactive values (tile and voxel).
763 12 ValueOffIter beginValueOff() { return tree().beginValueOff(); }
764 /// Return an iterator over all of this grid's inactive values (tile and voxel).
765 ValueOffCIter beginValueOff() const { return tree().cbeginValueOff(); }
766 /// Return an iterator over all of this grid's inactive values (tile and voxel).
767 22 ValueOffCIter cbeginValueOff() const { return tree().cbeginValueOff(); }
768 /// Return an iterator over all of this grid's values (tile and voxel).
769 ValueAllIter beginValueAll() { return tree().beginValueAll(); }
770 /// Return an iterator over all of this grid's values (tile and voxel).
771 3 ValueAllCIter beginValueAll() const { return tree().cbeginValueAll(); }
772 /// Return an iterator over all of this grid's values (tile and voxel).
773 27 ValueAllCIter cbeginValueAll() const { return tree().cbeginValueAll(); }
774
775 /// @}
776
777 /// @name Tools
778 /// @{
779
780 /// @brief Set all voxels within a given axis-aligned box to a constant value.
781 /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box
782 /// @param value the value to which to set voxels within the box
783 /// @param active if true, mark voxels within the box as active,
784 /// otherwise mark them as inactive
785 /// @note This operation generates a sparse, but not always optimally sparse,
786 /// representation of the filled box. Follow fill operations with a prune()
787 /// operation for optimal sparseness.
788 void sparseFill(const CoordBBox& bbox, const ValueType& value, bool active = true);
789 /// @brief Set all voxels within a given axis-aligned box to a constant value.
790 /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box
791 /// @param value the value to which to set voxels within the box
792 /// @param active if true, mark voxels within the box as active,
793 /// otherwise mark them as inactive
794 /// @note This operation generates a sparse, but not always optimally sparse,
795 /// representation of the filled box. Follow fill operations with a prune()
796 /// operation for optimal sparseness.
797 void fill(const CoordBBox& bbox, const ValueType& value, bool active = true);
798
799 /// @brief Set all voxels within a given axis-aligned box to a constant value
800 /// and ensure that those voxels are all represented at the leaf level.
801 /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box.
802 /// @param value the value to which to set voxels within the box.
803 /// @param active if true, mark voxels within the box as active,
804 /// otherwise mark them as inactive.
805 void denseFill(const CoordBBox& bbox, const ValueType& value, bool active = true);
806
807 /// Reduce the memory footprint of this grid by increasing its sparseness.
808 void pruneGrid(float tolerance = 0.0) override;
809
810 /// @brief Clip this grid to the given index-space bounding box.
811 /// @details Voxels that lie outside the bounding box are set to the background.
812 /// @warning Clipping a level set will likely produce a grid that is
813 /// no longer a valid level set.
814 void clip(const CoordBBox&) override;
815
816 /// @brief Efficiently merge another grid into this grid using one of several schemes.
817 /// @details This operation is primarily intended to combine grids that are mostly
818 /// non-overlapping (for example, intermediate grids from computations that are
819 /// parallelized across disjoint regions of space).
820 /// @warning This operation always empties the other grid.
821 void merge(Grid& other, MergePolicy policy = MERGE_ACTIVE_STATES);
822
823 /// @brief Union this grid's set of active values with the active values
824 /// of the other grid, whose value type may be different.
825 /// @details The resulting state of a value is active if the corresponding value
826 /// was already active OR if it is active in the other grid. Also, a resulting
827 /// value maps to a voxel if the corresponding value already mapped to a voxel
828 /// OR if it is a voxel in the other grid. Thus, a resulting value can only
829 /// map to a tile if the corresponding value already mapped to a tile
830 /// AND if it is a tile value in the other grid.
831 ///
832 /// @note This operation modifies only active states, not values.
833 /// Specifically, active tiles and voxels in this grid are not changed, and
834 /// tiles or voxels that were inactive in this grid but active in the other grid
835 /// are marked as active in this grid but left with their original values.
836 template<typename OtherTreeType>
837 void topologyUnion(const Grid<OtherTreeType>& other);
838
839 /// @brief Intersect this grid's set of active values with the active values
840 /// of the other grid, whose value type may be different.
841 /// @details The resulting state of a value is active only if the corresponding
842 /// value was already active AND if it is active in the other tree. Also, a
843 /// resulting value maps to a voxel if the corresponding value
844 /// already mapped to an active voxel in either of the two grids
845 /// and it maps to an active tile or voxel in the other grid.
846 ///
847 /// @note This operation can delete branches of this grid that overlap with
848 /// inactive tiles in the other grid. Also, because it can deactivate voxels,
849 /// it can create leaf nodes with no active values. Thus, it is recommended
850 /// to prune this grid after calling this method.
851 template<typename OtherTreeType>
852 void topologyIntersection(const Grid<OtherTreeType>& other);
853
854 /// @brief Difference this grid's set of active values with the active values
855 /// of the other grid, whose value type may be different.
856 /// @details After this method is called, voxels in this grid will be active
857 /// only if they were active to begin with and if the corresponding voxels
858 /// in the other grid were inactive.
859 ///
860 /// @note This operation can delete branches of this grid that overlap with
861 /// active tiles in the other grid. Also, because it can deactivate voxels,
862 /// it can create leaf nodes with no active values. Thus, it is recommended
863 /// to prune this grid after calling this method.
864 template<typename OtherTreeType>
865 void topologyDifference(const Grid<OtherTreeType>& other);
866
867 /// @}
868
869 /// @name Statistics
870 /// @{
871
872 /// Return the number of active voxels.
873
6/12
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1371 Index64 activeVoxelCount() const override { return tree().activeVoxelCount(); }
874 /// Return the axis-aligned bounding box of all active voxels.
875 CoordBBox evalActiveVoxelBoundingBox() const override;
876 /// Return the dimensions of the axis-aligned bounding box of all active voxels.
877 Coord evalActiveVoxelDim() const override;
878 /// Return the minimum and maximum active values in this grid.
879 OPENVDB_DEPRECATED_MESSAGE("Switch from grid->evalMinMax(minVal, maxVal) to \
880 tools::minMax(grid->tree()). Use threaded = false for serial execution")
881 void evalMinMax(ValueType& minVal, ValueType& maxVal) const;
882
883 /// Return the number of bytes of memory used by this grid.
884 /// @todo Add transform().memUsage()
885 342 Index64 memUsage() const override { return tree().memUsage(); }
886
887 /// @}
888
889
890 /// @name Tree
891 /// @{
892
893 //@{
894 /// @brief Return a pointer to this grid's tree, which might be
895 /// shared with other grids. The pointer is guaranteed to be non-null.
896 TreePtrType treePtr() { return mTree; }
897 ConstTreePtrType treePtr() const { return mTree; }
898 ConstTreePtrType constTreePtr() const { return mTree; }
899 464 TreeBase::ConstPtr constBaseTreePtr() const override { return mTree; }
900 //@}
901 /// @brief Return true if tree is not shared with another grid.
902 /// @note This is a virtual function with ABI=8
903 #if OPENVDB_ABI_VERSION_NUMBER >= 8
904 bool isTreeUnique() const final;
905 #else
906 bool isTreeUnique() const;
907 #endif
908 //@{
909 /// @brief Return a reference to this grid's tree, which might be
910 /// shared with other grids.
911 /// @note Calling setTree() on this grid invalidates all references
912 /// previously returned by this method.
913 TreeType& tree() { return *mTree; }
914 const TreeType& tree() const { return *mTree; }
915 const TreeType& constTree() const { return *mTree; }
916 //@}
917
918 /// @}
919
920 /// @name Tree
921 /// @{
922
923 /// @brief Associate the given tree with this grid, in place of its existing tree.
924 /// @throw ValueError if the tree pointer is null
925 /// @throw TypeError if the tree is not of type TreeType
926 /// @note Invalidates all references previously returned by baseTree(),
927 /// constBaseTree(), tree() or constTree().
928 void setTree(TreeBase::Ptr) override;
929
930 /// @brief Associate a new, empty tree with this grid, in place of its existing tree.
931 /// @note The new tree has the same background value as the existing tree.
932 void newTree() override;
933
934 /// @}
935
936
937 /// @name I/O
938 /// @{
939
940 /// @brief Read the grid topology from a stream.
941 /// This will read only the grid structure, not the actual data buffers.
942 void readTopology(std::istream&) override;
943 /// @brief Write the grid topology to a stream.
944 /// This will write only the grid structure, not the actual data buffers.
945 void writeTopology(std::ostream&) const override;
946
947 /// Read all data buffers for this grid.
948 void readBuffers(std::istream&) override;
949 /// Read all of this grid's data buffers that intersect the given index-space bounding box.
950 void readBuffers(std::istream&, const CoordBBox&) override;
951 /// @brief Read all of this grid's data buffers that are not yet resident in memory
952 /// (because delayed loading is in effect).
953 /// @details If this grid was read from a memory-mapped file, this operation
954 /// disconnects the grid from the file.
955 /// @sa io::File::open, io::MappedFile
956 void readNonresidentBuffers() const override;
957 /// Write out all data buffers for this grid.
958 void writeBuffers(std::ostream&) const override;
959
960 /// Output a human-readable description of this grid.
961 void print(std::ostream& = std::cout, int verboseLevel = 1) const override;
962
963 /// @}
964
965 /// @brief Return @c true if grids of this type require multiple I/O passes
966 /// to read and write data buffers.
967 /// @sa HasMultiPassIO
968 static inline bool hasMultiPassIO();
969
970
971 /// @name Registry
972 /// @{
973
974 /// Return @c true if this grid type is registered.
975
1/2
✓ Branch 2 taken 357 times.
✗ Branch 3 not taken.
772 static bool isRegistered() { return GridBase::isRegistered(Grid::gridType()); }
976 /// Register this grid type along with a factory function.
977
2/2
✓ Branch 2 taken 3909 times.
✓ Branch 3 taken 1 times.
15601 static void registerGrid() { GridBase::registerGrid(Grid::gridType(), Grid::factory); }
978 /// Remove this grid type from the registry.
979
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 static void unregisterGrid() { GridBase::unregisterGrid(Grid::gridType()); }
980
981 /// @}
982
983
984 private:
985 /// Deep copy metadata, but share tree and transform.
986 Grid(TreePtrType tree, const MetaMap& meta, math::Transform::Ptr xform);
987
988 /// Helper function for use with registerGrid()
989 880 static GridBase::Ptr factory() { return Grid::create(); }
990
991 TreePtrType mTree;
992 }; // class Grid
993
994
995 ////////////////////////////////////////
996
997
998 /// @brief Cast a generic grid pointer to a pointer to a grid of a concrete class.
999 ///
1000 /// Return a null pointer if the input pointer is null or if it
1001 /// points to a grid that is not of type @c GridType.
1002 ///
1003 /// @note Calling gridPtrCast<GridType>(grid) is equivalent to calling
1004 /// GridBase::grid<GridType>(grid).
1005 template<typename GridType>
1006 inline typename GridType::Ptr
1007 gridPtrCast(const GridBase::Ptr& grid)
1008 {
1009
29/58
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 19 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 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 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 1 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 1 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 1 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 1 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 1 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 1 times.
✗ Branch 86 not taken.
88 return GridBase::grid<GridType>(grid);
1010 }
1011
1012
1013 /// @brief Cast a generic const grid pointer to a const pointer to a grid
1014 /// of a concrete class.
1015 ///
1016 /// Return a null pointer if the input pointer is null or if it
1017 /// points to a grid that is not of type @c GridType.
1018 ///
1019 /// @note Calling gridConstPtrCast<GridType>(grid) is equivalent to calling
1020 /// GridBase::constGrid<GridType>(grid).
1021 template<typename GridType>
1022 inline typename GridType::ConstPtr
1023 gridConstPtrCast(const GridBase::ConstPtr& grid)
1024 {
1025
3/6
✓ 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.
3 return GridBase::constGrid<GridType>(grid);
1026 }
1027
1028
1029 ////////////////////////////////////////
1030
1031
1032 /// @{
1033 /// @brief Return a pointer to a deep copy of the given grid, provided that
1034 /// the grid's concrete type is @c GridType.
1035 ///
1036 /// Return a null pointer if the input pointer is null or if it
1037 /// points to a grid that is not of type @c GridType.
1038 template<typename GridType>
1039 inline typename GridType::Ptr
1040 deepCopyTypedGrid(const GridBase::ConstPtr& grid)
1041 {
1042 if (!grid || !grid->isType<GridType>()) return typename GridType::Ptr();
1043 return gridPtrCast<GridType>(grid->deepCopyGrid());
1044 }
1045
1046
1047 template<typename GridType>
1048 inline typename GridType::Ptr
1049 deepCopyTypedGrid(const GridBase& grid)
1050 {
1051 if (!grid.isType<GridType>()) return typename GridType::Ptr();
1052 return gridPtrCast<GridType>(grid.deepCopyGrid());
1053 }
1054 /// @}
1055
1056
1057 ////////////////////////////////////////
1058
1059
1060 //@{
1061 /// @brief This adapter allows code that is templated on a Tree type to
1062 /// accept either a Tree type or a Grid type.
1063 template<typename _TreeType>
1064 struct TreeAdapter
1065 {
1066 using TreeType = _TreeType;
1067 using NonConstTreeType = typename std::remove_const<TreeType>::type;
1068 using TreePtrType = typename TreeType::Ptr;
1069 using ConstTreePtrType = typename TreeType::ConstPtr;
1070 using NonConstTreePtrType = typename NonConstTreeType::Ptr;
1071 using GridType = Grid<TreeType>;
1072 using NonConstGridType = Grid<NonConstTreeType>;
1073 using GridPtrType = typename GridType::Ptr;
1074 using NonConstGridPtrType = typename NonConstGridType::Ptr;
1075 using ConstGridPtrType = typename GridType::ConstPtr;
1076 using ValueType = typename TreeType::ValueType;
1077 using AccessorType = typename tree::ValueAccessor<TreeType>;
1078 using ConstAccessorType = typename tree::ValueAccessor<const TreeType>;
1079 using NonConstAccessorType = typename tree::ValueAccessor<NonConstTreeType>;
1080
1081 static TreeType& tree(TreeType& t) { return t; }
1082 static TreeType& tree(GridType& g) { return g.tree(); }
1083 static const TreeType& tree(const TreeType& t) { return t; }
1084 static const TreeType& tree(const GridType& g) { return g.tree(); }
1085 static const TreeType& constTree(TreeType& t) { return t; }
1086 static const TreeType& constTree(GridType& g) { return g.constTree(); }
1087 static const TreeType& constTree(const TreeType& t) { return t; }
1088 static const TreeType& constTree(const GridType& g) { return g.constTree(); }
1089 };
1090
1091
1092 /// Partial specialization for Grid types
1093 template<typename _TreeType>
1094 struct TreeAdapter<Grid<_TreeType> >
1095 {
1096 using TreeType = _TreeType;
1097 using NonConstTreeType = typename std::remove_const<TreeType>::type;
1098 using TreePtrType = typename TreeType::Ptr;
1099 using ConstTreePtrType = typename TreeType::ConstPtr;
1100 using NonConstTreePtrType = typename NonConstTreeType::Ptr;
1101 using GridType = Grid<TreeType>;
1102 using NonConstGridType = Grid<NonConstTreeType>;
1103 using GridPtrType = typename GridType::Ptr;
1104 using NonConstGridPtrType = typename NonConstGridType::Ptr;
1105 using ConstGridPtrType = typename GridType::ConstPtr;
1106 using ValueType = typename TreeType::ValueType;
1107 using AccessorType = typename tree::ValueAccessor<TreeType>;
1108 using ConstAccessorType = typename tree::ValueAccessor<const TreeType>;
1109 using NonConstAccessorType = typename tree::ValueAccessor<NonConstTreeType>;
1110
1111 static TreeType& tree(TreeType& t) { return t; }
1112 static TreeType& tree(GridType& g) { return g.tree(); }
1113 static const TreeType& tree(const TreeType& t) { return t; }
1114 static const TreeType& tree(const GridType& g) { return g.tree(); }
1115 static const TreeType& constTree(TreeType& t) { return t; }
1116 static const TreeType& constTree(GridType& g) { return g.constTree(); }
1117 static const TreeType& constTree(const TreeType& t) { return t; }
1118 static const TreeType& constTree(const GridType& g) { return g.constTree(); }
1119 };
1120
1121 /// Partial specialization for ValueAccessor types
1122 template<typename _TreeType>
1123 struct TreeAdapter<tree::ValueAccessor<_TreeType> >
1124 {
1125 using TreeType = _TreeType;
1126 using NonConstTreeType = typename std::remove_const<TreeType>::type;
1127 using TreePtrType = typename TreeType::Ptr;
1128 using ConstTreePtrType = typename TreeType::ConstPtr;
1129 using NonConstTreePtrType = typename NonConstTreeType::Ptr;
1130 using GridType = Grid<TreeType>;
1131 using NonConstGridType = Grid<NonConstTreeType>;
1132 using GridPtrType = typename GridType::Ptr;
1133 using NonConstGridPtrType = typename NonConstGridType::Ptr;
1134 using ConstGridPtrType = typename GridType::ConstPtr;
1135 using ValueType = typename TreeType::ValueType;
1136 using AccessorType = typename tree::ValueAccessor<TreeType>;
1137 using ConstAccessorType = typename tree::ValueAccessor<const TreeType>;
1138 using NonConstAccessorType = typename tree::ValueAccessor<NonConstTreeType>;
1139
1140 static TreeType& tree(TreeType& t) { return t; }
1141 static TreeType& tree(GridType& g) { return g.tree(); }
1142 static TreeType& tree(AccessorType& a) { return a.tree(); }
1143 static const TreeType& tree(const TreeType& t) { return t; }
1144 static const TreeType& tree(const GridType& g) { return g.tree(); }
1145 static const TreeType& tree(const AccessorType& a) { return a.tree(); }
1146 static const TreeType& constTree(TreeType& t) { return t; }
1147 static const TreeType& constTree(GridType& g) { return g.constTree(); }
1148 static const TreeType& constTree(const TreeType& t) { return t; }
1149 static const TreeType& constTree(const GridType& g) { return g.constTree(); }
1150 };
1151
1152 //@}
1153
1154
1155 ////////////////////////////////////////
1156
1157
1158 /// @brief Metafunction that specifies whether a given leaf node, tree, or grid type
1159 /// requires multiple passes to read and write voxel data
1160 /// @details Multi-pass I/O allows one to optimize the data layout of leaf nodes
1161 /// for certain access patterns during delayed loading.
1162 /// @sa io::MultiPass
1163 template<typename LeafNodeType>
1164 struct HasMultiPassIO {
1165 static const bool value = std::is_base_of<io::MultiPass, LeafNodeType>::value;
1166 };
1167
1168 // Partial specialization for Tree types
1169 template<typename RootNodeType>
1170 struct HasMultiPassIO<tree::Tree<RootNodeType>> {
1171 // A tree is multi-pass if its (root node's) leaf node type is multi-pass.
1172 static const bool value = HasMultiPassIO<typename RootNodeType::LeafNodeType>::value;
1173 };
1174
1175 // Partial specialization for Grid types
1176 template<typename TreeType>
1177 struct HasMultiPassIO<Grid<TreeType>> {
1178 // A grid is multi-pass if its tree's leaf node type is multi-pass.
1179 static const bool value = HasMultiPassIO<typename TreeType::LeafNodeType>::value;
1180 };
1181
1182
1183 ////////////////////////////////////////
1184
1185 1 inline GridBase::GridBase(const MetaMap& meta, math::Transform::Ptr xform)
1186 : MetaMap(meta)
1187 1 , mTransform(xform)
1188 {
1189
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
1 if (!xform) OPENVDB_THROW(ValueError, "Transform pointer is null");
1190 1 }
1191
1192 template<typename GridType>
1193 inline typename GridType::Ptr
1194
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
175 GridBase::grid(const GridBase::Ptr& grid)
1195 {
1196 // The string comparison on type names is slower than a dynamic pointer cast, but
1197 // it is safer when pointers cross DSO boundaries, as they do in many Houdini nodes.
1198
9/16
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 122 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 122 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 119 times.
✓ Branch 10 taken 122 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 122 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 119 times.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
531 if (grid && grid->type() == GridType::gridType()) {
1199 return StaticPtrCast<GridType>(grid);
1200 }
1201 return typename GridType::Ptr();
1202 }
1203
1204
1205 template<typename GridType>
1206 inline typename GridType::ConstPtr
1207 GridBase::grid(const GridBase::ConstPtr& grid)
1208 {
1209 return ConstPtrCast<const GridType>(
1210 GridBase::grid<GridType>(ConstPtrCast<GridBase>(grid)));
1211 }
1212
1213
1214 template<typename GridType>
1215 inline typename GridType::ConstPtr
1216 GridBase::constGrid(const GridBase::Ptr& grid)
1217 {
1218 return ConstPtrCast<const GridType>(GridBase::grid<GridType>(grid));
1219 }
1220
1221
1222 template<typename GridType>
1223 inline typename GridType::ConstPtr
1224 6 GridBase::constGrid(const GridBase::ConstPtr& grid)
1225 {
1226 return ConstPtrCast<const GridType>(
1227
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
18 GridBase::grid<GridType>(ConstPtrCast<GridBase>(grid)));
1228 }
1229
1230
1231 inline TreeBase::Ptr
1232 28 GridBase::baseTreePtr()
1233 {
1234 28 return ConstPtrCast<TreeBase>(this->constBaseTreePtr());
1235 }
1236
1237
1238 inline void
1239
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25851 times.
25852 GridBase::setTransform(math::Transform::Ptr xform)
1240 {
1241
4/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25851 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
25855 if (!xform) OPENVDB_THROW(ValueError, "Transform pointer is null");
1242 mTransform = xform;
1243 25851 }
1244
1245
1246 ////////////////////////////////////////
1247
1248
1249 template<typename TreeT>
1250
2/4
✓ Branch 2 taken 418 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
750 inline Grid<TreeT>::Grid(): mTree(new TreeType)
1251 {
1252 750 }
1253
1254
1255 template<typename TreeT>
1256
2/4
✓ Branch 2 taken 23050 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 180 times.
✗ Branch 6 not taken.
42261 inline Grid<TreeT>::Grid(const ValueType &background): mTree(new TreeType(background))
1257 {
1258 42261 }
1259
1260
1261 template<typename TreeT>
1262 975 inline Grid<TreeT>::Grid(TreePtrType tree): mTree(tree)
1263 {
1264
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 880 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
975 if (!tree) OPENVDB_THROW(ValueError, "Tree pointer is null");
1265 975 }
1266
1267
1268 template<typename TreeT>
1269 2 inline Grid<TreeT>::Grid(TreePtrType tree, const MetaMap& meta, math::Transform::Ptr xform):
1270 GridBase(meta, xform),
1271
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
4 mTree(tree)
1272 {
1273
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
2 if (!tree) OPENVDB_THROW(ValueError, "Tree pointer is null");
1274 }
1275
1276
1277 template<typename TreeT>
1278 3964 inline Grid<TreeT>::Grid(const Grid& other):
1279 GridBase(other),
1280
1/2
✓ Branch 2 taken 1982 times.
✗ Branch 3 not taken.
3964 mTree(StaticPtrCast<TreeType>(other.mTree->copy()))
1281 {
1282 }
1283
1284
1285 template<typename TreeT>
1286 template<typename OtherTreeType>
1287 13 inline Grid<TreeT>::Grid(const Grid<OtherTreeType>& other):
1288 GridBase(other),
1289
3/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 2 times.
17 mTree(new TreeType(other.constTree()))
1290 {
1291 9 }
1292
1293
1294 template<typename TreeT>
1295 322 inline Grid<TreeT>::Grid(Grid& other, ShallowCopy):
1296 GridBase(other),
1297
17/138
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 96 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 46 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 5 times.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 33 taken 117 times.
✗ Branch 34 not taken.
✓ Branch 37 taken 4 times.
✗ Branch 38 not taken.
✓ Branch 41 taken 2 times.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 53 taken 2 times.
✗ Branch 54 not taken.
✓ Branch 57 taken 1 times.
✗ Branch 58 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✓ Branch 73 taken 8 times.
✗ Branch 74 not taken.
✓ Branch 77 taken 5 times.
✗ Branch 78 not taken.
✓ Branch 81 taken 4 times.
✗ Branch 82 not taken.
✓ Branch 85 taken 11 times.
✗ Branch 86 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✓ Branch 93 taken 1 times.
✗ Branch 94 not taken.
✓ Branch 97 taken 9 times.
✗ Branch 98 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 221 not taken.
✗ Branch 222 not taken.
✗ Branch 225 not taken.
✗ Branch 226 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 245 not taken.
✗ Branch 246 not taken.
✗ Branch 249 not taken.
✗ Branch 250 not taken.
✗ Branch 253 not taken.
✗ Branch 254 not taken.
✗ Branch 257 not taken.
✗ Branch 258 not taken.
✗ Branch 261 not taken.
✗ Branch 262 not taken.
✗ Branch 265 not taken.
✗ Branch 266 not taken.
✗ Branch 269 not taken.
✗ Branch 270 not taken.
✗ Branch 273 not taken.
✗ Branch 274 not taken.
322 mTree(other.mTree)
1298 {
1299 }
1300
1301
1302 template<typename TreeT>
1303 2 inline Grid<TreeT>::Grid(const GridBase& other):
1304 GridBase(other),
1305
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 mTree(new TreeType)
1306 {
1307 2 }
1308
1309
1310 //static
1311 template<typename TreeT>
1312 inline typename Grid<TreeT>::Ptr
1313 5512 Grid<TreeT>::create()
1314 {
1315
49/72
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 94 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 74 times.
✓ Branch 6 taken 96 times.
✓ Branch 7 taken 58 times.
✓ Branch 8 taken 70 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 67 times.
✓ Branch 12 taken 80 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 74 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 146 times.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 2 times.
✓ Branch 20 taken 67 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 297 times.
✓ Branch 23 taken 70 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 77 times.
✓ Branch 27 taken 295 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 117 times.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 164 times.
✓ Branch 33 taken 1 times.
✓ Branch 34 taken 4 times.
✓ Branch 35 taken 49 times.
✓ Branch 37 taken 35 times.
✓ Branch 38 taken 50 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✓ Branch 41 taken 49 times.
✓ Branch 42 taken 177 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 449 times.
✓ Branch 46 taken 1 times.
✓ Branch 47 taken 210 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 361 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 89 times.
✓ Branch 53 taken 103 times.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✓ Branch 56 taken 277 times.
✓ Branch 57 taken 89 times.
✓ Branch 58 taken 2 times.
✓ Branch 59 taken 398 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 875 times.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✓ Branch 65 taken 2 times.
✓ Branch 67 taken 153 times.
✗ Branch 68 not taken.
✓ Branch 72 taken 178 times.
✗ Branch 73 not taken.
✓ Branch 77 taken 178 times.
✗ Branch 78 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✓ Branch 86 taken 5380 times.
✗ Branch 87 not taken.
19085 return Grid::create(zeroVal<ValueType>());
1316 }
1317
1318
1319 //static
1320 template<typename TreeT>
1321 inline typename Grid<TreeT>::Ptr
1322 41767 Grid<TreeT>::create(const ValueType& background)
1323 {
1324
1/2
✓ Branch 2 taken 22867 times.
✗ Branch 3 not taken.
83534 return Ptr(new Grid(background));
1325 }
1326
1327
1328 //static
1329 template<typename TreeT>
1330 inline typename Grid<TreeT>::Ptr
1331 916 Grid<TreeT>::create(TreePtrType tree)
1332 {
1333
2/4
✓ Branch 1 taken 821 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 821 times.
✗ Branch 5 not taken.
1832 return Ptr(new Grid(tree));
1334 }
1335
1336
1337 //static
1338 template<typename TreeT>
1339 inline typename Grid<TreeT>::Ptr
1340 2 Grid<TreeT>::create(const GridBase& other)
1341 {
1342
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 return Ptr(new Grid(other));
1343 }
1344
1345
1346 ////////////////////////////////////////
1347
1348
1349 template<typename TreeT>
1350 inline typename Grid<TreeT>::ConstPtr
1351 322 Grid<TreeT>::copy() const
1352 {
1353
1/2
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
644 return ConstPtr{new Grid{*const_cast<Grid*>(this), ShallowCopy{}}};
1354 }
1355
1356
1357 template<typename TreeT>
1358 inline typename Grid<TreeT>::ConstPtr
1359 Grid<TreeT>::copyReplacingMetadata(const MetaMap& meta) const
1360 {
1361 math::Transform::Ptr transformPtr = ConstPtrCast<math::Transform>(
1362 this->constTransformPtr());
1363 TreePtrType treePtr = ConstPtrCast<TreeT>(this->constTreePtr());
1364 return ConstPtr{new Grid<TreeT>{treePtr, meta, transformPtr}};
1365 }
1366
1367 template<typename TreeT>
1368 inline typename Grid<TreeT>::ConstPtr
1369 Grid<TreeT>::copyReplacingTransform(math::Transform::Ptr xform) const
1370 {
1371 return this->copyReplacingMetadataAndTransform(*this, xform);
1372 }
1373
1374 template<typename TreeT>
1375 inline typename Grid<TreeT>::ConstPtr
1376 2 Grid<TreeT>::copyReplacingMetadataAndTransform(const MetaMap& meta,
1377 math::Transform::Ptr xform) const
1378 {
1379 2 TreePtrType treePtr = ConstPtrCast<TreeT>(this->constTreePtr());
1380
4/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
8 return ConstPtr{new Grid<TreeT>{treePtr, meta, xform}};
1381 }
1382
1383
1384 template<typename TreeT>
1385 inline typename Grid<TreeT>::Ptr
1386 10 Grid<TreeT>::copy()
1387 {
1388
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
20 return Ptr{new Grid{*this, ShallowCopy{}}};
1389 }
1390
1391
1392 template<typename TreeT>
1393 inline typename Grid<TreeT>::Ptr
1394 256 Grid<TreeT>::copyWithNewTree() const
1395 {
1396
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
256 Ptr result{new Grid{*const_cast<Grid*>(this), ShallowCopy{}}};
1397
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
256 result->newTree();
1398 256 return result;
1399 }
1400
1401
1402 template<typename TreeT>
1403 inline GridBase::Ptr
1404 2 Grid<TreeT>::copyGrid()
1405 {
1406 2 return this->copy();
1407 }
1408
1409 template<typename TreeT>
1410 inline GridBase::ConstPtr
1411 300 Grid<TreeT>::copyGrid() const
1412 {
1413 300 return this->copy();
1414 }
1415
1416 template<typename TreeT>
1417 inline GridBase::ConstPtr
1418 Grid<TreeT>::copyGridReplacingMetadata(const MetaMap& meta) const
1419 {
1420 return this->copyReplacingMetadata(meta);
1421 }
1422
1423 template<typename TreeT>
1424 inline GridBase::ConstPtr
1425 Grid<TreeT>::copyGridReplacingTransform(math::Transform::Ptr xform) const
1426 {
1427 return this->copyReplacingTransform(xform);
1428 }
1429
1430 template<typename TreeT>
1431 inline GridBase::ConstPtr
1432 2 Grid<TreeT>::copyGridReplacingMetadataAndTransform(const MetaMap& meta,
1433 math::Transform::Ptr xform) const
1434 {
1435
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
6 return this->copyReplacingMetadataAndTransform(meta, xform);
1436 }
1437
1438 template<typename TreeT>
1439 inline GridBase::Ptr
1440 20 Grid<TreeT>::copyGridWithNewTree() const
1441 {
1442 20 return this->copyWithNewTree();
1443 }
1444
1445
1446 ////////////////////////////////////////
1447
1448
1449 template<typename TreeT>
1450 inline bool
1451
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 Grid<TreeT>::isTreeUnique() const
1452 {
1453
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
7 return mTree.use_count() == 1;
1454 }
1455
1456
1457 template<typename TreeT>
1458 inline void
1459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
190 Grid<TreeT>::setTree(TreeBase::Ptr tree)
1460 {
1461
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
190 if (!tree) OPENVDB_THROW(ValueError, "Tree pointer is null");
1462
1/3
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 if (tree->type() != TreeType::treeType()) {
1463 OPENVDB_THROW(TypeError, "Cannot assign a tree of type "
1464 + tree->type() + " to a grid of type " + this->type());
1465 }
1466 190 mTree = StaticPtrCast<TreeType>(tree);
1467 }
1468
1469
1470 template<typename TreeT>
1471 inline void
1472 382 Grid<TreeT>::newTree()
1473 {
1474
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
382 mTree.reset(new TreeType(this->background()));
1475 }
1476
1477
1478 ////////////////////////////////////////
1479
1480
1481 template<typename TreeT>
1482 inline void
1483 Grid<TreeT>::sparseFill(const CoordBBox& bbox, const ValueType& value, bool active)
1484 {
1485 tree().sparseFill(bbox, value, active);
1486 39 }
1487
1488
1489 template<typename TreeT>
1490 inline void
1491 Grid<TreeT>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1492 {
1493 this->sparseFill(bbox, value, active);
1494 144 }
1495
1496 template<typename TreeT>
1497 inline void
1498 Grid<TreeT>::denseFill(const CoordBBox& bbox, const ValueType& value, bool active)
1499 {
1500 tree().denseFill(bbox, value, active);
1501 3454 }
1502
1503 template<typename TreeT>
1504 inline void
1505 4 Grid<TreeT>::pruneGrid(float tolerance)
1506 {
1507 const auto value = math::cwiseAdd(zeroVal<ValueType>(), tolerance);
1508
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
4 this->tree().prune(static_cast<ValueType>(value));
1509 }
1510
1511 template<typename TreeT>
1512 inline void
1513 12 Grid<TreeT>::clip(const CoordBBox& bbox)
1514 {
1515 tree().clip(bbox);
1516 }
1517
1518 template<typename TreeT>
1519 inline void
1520 Grid<TreeT>::merge(Grid& other, MergePolicy policy)
1521 {
1522 tree().merge(other.tree(), policy);
1523 }
1524
1525
1526 template<typename TreeT>
1527 template<typename OtherTreeType>
1528 inline void
1529 Grid<TreeT>::topologyUnion(const Grid<OtherTreeType>& other)
1530 {
1531 tree().topologyUnion(other.tree());
1532 6764 }
1533
1534
1535 template<typename TreeT>
1536 template<typename OtherTreeType>
1537 inline void
1538 Grid<TreeT>::topologyIntersection(const Grid<OtherTreeType>& other)
1539 {
1540 tree().topologyIntersection(other.tree());
1541 254 }
1542
1543
1544 template<typename TreeT>
1545 template<typename OtherTreeType>
1546 inline void
1547 Grid<TreeT>::topologyDifference(const Grid<OtherTreeType>& other)
1548 {
1549 tree().topologyDifference(other.tree());
1550 6 }
1551
1552
1553 ////////////////////////////////////////
1554
1555
1556 template<typename TreeT>
1557 inline void
1558 Grid<TreeT>::evalMinMax(ValueType& minVal, ValueType& maxVal) const
1559 {
1560 OPENVDB_NO_DEPRECATION_WARNING_BEGIN
1561 tree().evalMinMax(minVal, maxVal);
1562 OPENVDB_NO_DEPRECATION_WARNING_END
1563 }
1564
1565
1566 template<typename TreeT>
1567 inline CoordBBox
1568 696 Grid<TreeT>::evalActiveVoxelBoundingBox() const
1569 {
1570 705 CoordBBox bbox;
1571
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
705 tree().evalActiveVoxelBoundingBox(bbox);
1572 705 return bbox;
1573 }
1574
1575
1576 template<typename TreeT>
1577 inline Coord
1578 Grid<TreeT>::evalActiveVoxelDim() const
1579 {
1580 Coord dim;
1581
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const bool nonempty = tree().evalActiveVoxelDim(dim);
1582
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return (nonempty ? dim : Coord());
1583 }
1584
1585
1586 ////////////////////////////////////////
1587
1588
1589 /// @internal Consider using the stream tagging mechanism (see io::Archive)
1590 /// to specify the float precision, but note that the setting is per-grid.
1591
1592 template<typename TreeT>
1593 inline void
1594 226 Grid<TreeT>::readTopology(std::istream& is)
1595 {
1596 226 tree().readTopology(is, saveFloatAsHalf());
1597 }
1598
1599
1600 template<typename TreeT>
1601 inline void
1602 300 Grid<TreeT>::writeTopology(std::ostream& os) const
1603 {
1604 300 tree().writeTopology(os, saveFloatAsHalf());
1605 }
1606
1607
1608 template<typename TreeT>
1609 inline void
1610 230 Grid<TreeT>::readBuffers(std::istream& is)
1611 {
1612
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
40 if (!hasMultiPassIO() || (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_MULTIPASS_IO)) {
1613 190 tree().readBuffers(is, saveFloatAsHalf());
1614 } else {
1615 40 uint16_t numPasses = 1;
1616 40 is.read(reinterpret_cast<char*>(&numPasses), sizeof(uint16_t));
1617 40 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(is);
1618
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
40 assert(bool(meta));
1619
2/2
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 20 times.
372 for (uint16_t passIndex = 0; passIndex < numPasses; ++passIndex) {
1620
1/2
✓ Branch 1 taken 166 times.
✗ Branch 2 not taken.
332 uint32_t pass = (uint32_t(numPasses) << 16) | uint32_t(passIndex);
1621
1/2
✓ Branch 1 taken 166 times.
✗ Branch 2 not taken.
332 meta->setPass(pass);
1622
2/4
✓ Branch 1 taken 166 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 166 times.
✗ Branch 5 not taken.
332 tree().readBuffers(is, saveFloatAsHalf());
1623 }
1624 }
1625 }
1626
1627
1628 /// @todo Refactor this and the readBuffers() above
1629 /// once support for ABI 2 compatibility is dropped.
1630 template<typename TreeT>
1631 inline void
1632 10 Grid<TreeT>::readBuffers(std::istream& is, const CoordBBox& bbox)
1633 {
1634
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
2 if (!hasMultiPassIO() || (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_MULTIPASS_IO)) {
1635 8 tree().readBuffers(is, bbox, saveFloatAsHalf());
1636 } else {
1637 2 uint16_t numPasses = 1;
1638 2 is.read(reinterpret_cast<char*>(&numPasses), sizeof(uint16_t));
1639 2 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(is);
1640
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 assert(bool(meta));
1641
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
8 for (uint16_t passIndex = 0; passIndex < numPasses; ++passIndex) {
1642
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 uint32_t pass = (uint32_t(numPasses) << 16) | uint32_t(passIndex);
1643
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 meta->setPass(pass);
1644
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 tree().readBuffers(is, saveFloatAsHalf());
1645 }
1646 // Cannot clip inside readBuffers() when using multiple passes,
1647 // so instead clip afterwards.
1648 tree().clip(bbox);
1649 }
1650 }
1651
1652
1653 template<typename TreeT>
1654 inline void
1655 Grid<TreeT>::readNonresidentBuffers() const
1656 {
1657 tree().readNonresidentBuffers();
1658 }
1659
1660
1661 template<typename TreeT>
1662 inline void
1663 354 Grid<TreeT>::writeBuffers(std::ostream& os) const
1664 {
1665 if (!hasMultiPassIO()) {
1666 332 tree().writeBuffers(os, saveFloatAsHalf());
1667 } else {
1668 // Determine how many leaf buffer passes are required for this grid
1669 22 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(os);
1670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
22 assert(bool(meta));
1671 22 uint16_t numPasses = 1;
1672
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
22 meta->setCountingPasses(true);
1673
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
22 meta->setPass(0);
1674
2/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
22 tree().writeBuffers(os, saveFloatAsHalf());
1675
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
22 numPasses = static_cast<uint16_t>(meta->pass());
1676
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
22 os.write(reinterpret_cast<const char*>(&numPasses), sizeof(uint16_t));
1677
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
22 meta->setCountingPasses(false);
1678
1679 // Save out the data blocks of the grid.
1680
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 11 times.
186 for (uint16_t passIndex = 0; passIndex < numPasses; ++passIndex) {
1681
1/2
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
164 uint32_t pass = (uint32_t(numPasses) << 16) | uint32_t(passIndex);
1682
1/2
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
164 meta->setPass(pass);
1683
2/4
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
164 tree().writeBuffers(os, saveFloatAsHalf());
1684 }
1685 }
1686 }
1687
1688
1689 //static
1690 template<typename TreeT>
1691 inline bool
1692 Grid<TreeT>::hasMultiPassIO()
1693 {
1694 return HasMultiPassIO<Grid>::value;
1695 }
1696
1697
1698 template<typename TreeT>
1699 inline void
1700 Grid<TreeT>::print(std::ostream& os, int verboseLevel) const
1701 {
1702 tree().print(os, verboseLevel);
1703
1704 if (metaCount() > 0) {
1705 os << "Additional metadata:" << std::endl;
1706 for (ConstMetaIterator it = beginMeta(), end = endMeta(); it != end; ++it) {
1707 os << " " << it->first;
1708 if (it->second) {
1709 const std::string value = it->second->str();
1710 if (!value.empty()) os << ": " << value;
1711 }
1712 os << "\n";
1713 }
1714 }
1715
1716 os << "Transform:" << std::endl;
1717 transform().print(os, /*indent=*/" ");
1718 os << std::endl;
1719 }
1720
1721
1722 ////////////////////////////////////////
1723
1724
1725 template<typename GridType>
1726 inline typename GridType::Ptr
1727 createGrid(const typename GridType::ValueType& background)
1728 {
1729
18/35
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 102 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
144 return GridType::create(background);
1730 }
1731
1732
1733 template<typename GridType>
1734 inline typename GridType::Ptr
1735 createGrid()
1736 {
1737 2 return GridType::create();
1738 }
1739
1740
1741 template<typename TreePtrType>
1742 inline typename Grid<typename TreePtrType::element_type>::Ptr
1743 51 createGrid(TreePtrType tree)
1744 {
1745 using TreeType = typename TreePtrType::element_type;
1746
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
102 return Grid<TreeType>::create(tree);
1747 }
1748
1749
1750 template<typename GridType>
1751 typename GridType::Ptr
1752 339 createLevelSet(Real voxelSize, Real halfWidth)
1753 {
1754 using ValueType = typename GridType::ValueType;
1755
1756 // GridType::ValueType is required to be a floating-point scalar.
1757 static_assert(std::is_floating_point<ValueType>::value,
1758 "level-set grids must be floating-point-valued");
1759
1760 339 typename GridType::Ptr grid = GridType::create(
1761
1/2
✓ Branch 2 taken 337 times.
✗ Branch 3 not taken.
339 /*background=*/static_cast<ValueType>(voxelSize * halfWidth));
1762
3/8
✓ Branch 1 taken 337 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 337 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 337 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
678 grid->setTransform(math::Transform::createLinearTransform(voxelSize));
1763
1/2
✓ Branch 1 taken 337 times.
✗ Branch 2 not taken.
339 grid->setGridClass(GRID_LEVEL_SET);
1764 339 return grid;
1765 }
1766
1767
1768 ////////////////////////////////////////
1769
1770
1771 template<typename GridTypeListT, typename OpT>
1772 inline bool
1773 GridBase::apply(OpT& op) const
1774 {
1775 return GridTypeListT::template apply<OpT&, const GridBase>(std::ref(op), *this);
1776 }
1777
1778 template<typename GridTypeListT, typename OpT>
1779 inline bool
1780 GridBase::apply(OpT& op)
1781 {
1782 return GridTypeListT::template apply<OpT&, GridBase>(std::ref(op), *this);
1783 }
1784
1785 template<typename GridTypeListT, typename OpT>
1786 inline bool
1787 GridBase::apply(const OpT& op) const
1788 {
1789 return GridTypeListT::template apply<const OpT&, const GridBase>(std::ref(op), *this);
1790 }
1791
1792 template<typename GridTypeListT, typename OpT>
1793 inline bool
1794 GridBase::apply(const OpT& op)
1795 {
1796 return GridTypeListT::template apply<const OpT&, GridBase>(std::ref(op), *this);
1797 }
1798
1799
1800 } // namespace OPENVDB_VERSION_NAME
1801 } // namespace openvdb
1802
1803 #endif // OPENVDB_GRID_HAS_BEEN_INCLUDED
1804