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 |