| 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 |