GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/math/Maps.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 630 888 70.9%
Functions: 178 307 58.0%
Branches: 377 2299 16.4%

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) &minus; 1,0,0), (0,0,0) &minus; (0,1,0) and (0,0,0) &minus; (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) &minus; (1,0,0), (0,0,0) &minus; (0,1,0) and (0,0,0) &minus; (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