| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | /// @file math/Maps.h | ||
| 5 | |||
| 6 | #ifndef OPENVDB_MATH_MAPS_HAS_BEEN_INCLUDED | ||
| 7 | #define OPENVDB_MATH_MAPS_HAS_BEEN_INCLUDED | ||
| 8 | |||
| 9 | #include "Math.h" | ||
| 10 | #include "Mat4.h" | ||
| 11 | #include "Vec3.h" | ||
| 12 | #include "BBox.h" | ||
| 13 | #include "Coord.h" | ||
| 14 | #include <openvdb/io/io.h> // for io::getFormatVersion() | ||
| 15 | #include <openvdb/util/Name.h> | ||
| 16 | #include <openvdb/Types.h> | ||
| 17 | #include <cmath> // for std::abs() | ||
| 18 | #include <iostream> | ||
| 19 | #include <map> | ||
| 20 | #include <string> | ||
| 21 | |||
| 22 | namespace openvdb { | ||
| 23 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 24 | namespace OPENVDB_VERSION_NAME { | ||
| 25 | namespace math { | ||
| 26 | |||
| 27 | |||
| 28 | //////////////////////////////////////// | ||
| 29 | |||
| 30 | /// Forward declarations of the different map types | ||
| 31 | |||
| 32 | class MapBase; | ||
| 33 | class ScaleMap; | ||
| 34 | class TranslationMap; | ||
| 35 | class ScaleTranslateMap; | ||
| 36 | class UniformScaleMap; | ||
| 37 | class UniformScaleTranslateMap; | ||
| 38 | class AffineMap; | ||
| 39 | class UnitaryMap; | ||
| 40 | class NonlinearFrustumMap; | ||
| 41 | |||
| 42 | template<typename T1, typename T2> class CompoundMap; | ||
| 43 | |||
| 44 | using UnitaryAndTranslationMap = CompoundMap<UnitaryMap, TranslationMap>; | ||
| 45 | using SpectralDecomposedMap = CompoundMap<CompoundMap<UnitaryMap, ScaleMap>, UnitaryMap>; | ||
| 46 | using SymmetricMap = SpectralDecomposedMap; | ||
| 47 | using FullyDecomposedMap = CompoundMap<SymmetricMap, UnitaryAndTranslationMap>; | ||
| 48 | using PolarDecomposedMap = CompoundMap<SymmetricMap, UnitaryMap>; | ||
| 49 | |||
| 50 | |||
| 51 | //////////////////////////////////////// | ||
| 52 | |||
| 53 | /// Map traits | ||
| 54 | |||
| 55 | template<typename T> struct is_linear { static const bool value = false; }; | ||
| 56 | template<> struct is_linear<AffineMap> { static const bool value = true; }; | ||
| 57 | template<> struct is_linear<ScaleMap> { static const bool value = true; }; | ||
| 58 | template<> struct is_linear<UniformScaleMap> { static const bool value = true; }; | ||
| 59 | template<> struct is_linear<UnitaryMap> { static const bool value = true; }; | ||
| 60 | template<> struct is_linear<TranslationMap> { static const bool value = true; }; | ||
| 61 | template<> struct is_linear<ScaleTranslateMap> { static const bool value = true; }; | ||
| 62 | template<> struct is_linear<UniformScaleTranslateMap> { static const bool value = true; }; | ||
| 63 | |||
| 64 | template<typename T1, typename T2> struct is_linear<CompoundMap<T1, T2> > { | ||
| 65 | static const bool value = is_linear<T1>::value && is_linear<T2>::value; | ||
| 66 | }; | ||
| 67 | |||
| 68 | |||
| 69 | template<typename T> struct is_uniform_scale { static const bool value = false; }; | ||
| 70 | template<> struct is_uniform_scale<UniformScaleMap> { static const bool value = true; }; | ||
| 71 | |||
| 72 | template<typename T> struct is_uniform_scale_translate { static const bool value = false; }; | ||
| 73 | template<> struct is_uniform_scale_translate<TranslationMap> { static const bool value = true; }; | ||
| 74 | template<> struct is_uniform_scale_translate<UniformScaleTranslateMap> { | ||
| 75 | static const bool value = true; | ||
| 76 | }; | ||
| 77 | |||
| 78 | |||
| 79 | template<typename T> struct is_scale { static const bool value = false; }; | ||
| 80 | template<> struct is_scale<ScaleMap> { static const bool value = true; }; | ||
| 81 | |||
| 82 | template<typename T> struct is_scale_translate { static const bool value = false; }; | ||
| 83 | template<> struct is_scale_translate<ScaleTranslateMap> { static const bool value = true; }; | ||
| 84 | |||
| 85 | |||
| 86 | template<typename T> struct is_uniform_diagonal_jacobian { | ||
| 87 | static const bool value = is_uniform_scale<T>::value || is_uniform_scale_translate<T>::value; | ||
| 88 | }; | ||
| 89 | |||
| 90 | template<typename T> struct is_diagonal_jacobian { | ||
| 91 | static const bool value = is_scale<T>::value || is_scale_translate<T>::value; | ||
| 92 | }; | ||
| 93 | |||
| 94 | |||
| 95 | //////////////////////////////////////// | ||
| 96 | |||
| 97 | /// Utility methods | ||
| 98 | |||
| 99 | /// @brief Create a SymmetricMap from a symmetric matrix. | ||
| 100 | /// Decomposes the map into Rotation Diagonal Rotation^T | ||
| 101 | OPENVDB_API SharedPtr<SymmetricMap> createSymmetricMap(const Mat3d& m); | ||
| 102 | |||
| 103 | |||
| 104 | /// @brief General decomposition of a Matrix into a Unitary (e.g. rotation) | ||
| 105 | /// following a Symmetric (e.g. stretch & shear) | ||
| 106 | OPENVDB_API SharedPtr<FullyDecomposedMap> createFullyDecomposedMap(const Mat4d& m); | ||
| 107 | |||
| 108 | |||
| 109 | /// @brief Decomposes a general linear into translation following polar decomposition. | ||
| 110 | /// | ||
| 111 | /// T U S where: | ||
| 112 | /// | ||
| 113 | /// T: Translation | ||
| 114 | /// U: Unitary (rotation or reflection) | ||
| 115 | /// S: Symmetric | ||
| 116 | /// | ||
| 117 | /// @note: the Symmetric is automatically decomposed into Q D Q^T, where | ||
| 118 | /// Q is rotation and D is diagonal. | ||
| 119 | OPENVDB_API SharedPtr<PolarDecomposedMap> createPolarDecomposedMap(const Mat3d& m); | ||
| 120 | |||
| 121 | |||
| 122 | /// @brief reduces an AffineMap to a ScaleMap or a ScaleTranslateMap when it can | ||
| 123 | OPENVDB_API SharedPtr<MapBase> simplify(SharedPtr<AffineMap> affine); | ||
| 124 | |||
| 125 | /// @brief Returns the left pseudoInverse of the input matrix when the 3x3 part is symmetric | ||
| 126 | /// otherwise it zeros the 3x3 and reverses the translation. | ||
| 127 | OPENVDB_API Mat4d approxInverse(const Mat4d& mat); | ||
| 128 | |||
| 129 | |||
| 130 | //////////////////////////////////////// | ||
| 131 | |||
| 132 | |||
| 133 | /// @brief Abstract base class for maps | ||
| 134 | class OPENVDB_API MapBase | ||
| 135 | { | ||
| 136 | public: | ||
| 137 | using Ptr = SharedPtr<MapBase>; | ||
| 138 | using ConstPtr = SharedPtr<const MapBase>; | ||
| 139 | using MapFactory = Ptr (*)(); | ||
| 140 | |||
| 141 | 21965 | MapBase(const MapBase&) = default; | |
| 142 | virtual ~MapBase() = default; | ||
| 143 | |||
| 144 | virtual SharedPtr<AffineMap> getAffineMap() const = 0; | ||
| 145 | |||
| 146 | /// Return the name of this map's concrete type (e.g., @c "AffineMap"). | ||
| 147 | virtual Name type() const = 0; | ||
| 148 | |||
| 149 | /// Return @c true if this map is of concrete type @c MapT (e.g., AffineMap). | ||
| 150 | 119152 | template<typename MapT> bool isType() const { return this->type() == MapT::mapType(); } | |
| 151 | |||
| 152 | /// Return @c true if this map is equal to the given map. | ||
| 153 | virtual bool isEqual(const MapBase& other) const = 0; | ||
| 154 | |||
| 155 | /// Return @c true if this map is linear. | ||
| 156 | virtual bool isLinear() const = 0; | ||
| 157 | /// Return @c true if the spacing between the image of latice is uniform in all directions | ||
| 158 | virtual bool hasUniformScale() const = 0; | ||
| 159 | |||
| 160 | virtual Vec3d applyMap(const Vec3d& in) const = 0; | ||
| 161 | virtual Vec3d applyInverseMap(const Vec3d& in) const = 0; | ||
| 162 | |||
| 163 | //@{ | ||
| 164 | /// @brief Apply the Inverse Jacobian Transpose of this map to a vector. | ||
| 165 | /// For a linear map this is equivalent to applying the transpose of | ||
| 166 | /// inverse map excluding translation. | ||
| 167 | virtual Vec3d applyIJT(const Vec3d& in) const = 0; | ||
| 168 | virtual Vec3d applyIJT(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
| 169 | //@} | ||
| 170 | |||
| 171 | virtual Mat3d applyIJC(const Mat3d& m) const = 0; | ||
| 172 | virtual Mat3d applyIJC(const Mat3d& m, const Vec3d& v, const Vec3d& domainPos) const = 0; | ||
| 173 | |||
| 174 | |||
| 175 | virtual double determinant() const = 0; | ||
| 176 | virtual double determinant(const Vec3d&) const = 0; | ||
| 177 | |||
| 178 | |||
| 179 | //@{ | ||
| 180 | /// @brief Method to return the local size of a voxel. | ||
| 181 | /// When a location is specified as an argument, it is understood to be | ||
| 182 | /// be in the domain of the map (i.e. index space) | ||
| 183 | virtual Vec3d voxelSize() const = 0; | ||
| 184 | virtual Vec3d voxelSize(const Vec3d&) const = 0; | ||
| 185 | //@} | ||
| 186 | |||
| 187 | virtual void read(std::istream&) = 0; | ||
| 188 | virtual void write(std::ostream&) const = 0; | ||
| 189 | |||
| 190 | virtual std::string str() const = 0; | ||
| 191 | |||
| 192 | virtual MapBase::Ptr copy() const = 0; | ||
| 193 | |||
| 194 | //@{ | ||
| 195 | /// @brief Methods to update the map | ||
| 196 | virtual MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const = 0; | ||
| 197 | virtual MapBase::Ptr preTranslate(const Vec3d&) const = 0; | ||
| 198 | virtual MapBase::Ptr preScale(const Vec3d&) const = 0; | ||
| 199 | virtual MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const = 0; | ||
| 200 | |||
| 201 | virtual MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const = 0; | ||
| 202 | virtual MapBase::Ptr postTranslate(const Vec3d&) const = 0; | ||
| 203 | virtual MapBase::Ptr postScale(const Vec3d&) const = 0; | ||
| 204 | virtual MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const = 0; | ||
| 205 | //@} | ||
| 206 | |||
| 207 | //@{ | ||
| 208 | /// @brief Apply the Jacobian of this map to a vector. | ||
| 209 | /// For a linear map this is equivalent to applying the map excluding translation. | ||
| 210 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
| 211 | /// with that version lack a virtual table entry for this method. Do not call | ||
| 212 | /// this method from Houdini 12.5. | ||
| 213 | virtual Vec3d applyJacobian(const Vec3d& in) const = 0; | ||
| 214 | virtual Vec3d applyJacobian(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
| 215 | //@} | ||
| 216 | |||
| 217 | //@{ | ||
| 218 | /// @brief Apply the InverseJacobian of this map to a vector. | ||
| 219 | /// For a linear map this is equivalent to applying the map inverse excluding translation. | ||
| 220 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
| 221 | /// with that version lack a virtual table entry for this method. Do not call | ||
| 222 | /// this method from Houdini 12.5. | ||
| 223 | virtual Vec3d applyInverseJacobian(const Vec3d& in) const = 0; | ||
| 224 | virtual Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
| 225 | //@} | ||
| 226 | |||
| 227 | |||
| 228 | //@{ | ||
| 229 | /// @brief Apply the Jacobian transpose of this map to a vector. | ||
| 230 | /// For a linear map this is equivalent to applying the transpose of the map | ||
| 231 | /// excluding translation. | ||
| 232 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
| 233 | /// with that version lack a virtual table entry for this method. Do not call | ||
| 234 | /// this method from Houdini 12.5. | ||
| 235 | virtual Vec3d applyJT(const Vec3d& in) const = 0; | ||
| 236 | virtual Vec3d applyJT(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
| 237 | //@} | ||
| 238 | |||
| 239 | /// @brief Return a new map representing the inverse of this map. | ||
| 240 | /// @throw NotImplementedError if the map is a NonlinearFrustumMap. | ||
| 241 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
| 242 | /// with that version lack a virtual table entry for this method. Do not call | ||
| 243 | /// this method from Houdini 12.5. | ||
| 244 | virtual MapBase::Ptr inverseMap() const = 0; | ||
| 245 | |||
| 246 | protected: | ||
| 247 | 53841 | MapBase() {} | |
| 248 | |||
| 249 | template<typename MapT> | ||
| 250 | 12498 | static bool isEqualBase(const MapT& self, const MapBase& other) | |
| 251 | { | ||
| 252 |
4/5✓ Branch 1 taken 6244 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
|
12498 | return other.isType<MapT>() && (self == *static_cast<const MapT*>(&other)); |
| 253 | } | ||
| 254 | }; | ||
| 255 | |||
| 256 | |||
| 257 | //////////////////////////////////////// | ||
| 258 | |||
| 259 | |||
| 260 | /// @brief Threadsafe singleton object for accessing the map type-name dictionary. | ||
| 261 | /// Associates a map type-name with a factory function. | ||
| 262 | class OPENVDB_API MapRegistry | ||
| 263 | { | ||
| 264 | public: | ||
| 265 | using MapDictionary = std::map<Name, MapBase::MapFactory>; | ||
| 266 | |||
| 267 | static MapRegistry* instance(); | ||
| 268 | |||
| 269 | /// Create a new map of the given (registered) type name. | ||
| 270 | static MapBase::Ptr createMap(const Name&); | ||
| 271 | |||
| 272 | /// Return @c true if the given map type name is registered. | ||
| 273 | static bool isRegistered(const Name&); | ||
| 274 | |||
| 275 | /// Register a map type along with a factory function. | ||
| 276 | static void registerMap(const Name&, MapBase::MapFactory); | ||
| 277 | |||
| 278 | /// Remove a map type from the registry. | ||
| 279 | static void unregisterMap(const Name&); | ||
| 280 | |||
| 281 | /// Clear the map type registry. | ||
| 282 | static void clear(); | ||
| 283 | |||
| 284 | private: | ||
| 285 | MapRegistry() {} | ||
| 286 | |||
| 287 | static MapRegistry* staticInstance(); | ||
| 288 | |||
| 289 | MapDictionary mMap; | ||
| 290 | }; | ||
| 291 | |||
| 292 | |||
| 293 | //////////////////////////////////////// | ||
| 294 | |||
| 295 | |||
| 296 | /// @note Macro to use a final specifier from ABI=8 onwards. | ||
| 297 | #if OPENVDB_ABI_VERSION_NUMBER >= 8 | ||
| 298 | #define OPENVDB_MAP_CLASS_SPECIFIER final | ||
| 299 | #define OPENVDB_MAP_FUNC_SPECIFIER final | ||
| 300 | #else | ||
| 301 | #define OPENVDB_MAP_CLASS_SPECIFIER | ||
| 302 | #define OPENVDB_MAP_FUNC_SPECIFIER override | ||
| 303 | #endif | ||
| 304 | |||
| 305 | |||
| 306 | /// @brief A general linear transform using homogeneous coordinates to perform | ||
| 307 | /// rotation, scaling, shear and translation | ||
| 308 | /// @note This class is marked final with ABI=8 | ||
| 309 | class OPENVDB_API AffineMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
| 310 | { | ||
| 311 | public: | ||
| 312 | using Ptr = SharedPtr<AffineMap>; | ||
| 313 | using ConstPtr = SharedPtr<const AffineMap>; | ||
| 314 | |||
| 315 | 86 | AffineMap(): | |
| 316 | 86 | mMatrix(Mat4d::identity()), | |
| 317 | 86 | mMatrixInv(Mat4d::identity()), | |
| 318 | 86 | mJacobianInv(Mat3d::identity()), | |
| 319 | mDeterminant(1), | ||
| 320 | mVoxelSize(Vec3d(1,1,1)), | ||
| 321 | mIsDiagonal(true), | ||
| 322 | 86 | mIsIdentity(true) | |
| 323 | // the default constructor for translation is zero | ||
| 324 | { | ||
| 325 | 86 | } | |
| 326 | |||
| 327 | 11 | AffineMap(const Mat3d& m) | |
| 328 | 11 | { | |
| 329 | 11 | Mat4d mat4(Mat4d::identity()); | |
| 330 | mat4.setMat3(m); | ||
| 331 | 11 | mMatrix = mat4; | |
| 332 | 11 | updateAcceleration(); | |
| 333 | 11 | } | |
| 334 | |||
| 335 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | AffineMap(const Mat4d& m): mMatrix(m) |
| 336 | { | ||
| 337 | if (!isAffine(m)) { | ||
| 338 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 339 | "Tried to initialize an affine transform from a non-affine 4x4 matrix"); | ||
| 340 | } | ||
| 341 | 117 | updateAcceleration(); | |
| 342 | 117 | } | |
| 343 | |||
| 344 | 21955 | AffineMap(const AffineMap& other): | |
| 345 | MapBase(other), | ||
| 346 | mMatrix(other.mMatrix), | ||
| 347 | mMatrixInv(other.mMatrixInv), | ||
| 348 | mJacobianInv(other.mJacobianInv), | ||
| 349 | 21955 | mDeterminant(other.mDeterminant), | |
| 350 | mVoxelSize(other.mVoxelSize), | ||
| 351 | 21955 | mIsDiagonal(other.mIsDiagonal), | |
| 352 | 21955 | mIsIdentity(other.mIsIdentity) | |
| 353 | { | ||
| 354 | 21955 | } | |
| 355 | |||
| 356 | /// @brief constructor that merges the matrixes for two affine maps | ||
| 357 | 5 | AffineMap(const AffineMap& first, const AffineMap& second): | |
| 358 | 5 | mMatrix(first.mMatrix * second.mMatrix) | |
| 359 | { | ||
| 360 | 5 | updateAcceleration(); | |
| 361 | 5 | } | |
| 362 | |||
| 363 |
3/8✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
318 | ~AffineMap() override = default; |
| 364 | |||
| 365 | /// Return a MapBase::Ptr to a new AffineMap | ||
| 366 | 1 | static MapBase::Ptr create() { return MapBase::Ptr(new AffineMap()); } | |
| 367 | /// Return a MapBase::Ptr to a deep copy of this map | ||
| 368 | 38 | MapBase::Ptr copy() const override { return MapBase::Ptr(new AffineMap(*this)); } | |
| 369 | |||
| 370 | ✗ | MapBase::Ptr inverseMap() const override { return MapBase::Ptr(new AffineMap(mMatrixInv)); } | |
| 371 | |||
| 372 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(AffineMap::mapType()); } | |
| 373 | |||
| 374 | 338 | static void registerMap() | |
| 375 | { | ||
| 376 | 338 | MapRegistry::registerMap( | |
| 377 | 338 | AffineMap::mapType(), | |
| 378 | AffineMap::create); | ||
| 379 | 338 | } | |
| 380 | |||
| 381 | 150 | Name type() const override { return mapType(); } | |
| 382 |
10/120✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 335 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 25 taken 6 times.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ 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 not taken.
✗ Branch 74 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 97 not taken.
✗ 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 222 not taken.
✗ Branch 223 not taken.
✗ Branch 225 not taken.
✗ Branch 226 not taken.
|
430 | static Name mapType() { return Name("AffineMap"); } |
| 383 | |||
| 384 | /// Return @c true (an AffineMap is always linear). | ||
| 385 | 95 | bool isLinear() const override { return true; } | |
| 386 | |||
| 387 | /// Return @c false ( test if this is unitary with translation ) | ||
| 388 | 4 | bool hasUniformScale() const override | |
| 389 | { | ||
| 390 | Mat3d mat = mMatrix.getMat3(); | ||
| 391 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | const double det = mat.det(); |
| 392 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (isApproxEqual(det, double(0))) { |
| 393 | return false; | ||
| 394 | } else { | ||
| 395 | 4 | mat *= (1.0 / pow(std::abs(det), 1.0/3.0)); | |
| 396 | 4 | return isUnitary(mat); | |
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | 1 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 401 | |||
| 402 | 5 | bool operator==(const AffineMap& other) const | |
| 403 | { | ||
| 404 | // the Mat.eq() is approximate | ||
| 405 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | if (!mMatrix.eq(other.mMatrix)) { return false; } |
| 406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!mMatrixInv.eq(other.mMatrixInv)) { return false; } |
| 407 | return true; | ||
| 408 | } | ||
| 409 | |||
| 410 | 2 | bool operator!=(const AffineMap& other) const { return !(*this == other); } | |
| 411 | |||
| 412 | AffineMap& operator=(const AffineMap& other) | ||
| 413 | { | ||
| 414 | 53 | mMatrix = other.mMatrix; | |
| 415 | 53 | mMatrixInv = other.mMatrixInv; | |
| 416 | |||
| 417 | 53 | mJacobianInv = other.mJacobianInv; | |
| 418 | 53 | mDeterminant = other.mDeterminant; | |
| 419 | 53 | mVoxelSize = other.mVoxelSize; | |
| 420 | 53 | mIsDiagonal = other.mIsDiagonal; | |
| 421 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
|
42 | mIsIdentity = other.mIsIdentity; |
| 422 | return *this; | ||
| 423 | } | ||
| 424 | /// Return the image of @c in under the map | ||
| 425 | 2500069229 | Vec3d applyMap(const Vec3d& in) const override { return in * mMatrix; } | |
| 426 | /// Return the pre-image of @c in under the map | ||
| 427 | 322200 | Vec3d applyInverseMap(const Vec3d& in) const override {return in * mMatrixInv; } | |
| 428 | |||
| 429 | /// Return the Jacobian of the map applied to @a in. | ||
| 430 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const override { return applyJacobian(in); } | |
| 431 | /// Return the Jacobian of the map applied to @a in. | ||
| 432 | 12 | Vec3d applyJacobian(const Vec3d& in) const override { return mMatrix.transform3x3(in); } | |
| 433 | |||
| 434 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 435 | /// (i.e. inverse map with out translation) | ||
| 436 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const override { | |
| 437 | ✗ | return applyInverseJacobian(in); | |
| 438 | } | ||
| 439 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 440 | /// (i.e. inverse map with out translation) | ||
| 441 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { | |
| 442 | 11 | return mMatrixInv.transform3x3(in); | |
| 443 | } | ||
| 444 | |||
| 445 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
| 446 | /// This tranforms range-space gradients to domain-space gradients | ||
| 447 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const override { return applyJT(in); } | |
| 448 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
| 449 | ✗ | Vec3d applyJT(const Vec3d& in) const override { | |
| 450 | const double* m = mMatrix.asPointer(); | ||
| 451 | ✗ | return Vec3d( m[ 0] * in[0] + m[ 1] * in[1] + m[ 2] * in[2], | |
| 452 | ✗ | m[ 4] * in[0] + m[ 5] * in[1] + m[ 6] * in[2], | |
| 453 | ✗ | m[ 8] * in[0] + m[ 9] * in[1] + m[10] * in[2] ); | |
| 454 | } | ||
| 455 | |||
| 456 | /// Return the transpose of the inverse Jacobian of the map applied to @a in. | ||
| 457 | 4 | Vec3d applyIJT(const Vec3d& in, const Vec3d&) const override { return applyIJT(in); } | |
| 458 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
| 459 | 314998 | Vec3d applyIJT(const Vec3d& in) const override { return in * mJacobianInv; } | |
| 460 | /// Return the Jacobian Curvature: zero for a linear map | ||
| 461 | 32 | Mat3d applyIJC(const Mat3d& m) const override { | |
| 462 | 32 | return mJacobianInv.transpose()* m * mJacobianInv; | |
| 463 | } | ||
| 464 | 2 | Mat3d applyIJC(const Mat3d& in, const Vec3d& , const Vec3d& ) const override { | |
| 465 | 2 | return applyIJC(in); | |
| 466 | } | ||
| 467 | /// Return the determinant of the Jacobian, ignores argument | ||
| 468 | ✗ | double determinant(const Vec3d& ) const override { return determinant(); } | |
| 469 | /// Return the determinant of the Jacobian | ||
| 470 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | double determinant() const override { return mDeterminant; } |
| 471 | |||
| 472 | //@{ | ||
| 473 | /// @brief Return the lengths of the images of the segments | ||
| 474 | /// (0,0,0)-(1,0,0), (0,0,0)-(0,1,0) and (0,0,0)-(0,0,1). | ||
| 475 | 333005 | Vec3d voxelSize() const override { return mVoxelSize; } | |
| 476 | ✗ | Vec3d voxelSize(const Vec3d&) const override { return voxelSize(); } | |
| 477 | //@} | ||
| 478 | |||
| 479 | /// Return @c true if the underlying matrix is approximately an identity | ||
| 480 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | bool isIdentity() const { return mIsIdentity; } |
| 481 | /// Return @c true if the underylying matrix is diagonal | ||
| 482 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 101 times.
|
122 | bool isDiagonal() const { return mIsDiagonal; } |
| 483 | /// Return @c true if the map is equivalent to a ScaleMap | ||
| 484 | bool isScale() const { return isDiagonal(); } | ||
| 485 | /// Return @c true if the map is equivalent to a ScaleTranslateMap | ||
| 486 | 101 | bool isScaleTranslate() const { return math::isDiagonal(mMatrix.getMat3()); } | |
| 487 | |||
| 488 | |||
| 489 | // Methods that modify the existing affine map | ||
| 490 | |||
| 491 | //@{ | ||
| 492 | /// @brief Modify the existing affine map by pre-applying the given operation. | ||
| 493 | void accumPreRotation(Axis axis, double radians) | ||
| 494 | { | ||
| 495 | 24 | mMatrix.preRotate(axis, radians); | |
| 496 |
3/10✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
24 | updateAcceleration(); |
| 497 | 21 | } | |
| 498 | void accumPreScale(const Vec3d& v) | ||
| 499 | { | ||
| 500 | 20 | mMatrix.preScale(v); | |
| 501 |
1/8✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
20 | updateAcceleration(); |
| 502 | 14 | } | |
| 503 | void accumPreTranslation(const Vec3d& v) | ||
| 504 | { | ||
| 505 | 4 | mMatrix.preTranslate(v); | |
| 506 |
1/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4 | updateAcceleration(); |
| 507 | 4 | } | |
| 508 | void accumPreShear(Axis axis0, Axis axis1, double shear) | ||
| 509 | { | ||
| 510 | 7 | mMatrix.preShear(axis0, axis1, shear); | |
| 511 |
3/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
7 | updateAcceleration(); |
| 512 | 7 | } | |
| 513 | //@} | ||
| 514 | |||
| 515 | |||
| 516 | //@{ | ||
| 517 | /// @brief Modify the existing affine map by post-applying the given operation. | ||
| 518 | void accumPostRotation(Axis axis, double radians) | ||
| 519 | { | ||
| 520 | 24 | mMatrix.postRotate(axis, radians); | |
| 521 |
3/13✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
24 | updateAcceleration(); |
| 522 | 23 | } | |
| 523 | void accumPostScale(const Vec3d& v) | ||
| 524 | { | ||
| 525 | 3 | mMatrix.postScale(v); | |
| 526 |
1/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
3 | updateAcceleration(); |
| 527 | 2 | } | |
| 528 | void accumPostTranslation(const Vec3d& v) | ||
| 529 | { | ||
| 530 | 12 | mMatrix.postTranslate(v); | |
| 531 |
2/8✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
38 | updateAcceleration(); |
| 532 | 35 | } | |
| 533 | void accumPostShear(Axis axis0, Axis axis1, double shear) | ||
| 534 | { | ||
| 535 | 7 | mMatrix.postShear(axis0, axis1, shear); | |
| 536 |
3/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
7 | updateAcceleration(); |
| 537 | 7 | } | |
| 538 | //@} | ||
| 539 | |||
| 540 | |||
| 541 | /// read serialization | ||
| 542 | 1 | void read(std::istream& is) override { mMatrix.read(is); updateAcceleration(); } | |
| 543 | /// write serialization | ||
| 544 | 1 | void write(std::ostream& os) const override { mMatrix.write(os); } | |
| 545 | /// string serialization, useful for debugging | ||
| 546 | ✗ | std::string str() const override | |
| 547 | { | ||
| 548 | ✗ | std::ostringstream buffer; | |
| 549 | ✗ | buffer << " - mat4:\n" << mMatrix.str() << std::endl; | |
| 550 | ✗ | buffer << " - voxel dimensions: " << mVoxelSize << std::endl; | |
| 551 | ✗ | return buffer.str(); | |
| 552 | } | ||
| 553 | |||
| 554 | /// on-demand decomposition of the affine map | ||
| 555 | SharedPtr<FullyDecomposedMap> createDecomposedMap() | ||
| 556 | { | ||
| 557 | return createFullyDecomposedMap(mMatrix); | ||
| 558 | } | ||
| 559 | |||
| 560 | /// Return AffineMap::Ptr to a deep copy of the current AffineMap | ||
| 561 | 165 | AffineMap::Ptr getAffineMap() const override { return AffineMap::Ptr(new AffineMap(*this)); } | |
| 562 | |||
| 563 | /// Return AffineMap::Ptr to the inverse of this map | ||
| 564 | AffineMap::Ptr inverse() const { return AffineMap::Ptr(new AffineMap(mMatrixInv)); } | ||
| 565 | |||
| 566 | |||
| 567 | //@{ | ||
| 568 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 569 | /// of prepending the appropraite operation. | ||
| 570 | 2 | MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const override | |
| 571 | { | ||
| 572 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 573 | affineMap->accumPreRotation(axis, radians); | ||
| 574 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
| 575 | } | ||
| 576 | 4 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
| 577 | { | ||
| 578 | 4 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 579 | affineMap->accumPreTranslation(t); | ||
| 580 | 4 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
| 581 | } | ||
| 582 | 14 | MapBase::Ptr preScale(const Vec3d& s) const override | |
| 583 | { | ||
| 584 | 14 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 585 | affineMap->accumPreScale(s); | ||
| 586 | 14 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
| 587 | } | ||
| 588 | 3 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
| 589 | { | ||
| 590 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 591 | affineMap->accumPreShear(axis0, axis1, shear); | ||
| 592 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
| 593 | } | ||
| 594 | //@} | ||
| 595 | |||
| 596 | |||
| 597 | //@{ | ||
| 598 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 599 | /// of postfixing the appropraite operation. | ||
| 600 | 6 | MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const override | |
| 601 | { | ||
| 602 | 6 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 603 | affineMap->accumPostRotation(axis, radians); | ||
| 604 |
2/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
18 | return simplify(affineMap); |
| 605 | } | ||
| 606 | 9 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
| 607 | { | ||
| 608 | 9 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 609 | affineMap->accumPostTranslation(t); | ||
| 610 | 9 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
| 611 | } | ||
| 612 | 2 | MapBase::Ptr postScale(const Vec3d& s) const override | |
| 613 | { | ||
| 614 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 615 | affineMap->accumPostScale(s); | ||
| 616 | 2 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
| 617 | } | ||
| 618 | 3 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
| 619 | { | ||
| 620 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 621 | affineMap->accumPostShear(axis0, axis1, shear); | ||
| 622 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
| 623 | } | ||
| 624 | //@} | ||
| 625 | |||
| 626 | /// Return the matrix representation of this AffineMap | ||
| 627 |
8/52✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ 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 not taken.
✗ Branch 74 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
|
19 | Mat4d getMat4() const { return mMatrix;} |
| 628 | const Mat4d& getConstMat4() const {return mMatrix;} | ||
| 629 | const Mat3d& getConstJacobianInv() const {return mJacobianInv;} | ||
| 630 | |||
| 631 | private: | ||
| 632 | 261 | void updateAcceleration() { | |
| 633 | Mat3d mat3 = mMatrix.getMat3(); | ||
| 634 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | mDeterminant = mat3.det(); |
| 635 | |||
| 636 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (std::abs(mDeterminant) < (3.0 * math::Tolerance<double>::value())) { |
| 637 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 638 | "Tried to initialize an affine transform from a nearly singular matrix"); | ||
| 639 | } | ||
| 640 | 261 | mMatrixInv = mMatrix.inverse(); | |
| 641 | 261 | mJacobianInv = mat3.inverse().transpose(); | |
| 642 | 261 | mIsDiagonal = math::isDiagonal(mMatrix); | |
| 643 | 261 | mIsIdentity = math::isIdentity(mMatrix); | |
| 644 | 261 | Vec3d pos = applyMap(Vec3d(0,0,0)); | |
| 645 | 261 | mVoxelSize(0) = (applyMap(Vec3d(1,0,0)) - pos).length(); | |
| 646 | 261 | mVoxelSize(1) = (applyMap(Vec3d(0,1,0)) - pos).length(); | |
| 647 | 261 | mVoxelSize(2) = (applyMap(Vec3d(0,0,1)) - pos).length(); | |
| 648 | 261 | } | |
| 649 | |||
| 650 | // the underlying matrix | ||
| 651 | Mat4d mMatrix; | ||
| 652 | |||
| 653 | // stored for acceleration | ||
| 654 | Mat4d mMatrixInv; | ||
| 655 | Mat3d mJacobianInv; | ||
| 656 | double mDeterminant; | ||
| 657 | Vec3d mVoxelSize; | ||
| 658 | bool mIsDiagonal, mIsIdentity; | ||
| 659 | }; // class AffineMap | ||
| 660 | |||
| 661 | |||
| 662 | //////////////////////////////////////// | ||
| 663 | |||
| 664 | |||
| 665 | /// @brief A specialized Affine transform that scales along the principal axis | ||
| 666 | /// the scaling need not be uniform in the three-directions | ||
| 667 | /// @note This class is not marked final because UniformScaleMap inherits from it, | ||
| 668 | /// so some of the member methods are marked final instead. | ||
| 669 | class OPENVDB_API ScaleMap: public MapBase | ||
| 670 | { | ||
| 671 | public: | ||
| 672 | using Ptr = SharedPtr<ScaleMap>; | ||
| 673 | using ConstPtr = SharedPtr<const ScaleMap>; | ||
| 674 | |||
| 675 | 5 | ScaleMap(): MapBase(), mScaleValues(Vec3d(1,1,1)), mVoxelSize(Vec3d(1,1,1)), | |
| 676 | mScaleValuesInverse(Vec3d(1,1,1)), | ||
| 677 | 13 | mInvScaleSqr(1,1,1), mInvTwiceScale(0.5,0.5,0.5){} | |
| 678 | |||
| 679 | 25898 | ScaleMap(const Vec3d& scale): | |
| 680 | MapBase(), | ||
| 681 | mScaleValues(scale), | ||
| 682 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25898 times.
|
25898 | mVoxelSize(Vec3d(std::abs(scale(0)),std::abs(scale(1)), std::abs(scale(2)))) |
| 683 | { | ||
| 684 | 25898 | double determinant = scale[0]* scale[1] * scale[2]; | |
| 685 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25898 times.
|
25898 | if (std::abs(determinant) < 3.0 * math::Tolerance<double>::value()) { |
| 686 | ✗ | OPENVDB_THROW(ArithmeticError, "Non-zero scale values required"); | |
| 687 | } | ||
| 688 | 25898 | mScaleValuesInverse = 1.0 / mScaleValues; | |
| 689 | 25898 | mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse; | |
| 690 | 25898 | mInvTwiceScale = mScaleValuesInverse / 2; | |
| 691 | 25898 | } | |
| 692 | |||
| 693 | 5854 | ScaleMap(const ScaleMap& other): | |
| 694 | MapBase(), | ||
| 695 | mScaleValues(other.mScaleValues), | ||
| 696 | mVoxelSize(other.mVoxelSize), | ||
| 697 | mScaleValuesInverse(other.mScaleValuesInverse), | ||
| 698 | mInvScaleSqr(other.mInvScaleSqr), | ||
| 699 | 1 | mInvTwiceScale(other.mInvTwiceScale) | |
| 700 | { | ||
| 701 | } | ||
| 702 | |||
| 703 |
2/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
79 | ~ScaleMap() override = default; |
| 704 | |||
| 705 | /// Return a MapBase::Ptr to a new ScaleMap | ||
| 706 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new ScaleMap()); } | |
| 707 | /// Return a MapBase::Ptr to a deep copy of this map | ||
| 708 | 1 | MapBase::Ptr copy() const override { return MapBase::Ptr(new ScaleMap(*this)); } | |
| 709 | |||
| 710 | 1 | MapBase::Ptr inverseMap() const override { | |
| 711 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | return MapBase::Ptr(new ScaleMap(mScaleValuesInverse)); |
| 712 | } | ||
| 713 | |||
| 714 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(ScaleMap::mapType()); } | |
| 715 | |||
| 716 | 338 | static void registerMap() | |
| 717 | { | ||
| 718 | 338 | MapRegistry::registerMap( | |
| 719 | 338 | ScaleMap::mapType(), | |
| 720 | ScaleMap::create); | ||
| 721 | 338 | } | |
| 722 | |||
| 723 | 28 | Name type() const override { return mapType(); } | |
| 724 |
5/116✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 335 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ 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 not taken.
✗ Branch 74 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 97 not taken.
✗ 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 222 not taken.
✗ Branch 223 not taken.
|
359 | static Name mapType() { return Name("ScaleMap"); } |
| 725 | |||
| 726 | /// Return @c true (a ScaleMap is always linear). | ||
| 727 | 1050231 | bool isLinear() const OPENVDB_MAP_FUNC_SPECIFIER { return true; } | |
| 728 | |||
| 729 | /// Return @c true if the values have the same magitude (eg. -1, 1, -1 would be a rotation). | ||
| 730 |
2/2✓ Branch 0 taken 806 times.
✓ Branch 1 taken 2 times.
|
808 | bool hasUniformScale() const OPENVDB_MAP_FUNC_SPECIFIER |
| 731 | { | ||
| 732 | bool value = isApproxEqual( | ||
| 733 | std::abs(mScaleValues.x()), std::abs(mScaleValues.y()), double(5e-7)); | ||
| 734 |
3/4✓ Branch 0 taken 806 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 806 times.
|
808 | value = value && isApproxEqual( |
| 735 | std::abs(mScaleValues.x()), std::abs(mScaleValues.z()), double(5e-7)); | ||
| 736 | 808 | return value; | |
| 737 | } | ||
| 738 | |||
| 739 | /// Return the image of @c in under the map | ||
| 740 | 4372430807 | Vec3d applyMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
| 741 | { | ||
| 742 | return Vec3d( | ||
| 743 | in.x() * mScaleValues.x(), | ||
| 744 | in.y() * mScaleValues.y(), | ||
| 745 |
0/60✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
4372636682 | in.z() * mScaleValues.z()); |
| 746 | } | ||
| 747 | /// Return the pre-image of @c in under the map | ||
| 748 | 4474252314 | Vec3d applyInverseMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
| 749 | { | ||
| 750 | return Vec3d( | ||
| 751 | in.x() * mScaleValuesInverse.x(), | ||
| 752 | in.y() * mScaleValuesInverse.y(), | ||
| 753 |
0/16✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
4480744178 | in.z() * mScaleValuesInverse.z()); |
| 754 | } | ||
| 755 | /// Return the Jacobian of the map applied to @a in. | ||
| 756 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 757 | ✗ | return applyJacobian(in); | |
| 758 | } | ||
| 759 | /// Return the Jacobian of the map applied to @a in. | ||
| 760 | 205869 | Vec3d applyJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyMap(in); } | |
| 761 | |||
| 762 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 763 | /// (i.e. inverse map with out translation) | ||
| 764 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 765 | ✗ | return applyInverseJacobian(in); | |
| 766 | } | ||
| 767 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 768 | /// (i.e. inverse map with out translation) | ||
| 769 | 1048584 | Vec3d applyInverseJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 770 | 1048584 | return applyInverseMap(in); | |
| 771 | } | ||
| 772 | |||
| 773 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
| 774 | /// @details This tranforms range-space gradients to domain-space gradients | ||
| 775 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return applyJT(in); } | |
| 776 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
| 777 | ✗ | Vec3d applyJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyMap(in); } | |
| 778 | |||
| 779 | /// @brief Return the transpose of the inverse Jacobian of the map applied to @a in. | ||
| 780 | /// @details Ignores second argument | ||
| 781 | 4 | Vec3d applyIJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 782 | 4 | return applyIJT(in); | |
| 783 | } | ||
| 784 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
| 785 | ✗ | Vec3d applyIJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyInverseMap(in); } | |
| 786 | /// Return the Jacobian Curvature: zero for a linear map | ||
| 787 | 6 | Mat3d applyIJC(const Mat3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
| 788 | { | ||
| 789 | Mat3d tmp; | ||
| 790 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 18 times.
|
24 | for (int i = 0; i < 3; i++) { |
| 791 | tmp.setRow(i, in.row(i) * mScaleValuesInverse(i)); | ||
| 792 | } | ||
| 793 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
|
24 | for (int i = 0; i < 3; i++) { |
| 794 | tmp.setCol(i, tmp.col(i) * mScaleValuesInverse(i)); | ||
| 795 | } | ||
| 796 | 6 | return tmp; | |
| 797 | } | ||
| 798 | 6 | Mat3d applyIJC(const Mat3d& in, const Vec3d&, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 799 | 6 | return applyIJC(in); | |
| 800 | } | ||
| 801 | /// Return the product of the scale values, ignores argument | ||
| 802 | ✗ | double determinant(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return determinant(); } | |
| 803 | /// Return the product of the scale values | ||
| 804 | 11 | double determinant() const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 805 | 11 | return mScaleValues.x() * mScaleValues.y() * mScaleValues.z(); | |
| 806 | } | ||
| 807 | |||
| 808 | /// Return the scale values that define the map | ||
| 809 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | const Vec3d& getScale() const {return mScaleValues;} |
| 810 | |||
| 811 | /// Return the square of the scale. Used to optimize some finite difference calculations | ||
| 812 | const Vec3d& getInvScaleSqr() const { return mInvScaleSqr; } | ||
| 813 | /// Return 1/(2 scale). Used to optimize some finite difference calculations | ||
| 814 | const Vec3d& getInvTwiceScale() const { return mInvTwiceScale; } | ||
| 815 | /// Return 1/(scale) | ||
| 816 | const Vec3d& getInvScale() const { return mScaleValuesInverse; } | ||
| 817 | |||
| 818 | //@{ | ||
| 819 | /// @brief Return the lengths of the images of the segments | ||
| 820 | /// (0,0,0) − 1,0,0), (0,0,0) − (0,1,0) and (0,0,0) − (0,0,1). | ||
| 821 | /// @details This is equivalent to the absolute values of the scale values | ||
| 822 | 396662 | Vec3d voxelSize() const OPENVDB_MAP_FUNC_SPECIFIER { return mVoxelSize; } | |
| 823 | 62 | Vec3d voxelSize(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return voxelSize(); } | |
| 824 | //@} | ||
| 825 | |||
| 826 | /// read serialization | ||
| 827 | 135 | void read(std::istream& is) override | |
| 828 | { | ||
| 829 | mScaleValues.read(is); | ||
| 830 | mVoxelSize.read(is); | ||
| 831 | mScaleValuesInverse.read(is); | ||
| 832 | mInvScaleSqr.read(is); | ||
| 833 | mInvTwiceScale.read(is); | ||
| 834 | 135 | } | |
| 835 | /// write serialization | ||
| 836 | 164 | void write(std::ostream& os) const override | |
| 837 | { | ||
| 838 | mScaleValues.write(os); | ||
| 839 | mVoxelSize.write(os); | ||
| 840 | mScaleValuesInverse.write(os); | ||
| 841 | mInvScaleSqr.write(os); | ||
| 842 | mInvTwiceScale.write(os); | ||
| 843 | 164 | } | |
| 844 | /// string serialization, useful for debuging | ||
| 845 | ✗ | std::string str() const override | |
| 846 | { | ||
| 847 | ✗ | std::ostringstream buffer; | |
| 848 | ✗ | buffer << " - scale: " << mScaleValues << std::endl; | |
| 849 | ✗ | buffer << " - voxel dimensions: " << mVoxelSize << std::endl; | |
| 850 | ✗ | return buffer.str(); | |
| 851 | } | ||
| 852 | |||
| 853 | 1 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 854 | |||
| 855 | bool operator==(const ScaleMap& other) const | ||
| 856 | { | ||
| 857 | // ::eq() uses a tolerance | ||
| 858 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 6236 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
6237 | if (!mScaleValues.eq(other.mScaleValues)) { return false; } |
| 859 | return true; | ||
| 860 | } | ||
| 861 | |||
| 862 | bool operator!=(const ScaleMap& other) const { return !(*this == other); } | ||
| 863 | |||
| 864 | /// Return a AffineMap equivalent to this map | ||
| 865 | 46 | AffineMap::Ptr getAffineMap() const override | |
| 866 | { | ||
| 867 |
1/2✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
|
92 | return AffineMap::Ptr(new AffineMap(math::scale<Mat4d>(mScaleValues))); |
| 868 | } | ||
| 869 | |||
| 870 | |||
| 871 | |||
| 872 | //@{ | ||
| 873 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 874 | /// of prepending the appropraite operation to the existing map | ||
| 875 | 16 | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
| 876 | { | ||
| 877 | 16 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 878 | affineMap->accumPreRotation(axis, radians); | ||
| 879 |
2/6✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
48 | return simplify(affineMap); |
| 880 | } | ||
| 881 | |||
| 882 | MapBase::Ptr preTranslate(const Vec3d&) const override; | ||
| 883 | MapBase::Ptr preScale(const Vec3d&) const override; | ||
| 884 | 2 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
| 885 | { | ||
| 886 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 887 | affineMap->accumPreShear(axis0, axis1, shear); | ||
| 888 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
| 889 | } | ||
| 890 | //@} | ||
| 891 | |||
| 892 | |||
| 893 | //@{ | ||
| 894 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 895 | /// of prepending the appropraite operation to the existing map. | ||
| 896 | 4 | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
| 897 | { | ||
| 898 | 4 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 899 | affineMap->accumPostRotation(axis, radians); | ||
| 900 |
2/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
12 | return simplify(affineMap); |
| 901 | } | ||
| 902 | MapBase::Ptr postTranslate(const Vec3d&) const override; | ||
| 903 | MapBase::Ptr postScale(const Vec3d&) const override; | ||
| 904 | 2 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
| 905 | { | ||
| 906 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 907 | affineMap->accumPostShear(axis0, axis1, shear); | ||
| 908 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
| 909 | } | ||
| 910 | //@} | ||
| 911 | |||
| 912 | private: | ||
| 913 | Vec3d mScaleValues, mVoxelSize, mScaleValuesInverse, mInvScaleSqr, mInvTwiceScale; | ||
| 914 | }; // class ScaleMap | ||
| 915 | |||
| 916 | |||
| 917 | /// @brief A specialized Affine transform that scales along the principal axis | ||
| 918 | /// the scaling is uniform in the three-directions | ||
| 919 | /// @note This class is marked final with ABI=8 | ||
| 920 | class OPENVDB_API UniformScaleMap OPENVDB_MAP_CLASS_SPECIFIER: public ScaleMap | ||
| 921 | { | ||
| 922 | public: | ||
| 923 | using Ptr = SharedPtr<UniformScaleMap>; | ||
| 924 | using ConstPtr = SharedPtr<const UniformScaleMap>; | ||
| 925 | |||
| 926 |
13/21✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
|
154 | UniformScaleMap(): ScaleMap(Vec3d(1,1,1)) {} |
| 927 |
12/26✓ Branch 1 taken 25700 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
|
25707 | UniformScaleMap(double scale): ScaleMap(Vec3d(scale, scale, scale)) {} |
| 928 |
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.
|
5842 | UniformScaleMap(const UniformScaleMap& other): ScaleMap(other) {} |
| 929 |
6/14✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
31683 | ~UniformScaleMap() override = default; |
| 930 | |||
| 931 | /// Return a MapBase::Ptr to a new UniformScaleMap | ||
| 932 | 270 | static MapBase::Ptr create() { return MapBase::Ptr(new UniformScaleMap()); } | |
| 933 | /// Return a MapBase::Ptr to a deep copy of this map | ||
| 934 | 5840 | MapBase::Ptr copy() const override { return MapBase::Ptr(new UniformScaleMap(*this)); } | |
| 935 | |||
| 936 | ✗ | MapBase::Ptr inverseMap() const override | |
| 937 | { | ||
| 938 | const Vec3d& invScale = getInvScale(); | ||
| 939 | ✗ | return MapBase::Ptr(new UniformScaleMap( invScale[0])); | |
| 940 | } | ||
| 941 | |||
| 942 | 1 | static bool isRegistered() { return MapRegistry::isRegistered(UniformScaleMap::mapType()); } | |
| 943 | 337 | static void registerMap() | |
| 944 | { | ||
| 945 | 337 | MapRegistry::registerMap( | |
| 946 | 337 | UniformScaleMap::mapType(), | |
| 947 | UniformScaleMap::create); | ||
| 948 | 337 | } | |
| 949 | |||
| 950 | 101120 | Name type() const override { return mapType(); } | |
| 951 |
27/146✓ Branch 2 taken 59629 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 32 times.
✓ Branch 7 taken 333 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 25 taken 6 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 49 taken 2 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✓ Branch 57 taken 1 times.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 73 taken 1 times.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✓ Branch 85 taken 1 times.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✓ Branch 89 taken 2 times.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✓ Branch 105 taken 1 times.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✓ Branch 121 taken 1 times.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✓ Branch 125 taken 4 times.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✓ Branch 129 taken 12 times.
✗ 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 taken 2 times.
✗ 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 taken 1 times.
✗ Branch 174 not taken.
✓ Branch 177 taken 1 times.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✓ Branch 189 taken 1 times.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✓ Branch 201 taken 5 times.
✗ 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 222 not taken.
✗ Branch 223 not taken.
|
110603 | static Name mapType() { return Name("UniformScaleMap"); } |
| 952 | |||
| 953 | 6236 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 954 | |||
| 955 | bool operator==(const UniformScaleMap& other) const { return ScaleMap::operator==(other); } | ||
| 956 | bool operator!=(const UniformScaleMap& other) const { return !(*this == other); } | ||
| 957 | |||
| 958 | /// @brief Return a MapBase::Ptr to a UniformScaleTraslateMap that is the result of | ||
| 959 | /// pre-translation on this map | ||
| 960 | MapBase::Ptr preTranslate(const Vec3d&) const override; | ||
| 961 | |||
| 962 | /// @brief Return a MapBase::Ptr to a UniformScaleTraslateMap that is the result of | ||
| 963 | /// post-translation on this map | ||
| 964 | MapBase::Ptr postTranslate(const Vec3d&) const override; | ||
| 965 | |||
| 966 | }; // class UniformScaleMap | ||
| 967 | |||
| 968 | |||
| 969 | //////////////////////////////////////// | ||
| 970 | |||
| 971 | |||
| 972 | inline MapBase::Ptr | ||
| 973 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
|
19 | ScaleMap::preScale(const Vec3d& v) const |
| 974 | { | ||
| 975 | const Vec3d new_scale(v * mScaleValues); | ||
| 976 |
4/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1 times.
|
19 | if (isApproxEqual(new_scale[0],new_scale[1]) && isApproxEqual(new_scale[0],new_scale[2])) { |
| 977 | 10 | return MapBase::Ptr(new UniformScaleMap(new_scale[0])); | |
| 978 | } else { | ||
| 979 |
1/2✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | return MapBase::Ptr(new ScaleMap(new_scale)); |
| 980 | } | ||
| 981 | } | ||
| 982 | |||
| 983 | |||
| 984 | inline MapBase::Ptr | ||
| 985 | 1 | ScaleMap::postScale(const Vec3d& v) const | |
| 986 | { // pre-post Scale are the same for a scale map | ||
| 987 | 3 | return preScale(v); | |
| 988 | } | ||
| 989 | |||
| 990 | |||
| 991 | /// @brief A specialized linear transform that performs a translation | ||
| 992 | /// @note This class is marked final with ABI=8 | ||
| 993 | class OPENVDB_API TranslationMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
| 994 | { | ||
| 995 | public: | ||
| 996 | using Ptr = SharedPtr<TranslationMap>; | ||
| 997 | using ConstPtr = SharedPtr<const TranslationMap>; | ||
| 998 | |||
| 999 | // default constructor is a translation by zero. | ||
| 1000 |
3/5✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
6 | TranslationMap(): MapBase(), mTranslation(Vec3d(0,0,0)) {} |
| 1001 |
7/14✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
|
10 | TranslationMap(const Vec3d& t): MapBase(), mTranslation(t) {} |
| 1002 | ✗ | TranslationMap(const TranslationMap& other): MapBase(), mTranslation(other.mTranslation) {} | |
| 1003 | |||
| 1004 |
4/12✓ 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 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
12 | ~TranslationMap() override = default; |
| 1005 | |||
| 1006 | /// Return a MapBase::Ptr to a new TranslationMap | ||
| 1007 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new TranslationMap()); } | |
| 1008 | /// Return a MapBase::Ptr to a deep copy of this map | ||
| 1009 | ✗ | MapBase::Ptr copy() const override { return MapBase::Ptr(new TranslationMap(*this)); } | |
| 1010 | |||
| 1011 | 1 | MapBase::Ptr inverseMap() const override { | |
| 1012 | 1 | return MapBase::Ptr(new TranslationMap(-mTranslation)); | |
| 1013 | } | ||
| 1014 | |||
| 1015 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(TranslationMap::mapType()); } | |
| 1016 | |||
| 1017 | 338 | static void registerMap() | |
| 1018 | { | ||
| 1019 | 338 | MapRegistry::registerMap( | |
| 1020 | 338 | TranslationMap::mapType(), | |
| 1021 | TranslationMap::create); | ||
| 1022 | 338 | } | |
| 1023 | |||
| 1024 | 2 | Name type() const override { return mapType(); } | |
| 1025 |
3/144✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 341 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 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 222 not taken.
✗ Branch 223 not taken.
|
343 | static Name mapType() { return Name("TranslationMap"); } |
| 1026 | |||
| 1027 | /// Return @c true (a TranslationMap is always linear). | ||
| 1028 | ✗ | bool isLinear() const override { return true; } | |
| 1029 | |||
| 1030 | /// Return @c false (by convention true) | ||
| 1031 | ✗ | bool hasUniformScale() const override { return true; } | |
| 1032 | |||
| 1033 | /// Return the image of @c in under the map | ||
| 1034 | 1 | Vec3d applyMap(const Vec3d& in) const override { return in + mTranslation; } | |
| 1035 | /// Return the pre-image of @c in under the map | ||
| 1036 | ✗ | Vec3d applyInverseMap(const Vec3d& in) const override { return in - mTranslation; } | |
| 1037 | /// Return the Jacobian of the map applied to @a in. | ||
| 1038 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const override { return applyJacobian(in); } | |
| 1039 | /// Return the Jacobian of the map applied to @a in. | ||
| 1040 | ✗ | Vec3d applyJacobian(const Vec3d& in) const override { return in; } | |
| 1041 | |||
| 1042 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 1043 | /// (i.e. inverse map with out translation) | ||
| 1044 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const override { | |
| 1045 | ✗ | return applyInverseJacobian(in); | |
| 1046 | } | ||
| 1047 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 1048 | /// (i.e. inverse map with out translation) | ||
| 1049 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { return in; } | |
| 1050 | |||
| 1051 | |||
| 1052 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
| 1053 | /// @details This tranforms range-space gradients to domain-space gradients | ||
| 1054 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const override { return applyJT(in); } | |
| 1055 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
| 1056 | 1 | Vec3d applyJT(const Vec3d& in) const override { return in; } | |
| 1057 | |||
| 1058 | /// @brief Return the transpose of the inverse Jacobian (Identity for TranslationMap) | ||
| 1059 | /// of the map applied to @c in, ignores second argument | ||
| 1060 | ✗ | Vec3d applyIJT(const Vec3d& in, const Vec3d& ) const override { return applyIJT(in);} | |
| 1061 | /// @brief Return the transpose of the inverse Jacobian (Identity for TranslationMap) | ||
| 1062 | /// of the map applied to @c in | ||
| 1063 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Vec3d applyIJT(const Vec3d& in) const override {return in;} |
| 1064 | /// Return the Jacobian Curvature: zero for a linear map | ||
| 1065 | ✗ | Mat3d applyIJC(const Mat3d& mat) const override {return mat;} | |
| 1066 | ✗ | Mat3d applyIJC(const Mat3d& mat, const Vec3d&, const Vec3d&) const override { | |
| 1067 | ✗ | return applyIJC(mat); | |
| 1068 | } | ||
| 1069 | |||
| 1070 | /// Return @c 1 | ||
| 1071 | ✗ | double determinant(const Vec3d& ) const override { return determinant(); } | |
| 1072 | /// Return @c 1 | ||
| 1073 | ✗ | double determinant() const override { return 1.0; } | |
| 1074 | |||
| 1075 | /// Return (1,1,1). | ||
| 1076 | ✗ | Vec3d voxelSize() const override { return Vec3d(1,1,1);} | |
| 1077 | /// Return (1,1,1). | ||
| 1078 | ✗ | Vec3d voxelSize(const Vec3d&) const override { return voxelSize();} | |
| 1079 | |||
| 1080 | /// Return the translation vector | ||
| 1081 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | const Vec3d& getTranslation() const { return mTranslation; } |
| 1082 | |||
| 1083 | /// read serialization | ||
| 1084 | ✗ | void read(std::istream& is) override { mTranslation.read(is); } | |
| 1085 | /// write serialization | ||
| 1086 | ✗ | void write(std::ostream& os) const override { mTranslation.write(os); } | |
| 1087 | /// string serialization, useful for debuging | ||
| 1088 | ✗ | std::string str() const override | |
| 1089 | { | ||
| 1090 | ✗ | std::ostringstream buffer; | |
| 1091 | ✗ | buffer << " - translation: " << mTranslation << std::endl; | |
| 1092 | ✗ | return buffer.str(); | |
| 1093 | } | ||
| 1094 | |||
| 1095 | ✗ | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 1096 | |||
| 1097 | bool operator==(const TranslationMap& other) const | ||
| 1098 | { | ||
| 1099 | // ::eq() uses a tolerance | ||
| 1100 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | return mTranslation.eq(other.mTranslation); |
| 1101 | } | ||
| 1102 | |||
| 1103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const TranslationMap& other) const { return !(*this == other); } |
| 1104 | |||
| 1105 | /// Return AffineMap::Ptr to an AffineMap equivalent to *this | ||
| 1106 | 1 | AffineMap::Ptr getAffineMap() const override | |
| 1107 | { | ||
| 1108 | 1 | Mat4d matrix(Mat4d::identity()); | |
| 1109 | matrix.setTranslation(mTranslation); | ||
| 1110 | |||
| 1111 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | AffineMap::Ptr affineMap(new AffineMap(matrix)); |
| 1112 | 1 | return affineMap; | |
| 1113 | } | ||
| 1114 | |||
| 1115 | //@{ | ||
| 1116 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1117 | /// of prepending the appropriate operation. | ||
| 1118 | ✗ | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
| 1119 | { | ||
| 1120 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1121 | affineMap->accumPreRotation(axis, radians); | ||
| 1122 | ✗ | return simplify(affineMap); | |
| 1123 | |||
| 1124 | } | ||
| 1125 | ✗ | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
| 1126 | { | ||
| 1127 | ✗ | return MapBase::Ptr(new TranslationMap(t + mTranslation)); | |
| 1128 | } | ||
| 1129 | |||
| 1130 | MapBase::Ptr preScale(const Vec3d& v) const override; | ||
| 1131 | |||
| 1132 | ✗ | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
| 1133 | { | ||
| 1134 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1135 | affineMap->accumPreShear(axis0, axis1, shear); | ||
| 1136 | ✗ | return simplify(affineMap); | |
| 1137 | } | ||
| 1138 | //@} | ||
| 1139 | |||
| 1140 | //@{ | ||
| 1141 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1142 | /// of postfixing the appropriate operation. | ||
| 1143 | ✗ | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
| 1144 | { | ||
| 1145 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1146 | affineMap->accumPostRotation(axis, radians); | ||
| 1147 | ✗ | return simplify(affineMap); | |
| 1148 | |||
| 1149 | } | ||
| 1150 | ✗ | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
| 1151 | { // post and pre are the same for this | ||
| 1152 | ✗ | return MapBase::Ptr(new TranslationMap(t + mTranslation)); | |
| 1153 | } | ||
| 1154 | |||
| 1155 | MapBase::Ptr postScale(const Vec3d& v) const override; | ||
| 1156 | |||
| 1157 | ✗ | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
| 1158 | { | ||
| 1159 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1160 | affineMap->accumPostShear(axis0, axis1, shear); | ||
| 1161 | ✗ | return simplify(affineMap); | |
| 1162 | } | ||
| 1163 | //@} | ||
| 1164 | |||
| 1165 | private: | ||
| 1166 | Vec3d mTranslation; | ||
| 1167 | }; // class TranslationMap | ||
| 1168 | |||
| 1169 | |||
| 1170 | //////////////////////////////////////// | ||
| 1171 | |||
| 1172 | |||
| 1173 | /// @brief A specialized Affine transform that scales along the principal axis | ||
| 1174 | /// the scaling need not be uniform in the three-directions, and then | ||
| 1175 | /// translates the result. | ||
| 1176 | /// @note This class is not marked final because UniformScaleMap inherits from it, | ||
| 1177 | /// so some of the member methods are marked final instead. | ||
| 1178 | class OPENVDB_API ScaleTranslateMap: public MapBase | ||
| 1179 | { | ||
| 1180 | public: | ||
| 1181 | using Ptr = SharedPtr<ScaleTranslateMap>; | ||
| 1182 | using ConstPtr = SharedPtr<const ScaleTranslateMap>; | ||
| 1183 | |||
| 1184 | 1 | ScaleTranslateMap(): | |
| 1185 | MapBase(), | ||
| 1186 | mTranslation(Vec3d(0,0,0)), | ||
| 1187 | mScaleValues(Vec3d(1,1,1)), | ||
| 1188 | mVoxelSize(Vec3d(1,1,1)), | ||
| 1189 | mScaleValuesInverse(Vec3d(1,1,1)), | ||
| 1190 | mInvScaleSqr(1,1,1), | ||
| 1191 | 9 | mInvTwiceScale(0.5,0.5,0.5) | |
| 1192 | { | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | 49 | ScaleTranslateMap(const Vec3d& scale, const Vec3d& translate): | |
| 1196 | MapBase(), | ||
| 1197 | mTranslation(translate), | ||
| 1198 | mScaleValues(scale), | ||
| 1199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
|
49 | mVoxelSize(std::abs(scale(0)), std::abs(scale(1)), std::abs(scale(2))) |
| 1200 | { | ||
| 1201 | 49 | const double determinant = scale[0]* scale[1] * scale[2]; | |
| 1202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
|
49 | if (std::abs(determinant) < 3.0 * math::Tolerance<double>::value()) { |
| 1203 | ✗ | OPENVDB_THROW(ArithmeticError, "Non-zero scale values required"); | |
| 1204 | } | ||
| 1205 | 49 | mScaleValuesInverse = 1.0 / mScaleValues; | |
| 1206 | 49 | mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse; | |
| 1207 | 49 | mInvTwiceScale = mScaleValuesInverse / 2; | |
| 1208 | 49 | } | |
| 1209 | |||
| 1210 | 2 | ScaleTranslateMap(const ScaleMap& scale, const TranslationMap& translate): | |
| 1211 | MapBase(), | ||
| 1212 | mTranslation(translate.getTranslation()), | ||
| 1213 | mScaleValues(scale.getScale()), | ||
| 1214 | mVoxelSize(std::abs(mScaleValues(0)), | ||
| 1215 | std::abs(mScaleValues(1)), | ||
| 1216 | std::abs(mScaleValues(2))), | ||
| 1217 | 2 | mScaleValuesInverse(1.0 / scale.getScale()) | |
| 1218 | { | ||
| 1219 | 2 | mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse; | |
| 1220 | 2 | mInvTwiceScale = mScaleValuesInverse / 2; | |
| 1221 | 2 | } | |
| 1222 | |||
| 1223 | 1 | ScaleTranslateMap(const ScaleTranslateMap& other): | |
| 1224 | MapBase(), | ||
| 1225 | mTranslation(other.mTranslation), | ||
| 1226 | mScaleValues(other.mScaleValues), | ||
| 1227 | mVoxelSize(other.mVoxelSize), | ||
| 1228 | mScaleValuesInverse(other.mScaleValuesInverse), | ||
| 1229 | mInvScaleSqr(other.mInvScaleSqr), | ||
| 1230 | ✗ | mInvTwiceScale(other.mInvTwiceScale) | |
| 1231 | {} | ||
| 1232 | |||
| 1233 |
1/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
37 | ~ScaleTranslateMap() override = default; |
| 1234 | |||
| 1235 | /// Return a MapBase::Ptr to a new ScaleTranslateMap | ||
| 1236 | 1 | static MapBase::Ptr create() { return MapBase::Ptr(new ScaleTranslateMap()); } | |
| 1237 | /// Return a MapBase::Ptr to a deep copy of this map | ||
| 1238 | ✗ | MapBase::Ptr copy() const override { return MapBase::Ptr(new ScaleTranslateMap(*this)); } | |
| 1239 | |||
| 1240 | 1 | MapBase::Ptr inverseMap() const override | |
| 1241 | { | ||
| 1242 | return MapBase::Ptr(new ScaleTranslateMap( | ||
| 1243 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | mScaleValuesInverse, -mScaleValuesInverse * mTranslation)); |
| 1244 | } | ||
| 1245 | |||
| 1246 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(ScaleTranslateMap::mapType()); } | |
| 1247 | |||
| 1248 | 338 | static void registerMap() | |
| 1249 | { | ||
| 1250 | 338 | MapRegistry::registerMap( | |
| 1251 | 338 | ScaleTranslateMap::mapType(), | |
| 1252 | ScaleTranslateMap::create); | ||
| 1253 | 338 | } | |
| 1254 | |||
| 1255 | 8 | Name type() const override { return mapType(); } | |
| 1256 |
6/119✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 335 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ 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 not taken.
✗ Branch 74 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 97 not taken.
✗ 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 222 not taken.
✗ Branch 223 not taken.
|
348 | static Name mapType() { return Name("ScaleTranslateMap"); } |
| 1257 | |||
| 1258 | /// Return @c true (a ScaleTranslateMap is always linear). | ||
| 1259 | 8 | bool isLinear() const OPENVDB_MAP_FUNC_SPECIFIER { return true; } | |
| 1260 | |||
| 1261 | /// @brief Return @c true if the scale values have the same magnitude | ||
| 1262 | /// (eg. -1, 1, -1 would be a rotation). | ||
| 1263 | ✗ | bool hasUniformScale() const OPENVDB_MAP_FUNC_SPECIFIER | |
| 1264 | { | ||
| 1265 | bool value = isApproxEqual( | ||
| 1266 | std::abs(mScaleValues.x()), std::abs(mScaleValues.y()), double(5e-7)); | ||
| 1267 |
3/12✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
2 | value = value && isApproxEqual( |
| 1268 | std::abs(mScaleValues.x()), std::abs(mScaleValues.z()), double(5e-7)); | ||
| 1269 | ✗ | return value; | |
| 1270 | } | ||
| 1271 | |||
| 1272 | /// Return the image of @c under the map | ||
| 1273 | 9051559 | Vec3d applyMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
| 1274 | { | ||
| 1275 | return Vec3d( | ||
| 1276 |
0/60✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
9051560 | in.x() * mScaleValues.x() + mTranslation.x(), |
| 1277 |
4/64✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
9051564 | in.y() * mScaleValues.y() + mTranslation.y(), |
| 1278 |
4/64✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
9051564 | in.z() * mScaleValues.z() + mTranslation.z()); |
| 1279 | } | ||
| 1280 | /// Return the pre-image of @c under the map | ||
| 1281 | 22 | Vec3d applyInverseMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
| 1282 | { | ||
| 1283 | return Vec3d( | ||
| 1284 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
24 | (in.x() - mTranslation.x() ) * mScaleValuesInverse.x(), |
| 1285 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
24 | (in.y() - mTranslation.y() ) * mScaleValuesInverse.y(), |
| 1286 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
24 | (in.z() - mTranslation.z() ) * mScaleValuesInverse.z()); |
| 1287 | } | ||
| 1288 | |||
| 1289 | /// Return the Jacobian of the map applied to @a in. | ||
| 1290 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 1291 | ✗ | return applyJacobian(in); | |
| 1292 | } | ||
| 1293 | /// Return the Jacobian of the map applied to @a in. | ||
| 1294 | 2 | Vec3d applyJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return in * mScaleValues; } | |
| 1295 | |||
| 1296 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 1297 | /// (i.e. inverse map with out translation) | ||
| 1298 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 1299 | ✗ | return applyInverseJacobian(in); | |
| 1300 | } | ||
| 1301 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 1302 | /// (i.e. inverse map with out translation) | ||
| 1303 | 2 | Vec3d applyInverseJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 1304 | 2 | return in * mScaleValuesInverse; | |
| 1305 | } | ||
| 1306 | |||
| 1307 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
| 1308 | /// @details This tranforms range-space gradients to domain-space gradients | ||
| 1309 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return applyJT(in); } | |
| 1310 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
| 1311 | ✗ | Vec3d applyJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyJacobian(in); } | |
| 1312 | |||
| 1313 | /// @brief Return the transpose of the inverse Jacobian of the map applied to @a in | ||
| 1314 | /// @details Ignores second argument | ||
| 1315 | ✗ | Vec3d applyIJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 1316 | ✗ | return applyIJT(in); | |
| 1317 | } | ||
| 1318 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
| 1319 | ✗ | Vec3d applyIJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
| 1320 | { | ||
| 1321 | return Vec3d( | ||
| 1322 | in.x() * mScaleValuesInverse.x(), | ||
| 1323 | in.y() * mScaleValuesInverse.y(), | ||
| 1324 |
4/16✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
4 | in.z() * mScaleValuesInverse.z()); |
| 1325 | } | ||
| 1326 | /// Return the Jacobian Curvature: zero for a linear map | ||
| 1327 | ✗ | Mat3d applyIJC(const Mat3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
| 1328 | { | ||
| 1329 | Mat3d tmp; | ||
| 1330 | ✗ | for (int i=0; i<3; i++){ | |
| 1331 | tmp.setRow(i, in.row(i)*mScaleValuesInverse(i)); | ||
| 1332 | } | ||
| 1333 | ✗ | for (int i=0; i<3; i++){ | |
| 1334 | tmp.setCol(i, tmp.col(i)*mScaleValuesInverse(i)); | ||
| 1335 | } | ||
| 1336 | ✗ | return tmp; | |
| 1337 | } | ||
| 1338 | ✗ | Mat3d applyIJC(const Mat3d& in, const Vec3d&, const Vec3d& ) const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 1339 | ✗ | return applyIJC(in); | |
| 1340 | } | ||
| 1341 | |||
| 1342 | /// Return the product of the scale values, ignores argument | ||
| 1343 | ✗ | double determinant(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return determinant(); } | |
| 1344 | /// Return the product of the scale values | ||
| 1345 | ✗ | double determinant() const OPENVDB_MAP_FUNC_SPECIFIER { | |
| 1346 | ✗ | return mScaleValues.x() * mScaleValues.y() * mScaleValues.z(); | |
| 1347 | } | ||
| 1348 | /// Return the absolute values of the scale values | ||
| 1349 | 16 | Vec3d voxelSize() const OPENVDB_MAP_FUNC_SPECIFIER { return mVoxelSize;} | |
| 1350 | /// Return the absolute values of the scale values, ignores argument | ||
| 1351 | ✗ | Vec3d voxelSize(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return voxelSize();} | |
| 1352 | |||
| 1353 | /// Returns the scale values | ||
| 1354 | const Vec3d& getScale() const { return mScaleValues; } | ||
| 1355 | /// Returns the translation | ||
| 1356 | const Vec3d& getTranslation() const { return mTranslation; } | ||
| 1357 | |||
| 1358 | /// Return the square of the scale. Used to optimize some finite difference calculations | ||
| 1359 | const Vec3d& getInvScaleSqr() const {return mInvScaleSqr;} | ||
| 1360 | /// Return 1/(2 scale). Used to optimize some finite difference calculations | ||
| 1361 | const Vec3d& getInvTwiceScale() const {return mInvTwiceScale;} | ||
| 1362 | /// Return 1/(scale) | ||
| 1363 | const Vec3d& getInvScale() const {return mScaleValuesInverse; } | ||
| 1364 | |||
| 1365 | /// read serialization | ||
| 1366 | 1 | void read(std::istream& is) override | |
| 1367 | { | ||
| 1368 | mTranslation.read(is); | ||
| 1369 | mScaleValues.read(is); | ||
| 1370 | mVoxelSize.read(is); | ||
| 1371 | mScaleValuesInverse.read(is); | ||
| 1372 | mInvScaleSqr.read(is); | ||
| 1373 | mInvTwiceScale.read(is); | ||
| 1374 | 1 | } | |
| 1375 | /// write serialization | ||
| 1376 | 1 | void write(std::ostream& os) const override | |
| 1377 | { | ||
| 1378 | mTranslation.write(os); | ||
| 1379 | mScaleValues.write(os); | ||
| 1380 | mVoxelSize.write(os); | ||
| 1381 | mScaleValuesInverse.write(os); | ||
| 1382 | mInvScaleSqr.write(os); | ||
| 1383 | mInvTwiceScale.write(os); | ||
| 1384 | 1 | } | |
| 1385 | /// string serialization, useful for debuging | ||
| 1386 | ✗ | std::string str() const override | |
| 1387 | { | ||
| 1388 | ✗ | std::ostringstream buffer; | |
| 1389 | ✗ | buffer << " - translation: " << mTranslation << std::endl; | |
| 1390 | ✗ | buffer << " - scale: " << mScaleValues << std::endl; | |
| 1391 | ✗ | buffer << " - voxel dimensions: " << mVoxelSize << std::endl; | |
| 1392 | ✗ | return buffer.str(); | |
| 1393 | } | ||
| 1394 | |||
| 1395 | ✗ | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 1396 | |||
| 1397 | 5 | bool operator==(const ScaleTranslateMap& other) const | |
| 1398 | { | ||
| 1399 | // ::eq() uses a tolerance | ||
| 1400 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (!mScaleValues.eq(other.mScaleValues)) { return false; } |
| 1401 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | if (!mTranslation.eq(other.mTranslation)) { return false; } |
| 1402 | return true; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const ScaleTranslateMap& other) const { return !(*this == other); } |
| 1406 | |||
| 1407 | /// Return AffineMap::Ptr to an AffineMap equivalent to *this | ||
| 1408 | 26 | AffineMap::Ptr getAffineMap() const override | |
| 1409 | { | ||
| 1410 |
2/4✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
|
52 | AffineMap::Ptr affineMap(new AffineMap(math::scale<Mat4d>(mScaleValues))); |
| 1411 | 26 | affineMap->accumPostTranslation(mTranslation); | |
| 1412 | 26 | return affineMap; | |
| 1413 | } | ||
| 1414 | |||
| 1415 | //@{ | ||
| 1416 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1417 | /// of prepending the appropraite operation. | ||
| 1418 | 3 | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
| 1419 | { | ||
| 1420 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1421 | affineMap->accumPreRotation(axis, radians); | ||
| 1422 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
| 1423 | } | ||
| 1424 | 1 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
| 1425 | { | ||
| 1426 | const Vec3d& s = mScaleValues; | ||
| 1427 | const Vec3d scaled_trans( t.x() * s.x(), | ||
| 1428 | t.y() * s.y(), | ||
| 1429 | 1 | t.z() * s.z() ); | |
| 1430 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | return MapBase::Ptr( new ScaleTranslateMap(mScaleValues, mTranslation + scaled_trans)); |
| 1431 | } | ||
| 1432 | |||
| 1433 | MapBase::Ptr preScale(const Vec3d& v) const override; | ||
| 1434 | |||
| 1435 | 2 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
| 1436 | { | ||
| 1437 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1438 | affineMap->accumPreShear(axis0, axis1, shear); | ||
| 1439 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
| 1440 | } | ||
| 1441 | //@} | ||
| 1442 | |||
| 1443 | //@{ | ||
| 1444 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1445 | /// of postfixing the appropraite operation. | ||
| 1446 | 3 | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
| 1447 | { | ||
| 1448 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1449 | affineMap->accumPostRotation(axis, radians); | ||
| 1450 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
| 1451 | } | ||
| 1452 | 1 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
| 1453 | { | ||
| 1454 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | return MapBase::Ptr( new ScaleTranslateMap(mScaleValues, mTranslation + t)); |
| 1455 | } | ||
| 1456 | |||
| 1457 | MapBase::Ptr postScale(const Vec3d& v) const override; | ||
| 1458 | |||
| 1459 | 2 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
| 1460 | { | ||
| 1461 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1462 | affineMap->accumPostShear(axis0, axis1, shear); | ||
| 1463 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
| 1464 | } | ||
| 1465 | //@} | ||
| 1466 | |||
| 1467 | private: | ||
| 1468 | Vec3d mTranslation, mScaleValues, mVoxelSize, mScaleValuesInverse, | ||
| 1469 | mInvScaleSqr, mInvTwiceScale; | ||
| 1470 | }; // class ScaleTanslateMap | ||
| 1471 | |||
| 1472 | |||
| 1473 | inline MapBase::Ptr | ||
| 1474 | 5 | ScaleMap::postTranslate(const Vec3d& t) const | |
| 1475 | { | ||
| 1476 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
10 | return MapBase::Ptr(new ScaleTranslateMap(mScaleValues, t)); |
| 1477 | } | ||
| 1478 | |||
| 1479 | |||
| 1480 | inline MapBase::Ptr | ||
| 1481 | 2 | ScaleMap::preTranslate(const Vec3d& t) const | |
| 1482 | { | ||
| 1483 | |||
| 1484 | const Vec3d& s = mScaleValues; | ||
| 1485 | const Vec3d scaled_trans( t.x() * s.x(), | ||
| 1486 | t.y() * s.y(), | ||
| 1487 | 2 | t.z() * s.z() ); | |
| 1488 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | return MapBase::Ptr(new ScaleTranslateMap(mScaleValues, scaled_trans)); |
| 1489 | } | ||
| 1490 | |||
| 1491 | |||
| 1492 | /// @brief A specialized Affine transform that uniformaly scales along the principal axis | ||
| 1493 | /// and then translates the result. | ||
| 1494 | /// @note This class is marked final with ABI=8 | ||
| 1495 | class OPENVDB_API UniformScaleTranslateMap OPENVDB_MAP_CLASS_SPECIFIER: public ScaleTranslateMap | ||
| 1496 | { | ||
| 1497 | public: | ||
| 1498 | using Ptr = SharedPtr<UniformScaleTranslateMap>; | ||
| 1499 | using ConstPtr = SharedPtr<const UniformScaleTranslateMap>; | ||
| 1500 | |||
| 1501 | 8 | UniformScaleTranslateMap():ScaleTranslateMap(Vec3d(1,1,1), Vec3d(0,0,0)) {} | |
| 1502 | 20 | UniformScaleTranslateMap(double scale, const Vec3d& translate): | |
| 1503 |
9/32✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 7 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
|
20 | ScaleTranslateMap(Vec3d(scale,scale,scale), translate) {} |
| 1504 | 2 | UniformScaleTranslateMap(const UniformScaleMap& scale, const TranslationMap& translate): | |
| 1505 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
|
2 | ScaleTranslateMap(scale.getScale(), translate.getTranslation()) {} |
| 1506 | |||
| 1507 | 1 | UniformScaleTranslateMap(const UniformScaleTranslateMap& other):ScaleTranslateMap(other) {} | |
| 1508 |
2/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
21 | ~UniformScaleTranslateMap() override = default; |
| 1509 | |||
| 1510 | /// Return a MapBase::Ptr to a new UniformScaleTranslateMap | ||
| 1511 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new UniformScaleTranslateMap()); } | |
| 1512 | /// Return a MapBase::Ptr to a deep copy of this map | ||
| 1513 | 1 | MapBase::Ptr copy() const override { return MapBase::Ptr(new UniformScaleTranslateMap(*this)); } | |
| 1514 | |||
| 1515 | 1 | MapBase::Ptr inverseMap() const override | |
| 1516 | { | ||
| 1517 | const Vec3d& scaleInv = getInvScale(); | ||
| 1518 | const Vec3d& trans = getTranslation(); | ||
| 1519 | 2 | return MapBase::Ptr(new UniformScaleTranslateMap(scaleInv[0], -scaleInv[0] * trans)); | |
| 1520 | } | ||
| 1521 | |||
| 1522 | 1 | static bool isRegistered() | |
| 1523 | { | ||
| 1524 | 1 | return MapRegistry::isRegistered(UniformScaleTranslateMap::mapType()); | |
| 1525 | } | ||
| 1526 | |||
| 1527 | 337 | static void registerMap() | |
| 1528 | { | ||
| 1529 | 337 | MapRegistry::registerMap( | |
| 1530 | 337 | UniformScaleTranslateMap::mapType(), UniformScaleTranslateMap::create); | |
| 1531 | 337 | } | |
| 1532 | |||
| 1533 | 32 | Name type() const override { return mapType(); } | |
| 1534 |
5/144✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 333 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 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 222 not taken.
✗ Branch 223 not taken.
|
360 | static Name mapType() { return Name("UniformScaleTranslateMap"); } |
| 1535 | |||
| 1536 | 3 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 1537 | |||
| 1538 | bool operator==(const UniformScaleTranslateMap& other) const | ||
| 1539 | { | ||
| 1540 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | return ScaleTranslateMap::operator==(other); |
| 1541 | } | ||
| 1542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const UniformScaleTranslateMap& other) const { return !(*this == other); } |
| 1543 | |||
| 1544 | /// @brief Return a MapBase::Ptr to a UniformScaleTranslateMap that is | ||
| 1545 | /// the result of prepending translation on this map. | ||
| 1546 | 1 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
| 1547 | { | ||
| 1548 | const double scale = this->getScale().x(); | ||
| 1549 | 1 | const Vec3d new_trans = this->getTranslation() + scale * t; | |
| 1550 | 2 | return MapBase::Ptr( new UniformScaleTranslateMap(scale, new_trans)); | |
| 1551 | } | ||
| 1552 | |||
| 1553 | /// @brief Return a MapBase::Ptr to a UniformScaleTranslateMap that is | ||
| 1554 | /// the result of postfixing translation on this map. | ||
| 1555 | 1 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
| 1556 | { | ||
| 1557 | const double scale = this->getScale().x(); | ||
| 1558 | 2 | return MapBase::Ptr( new UniformScaleTranslateMap(scale, this->getTranslation() + t)); | |
| 1559 | } | ||
| 1560 | }; // class UniformScaleTanslateMap | ||
| 1561 | |||
| 1562 | |||
| 1563 | inline MapBase::Ptr | ||
| 1564 | 1 | UniformScaleMap::postTranslate(const Vec3d& t) const | |
| 1565 | { | ||
| 1566 | const double scale = this->getScale().x(); | ||
| 1567 | 2 | return MapBase::Ptr(new UniformScaleTranslateMap(scale, t)); | |
| 1568 | } | ||
| 1569 | |||
| 1570 | |||
| 1571 | inline MapBase::Ptr | ||
| 1572 | 7 | UniformScaleMap::preTranslate(const Vec3d& t) const | |
| 1573 | { | ||
| 1574 | const double scale = this->getScale().x(); | ||
| 1575 | 14 | return MapBase::Ptr(new UniformScaleTranslateMap(scale, scale*t)); | |
| 1576 | } | ||
| 1577 | |||
| 1578 | |||
| 1579 | inline MapBase::Ptr | ||
| 1580 | ✗ | TranslationMap::preScale(const Vec3d& v) const | |
| 1581 | { | ||
| 1582 | ✗ | if (isApproxEqual(v[0],v[1]) && isApproxEqual(v[0],v[2])) { | |
| 1583 | ✗ | return MapBase::Ptr(new UniformScaleTranslateMap(v[0], mTranslation)); | |
| 1584 | } else { | ||
| 1585 | ✗ | return MapBase::Ptr(new ScaleTranslateMap(v, mTranslation)); | |
| 1586 | } | ||
| 1587 | } | ||
| 1588 | |||
| 1589 | |||
| 1590 | inline MapBase::Ptr | ||
| 1591 | ✗ | TranslationMap::postScale(const Vec3d& v) const | |
| 1592 | { | ||
| 1593 | ✗ | if (isApproxEqual(v[0],v[1]) && isApproxEqual(v[0],v[2])) { | |
| 1594 | ✗ | return MapBase::Ptr(new UniformScaleTranslateMap(v[0], v[0]*mTranslation)); | |
| 1595 | } else { | ||
| 1596 | const Vec3d trans(mTranslation.x()*v.x(), | ||
| 1597 | mTranslation.y()*v.y(), | ||
| 1598 | ✗ | mTranslation.z()*v.z()); | |
| 1599 | ✗ | return MapBase::Ptr(new ScaleTranslateMap(v, trans)); | |
| 1600 | } | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | |||
| 1604 | inline MapBase::Ptr | ||
| 1605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | ScaleTranslateMap::preScale(const Vec3d& v) const |
| 1606 | { | ||
| 1607 | const Vec3d new_scale( v * mScaleValues ); | ||
| 1608 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | if (isApproxEqual(new_scale[0],new_scale[1]) && isApproxEqual(new_scale[0],new_scale[2])) { |
| 1609 | ✗ | return MapBase::Ptr( new UniformScaleTranslateMap(new_scale[0], mTranslation)); | |
| 1610 | } else { | ||
| 1611 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return MapBase::Ptr( new ScaleTranslateMap(new_scale, mTranslation)); |
| 1612 | } | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | |||
| 1616 | inline MapBase::Ptr | ||
| 1617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | ScaleTranslateMap::postScale(const Vec3d& v) const |
| 1618 | { | ||
| 1619 | const Vec3d new_scale( v * mScaleValues ); | ||
| 1620 | const Vec3d new_trans( mTranslation.x()*v.x(), | ||
| 1621 | mTranslation.y()*v.y(), | ||
| 1622 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | mTranslation.z()*v.z() ); |
| 1623 | |||
| 1624 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | if (isApproxEqual(new_scale[0],new_scale[1]) && isApproxEqual(new_scale[0],new_scale[2])) { |
| 1625 | ✗ | return MapBase::Ptr( new UniformScaleTranslateMap(new_scale[0], new_trans)); | |
| 1626 | } else { | ||
| 1627 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return MapBase::Ptr( new ScaleTranslateMap(new_scale, new_trans)); |
| 1628 | } | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | |||
| 1632 | //////////////////////////////////////// | ||
| 1633 | |||
| 1634 | |||
| 1635 | /// @brief A specialized linear transform that performs a unitary maping | ||
| 1636 | /// i.e. rotation and or reflection. | ||
| 1637 | /// @note This class is marked final with ABI=8 | ||
| 1638 | class OPENVDB_API UnitaryMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
| 1639 | { | ||
| 1640 | public: | ||
| 1641 | using Ptr = SharedPtr<UnitaryMap>; | ||
| 1642 | using ConstPtr = SharedPtr<const UnitaryMap>; | ||
| 1643 | |||
| 1644 | /// default constructor makes an Idenity. | ||
| 1645 | ✗ | UnitaryMap(): mAffineMap(Mat4d::identity()) | |
| 1646 | { | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | 3 | UnitaryMap(const Vec3d& axis, double radians) | |
| 1650 | 3 | { | |
| 1651 | Mat3d matrix; | ||
| 1652 | matrix.setToRotation(axis, radians); | ||
| 1653 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | mAffineMap = AffineMap(matrix); |
| 1654 | 3 | } | |
| 1655 | |||
| 1656 | ✗ | UnitaryMap(Axis axis, double radians) | |
| 1657 | { | ||
| 1658 | Mat4d matrix; | ||
| 1659 | matrix.setToRotation(axis, radians); | ||
| 1660 | ✗ | mAffineMap = AffineMap(matrix); | |
| 1661 | } | ||
| 1662 | |||
| 1663 | 3 | UnitaryMap(const Mat3d& m) | |
| 1664 | 3 | { | |
| 1665 | // test that the mat3 is a rotation || reflection | ||
| 1666 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!isUnitary(m)) { |
| 1667 | ✗ | OPENVDB_THROW(ArithmeticError, "Matrix initializing unitary map was not unitary"); | |
| 1668 | } | ||
| 1669 | |||
| 1670 | 3 | Mat4d matrix(Mat4d::identity()); | |
| 1671 | matrix.setMat3(m); | ||
| 1672 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | mAffineMap = AffineMap(matrix); |
| 1673 | 3 | } | |
| 1674 | |||
| 1675 | 1 | UnitaryMap(const Mat4d& m) | |
| 1676 | 1 | { | |
| 1677 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!isInvertible(m)) { |
| 1678 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1679 | "4x4 Matrix initializing unitary map was not unitary: not invertible"); | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | if (!isAffine(m)) { | ||
| 1683 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1684 | "4x4 Matrix initializing unitary map was not unitary: not affine"); | ||
| 1685 | } | ||
| 1686 | |||
| 1687 | if (hasTranslation(m)) { | ||
| 1688 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1689 | "4x4 Matrix initializing unitary map was not unitary: had translation"); | ||
| 1690 | } | ||
| 1691 | |||
| 1692 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!isUnitary(m.getMat3())) { |
| 1693 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1694 | "4x4 Matrix initializing unitary map was not unitary"); | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | 1 | mAffineMap = AffineMap(m); | |
| 1698 | 1 | } | |
| 1699 | |||
| 1700 | 10 | UnitaryMap(const UnitaryMap& other): | |
| 1701 | MapBase(other), | ||
| 1702 | 4 | mAffineMap(other.mAffineMap) | |
| 1703 | { | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | ✗ | UnitaryMap(const UnitaryMap& first, const UnitaryMap& second): | |
| 1707 | ✗ | mAffineMap(*(first.getAffineMap()), *(second.getAffineMap())) | |
| 1708 | { | ||
| 1709 | } | ||
| 1710 | |||
| 1711 |
1/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4 | ~UnitaryMap() override = default; |
| 1712 | |||
| 1713 | /// Return a MapBase::Ptr to a new UnitaryMap | ||
| 1714 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new UnitaryMap()); } | |
| 1715 | /// Returns a MapBase::Ptr to a deep copy of *this | ||
| 1716 | ✗ | MapBase::Ptr copy() const override { return MapBase::Ptr(new UnitaryMap(*this)); } | |
| 1717 | |||
| 1718 | 1 | MapBase::Ptr inverseMap() const override | |
| 1719 | { | ||
| 1720 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | return MapBase::Ptr(new UnitaryMap(mAffineMap.getMat4().inverse())); |
| 1721 | } | ||
| 1722 | |||
| 1723 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(UnitaryMap::mapType()); } | |
| 1724 | |||
| 1725 | 323 | static void registerMap() | |
| 1726 | { | ||
| 1727 | 323 | MapRegistry::registerMap( | |
| 1728 | 323 | UnitaryMap::mapType(), | |
| 1729 | UnitaryMap::create); | ||
| 1730 | 323 | } | |
| 1731 | |||
| 1732 | /// Return @c UnitaryMap | ||
| 1733 | 2 | Name type() const override { return mapType(); } | |
| 1734 | /// Return @c UnitaryMap | ||
| 1735 |
4/143✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 323 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 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 222 not taken.
✗ Branch 223 not taken.
|
328 | static Name mapType() { return Name("UnitaryMap"); } |
| 1736 | |||
| 1737 | /// Return @c true (a UnitaryMap is always linear). | ||
| 1738 | ✗ | bool isLinear() const override { return true; } | |
| 1739 | |||
| 1740 | /// Return @c false (by convention true) | ||
| 1741 | ✗ | bool hasUniformScale() const override { return true; } | |
| 1742 | |||
| 1743 | ✗ | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 1744 | |||
| 1745 | bool operator==(const UnitaryMap& other) const | ||
| 1746 | { | ||
| 1747 | // compare underlying linear map. | ||
| 1748 |
2/6✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | if (mAffineMap!=other.mAffineMap) return false; |
| 1749 | return true; | ||
| 1750 | } | ||
| 1751 | |||
| 1752 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const UnitaryMap& other) const { return !(*this == other); } |
| 1753 | /// Return the image of @c in under the map | ||
| 1754 | 1 | Vec3d applyMap(const Vec3d& in) const override { return mAffineMap.applyMap(in); } | |
| 1755 | /// Return the pre-image of @c in under the map | ||
| 1756 | ✗ | Vec3d applyInverseMap(const Vec3d& in) const override { return mAffineMap.applyInverseMap(in); } | |
| 1757 | |||
| 1758 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const override { return applyJacobian(in); } | |
| 1759 | /// Return the Jacobian of the map applied to @a in. | ||
| 1760 | ✗ | Vec3d applyJacobian(const Vec3d& in) const override { return mAffineMap.applyJacobian(in); } | |
| 1761 | |||
| 1762 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 1763 | /// (i.e. inverse map with out translation) | ||
| 1764 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const override { | |
| 1765 | ✗ | return applyInverseJacobian(in); | |
| 1766 | } | ||
| 1767 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 1768 | /// (i.e. inverse map with out translation) | ||
| 1769 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { | |
| 1770 | ✗ | return mAffineMap.applyInverseJacobian(in); | |
| 1771 | } | ||
| 1772 | |||
| 1773 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
| 1774 | /// @details This tranforms range-space gradients to domain-space gradients | ||
| 1775 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const override { return applyJT(in); } | |
| 1776 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
| 1777 | ✗ | Vec3d applyJT(const Vec3d& in) const override { | |
| 1778 | ✗ | return applyInverseMap(in); // the transpose of the unitary map is its inverse | |
| 1779 | } | ||
| 1780 | |||
| 1781 | |||
| 1782 | /// @brief Return the transpose of the inverse Jacobian of the map applied to @a in | ||
| 1783 | /// @details Ignores second argument | ||
| 1784 | ✗ | Vec3d applyIJT(const Vec3d& in, const Vec3d& ) const override { return applyIJT(in);} | |
| 1785 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
| 1786 | ✗ | Vec3d applyIJT(const Vec3d& in) const override { return mAffineMap.applyIJT(in); } | |
| 1787 | /// Return the Jacobian Curvature: zero for a linear map | ||
| 1788 | ✗ | Mat3d applyIJC(const Mat3d& in) const override { return mAffineMap.applyIJC(in); } | |
| 1789 | ✗ | Mat3d applyIJC(const Mat3d& in, const Vec3d&, const Vec3d& ) const override { | |
| 1790 | ✗ | return applyIJC(in); | |
| 1791 | } | ||
| 1792 | |||
| 1793 | /// Return the determinant of the Jacobian, ignores argument | ||
| 1794 | ✗ | double determinant(const Vec3d&) const override { return determinant(); } | |
| 1795 | /// Return the determinant of the Jacobian | ||
| 1796 | ✗ | double determinant() const override { return mAffineMap.determinant(); } | |
| 1797 | |||
| 1798 | |||
| 1799 | /// @{ | ||
| 1800 | /// @brief Returns the lengths of the images of the segments | ||
| 1801 | /// (0,0,0) − (1,0,0), (0,0,0) − (0,1,0) and (0,0,0) − (0,0,1). | ||
| 1802 | ✗ | Vec3d voxelSize() const override { return mAffineMap.voxelSize();} | |
| 1803 | ✗ | Vec3d voxelSize(const Vec3d&) const override { return voxelSize();} | |
| 1804 | /// @} | ||
| 1805 | |||
| 1806 | /// read serialization | ||
| 1807 | ✗ | void read(std::istream& is) override | |
| 1808 | { | ||
| 1809 | ✗ | mAffineMap.read(is); | |
| 1810 | } | ||
| 1811 | |||
| 1812 | /// write serialization | ||
| 1813 | ✗ | void write(std::ostream& os) const override | |
| 1814 | { | ||
| 1815 | mAffineMap.write(os); | ||
| 1816 | } | ||
| 1817 | /// string serialization, useful for debuging | ||
| 1818 | ✗ | std::string str() const override | |
| 1819 | { | ||
| 1820 | ✗ | std::ostringstream buffer; | |
| 1821 | ✗ | buffer << mAffineMap.str(); | |
| 1822 | ✗ | return buffer.str(); | |
| 1823 | } | ||
| 1824 | /// Return AffineMap::Ptr to an AffineMap equivalent to *this | ||
| 1825 | 4 | AffineMap::Ptr getAffineMap() const override { | |
| 1826 | 4 | return AffineMap::Ptr(new AffineMap(mAffineMap)); | |
| 1827 | } | ||
| 1828 | |||
| 1829 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1830 | /// of prepending the given rotation. | ||
| 1831 | ✗ | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
| 1832 | { | ||
| 1833 | ✗ | UnitaryMap first(axis, radians); | |
| 1834 | ✗ | UnitaryMap::Ptr unitaryMap(new UnitaryMap(first, *this)); | |
| 1835 | ✗ | return StaticPtrCast<MapBase, UnitaryMap>(unitaryMap); | |
| 1836 | } | ||
| 1837 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1838 | /// of prepending the given translation. | ||
| 1839 | ✗ | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
| 1840 | { | ||
| 1841 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1842 | affineMap->accumPreTranslation(t); | ||
| 1843 | ✗ | return simplify(affineMap); | |
| 1844 | } | ||
| 1845 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1846 | /// of prepending the given scale. | ||
| 1847 | ✗ | MapBase::Ptr preScale(const Vec3d& v) const override | |
| 1848 | { | ||
| 1849 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1850 | affineMap->accumPreScale(v); | ||
| 1851 | ✗ | return simplify(affineMap); | |
| 1852 | } | ||
| 1853 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1854 | /// of prepending the given shear. | ||
| 1855 | ✗ | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
| 1856 | { | ||
| 1857 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1858 | affineMap->accumPreShear(axis0, axis1, shear); | ||
| 1859 | ✗ | return simplify(affineMap); | |
| 1860 | } | ||
| 1861 | |||
| 1862 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1863 | /// of appending the given rotation. | ||
| 1864 | ✗ | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
| 1865 | { | ||
| 1866 | ✗ | UnitaryMap second(axis, radians); | |
| 1867 | ✗ | UnitaryMap::Ptr unitaryMap(new UnitaryMap(*this, second)); | |
| 1868 | ✗ | return StaticPtrCast<MapBase, UnitaryMap>(unitaryMap); | |
| 1869 | } | ||
| 1870 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1871 | /// of appending the given translation. | ||
| 1872 | ✗ | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
| 1873 | { | ||
| 1874 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1875 | affineMap->accumPostTranslation(t); | ||
| 1876 | ✗ | return simplify(affineMap); | |
| 1877 | } | ||
| 1878 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1879 | /// of appending the given scale. | ||
| 1880 | ✗ | MapBase::Ptr postScale(const Vec3d& v) const override | |
| 1881 | { | ||
| 1882 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1883 | affineMap->accumPostScale(v); | ||
| 1884 | ✗ | return simplify(affineMap); | |
| 1885 | } | ||
| 1886 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 1887 | /// of appending the given shear. | ||
| 1888 | ✗ | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
| 1889 | { | ||
| 1890 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
| 1891 | affineMap->accumPostShear(axis0, axis1, shear); | ||
| 1892 | ✗ | return simplify(affineMap); | |
| 1893 | } | ||
| 1894 | |||
| 1895 | private: | ||
| 1896 | AffineMap mAffineMap; | ||
| 1897 | }; // class UnitaryMap | ||
| 1898 | |||
| 1899 | |||
| 1900 | //////////////////////////////////////// | ||
| 1901 | |||
| 1902 | |||
| 1903 | /// @brief This map is composed of three steps. | ||
| 1904 | /// First it will take a box of size (Lx X Ly X Lz) defined by a member data bounding box | ||
| 1905 | /// and map it into a frustum with near plane (1 X Ly/Lx) and prescribed depth | ||
| 1906 | /// Then this frustum is transformed by an internal second map: most often a uniform scale, | ||
| 1907 | /// but other effects can be achieved by accumulating translation, shear and rotation: these | ||
| 1908 | /// are all applied to the second map | ||
| 1909 | /// @note This class is marked final with ABI=8 | ||
| 1910 | class OPENVDB_API NonlinearFrustumMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
| 1911 | { | ||
| 1912 | public: | ||
| 1913 | using Ptr = SharedPtr<NonlinearFrustumMap>; | ||
| 1914 | using ConstPtr = SharedPtr<const NonlinearFrustumMap>; | ||
| 1915 | |||
| 1916 | ✗ | NonlinearFrustumMap(): | |
| 1917 | MapBase(), | ||
| 1918 | ✗ | mBBox(Vec3d(0), Vec3d(1)), | |
| 1919 | mTaper(1), | ||
| 1920 | ✗ | mDepth(1) | |
| 1921 | { | ||
| 1922 | ✗ | init(); | |
| 1923 | } | ||
| 1924 | |||
| 1925 | /// @brief Constructor that takes an index-space bounding box | ||
| 1926 | /// to be mapped into a frustum with a given @a depth and @a taper | ||
| 1927 | /// (defined as ratio of nearplane/farplane). | ||
| 1928 | 10 | NonlinearFrustumMap(const BBoxd& bb, double taper, double depth): | |
| 1929 | 10 | MapBase(),mBBox(bb), mTaper(taper), mDepth(depth) | |
| 1930 | { | ||
| 1931 | 10 | init(); | |
| 1932 | } | ||
| 1933 | |||
| 1934 | /// @brief Constructor that takes an index-space bounding box | ||
| 1935 | /// to be mapped into a frustum with a given @a depth and @a taper | ||
| 1936 | /// (defined as ratio of nearplane/farplane). | ||
| 1937 | /// @details This frustum is further modifed by the @a secondMap, | ||
| 1938 | /// intended to be a simple translation and rotation and uniform scale | ||
| 1939 | 34 | NonlinearFrustumMap(const BBoxd& bb, double taper, double depth, | |
| 1940 | 34 | const MapBase::Ptr& secondMap): | |
| 1941 | 34 | mBBox(bb), mTaper(taper), mDepth(depth) | |
| 1942 | { | ||
| 1943 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
|
34 | if (!secondMap->isLinear() ) { |
| 1944 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1945 | "The second map in the Frustum transfrom must be linear"); | ||
| 1946 | } | ||
| 1947 | 34 | mSecondMap = *( secondMap->getAffineMap() ); | |
| 1948 | 34 | init(); | |
| 1949 | 34 | } | |
| 1950 | |||
| 1951 | 21728 | NonlinearFrustumMap(const NonlinearFrustumMap& other): | |
| 1952 | MapBase(), | ||
| 1953 | mBBox(other.mBBox), | ||
| 1954 | 21728 | mTaper(other.mTaper), | |
| 1955 | 21728 | mDepth(other.mDepth), | |
| 1956 | 21728 | mSecondMap(other.mSecondMap), | |
| 1957 | 21728 | mHasSimpleAffine(other.mHasSimpleAffine) | |
| 1958 | { | ||
| 1959 | 21728 | init(); | |
| 1960 | 21728 | } | |
| 1961 | |||
| 1962 | /// @brief Constructor from a camera frustum | ||
| 1963 | /// | ||
| 1964 | /// @param position the tip of the frustum (i.e., the camera's position). | ||
| 1965 | /// @param direction a vector pointing from @a position toward the near plane. | ||
| 1966 | /// @param up a non-unit vector describing the direction and extent of | ||
| 1967 | /// the frustum's intersection on the near plane. Together, | ||
| 1968 | /// @a up must be orthogonal to @a direction. | ||
| 1969 | /// @param aspect the aspect ratio of the frustum intersection with near plane | ||
| 1970 | /// defined as width / height | ||
| 1971 | /// @param z_near,depth the distance from @a position along @a direction to the | ||
| 1972 | /// near and far planes of the frustum. | ||
| 1973 | /// @param x_count the number of voxels, aligned with @a left, | ||
| 1974 | /// across the face of the frustum | ||
| 1975 | /// @param z_count the number of voxels, aligned with @a direction, | ||
| 1976 | /// between the near and far planes | ||
| 1977 | 7 | NonlinearFrustumMap(const Vec3d& position, | |
| 1978 | const Vec3d& direction, | ||
| 1979 | const Vec3d& up, | ||
| 1980 | double aspect /* width / height */, | ||
| 1981 | double z_near, double depth, | ||
| 1982 | 7 | Coord::ValueType x_count, Coord::ValueType z_count) { | |
| 1983 | |||
| 1984 | /// @todo check that depth > 0 | ||
| 1985 | /// @todo check up.length > 0 | ||
| 1986 | /// @todo check that direction dot up = 0 | ||
| 1987 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(depth > 0)) { |
| 1988 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1989 | "The frustum depth must be non-zero and positive"); | ||
| 1990 | } | ||
| 1991 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(up.length() > 0)) { |
| 1992 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1993 | "The frustum height must be non-zero and positive"); | ||
| 1994 | } | ||
| 1995 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(aspect > 0)) { |
| 1996 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 1997 | "The frustum aspect ratio must be non-zero and positive"); | ||
| 1998 | } | ||
| 1999 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(isApproxEqual(up.dot(direction), 0.))) { |
| 2000 | ✗ | OPENVDB_THROW(ArithmeticError, | |
| 2001 | "The frustum up orientation must be perpendicular to into-frustum direction"); | ||
| 2002 | } | ||
| 2003 | |||
| 2004 | 7 | double near_plane_height = 2 * up.length(); | |
| 2005 | 7 | double near_plane_width = aspect * near_plane_height; | |
| 2006 | |||
| 2007 | 7 | Coord::ValueType y_count = static_cast<int>(Round(x_count / aspect)); | |
| 2008 | |||
| 2009 | 7 | mBBox = BBoxd(Vec3d(0,0,0), Vec3d(x_count, y_count, z_count)); | |
| 2010 | 7 | mDepth = depth / near_plane_width; // depth non-dimensionalized on width | |
| 2011 | 7 | double gamma = near_plane_width / z_near; | |
| 2012 | 7 | mTaper = 1./(mDepth*gamma + 1.); | |
| 2013 | |||
| 2014 | 7 | Vec3d direction_unit = direction; | |
| 2015 | 7 | direction_unit.normalize(); | |
| 2016 | |||
| 2017 | 7 | Mat4d r1(Mat4d::identity()); | |
| 2018 | 7 | r1.setToRotation(/*from*/Vec3d(0,0,1), /*to */direction_unit); | |
| 2019 | 7 | Mat4d r2(Mat4d::identity()); | |
| 2020 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
14 | Vec3d temp = r1.inverse().transform(up); |
| 2021 | 7 | r2.setToRotation(/*from*/Vec3d(0,1,0), /*to*/temp ); | |
| 2022 | Mat4d scale = math::scale<Mat4d>( | ||
| 2023 | 7 | Vec3d(near_plane_width, near_plane_width, near_plane_width)); | |
| 2024 | |||
| 2025 | // move the near plane to origin, rotate to align with axis, and scale down | ||
| 2026 | // T_inv * R1_inv * R2_inv * scale_inv | ||
| 2027 |
1/2✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
|
7 | Mat4d mat = scale * r2 * r1; |
| 2028 | 7 | mat.setTranslation(position + z_near*direction_unit); | |
| 2029 | |||
| 2030 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | mSecondMap = AffineMap(mat); |
| 2031 | |||
| 2032 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | init(); |
| 2033 | 7 | } | |
| 2034 | |||
| 2035 |
4/16✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
21767 | ~NonlinearFrustumMap() override = default; |
| 2036 | |||
| 2037 | /// Return a MapBase::Ptr to a new NonlinearFrustumMap | ||
| 2038 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new NonlinearFrustumMap()); } | |
| 2039 | /// Return a MapBase::Ptr to a deep copy of this map | ||
| 2040 |
1/2✓ Branch 2 taken 21728 times.
✗ Branch 3 not taken.
|
43456 | MapBase::Ptr copy() const override { return MapBase::Ptr(new NonlinearFrustumMap(*this)); } |
| 2041 | |||
| 2042 | /// @brief Not implemented, since there is currently no map type that can | ||
| 2043 | /// represent the inverse of a frustum | ||
| 2044 | /// @throw NotImplementedError | ||
| 2045 | ✗ | MapBase::Ptr inverseMap() const override | |
| 2046 | { | ||
| 2047 | ✗ | OPENVDB_THROW(NotImplementedError, | |
| 2048 | "inverseMap() is not implemented for NonlinearFrustumMap"); | ||
| 2049 | } | ||
| 2050 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(NonlinearFrustumMap::mapType()); } | |
| 2051 | |||
| 2052 | 332 | static void registerMap() | |
| 2053 | { | ||
| 2054 | 332 | MapRegistry::registerMap( | |
| 2055 | 332 | NonlinearFrustumMap::mapType(), | |
| 2056 | NonlinearFrustumMap::create); | ||
| 2057 | 332 | } | |
| 2058 | /// Return @c NonlinearFrustumMap | ||
| 2059 | 43516 | Name type() const override { return mapType(); } | |
| 2060 | /// Return @c NonlinearFrustumMap | ||
| 2061 |
2/116✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 332 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ 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 not taken.
✗ Branch 74 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 97 not taken.
✗ 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 222 not taken.
✗ Branch 223 not taken.
|
22116 | static Name mapType() { return Name("NonlinearFrustumMap"); } |
| 2062 | |||
| 2063 | /// Return @c false (a NonlinearFrustumMap is never linear). | ||
| 2064 | 43433 | bool isLinear() const override { return false; } | |
| 2065 | |||
| 2066 | /// Return @c false (by convention false) | ||
| 2067 | ✗ | bool hasUniformScale() const override { return false; } | |
| 2068 | |||
| 2069 | /// Return @c true if the map is equivalent to an identity | ||
| 2070 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | bool isIdentity() const |
| 2071 | { | ||
| 2072 | // The frustum can only be consistent with a linear map if the taper value is 1 | ||
| 2073 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!isApproxEqual(mTaper, double(1)) ) return false; |
| 2074 | |||
| 2075 | // There are various ways an identity can decomposed between the two parts of the | ||
| 2076 | // map. Best to just check that the principle vectors are stationary. | ||
| 2077 | const Vec3d e1(1,0,0); | ||
| 2078 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | if (!applyMap(e1).eq(e1)) return false; |
| 2079 | |||
| 2080 | const Vec3d e2(0,1,0); | ||
| 2081 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (!applyMap(e2).eq(e2)) return false; |
| 2082 | |||
| 2083 | const Vec3d e3(0,0,1); | ||
| 2084 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (!applyMap(e3).eq(e3)) return false; |
| 2085 | |||
| 2086 | return true; | ||
| 2087 | } | ||
| 2088 | |||
| 2089 | 8 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
| 2090 | |||
| 2091 | 3 | bool operator==(const NonlinearFrustumMap& other) const | |
| 2092 | { | ||
| 2093 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (mBBox!=other.mBBox) return false; |
| 2094 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!isApproxEqual(mTaper, other.mTaper)) return false; |
| 2095 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!isApproxEqual(mDepth, other.mDepth)) return false; |
| 2096 | |||
| 2097 | // Two linear transforms are equivalent iff they have the same translation | ||
| 2098 | // and have the same affects on orthongal spanning basis check translation | ||
| 2099 | Vec3d e(0,0,0); | ||
| 2100 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
| 2101 | /// check spanning vectors | ||
| 2102 | 3 | e(0) = 1; | |
| 2103 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
| 2104 | 3 | e(0) = 0; | |
| 2105 | 3 | e(1) = 1; | |
| 2106 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
| 2107 | 3 | e(1) = 0; | |
| 2108 | 3 | e(2) = 1; | |
| 2109 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
| 2110 | return true; | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | bool operator!=(const NonlinearFrustumMap& other) const { return !(*this == other); } | ||
| 2114 | |||
| 2115 | /// Return the image of @c in under the map | ||
| 2116 | 2499599586 | Vec3d applyMap(const Vec3d& in) const override | |
| 2117 | { | ||
| 2118 | 2499599586 | return mSecondMap.applyMap(applyFrustumMap(in)); | |
| 2119 | } | ||
| 2120 | |||
| 2121 | /// Return the pre-image of @c in under the map | ||
| 2122 | 143874285 | Vec3d applyInverseMap(const Vec3d& in) const override | |
| 2123 | { | ||
| 2124 | 143874285 | return applyFrustumInverseMap(mSecondMap.applyInverseMap(in)); | |
| 2125 | } | ||
| 2126 | /// Return the Jacobian of the linear second map applied to @c in | ||
| 2127 | ✗ | Vec3d applyJacobian(const Vec3d& in) const override { return mSecondMap.applyJacobian(in); } | |
| 2128 | /// Return the Jacobian defined at @c isloc applied to @c in | ||
| 2129 | 1 | Vec3d applyJacobian(const Vec3d& in, const Vec3d& isloc) const override | |
| 2130 | { | ||
| 2131 | // Move the center of the x-face of the bbox | ||
| 2132 | // to the origin in index space. | ||
| 2133 | 1 | Vec3d centered(isloc); | |
| 2134 | 1 | centered = centered - mBBox.min(); | |
| 2135 | 1 | centered.x() -= mXo; | |
| 2136 | 1 | centered.y() -= mYo; | |
| 2137 | |||
| 2138 | // scale the z-direction on depth / K count | ||
| 2139 | 1 | const double zprime = centered.z()*mDepthOnLz; | |
| 2140 | |||
| 2141 | 1 | const double scale = (mGamma * zprime + 1.) / mLx; | |
| 2142 | 1 | const double scale2 = mGamma * mDepthOnLz / mLx; | |
| 2143 | |||
| 2144 | 1 | const Vec3d tmp(scale * in.x() + scale2 * centered.x()* in.z(), | |
| 2145 | 1 | scale * in.y() + scale2 * centered.y()* in.z(), | |
| 2146 | 1 | mDepthOnLz * in.z()); | |
| 2147 | |||
| 2148 | 1 | return mSecondMap.applyJacobian(tmp); | |
| 2149 | } | ||
| 2150 | |||
| 2151 | |||
| 2152 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
| 2153 | /// (i.e. inverse map with out translation) | ||
| 2154 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { | |
| 2155 | ✗ | return mSecondMap.applyInverseJacobian(in); | |
| 2156 | } | ||
| 2157 | /// Return the Inverse Jacobian defined at @c isloc of the map applied to @a in. | ||
| 2158 | 1 | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d& isloc) const override { | |
| 2159 | |||
| 2160 | // Move the center of the x-face of the bbox | ||
| 2161 | // to the origin in index space. | ||
| 2162 | 1 | Vec3d centered(isloc); | |
| 2163 | 1 | centered = centered - mBBox.min(); | |
| 2164 | 1 | centered.x() -= mXo; | |
| 2165 | 1 | centered.y() -= mYo; | |
| 2166 | |||
| 2167 | // scale the z-direction on depth / K count | ||
| 2168 | 1 | const double zprime = centered.z()*mDepthOnLz; | |
| 2169 | |||
| 2170 | 1 | const double scale = (mGamma * zprime + 1.) / mLx; | |
| 2171 | 1 | const double scale2 = mGamma * mDepthOnLz / mLx; | |
| 2172 | |||
| 2173 | |||
| 2174 | Vec3d out = mSecondMap.applyInverseJacobian(in); | ||
| 2175 | |||
| 2176 | 1 | out.x() = (out.x() - scale2 * centered.x() * out.z() / mDepthOnLz) / scale; | |
| 2177 | 1 | out.y() = (out.y() - scale2 * centered.y() * out.z() / mDepthOnLz) / scale; | |
| 2178 | 1 | out.z() = out.z() / mDepthOnLz; | |
| 2179 | |||
| 2180 | 1 | return out; | |
| 2181 | } | ||
| 2182 | |||
| 2183 | /// @brief Return the Jacobian Transpose of the map applied to vector @c in at @c indexloc. | ||
| 2184 | /// @details This tranforms range-space gradients to domain-space gradients. | ||
| 2185 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d& isloc) const override { | |
| 2186 | ✗ | const Vec3d tmp = mSecondMap.applyJT(in); | |
| 2187 | // Move the center of the x-face of the bbox | ||
| 2188 | // to the origin in index space. | ||
| 2189 | ✗ | Vec3d centered(isloc); | |
| 2190 | ✗ | centered = centered - mBBox.min(); | |
| 2191 | ✗ | centered.x() -= mXo; | |
| 2192 | ✗ | centered.y() -= mYo; | |
| 2193 | |||
| 2194 | // scale the z-direction on depth / K count | ||
| 2195 | ✗ | const double zprime = centered.z()*mDepthOnLz; | |
| 2196 | |||
| 2197 | ✗ | const double scale = (mGamma * zprime + 1.) / mLx; | |
| 2198 | ✗ | const double scale2 = mGamma * mDepthOnLz / mLx; | |
| 2199 | |||
| 2200 | return Vec3d(scale * tmp.x(), | ||
| 2201 | scale * tmp.y(), | ||
| 2202 | ✗ | scale2 * centered.x()* tmp.x() + | |
| 2203 | ✗ | scale2 * centered.y()* tmp.y() + | |
| 2204 | ✗ | mDepthOnLz * tmp.z()); | |
| 2205 | } | ||
| 2206 | /// Return the Jacobian Transpose of the second map applied to @c in. | ||
| 2207 | ✗ | Vec3d applyJT(const Vec3d& in) const override { | |
| 2208 | ✗ | return mSecondMap.applyJT(in); | |
| 2209 | } | ||
| 2210 | |||
| 2211 | /// Return the transpose of the inverse Jacobian of the linear second map applied to @c in | ||
| 2212 | ✗ | Vec3d applyIJT(const Vec3d& in) const override { return mSecondMap.applyIJT(in); } | |
| 2213 | |||
| 2214 | // the Jacobian of the nonlinear part of the transform is a sparse matrix | ||
| 2215 | // Jacobian^(-T) = | ||
| 2216 | // | ||
| 2217 | // (Lx)( 1/s 0 0 ) | ||
| 2218 | // ( 0 1/s 0 ) | ||
| 2219 | // ( -(x-xo)g/(sLx) -(y-yo)g/(sLx) Lz/(Depth Lx) ) | ||
| 2220 | /// Return the transpose of the inverse Jacobain (at @c locW applied to @c in. | ||
| 2221 | /// @c ijk is the location in the pre-image space (e.g. index space) | ||
| 2222 | 2 | Vec3d applyIJT(const Vec3d& d1_is, const Vec3d& ijk) const override | |
| 2223 | { | ||
| 2224 | 2 | const Vec3d loc = applyFrustumMap(ijk); | |
| 2225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | const double s = mGamma * loc.z() + 1.; |
| 2226 | |||
| 2227 | // verify that we aren't at the singularity | ||
| 2228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (isApproxEqual(s, 0.)) { |
| 2229 | ✗ | OPENVDB_THROW(ArithmeticError, "Tried to evaluate the frustum transform" | |
| 2230 | " at the singular focal point (e.g. camera)"); | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | 2 | const double sinv = 1.0/s; // 1/(z*gamma + 1) | |
| 2234 | 2 | const double pt0 = mLx * sinv; // Lx / (z*gamma +1) | |
| 2235 | 2 | const double pt1 = mGamma * pt0; // gamma * Lx / ( z*gamma +1) | |
| 2236 | 2 | const double pt2 = pt1 * sinv; // gamma * Lx / ( z*gamma +1)**2 | |
| 2237 | |||
| 2238 | const Mat3d& jacinv = mSecondMap.getConstJacobianInv(); | ||
| 2239 | |||
| 2240 | // compute \frac{\partial E_i}{\partial x_j} | ||
| 2241 | 2 | Mat3d gradE(Mat3d::zero()); | |
| 2242 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (int j = 0; j < 3; ++j ) { |
| 2243 | 6 | gradE(0,j) = pt0 * jacinv(0,j) - pt2 * loc.x()*jacinv(2,j); | |
| 2244 | 6 | gradE(1,j) = pt0 * jacinv(1,j) - pt2 * loc.y()*jacinv(2,j); | |
| 2245 | 6 | gradE(2,j) = (1./mDepthOnLz) * jacinv(2,j); | |
| 2246 | } | ||
| 2247 | |||
| 2248 | Vec3d result; | ||
| 2249 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (int i = 0; i < 3; ++i) { |
| 2250 | 6 | result(i) = d1_is(0) * gradE(0,i) + d1_is(1) * gradE(1,i) + d1_is(2) * gradE(2,i); | |
| 2251 | } | ||
| 2252 | |||
| 2253 | 2 | return result; | |
| 2254 | |||
| 2255 | } | ||
| 2256 | |||
| 2257 | /// Return the Jacobian Curvature for the linear second map | ||
| 2258 | ✗ | Mat3d applyIJC(const Mat3d& in) const override { return mSecondMap.applyIJC(in); } | |
| 2259 | /// Return the Jacobian Curvature: all the second derivatives in range space | ||
| 2260 | /// @param d2_is second derivative matrix computed in index space | ||
| 2261 | /// @param d1_is gradient computed in index space | ||
| 2262 | /// @param ijk the index space location where the result is computed | ||
| 2263 | 1 | Mat3d applyIJC(const Mat3d& d2_is, const Vec3d& d1_is, const Vec3d& ijk) const override | |
| 2264 | { | ||
| 2265 | 1 | const Vec3d loc = applyFrustumMap(ijk); | |
| 2266 | |||
| 2267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | const double s = mGamma * loc.z() + 1.; |
| 2268 | |||
| 2269 | // verify that we aren't at the singularity | ||
| 2270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (isApproxEqual(s, 0.)) { |
| 2271 | ✗ | OPENVDB_THROW(ArithmeticError, "Tried to evaluate the frustum transform" | |
| 2272 | " at the singular focal point (e.g. camera)"); | ||
| 2273 | } | ||
| 2274 | |||
| 2275 | // precompute | ||
| 2276 | 1 | const double sinv = 1.0/s; // 1/(z*gamma + 1) | |
| 2277 | 1 | const double pt0 = mLx * sinv; // Lx / (z*gamma +1) | |
| 2278 | 1 | const double pt1 = mGamma * pt0; // gamma * Lx / ( z*gamma +1) | |
| 2279 | 1 | const double pt2 = pt1 * sinv; // gamma * Lx / ( z*gamma +1)**2 | |
| 2280 | 1 | const double pt3 = pt2 * sinv; // gamma * Lx / ( z*gamma +1)**3 | |
| 2281 | |||
| 2282 | const Mat3d& jacinv = mSecondMap.getConstJacobianInv(); | ||
| 2283 | |||
| 2284 | // compute \frac{\partial^2 E_i}{\partial x_j \partial x_k} | ||
| 2285 | |||
| 2286 | 1 | Mat3d matE0(Mat3d::zero()); | |
| 2287 | 1 | Mat3d matE1(Mat3d::zero()); // matE2 = 0 | |
| 2288 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for(int j = 0; j < 3; j++) { |
| 2289 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for (int k = 0; k < 3; k++) { |
| 2290 | |||
| 2291 | 9 | const double pt4 = 2. * jacinv(2,j) * jacinv(2,k) * pt3; | |
| 2292 | |||
| 2293 | 9 | matE0(j,k) = -(jacinv(0,j) * jacinv(2,k) + jacinv(2,j) * jacinv(0,k)) * pt2 + | |
| 2294 | 9 | pt4 * loc.x(); | |
| 2295 | |||
| 2296 | 9 | matE1(j,k) = -(jacinv(1,j) * jacinv(2,k) + jacinv(2,j) * jacinv(1,k)) * pt2 + | |
| 2297 | 9 | pt4 * loc.y(); | |
| 2298 | } | ||
| 2299 | } | ||
| 2300 | |||
| 2301 | // compute \frac{\partial E_i}{\partial x_j} | ||
| 2302 | 1 | Mat3d gradE(Mat3d::zero()); | |
| 2303 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int j = 0; j < 3; ++j ) { |
| 2304 | 3 | gradE(0,j) = pt0 * jacinv(0,j) - pt2 * loc.x()*jacinv(2,j); | |
| 2305 | 3 | gradE(1,j) = pt0 * jacinv(1,j) - pt2 * loc.y()*jacinv(2,j); | |
| 2306 | 3 | gradE(2,j) = (1./mDepthOnLz) * jacinv(2,j); | |
| 2307 | } | ||
| 2308 | |||
| 2309 | 1 | Mat3d result(Mat3d::zero()); | |
| 2310 | // compute \fac{\partial E_j}{\partial x_m} \fac{\partial E_i}{\partial x_n} | ||
| 2311 | // \frac{\partial^2 input}{\partial E_i \partial E_j} | ||
| 2312 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int m = 0; m < 3; ++m ) { |
| 2313 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for ( int n = 0; n < 3; ++n) { |
| 2314 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
|
36 | for (int i = 0; i < 3; ++i ) { |
| 2315 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
|
108 | for (int j = 0; j < 3; ++j) { |
| 2316 | 81 | result(m, n) += gradE(j, m) * gradE(i, n) * d2_is(i, j); | |
| 2317 | } | ||
| 2318 | } | ||
| 2319 | } | ||
| 2320 | } | ||
| 2321 | |||
| 2322 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int m = 0; m < 3; ++m ) { |
| 2323 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for ( int n = 0; n < 3; ++n) { |
| 2324 | 9 | result(m, n) += | |
| 2325 | 9 | matE0(m, n) * d1_is(0) + matE1(m, n) * d1_is(1);// + matE2(m, n) * d1_is(2); | |
| 2326 | } | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | 1 | return result; | |
| 2330 | } | ||
| 2331 | |||
| 2332 | /// Return the determinant of the Jacobian of linear second map | ||
| 2333 | ✗ | double determinant() const override {return mSecondMap.determinant();} // no implementation | |
| 2334 | |||
| 2335 | /// Return the determinate of the Jacobian evaluated at @c loc | ||
| 2336 | /// @c loc is a location in the pre-image space (e.g., index space) | ||
| 2337 | ✗ | double determinant(const Vec3d& loc) const override | |
| 2338 | { | ||
| 2339 | ✗ | double s = mGamma * loc.z() + 1.0; | |
| 2340 | ✗ | double frustum_determinant = s * s * mDepthOnLzLxLx; | |
| 2341 | ✗ | return mSecondMap.determinant() * frustum_determinant; | |
| 2342 | } | ||
| 2343 | |||
| 2344 | /// Return the size of a voxel at the center of the near plane | ||
| 2345 | 21728 | Vec3d voxelSize() const override | |
| 2346 | { | ||
| 2347 | 21728 | const Vec3d loc( 0.5*(mBBox.min().x() + mBBox.max().x()), | |
| 2348 | 21728 | 0.5*(mBBox.min().y() + mBBox.max().y()), | |
| 2349 | 21728 | mBBox.min().z()); | |
| 2350 | |||
| 2351 | 21728 | return voxelSize(loc); | |
| 2352 | |||
| 2353 | } | ||
| 2354 | |||
| 2355 | /// @brief Returns the lengths of the images of the three segments | ||
| 2356 | /// from @a loc to @a loc + (1,0,0), from @a loc to @a loc + (0,1,0) | ||
| 2357 | /// and from @a loc to @a loc + (0,0,1) | ||
| 2358 | /// @param loc a location in the pre-image space (e.g., index space) | ||
| 2359 | 1645249 | Vec3d voxelSize(const Vec3d& loc) const override | |
| 2360 | { | ||
| 2361 | 1645249 | Vec3d out, pos = applyMap(loc); | |
| 2362 | 1645249 | out(0) = (applyMap(loc + Vec3d(1,0,0)) - pos).length(); | |
| 2363 | 1645249 | out(1) = (applyMap(loc + Vec3d(0,1,0)) - pos).length(); | |
| 2364 | 1645249 | out(2) = (applyMap(loc + Vec3d(0,0,1)) - pos).length(); | |
| 2365 | 1645249 | return out; | |
| 2366 | } | ||
| 2367 | |||
| 2368 | ✗ | AffineMap::Ptr getAffineMap() const override { return mSecondMap.getAffineMap(); } | |
| 2369 | |||
| 2370 | /// set the taper value, the ratio of nearplane width / far plane width | ||
| 2371 | void setTaper(double t) { mTaper = t; init();} | ||
| 2372 | /// Return the taper value. | ||
| 2373 | ✗ | double getTaper() const { return mTaper; } | |
| 2374 | /// set the frustum depth: distance between near and far plane = frustm depth * frustm x-width | ||
| 2375 | void setDepth(double d) { mDepth = d; init();} | ||
| 2376 | /// Return the unscaled frustm depth | ||
| 2377 |
1/3✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1 | double getDepth() const { return mDepth; } |
| 2378 | // gamma a non-dimensional number: nearplane x-width / camera to near plane distance | ||
| 2379 | 1 | double getGamma() const { return mGamma; } | |
| 2380 | |||
| 2381 | /// Return the bounding box that defines the frustum in pre-image space | ||
| 2382 |
2/6✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
4 | const BBoxd& getBBox() const { return mBBox; } |
| 2383 | |||
| 2384 | /// Return MapBase::Ptr& to the second map | ||
| 2385 | const AffineMap& secondMap() const { return mSecondMap; } | ||
| 2386 | /// Return @c true if the the bounding box in index space that defines the region that | ||
| 2387 | /// is maped into the frustum is non-zero, otherwise @c false | ||
| 2388 | bool isValid() const { return !mBBox.empty();} | ||
| 2389 | |||
| 2390 | /// Return @c true if the second map is a uniform scale, Rotation and translation | ||
| 2391 |
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.
|
3 | bool hasSimpleAffine() const { return mHasSimpleAffine; } |
| 2392 | |||
| 2393 | /// read serialization | ||
| 2394 | ✗ | void read(std::istream& is) override | |
| 2395 | { | ||
| 2396 | // for backward compatibility with earlier version | ||
| 2397 | ✗ | if (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_FLOAT_FRUSTUM_BBOX ) { | |
| 2398 | ✗ | CoordBBox bb; | |
| 2399 | ✗ | bb.read(is); | |
| 2400 | ✗ | mBBox = BBoxd(bb.min().asVec3d(), bb.max().asVec3d()); | |
| 2401 | } else { | ||
| 2402 | ✗ | mBBox.read(is); | |
| 2403 | } | ||
| 2404 | |||
| 2405 | ✗ | is.read(reinterpret_cast<char*>(&mTaper), sizeof(double)); | |
| 2406 | ✗ | is.read(reinterpret_cast<char*>(&mDepth), sizeof(double)); | |
| 2407 | |||
| 2408 | // Read the second maps type. | ||
| 2409 | ✗ | Name type = readString(is); | |
| 2410 | |||
| 2411 | // Check if the map has been registered. | ||
| 2412 | ✗ | if(!MapRegistry::isRegistered(type)) { | |
| 2413 | ✗ | OPENVDB_THROW(KeyError, "Map " << type << " is not registered"); | |
| 2414 | } | ||
| 2415 | |||
| 2416 | // Create the second map of the type and then read it in. | ||
| 2417 | ✗ | MapBase::Ptr proxy = math::MapRegistry::createMap(type); | |
| 2418 | ✗ | proxy->read(is); | |
| 2419 | ✗ | mSecondMap = *(proxy->getAffineMap()); | |
| 2420 | ✗ | init(); | |
| 2421 | } | ||
| 2422 | |||
| 2423 | /// write serialization | ||
| 2424 | ✗ | void write(std::ostream& os) const override | |
| 2425 | { | ||
| 2426 | ✗ | mBBox.write(os); | |
| 2427 | ✗ | os.write(reinterpret_cast<const char*>(&mTaper), sizeof(double)); | |
| 2428 | ✗ | os.write(reinterpret_cast<const char*>(&mDepth), sizeof(double)); | |
| 2429 | |||
| 2430 | ✗ | writeString(os, mSecondMap.type()); | |
| 2431 | mSecondMap.write(os); | ||
| 2432 | } | ||
| 2433 | |||
| 2434 | /// string serialization, useful for debuging | ||
| 2435 | ✗ | std::string str() const override | |
| 2436 | { | ||
| 2437 | ✗ | std::ostringstream buffer; | |
| 2438 | ✗ | buffer << " - taper: " << mTaper << std::endl; | |
| 2439 | ✗ | buffer << " - depth: " << mDepth << std::endl; | |
| 2440 | ✗ | buffer << " SecondMap: "<< mSecondMap.type() << std::endl; | |
| 2441 | ✗ | buffer << mSecondMap.str() << std::endl; | |
| 2442 | ✗ | return buffer.str(); | |
| 2443 | } | ||
| 2444 | |||
| 2445 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2446 | /// of prepending the given rotation to the linear part of this map | ||
| 2447 | 1 | MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const override | |
| 2448 | { | ||
| 2449 | return MapBase::Ptr( | ||
| 2450 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.preRotate(radians, axis))); |
| 2451 | } | ||
| 2452 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2453 | /// of prepending the given translation to the linear part of this map | ||
| 2454 | 2 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
| 2455 | { | ||
| 2456 | return MapBase::Ptr( | ||
| 2457 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.preTranslate(t))); |
| 2458 | } | ||
| 2459 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2460 | /// of prepending the given scale to the linear part of this map | ||
| 2461 | 13 | MapBase::Ptr preScale(const Vec3d& s) const override | |
| 2462 | { | ||
| 2463 | return MapBase::Ptr( | ||
| 2464 |
2/4✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
|
26 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.preScale(s))); |
| 2465 | } | ||
| 2466 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2467 | /// of prepending the given shear to the linear part of this map | ||
| 2468 | 1 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
| 2469 | { | ||
| 2470 | return MapBase::Ptr(new NonlinearFrustumMap( | ||
| 2471 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | mBBox, mTaper, mDepth, mSecondMap.preShear(shear, axis0, axis1))); |
| 2472 | } | ||
| 2473 | |||
| 2474 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2475 | /// of appending the given rotation to the linear part of this map. | ||
| 2476 | 3 | MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const override | |
| 2477 | { | ||
| 2478 | return MapBase::Ptr( | ||
| 2479 |
2/4✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
6 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.postRotate(radians, axis))); |
| 2480 | } | ||
| 2481 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2482 | /// of appending the given translation to the linear part of this map. | ||
| 2483 | 6 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
| 2484 | { | ||
| 2485 | return MapBase::Ptr( | ||
| 2486 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
12 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.postTranslate(t))); |
| 2487 | } | ||
| 2488 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2489 | /// of appending the given scale to the linear part of this map. | ||
| 2490 | 1 | MapBase::Ptr postScale(const Vec3d& s) const override | |
| 2491 | { | ||
| 2492 | return MapBase::Ptr( | ||
| 2493 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.postScale(s))); |
| 2494 | } | ||
| 2495 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
| 2496 | /// of appending the given shear to the linear part of this map. | ||
| 2497 | 1 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
| 2498 | { | ||
| 2499 | return MapBase::Ptr(new NonlinearFrustumMap( | ||
| 2500 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | mBBox, mTaper, mDepth, mSecondMap.postShear(shear, axis0, axis1))); |
| 2501 | } | ||
| 2502 | |||
| 2503 | private: | ||
| 2504 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | void init() |
| 2505 | { | ||
| 2506 | // set up as a frustum | ||
| 2507 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | mLx = mBBox.extents().x(); |
| 2508 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | mLy = mBBox.extents().y(); |
| 2509 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | mLz = mBBox.extents().z(); |
| 2510 | |||
| 2511 |
3/6✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21779 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21779 times.
|
21779 | if (isApproxEqual(mLx,0.) || isApproxEqual(mLy,0.) || isApproxEqual(mLz,0.) ) { |
| 2512 | ✗ | OPENVDB_THROW(ArithmeticError, "The index space bounding box" | |
| 2513 | " must have at least two index points in each direction."); | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | 21779 | mXo = 0.5* mLx; | |
| 2517 | 21779 | mYo = 0.5* mLy; | |
| 2518 | |||
| 2519 | // mDepth is non-dimensionalized on near | ||
| 2520 | 21779 | mGamma = (1./mTaper - 1) / mDepth; | |
| 2521 | |||
| 2522 | 21779 | mDepthOnLz = mDepth/mLz; | |
| 2523 | 21779 | mDepthOnLzLxLx = mDepthOnLz/(mLx * mLx); | |
| 2524 | |||
| 2525 | /// test for shear and non-uniform scale | ||
| 2526 |
2/2✓ Branch 0 taken 19862 times.
✓ Branch 1 taken 1917 times.
|
21779 | mHasSimpleAffine = true; |
| 2527 | Vec3d tmp = mSecondMap.voxelSize(); | ||
| 2528 | |||
| 2529 | /// false if there is non-uniform scale | ||
| 2530 |
2/2✓ Branch 0 taken 19862 times.
✓ Branch 1 taken 1917 times.
|
21786 | if (!isApproxEqual(tmp(0), tmp(1))) { mHasSimpleAffine = false; return; } |
| 2531 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1910 times.
|
1917 | if (!isApproxEqual(tmp(0), tmp(2))) { mHasSimpleAffine = false; return; } |
| 2532 | |||
| 2533 | 1910 | Vec3d trans = mSecondMap.applyMap(Vec3d(0,0,0)); | |
| 2534 | /// look for shear | ||
| 2535 | 1910 | Vec3d tmp1 = mSecondMap.applyMap(Vec3d(1,0,0)) - trans; | |
| 2536 | 1910 | Vec3d tmp2 = mSecondMap.applyMap(Vec3d(0,1,0)) - trans; | |
| 2537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | Vec3d tmp3 = mSecondMap.applyMap(Vec3d(0,0,1)) - trans; |
| 2538 | |||
| 2539 | /// false if there is shear | ||
| 2540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (!isApproxEqual(tmp1.dot(tmp2), 0., 1.e-7)) { mHasSimpleAffine = false; return; } |
| 2541 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (!isApproxEqual(tmp2.dot(tmp3), 0., 1.e-7)) { mHasSimpleAffine = false; return; } |
| 2542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (!isApproxEqual(tmp3.dot(tmp1), 0., 1.e-7)) { mHasSimpleAffine = false; return; } |
| 2543 | } | ||
| 2544 | |||
| 2545 | 2499599589 | Vec3d applyFrustumMap(const Vec3d& in) const | |
| 2546 | { | ||
| 2547 | |||
| 2548 | // Move the center of the x-face of the bbox | ||
| 2549 | // to the origin in index space. | ||
| 2550 | 2499599589 | Vec3d out(in); | |
| 2551 | 2499599589 | out = out - mBBox.min(); | |
| 2552 | 2499599589 | out.x() -= mXo; | |
| 2553 | 2499599589 | out.y() -= mYo; | |
| 2554 | |||
| 2555 | // scale the z-direction on depth / K count | ||
| 2556 | 2499599589 | out.z() *= mDepthOnLz; | |
| 2557 | |||
| 2558 | 2499599589 | double scale = (mGamma * out.z() + 1.)/ mLx; | |
| 2559 | |||
| 2560 | // scale the x-y on the length I count and apply tapper | ||
| 2561 | 2499599589 | out.x() *= scale ; | |
| 2562 | 2499599589 | out.y() *= scale ; | |
| 2563 | |||
| 2564 | 2499599589 | return out; | |
| 2565 | } | ||
| 2566 | |||
| 2567 | 143874285 | Vec3d applyFrustumInverseMap(const Vec3d& in) const | |
| 2568 | { | ||
| 2569 | // invert taper and resize: scale = 1/( (z+1)/2 (mt-1) + 1) | ||
| 2570 | 143874285 | Vec3d out(in); | |
| 2571 | 143874285 | double invScale = mLx / (mGamma * out.z() + 1.); | |
| 2572 | 143874285 | out.x() *= invScale; | |
| 2573 | 143874285 | out.y() *= invScale; | |
| 2574 | |||
| 2575 | 143874285 | out.x() += mXo; | |
| 2576 | 143874285 | out.y() += mYo; | |
| 2577 | |||
| 2578 | 143874285 | out.z() /= mDepthOnLz; | |
| 2579 | |||
| 2580 | // move back | ||
| 2581 | 143874285 | out = out + mBBox.min(); | |
| 2582 | 143874285 | return out; | |
| 2583 | } | ||
| 2584 | |||
| 2585 | // bounding box in index space used in Frustum transforms. | ||
| 2586 | BBoxd mBBox; | ||
| 2587 | |||
| 2588 | // taper value used in constructing Frustums. | ||
| 2589 | double mTaper; | ||
| 2590 | double mDepth; | ||
| 2591 | |||
| 2592 | // defines the second map | ||
| 2593 | AffineMap mSecondMap; | ||
| 2594 | |||
| 2595 | // these are derived from the above. | ||
| 2596 | double mLx, mLy, mLz; | ||
| 2597 | double mXo, mYo, mGamma, mDepthOnLz, mDepthOnLzLxLx; | ||
| 2598 | |||
| 2599 | // true: if the mSecondMap is linear and has no shear, and has no non-uniform scale | ||
| 2600 | bool mHasSimpleAffine; | ||
| 2601 | }; // class NonlinearFrustumMap | ||
| 2602 | |||
| 2603 | |||
| 2604 | //////////////////////////////////////// | ||
| 2605 | |||
| 2606 | |||
| 2607 | /// @brief Creates the composition of two maps, each of which could be a composition. | ||
| 2608 | /// In the case that each component of the composition classified as linear an | ||
| 2609 | /// acceleration AffineMap is stored. | ||
| 2610 | template<typename FirstMapType, typename SecondMapType> | ||
| 2611 |
1/4✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
4 | class CompoundMap |
| 2612 | { | ||
| 2613 | public: | ||
| 2614 | using MyType = CompoundMap<FirstMapType, SecondMapType>; | ||
| 2615 | |||
| 2616 | using Ptr = SharedPtr<MyType>; | ||
| 2617 | using ConstPtr = SharedPtr<const MyType>; | ||
| 2618 | |||
| 2619 | |||
| 2620 | CompoundMap() { updateAffineMatrix(); } | ||
| 2621 | |||
| 2622 | 14 | CompoundMap(const FirstMapType& f, const SecondMapType& s): mFirstMap(f), mSecondMap(s) | |
| 2623 | { | ||
| 2624 | 10 | updateAffineMatrix(); | |
| 2625 | 10 | } | |
| 2626 | |||
| 2627 | 12 | CompoundMap(const MyType& other): | |
| 2628 | 4 | mFirstMap(other.mFirstMap), | |
| 2629 | mSecondMap(other.mSecondMap), | ||
| 2630 | 16 | mAffineMap(other.mAffineMap) | |
| 2631 | 12 | {} | |
| 2632 | |||
| 2633 | Name type() const { return mapType(); } | ||
| 2634 | static Name mapType() | ||
| 2635 | { | ||
| 2636 | return (FirstMapType::mapType() + Name(":") + SecondMapType::mapType()); | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | bool operator==(const MyType& other) const | ||
| 2640 | { | ||
| 2641 | if (mFirstMap != other.mFirstMap) return false; | ||
| 2642 | if (mSecondMap != other.mSecondMap) return false; | ||
| 2643 | if (mAffineMap != other.mAffineMap) return false; | ||
| 2644 | return true; | ||
| 2645 | } | ||
| 2646 | |||
| 2647 | bool operator!=(const MyType& other) const { return !(*this == other); } | ||
| 2648 | |||
| 2649 | MyType& operator=(const MyType& other) | ||
| 2650 | { | ||
| 2651 | mFirstMap = other.mFirstMap; | ||
| 2652 | mSecondMap = other.mSecondMap; | ||
| 2653 | mAffineMap = other.mAffineMap; | ||
| 2654 | return *this; | ||
| 2655 | } | ||
| 2656 | |||
| 2657 | bool isIdentity() const | ||
| 2658 | { | ||
| 2659 | if (is_linear<MyType>::value) { | ||
| 2660 | return mAffineMap.isIdentity(); | ||
| 2661 | } else { | ||
| 2662 | return mFirstMap.isIdentity()&&mSecondMap.isIdentity(); | ||
| 2663 | } | ||
| 2664 | } | ||
| 2665 | |||
| 2666 | bool isDiagonal() const { | ||
| 2667 | if (is_linear<MyType>::value) { | ||
| 2668 | return mAffineMap.isDiagonal(); | ||
| 2669 | } else { | ||
| 2670 | return mFirstMap.isDiagonal()&&mSecondMap.isDiagonal(); | ||
| 2671 | } | ||
| 2672 | } | ||
| 2673 | |||
| 2674 | 8 | AffineMap::Ptr getAffineMap() const | |
| 2675 | { | ||
| 2676 | if (is_linear<MyType>::value) { | ||
| 2677 | 8 | AffineMap::Ptr affine(new AffineMap(mAffineMap)); | |
| 2678 | 8 | return affine; | |
| 2679 | } else { | ||
| 2680 | OPENVDB_THROW(ArithmeticError, | ||
| 2681 | "Constant affine matrix representation not possible for this nonlinear map"); | ||
| 2682 | } | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | // direct decompotion | ||
| 2686 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const FirstMapType& firstMap() const { return mFirstMap; } |
| 2687 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const SecondMapType& secondMap() const {return mSecondMap; } |
| 2688 | |||
| 2689 | void setFirstMap(const FirstMapType& first) { mFirstMap = first; updateAffineMatrix(); } | ||
| 2690 | void setSecondMap(const SecondMapType& second) { mSecondMap = second; updateAffineMatrix(); } | ||
| 2691 | |||
| 2692 | void read(std::istream& is) | ||
| 2693 | { | ||
| 2694 | mAffineMap.read(is); | ||
| 2695 | mFirstMap.read(is); | ||
| 2696 | mSecondMap.read(is); | ||
| 2697 | } | ||
| 2698 | void write(std::ostream& os) const | ||
| 2699 | { | ||
| 2700 | mAffineMap.write(os); | ||
| 2701 | mFirstMap.write(os); | ||
| 2702 | mSecondMap.write(os); | ||
| 2703 | } | ||
| 2704 | |||
| 2705 | private: | ||
| 2706 | 10 | void updateAffineMatrix() | |
| 2707 | { | ||
| 2708 | if (is_linear<MyType>::value) { | ||
| 2709 | // both maps need to be linear, these methods are only defined for linear maps | ||
| 2710 | 10 | AffineMap::Ptr first = mFirstMap.getAffineMap(); | |
| 2711 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | AffineMap::Ptr second= mSecondMap.getAffineMap(); |
| 2712 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
10 | mAffineMap = AffineMap(*first, *second); |
| 2713 | } | ||
| 2714 | 10 | } | |
| 2715 | |||
| 2716 | FirstMapType mFirstMap; | ||
| 2717 | SecondMapType mSecondMap; | ||
| 2718 | // used for acceleration | ||
| 2719 | AffineMap mAffineMap; | ||
| 2720 | }; // class CompoundMap | ||
| 2721 | |||
| 2722 | } // namespace math | ||
| 2723 | } // namespace OPENVDB_VERSION_NAME | ||
| 2724 | } // namespace openvdb | ||
| 2725 | |||
| 2726 | #endif // OPENVDB_MATH_MAPS_HAS_BEEN_INCLUDED | ||
| 2727 |