OpenVDB 9.0.0
Maps.h
Go to the documentation of this file.
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
22namespace openvdb {
24namespace OPENVDB_VERSION_NAME {
25namespace math {
26
27
28////////////////////////////////////////
29
30/// Forward declarations of the different map types
31
32class MapBase;
33class ScaleMap;
34class TranslationMap;
35class ScaleTranslateMap;
36class UniformScaleMap;
37class UniformScaleTranslateMap;
38class AffineMap;
39class UnitaryMap;
40class NonlinearFrustumMap;
41
42template<typename T1, typename T2> class CompoundMap;
43
49
50
51////////////////////////////////////////
52
53/// Map traits
54
55template<typename T> struct is_linear { static const bool value = false; };
56template<> struct is_linear<AffineMap> { static const bool value = true; };
57template<> struct is_linear<ScaleMap> { static const bool value = true; };
58template<> struct is_linear<UniformScaleMap> { static const bool value = true; };
59template<> struct is_linear<UnitaryMap> { static const bool value = true; };
60template<> struct is_linear<TranslationMap> { static const bool value = true; };
61template<> struct is_linear<ScaleTranslateMap> { static const bool value = true; };
62template<> struct is_linear<UniformScaleTranslateMap> { static const bool value = true; };
63
64template<typename T1, typename T2> struct is_linear<CompoundMap<T1, T2> > {
66};
67
68
69template<typename T> struct is_uniform_scale { static const bool value = false; };
70template<> struct is_uniform_scale<UniformScaleMap> { static const bool value = true; };
71
72template<typename T> struct is_uniform_scale_translate { static const bool value = false; };
73template<> struct is_uniform_scale_translate<TranslationMap> { static const bool value = true; };
75 static const bool value = true;
76};
77
78
79template<typename T> struct is_scale { static const bool value = false; };
80template<> struct is_scale<ScaleMap> { static const bool value = true; };
81
82template<typename T> struct is_scale_translate { static const bool value = false; };
83template<> struct is_scale_translate<ScaleTranslateMap> { static const bool value = true; };
84
85
86template<typename T> struct is_uniform_diagonal_jacobian {
88};
89
90template<typename T> struct is_diagonal_jacobian {
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
102
103
104/// @brief General decomposition of a Matrix into a Unitary (e.g. rotation)
105/// following a Symmetric (e.g. stretch & shear)
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.
120
121
122/// @brief reduces an AffineMap to a ScaleMap or a ScaleTranslateMap when it can
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.
128
129
130////////////////////////////////////////
131
132
133/// @brief Abstract base class for maps
135{
136public:
139 using MapFactory = Ptr (*)();
140
141 MapBase(const MapBase&) = default;
142 virtual ~MapBase() = default;
143
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 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
246protected:
248
249 template<typename MapT>
250 static bool isEqualBase(const MapT& self, const MapBase& other)
251 {
252 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.
263{
264public:
265 using MapDictionary = std::map<Name, MapBase::MapFactory>;
266
268
269 /// Create a new map of the given (registered) type 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.
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
284private:
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
310{
311public:
314
316 mMatrix(Mat4d::identity()),
317 mMatrixInv(Mat4d::identity()),
318 mJacobianInv(Mat3d::identity()),
319 mDeterminant(1),
320 mVoxelSize(Vec3d(1,1,1)),
321 mIsDiagonal(true),
322 mIsIdentity(true)
323 // the default constructor for translation is zero
324 {
325 }
326
327 AffineMap(const Mat3d& m)
328 {
329 Mat4d mat4(Mat4d::identity());
330 mat4.setMat3(m);
331 mMatrix = mat4;
332 updateAcceleration();
333 }
334
335 AffineMap(const Mat4d& m): mMatrix(m)
336 {
337 if (!isAffine(m)) {
339 "Tried to initialize an affine transform from a non-affine 4x4 matrix");
340 }
341 updateAcceleration();
342 }
343
344 AffineMap(const AffineMap& other):
345 MapBase(other),
346 mMatrix(other.mMatrix),
347 mMatrixInv(other.mMatrixInv),
348 mJacobianInv(other.mJacobianInv),
349 mDeterminant(other.mDeterminant),
350 mVoxelSize(other.mVoxelSize),
351 mIsDiagonal(other.mIsDiagonal),
352 mIsIdentity(other.mIsIdentity)
353 {
354 }
355
356 /// @brief constructor that merges the matrixes for two affine maps
357 AffineMap(const AffineMap& first, const AffineMap& second):
358 mMatrix(first.mMatrix * second.mMatrix)
359 {
360 updateAcceleration();
361 }
362
363 ~AffineMap() override = default;
364
365 /// Return a MapBase::Ptr to a new AffineMap
366 static MapBase::Ptr create() { return MapBase::Ptr(new AffineMap()); }
367 /// Return a MapBase::Ptr to a deep copy of this map
368 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 static bool isRegistered() { return MapRegistry::isRegistered(AffineMap::mapType()); }
373
374 static void registerMap()
375 {
376 MapRegistry::registerMap(
377 AffineMap::mapType(),
378 AffineMap::create);
379 }
380
381 Name type() const override { return mapType(); }
382 static Name mapType() { return Name("AffineMap"); }
383
384 /// Return @c true (an AffineMap is always linear).
385 bool isLinear() const override { return true; }
386
387 /// Return @c false ( test if this is unitary with translation )
388 bool hasUniformScale() const override
389 {
390 Mat3d mat = mMatrix.getMat3();
391 const double det = mat.det();
392 if (isApproxEqual(det, double(0))) {
393 return false;
394 } else {
395 mat *= (1.0 / pow(std::abs(det), 1.0/3.0));
396 return isUnitary(mat);
397 }
398 }
399
400 bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); }
401
402 bool operator==(const AffineMap& other) const
403 {
404 // the Mat.eq() is approximate
405 if (!mMatrix.eq(other.mMatrix)) { return false; }
406 if (!mMatrixInv.eq(other.mMatrixInv)) { return false; }
407 return true;
408 }
409
410 bool operator!=(const AffineMap& other) const { return !(*this == other); }
411
413 {
414 mMatrix = other.mMatrix;
415 mMatrixInv = other.mMatrixInv;
416
417 mJacobianInv = other.mJacobianInv;
418 mDeterminant = other.mDeterminant;
419 mVoxelSize = other.mVoxelSize;
420 mIsDiagonal = other.mIsDiagonal;
421 mIsIdentity = other.mIsIdentity;
422 return *this;
423 }
424 /// Return the image of @c in under the map
425 Vec3d applyMap(const Vec3d& in) const override { return in * mMatrix; }
426 /// Return the pre-image of @c in under the map
427 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 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 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 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 Vec3d applyIJT(const Vec3d& in) const override { return in * mJacobianInv; }
460 /// Return the Jacobian Curvature: zero for a linear map
461 Mat3d applyIJC(const Mat3d& m) const override {
462 return mJacobianInv.transpose()* m * mJacobianInv;
463 }
464 Mat3d applyIJC(const Mat3d& in, const Vec3d& , const Vec3d& ) const override {
465 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 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 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 bool isIdentity() const { return mIsIdentity; }
481 /// Return @c true if the underylying matrix is diagonal
482 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 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 mMatrix.preRotate(axis, radians);
496 updateAcceleration();
497 }
498 void accumPreScale(const Vec3d& v)
499 {
500 mMatrix.preScale(v);
501 updateAcceleration();
502 }
504 {
505 mMatrix.preTranslate(v);
506 updateAcceleration();
507 }
508 void accumPreShear(Axis axis0, Axis axis1, double shear)
509 {
510 mMatrix.preShear(axis0, axis1, shear);
511 updateAcceleration();
512 }
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 mMatrix.postRotate(axis, radians);
521 updateAcceleration();
522 }
523 void accumPostScale(const Vec3d& v)
524 {
525 mMatrix.postScale(v);
526 updateAcceleration();
527 }
529 {
530 mMatrix.postTranslate(v);
531 updateAcceleration();
532 }
533 void accumPostShear(Axis axis0, Axis axis1, double shear)
534 {
535 mMatrix.postShear(axis0, axis1, shear);
536 updateAcceleration();
537 }
538 //@}
539
540
541 /// read serialization
542 void read(std::istream& is) override { mMatrix.read(is); updateAcceleration(); }
543 /// write serialization
544 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
556 {
557 return createFullyDecomposedMap(mMatrix);
558 }
559
560 /// Return AffineMap::Ptr to a deep copy of the current AffineMap
561 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 MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const override
571 {
572 AffineMap::Ptr affineMap = getAffineMap();
573 affineMap->accumPreRotation(axis, radians);
574 return simplify(affineMap);
575 }
576 MapBase::Ptr preTranslate(const Vec3d& t) const override
577 {
578 AffineMap::Ptr affineMap = getAffineMap();
579 affineMap->accumPreTranslation(t);
580 return StaticPtrCast<MapBase, AffineMap>(affineMap);
581 }
582 MapBase::Ptr preScale(const Vec3d& s) const override
583 {
584 AffineMap::Ptr affineMap = getAffineMap();
585 affineMap->accumPreScale(s);
586 return StaticPtrCast<MapBase, AffineMap>(affineMap);
587 }
588 MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
589 {
590 AffineMap::Ptr affineMap = getAffineMap();
591 affineMap->accumPreShear(axis0, axis1, shear);
592 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 MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const override
601 {
602 AffineMap::Ptr affineMap = getAffineMap();
603 affineMap->accumPostRotation(axis, radians);
604 return simplify(affineMap);
605 }
606 MapBase::Ptr postTranslate(const Vec3d& t) const override
607 {
608 AffineMap::Ptr affineMap = getAffineMap();
609 affineMap->accumPostTranslation(t);
610 return StaticPtrCast<MapBase, AffineMap>(affineMap);
611 }
612 MapBase::Ptr postScale(const Vec3d& s) const override
613 {
614 AffineMap::Ptr affineMap = getAffineMap();
615 affineMap->accumPostScale(s);
616 return StaticPtrCast<MapBase, AffineMap>(affineMap);
617 }
618 MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
619 {
620 AffineMap::Ptr affineMap = getAffineMap();
621 affineMap->accumPostShear(axis0, axis1, shear);
622 return simplify(affineMap);
623 }
624 //@}
625
626 /// Return the matrix representation of this AffineMap
627 Mat4d getMat4() const { return mMatrix;}
628 const Mat4d& getConstMat4() const {return mMatrix;}
629 const Mat3d& getConstJacobianInv() const {return mJacobianInv;}
630
631private:
632 void updateAcceleration() {
633 Mat3d mat3 = mMatrix.getMat3();
634 mDeterminant = mat3.det();
635
636 if (std::abs(mDeterminant) < (3.0 * math::Tolerance<double>::value())) {
638 "Tried to initialize an affine transform from a nearly singular matrix");
639 }
640 mMatrixInv = mMatrix.inverse();
641 mJacobianInv = mat3.inverse().transpose();
642 mIsDiagonal = math::isDiagonal(mMatrix);
643 mIsIdentity = math::isIdentity(mMatrix);
644 Vec3d pos = applyMap(Vec3d(0,0,0));
645 mVoxelSize(0) = (applyMap(Vec3d(1,0,0)) - pos).length();
646 mVoxelSize(1) = (applyMap(Vec3d(0,1,0)) - pos).length();
647 mVoxelSize(2) = (applyMap(Vec3d(0,0,1)) - pos).length();
648 }
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.
670{
671public:
674
675 ScaleMap(): MapBase(), mScaleValues(Vec3d(1,1,1)), mVoxelSize(Vec3d(1,1,1)),
676 mScaleValuesInverse(Vec3d(1,1,1)),
677 mInvScaleSqr(1,1,1), mInvTwiceScale(0.5,0.5,0.5){}
678
680 MapBase(),
681 mScaleValues(scale),
682 mVoxelSize(Vec3d(std::abs(scale(0)),std::abs(scale(1)), std::abs(scale(2))))
683 {
684 double determinant = scale[0]* scale[1] * scale[2];
685 if (std::abs(determinant) < 3.0 * math::Tolerance<double>::value()) {
686 OPENVDB_THROW(ArithmeticError, "Non-zero scale values required");
687 }
688 mScaleValuesInverse = 1.0 / mScaleValues;
689 mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse;
690 mInvTwiceScale = mScaleValuesInverse / 2;
691 }
692
693 ScaleMap(const ScaleMap& other):
694 MapBase(),
695 mScaleValues(other.mScaleValues),
696 mVoxelSize(other.mVoxelSize),
697 mScaleValuesInverse(other.mScaleValuesInverse),
698 mInvScaleSqr(other.mInvScaleSqr),
699 mInvTwiceScale(other.mInvTwiceScale)
700 {
701 }
702
703 ~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 MapBase::Ptr copy() const override { return MapBase::Ptr(new ScaleMap(*this)); }
709
710 MapBase::Ptr inverseMap() const override {
711 return MapBase::Ptr(new ScaleMap(mScaleValuesInverse));
712 }
713
714 static bool isRegistered() { return MapRegistry::isRegistered(ScaleMap::mapType()); }
715
716 static void registerMap()
717 {
718 MapRegistry::registerMap(
719 ScaleMap::mapType(),
720 ScaleMap::create);
721 }
722
723 Name type() const override { return mapType(); }
724 static Name mapType() { return Name("ScaleMap"); }
725
726 /// Return @c true (a ScaleMap is always linear).
727 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).
731 {
732 bool value = isApproxEqual(
733 std::abs(mScaleValues.x()), std::abs(mScaleValues.y()), double(5e-7));
735 std::abs(mScaleValues.x()), std::abs(mScaleValues.z()), double(5e-7));
736 return value;
737 }
738
739 /// Return the image of @c in under the map
741 {
742 return Vec3d(
743 in.x() * mScaleValues.x(),
744 in.y() * mScaleValues.y(),
745 in.z() * mScaleValues.z());
746 }
747 /// Return the pre-image of @c in under the map
749 {
750 return Vec3d(
751 in.x() * mScaleValuesInverse.x(),
752 in.y() * mScaleValuesInverse.y(),
753 in.z() * mScaleValuesInverse.z());
754 }
755 /// Return the Jacobian of the map applied to @a in.
757 return applyJacobian(in);
758 }
759 /// Return the Jacobian of the map applied to @a in.
760 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)
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)
770 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
782 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
788 {
789 Mat3d tmp;
790 for (int i = 0; i < 3; i++) {
791 tmp.setRow(i, in.row(i) * mScaleValuesInverse(i));
792 }
793 for (int i = 0; i < 3; i++) {
794 tmp.setCol(i, tmp.col(i) * mScaleValuesInverse(i));
795 }
796 return tmp;
797 }
798 Mat3d applyIJC(const Mat3d& in, const Vec3d&, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER {
799 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
805 return mScaleValues.x() * mScaleValues.y() * mScaleValues.z();
806 }
807
808 /// Return the scale values that define the map
809 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 Vec3d voxelSize() const OPENVDB_MAP_FUNC_SPECIFIER { return mVoxelSize; }
824 //@}
825
826 /// read serialization
827 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 }
835 /// write serialization
836 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 }
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 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 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
866 {
867 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 MapBase::Ptr preRotate(double radians, Axis axis) const override
876 {
877 AffineMap::Ptr affineMap = getAffineMap();
878 affineMap->accumPreRotation(axis, radians);
879 return simplify(affineMap);
880 }
881
882 MapBase::Ptr preTranslate(const Vec3d&) const override;
883 MapBase::Ptr preScale(const Vec3d&) const override;
884 MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
885 {
886 AffineMap::Ptr affineMap = getAffineMap();
887 affineMap->accumPreShear(axis0, axis1, shear);
888 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 MapBase::Ptr postRotate(double radians, Axis axis) const override
897 {
898 AffineMap::Ptr affineMap = getAffineMap();
899 affineMap->accumPostRotation(axis, radians);
900 return simplify(affineMap);
901 }
902 MapBase::Ptr postTranslate(const Vec3d&) const override;
903 MapBase::Ptr postScale(const Vec3d&) const override;
904 MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
905 {
906 AffineMap::Ptr affineMap = getAffineMap();
907 affineMap->accumPostShear(axis0, axis1, shear);
908 return simplify(affineMap);
909 }
910 //@}
911
912private:
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
921{
922public:
925
928 UniformScaleMap(const UniformScaleMap& other): ScaleMap(other) {}
929 ~UniformScaleMap() override = default;
930
931 /// Return a MapBase::Ptr to a new UniformScaleMap
933 /// Return a MapBase::Ptr to a deep copy of this map
934 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 static bool isRegistered() { return MapRegistry::isRegistered(UniformScaleMap::mapType()); }
943 static void registerMap()
944 {
945 MapRegistry::registerMap(
946 UniformScaleMap::mapType(),
947 UniformScaleMap::create);
948 }
949
950 Name type() const override { return mapType(); }
951 static Name mapType() { return Name("UniformScaleMap"); }
952
953 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
972inline MapBase::Ptr
973ScaleMap::preScale(const Vec3d& v) const
974{
975 const Vec3d new_scale(v * mScaleValues);
976 if (isApproxEqual(new_scale[0],new_scale[1]) && isApproxEqual(new_scale[0],new_scale[2])) {
977 return MapBase::Ptr(new UniformScaleMap(new_scale[0]));
978 } else {
979 return MapBase::Ptr(new ScaleMap(new_scale));
980 }
981}
982
983
984inline MapBase::Ptr
985ScaleMap::postScale(const Vec3d& v) const
986{ // pre-post Scale are the same for a scale map
987 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
994{
995public:
998
999 // default constructor is a translation by zero.
1000 TranslationMap(): MapBase(), mTranslation(Vec3d(0,0,0)) {}
1001 TranslationMap(const Vec3d& t): MapBase(), mTranslation(t) {}
1002 TranslationMap(const TranslationMap& other): MapBase(), mTranslation(other.mTranslation) {}
1003
1004 ~TranslationMap() override = default;
1005
1006 /// Return a MapBase::Ptr to a 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 MapBase::Ptr inverseMap() const override {
1012 return MapBase::Ptr(new TranslationMap(-mTranslation));
1013 }
1014
1015 static bool isRegistered() { return MapRegistry::isRegistered(TranslationMap::mapType()); }
1016
1017 static void registerMap()
1018 {
1019 MapRegistry::registerMap(
1020 TranslationMap::mapType(),
1021 TranslationMap::create);
1022 }
1023
1024 Name type() const override { return mapType(); }
1025 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 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 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 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 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 return mTranslation.eq(other.mTranslation);
1101 }
1102
1103 bool operator!=(const TranslationMap& other) const { return !(*this == other); }
1104
1105 /// Return AffineMap::Ptr to an AffineMap equivalent to *this
1107 {
1108 Mat4d matrix(Mat4d::identity());
1109 matrix.setTranslation(mTranslation);
1110
1111 AffineMap::Ptr affineMap(new AffineMap(matrix));
1112 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
1165private:
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.
1179{
1180public:
1183
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 mInvTwiceScale(0.5,0.5,0.5)
1192 {
1193 }
1194
1195 ScaleTranslateMap(const Vec3d& scale, const Vec3d& translate):
1196 MapBase(),
1197 mTranslation(translate),
1198 mScaleValues(scale),
1199 mVoxelSize(std::abs(scale(0)), std::abs(scale(1)), std::abs(scale(2)))
1200 {
1201 const double determinant = scale[0]* scale[1] * scale[2];
1202 if (std::abs(determinant) < 3.0 * math::Tolerance<double>::value()) {
1203 OPENVDB_THROW(ArithmeticError, "Non-zero scale values required");
1204 }
1205 mScaleValuesInverse = 1.0 / mScaleValues;
1206 mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse;
1207 mInvTwiceScale = mScaleValuesInverse / 2;
1208 }
1209
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 mScaleValuesInverse(1.0 / scale.getScale())
1218 {
1219 mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse;
1220 mInvTwiceScale = mScaleValuesInverse / 2;
1221 }
1222
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 ~ScaleTranslateMap() override = default;
1234
1235 /// Return a MapBase::Ptr to a 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 MapBase::Ptr inverseMap() const override
1241 {
1243 mScaleValuesInverse, -mScaleValuesInverse * mTranslation));
1244 }
1245
1246 static bool isRegistered() { return MapRegistry::isRegistered(ScaleTranslateMap::mapType()); }
1247
1248 static void registerMap()
1249 {
1250 MapRegistry::registerMap(
1251 ScaleTranslateMap::mapType(),
1252 ScaleTranslateMap::create);
1253 }
1254
1255 Name type() const override { return mapType(); }
1256 static Name mapType() { return Name("ScaleTranslateMap"); }
1257
1258 /// Return @c true (a ScaleTranslateMap is always linear).
1259 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).
1264 {
1265 bool value = isApproxEqual(
1266 std::abs(mScaleValues.x()), std::abs(mScaleValues.y()), double(5e-7));
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
1274 {
1275 return Vec3d(
1276 in.x() * mScaleValues.x() + mTranslation.x(),
1277 in.y() * mScaleValues.y() + mTranslation.y(),
1278 in.z() * mScaleValues.z() + mTranslation.z());
1279 }
1280 /// Return the pre-image of @c under the map
1282 {
1283 return Vec3d(
1284 (in.x() - mTranslation.x() ) * mScaleValuesInverse.x(),
1285 (in.y() - mTranslation.y() ) * mScaleValuesInverse.y(),
1286 (in.z() - mTranslation.z() ) * mScaleValuesInverse.z());
1287 }
1288
1289 /// Return the Jacobian of the map applied to @a in.
1291 return applyJacobian(in);
1292 }
1293 /// Return the Jacobian of the map applied to @a in.
1294 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)
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)
1304 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
1316 return applyIJT(in);
1317 }
1318 /// Return the transpose of the inverse Jacobian of the map applied to @c in
1320 {
1321 return Vec3d(
1322 in.x() * mScaleValuesInverse.x(),
1323 in.y() * mScaleValuesInverse.y(),
1324 in.z() * mScaleValuesInverse.z());
1325 }
1326 /// Return the Jacobian Curvature: zero for a linear map
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
1346 return mScaleValues.x() * mScaleValues.y() * mScaleValues.z();
1347 }
1348 /// Return the absolute values of the scale values
1349 Vec3d voxelSize() const OPENVDB_MAP_FUNC_SPECIFIER { return mVoxelSize;}
1350 /// Return the absolute values of the scale values, ignores argument
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 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 }
1375 /// write serialization
1376 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 }
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 bool operator==(const ScaleTranslateMap& other) const
1398 {
1399 // ::eq() uses a tolerance
1400 if (!mScaleValues.eq(other.mScaleValues)) { return false; }
1401 if (!mTranslation.eq(other.mTranslation)) { return false; }
1402 return true;
1403 }
1404
1405 bool operator!=(const ScaleTranslateMap& other) const { return !(*this == other); }
1406
1407 /// Return AffineMap::Ptr to an AffineMap equivalent to *this
1409 {
1410 AffineMap::Ptr affineMap(new AffineMap(math::scale<Mat4d>(mScaleValues)));
1411 affineMap->accumPostTranslation(mTranslation);
1412 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 MapBase::Ptr preRotate(double radians, Axis axis) const override
1419 {
1420 AffineMap::Ptr affineMap = getAffineMap();
1421 affineMap->accumPreRotation(axis, radians);
1422 return simplify(affineMap);
1423 }
1424 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 t.z() * s.z() );
1430 return MapBase::Ptr( new ScaleTranslateMap(mScaleValues, mTranslation + scaled_trans));
1431 }
1432
1433 MapBase::Ptr preScale(const Vec3d& v) const override;
1434
1435 MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
1436 {
1437 AffineMap::Ptr affineMap = getAffineMap();
1438 affineMap->accumPreShear(axis0, axis1, shear);
1439 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 MapBase::Ptr postRotate(double radians, Axis axis) const override
1447 {
1448 AffineMap::Ptr affineMap = getAffineMap();
1449 affineMap->accumPostRotation(axis, radians);
1450 return simplify(affineMap);
1451 }
1452 MapBase::Ptr postTranslate(const Vec3d& t) const override
1453 {
1454 return MapBase::Ptr( new ScaleTranslateMap(mScaleValues, mTranslation + t));
1455 }
1456
1457 MapBase::Ptr postScale(const Vec3d& v) const override;
1458
1459 MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
1460 {
1461 AffineMap::Ptr affineMap = getAffineMap();
1462 affineMap->accumPostShear(axis0, axis1, shear);
1463 return simplify(affineMap);
1464 }
1465 //@}
1466
1467private:
1468 Vec3d mTranslation, mScaleValues, mVoxelSize, mScaleValuesInverse,
1469 mInvScaleSqr, mInvTwiceScale;
1470}; // class ScaleTanslateMap
1471
1472
1473inline MapBase::Ptr
1474ScaleMap::postTranslate(const Vec3d& t) const
1475{
1476 return MapBase::Ptr(new ScaleTranslateMap(mScaleValues, t));
1477}
1478
1479
1480inline MapBase::Ptr
1481ScaleMap::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 t.z() * s.z() );
1488 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
1496{
1497public:
1500
1502 UniformScaleTranslateMap(double scale, const Vec3d& translate):
1503 ScaleTranslateMap(Vec3d(scale,scale,scale), translate) {}
1505 ScaleTranslateMap(scale.getScale(), translate.getTranslation()) {}
1506
1508 ~UniformScaleTranslateMap() override = default;
1509
1510 /// Return a MapBase::Ptr to a new UniformScaleTranslateMap
1512 /// Return a MapBase::Ptr to a deep copy of this map
1513 MapBase::Ptr copy() const override { return MapBase::Ptr(new UniformScaleTranslateMap(*this)); }
1514
1515 MapBase::Ptr inverseMap() const override
1516 {
1517 const Vec3d& scaleInv = getInvScale();
1518 const Vec3d& trans = getTranslation();
1519 return MapBase::Ptr(new UniformScaleTranslateMap(scaleInv[0], -scaleInv[0] * trans));
1520 }
1521
1522 static bool isRegistered()
1523 {
1524 return MapRegistry::isRegistered(UniformScaleTranslateMap::mapType());
1525 }
1526
1527 static void registerMap()
1528 {
1529 MapRegistry::registerMap(
1530 UniformScaleTranslateMap::mapType(), UniformScaleTranslateMap::create);
1531 }
1532
1533 Name type() const override { return mapType(); }
1534 static Name mapType() { return Name("UniformScaleTranslateMap"); }
1535
1536 bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); }
1537
1538 bool operator==(const UniformScaleTranslateMap& other) const
1539 {
1540 return ScaleTranslateMap::operator==(other);
1541 }
1542 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 MapBase::Ptr preTranslate(const Vec3d& t) const override
1547 {
1548 const double scale = this->getScale().x();
1549 const Vec3d new_trans = this->getTranslation() + scale * t;
1550 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 MapBase::Ptr postTranslate(const Vec3d& t) const override
1556 {
1557 const double scale = this->getScale().x();
1558 return MapBase::Ptr( new UniformScaleTranslateMap(scale, this->getTranslation() + t));
1559 }
1560}; // class UniformScaleTanslateMap
1561
1562
1563inline MapBase::Ptr
1564UniformScaleMap::postTranslate(const Vec3d& t) const
1565{
1566 const double scale = this->getScale().x();
1568}
1569
1570
1571inline MapBase::Ptr
1572UniformScaleMap::preTranslate(const Vec3d& t) const
1573{
1574 const double scale = this->getScale().x();
1576}
1577
1578
1579inline MapBase::Ptr
1580TranslationMap::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
1590inline MapBase::Ptr
1591TranslationMap::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
1604inline MapBase::Ptr
1605ScaleTranslateMap::preScale(const Vec3d& v) const
1606{
1607 const Vec3d new_scale( v * mScaleValues );
1608 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 return MapBase::Ptr( new ScaleTranslateMap(new_scale, mTranslation));
1612 }
1613}
1614
1615
1616inline MapBase::Ptr
1617ScaleTranslateMap::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 mTranslation.z()*v.z() );
1623
1624 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 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
1639{
1640public:
1643
1644 /// default constructor makes an Idenity.
1645 UnitaryMap(): mAffineMap(Mat4d::identity())
1646 {
1647 }
1648
1649 UnitaryMap(const Vec3d& axis, double radians)
1650 {
1651 Mat3d matrix;
1652 matrix.setToRotation(axis, radians);
1653 mAffineMap = AffineMap(matrix);
1654 }
1655
1656 UnitaryMap(Axis axis, double radians)
1657 {
1658 Mat4d matrix;
1659 matrix.setToRotation(axis, radians);
1660 mAffineMap = AffineMap(matrix);
1661 }
1662
1664 {
1665 // test that the mat3 is a rotation || reflection
1666 if (!isUnitary(m)) {
1667 OPENVDB_THROW(ArithmeticError, "Matrix initializing unitary map was not unitary");
1668 }
1669
1670 Mat4d matrix(Mat4d::identity());
1671 matrix.setMat3(m);
1672 mAffineMap = AffineMap(matrix);
1673 }
1674
1676 {
1677 if (!isInvertible(m)) {
1679 "4x4 Matrix initializing unitary map was not unitary: not invertible");
1680 }
1681
1682 if (!isAffine(m)) {
1684 "4x4 Matrix initializing unitary map was not unitary: not affine");
1685 }
1686
1687 if (hasTranslation(m)) {
1689 "4x4 Matrix initializing unitary map was not unitary: had translation");
1690 }
1691
1692 if (!isUnitary(m.getMat3())) {
1694 "4x4 Matrix initializing unitary map was not unitary");
1695 }
1696
1697 mAffineMap = AffineMap(m);
1698 }
1699
1700 UnitaryMap(const UnitaryMap& other):
1701 MapBase(other),
1702 mAffineMap(other.mAffineMap)
1703 {
1704 }
1705
1706 UnitaryMap(const UnitaryMap& first, const UnitaryMap& second):
1707 mAffineMap(*(first.getAffineMap()), *(second.getAffineMap()))
1708 {
1709 }
1710
1711 ~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 MapBase::Ptr inverseMap() const override
1719 {
1720 return MapBase::Ptr(new UnitaryMap(mAffineMap.getMat4().inverse()));
1721 }
1722
1723 static bool isRegistered() { return MapRegistry::isRegistered(UnitaryMap::mapType()); }
1724
1725 static void registerMap()
1726 {
1727 MapRegistry::registerMap(
1728 UnitaryMap::mapType(),
1729 UnitaryMap::create);
1730 }
1731
1732 /// Return @c UnitaryMap
1733 Name type() const override { return mapType(); }
1734 /// Return @c UnitaryMap
1735 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 if (mAffineMap!=other.mAffineMap) return false;
1749 return true;
1750 }
1751
1752 bool operator!=(const UnitaryMap& other) const { return !(*this == other); }
1753 /// Return the image of @c in under the map
1754 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 AffineMap::Ptr getAffineMap() const override {
1826 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
1895private:
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
1911{
1912public:
1915
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 NonlinearFrustumMap(const BBoxd& bb, double taper, double depth):
1929 MapBase(),mBBox(bb), mTaper(taper), mDepth(depth)
1930 {
1931 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 NonlinearFrustumMap(const BBoxd& bb, double taper, double depth,
1940 const MapBase::Ptr& secondMap):
1941 mBBox(bb), mTaper(taper), mDepth(depth)
1942 {
1943 if (!secondMap->isLinear() ) {
1945 "The second map in the Frustum transfrom must be linear");
1946 }
1947 mSecondMap = *( secondMap->getAffineMap() );
1948 init();
1949 }
1950
1952 MapBase(),
1953 mBBox(other.mBBox),
1954 mTaper(other.mTaper),
1955 mDepth(other.mDepth),
1956 mSecondMap(other.mSecondMap),
1957 mHasSimpleAffine(other.mHasSimpleAffine)
1958 {
1959 init();
1960 }
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
1978 const Vec3d& direction,
1979 const Vec3d& up,
1980 double aspect /* width / height */,
1981 double z_near, double depth,
1982 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 if (!(depth > 0)) {
1989 "The frustum depth must be non-zero and positive");
1990 }
1991 if (!(up.length() > 0)) {
1993 "The frustum height must be non-zero and positive");
1994 }
1995 if (!(aspect > 0)) {
1997 "The frustum aspect ratio must be non-zero and positive");
1998 }
1999 if (!(isApproxEqual(up.dot(direction), 0.))) {
2001 "The frustum up orientation must be perpendicular to into-frustum direction");
2002 }
2003
2004 double near_plane_height = 2 * up.length();
2005 double near_plane_width = aspect * near_plane_height;
2006
2007 Coord::ValueType y_count = static_cast<int>(Round(x_count / aspect));
2008
2009 mBBox = BBoxd(Vec3d(0,0,0), Vec3d(x_count, y_count, z_count));
2010 mDepth = depth / near_plane_width; // depth non-dimensionalized on width
2011 double gamma = near_plane_width / z_near;
2012 mTaper = 1./(mDepth*gamma + 1.);
2013
2014 Vec3d direction_unit = direction;
2015 direction_unit.normalize();
2016
2017 Mat4d r1(Mat4d::identity());
2018 r1.setToRotation(/*from*/Vec3d(0,0,1), /*to */direction_unit);
2019 Mat4d r2(Mat4d::identity());
2020 Vec3d temp = r1.inverse().transform(up);
2021 r2.setToRotation(/*from*/Vec3d(0,1,0), /*to*/temp );
2022 Mat4d scale = math::scale<Mat4d>(
2023 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 Mat4d mat = scale * r2 * r1;
2028 mat.setTranslation(position + z_near*direction_unit);
2029
2030 mSecondMap = AffineMap(mat);
2031
2032 init();
2033 }
2034
2035 ~NonlinearFrustumMap() override = default;
2036
2037 /// Return a MapBase::Ptr to a new NonlinearFrustumMap
2039 /// Return a MapBase::Ptr to a deep copy of this map
2040 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 {
2048 "inverseMap() is not implemented for NonlinearFrustumMap");
2049 }
2050 static bool isRegistered() { return MapRegistry::isRegistered(NonlinearFrustumMap::mapType()); }
2051
2052 static void registerMap()
2053 {
2054 MapRegistry::registerMap(
2055 NonlinearFrustumMap::mapType(),
2056 NonlinearFrustumMap::create);
2057 }
2058 /// Return @c NonlinearFrustumMap
2059 Name type() const override { return mapType(); }
2060 /// Return @c NonlinearFrustumMap
2061 static Name mapType() { return Name("NonlinearFrustumMap"); }
2062
2063 /// Return @c false (a NonlinearFrustumMap is never linear).
2064 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 bool isIdentity() const
2071 {
2072 // The frustum can only be consistent with a linear map if the taper value is 1
2073 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 if (!applyMap(e1).eq(e1)) return false;
2079
2080 const Vec3d e2(0,1,0);
2081 if (!applyMap(e2).eq(e2)) return false;
2082
2083 const Vec3d e3(0,0,1);
2084 if (!applyMap(e3).eq(e3)) return false;
2085
2086 return true;
2087 }
2088
2089 bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); }
2090
2091 bool operator==(const NonlinearFrustumMap& other) const
2092 {
2093 if (mBBox!=other.mBBox) return false;
2094 if (!isApproxEqual(mTaper, other.mTaper)) return false;
2095 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 if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false;
2101 /// check spanning vectors
2102 e(0) = 1;
2103 if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false;
2104 e(0) = 0;
2105 e(1) = 1;
2106 if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false;
2107 e(1) = 0;
2108 e(2) = 1;
2109 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 Vec3d applyMap(const Vec3d& in) const override
2117 {
2118 return mSecondMap.applyMap(applyFrustumMap(in));
2119 }
2120
2121 /// Return the pre-image of @c in under the map
2122 Vec3d applyInverseMap(const Vec3d& in) const override
2123 {
2124 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 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 Vec3d centered(isloc);
2134 centered = centered - mBBox.min();
2135 centered.x() -= mXo;
2136 centered.y() -= mYo;
2137
2138 // scale the z-direction on depth / K count
2139 const double zprime = centered.z()*mDepthOnLz;
2140
2141 const double scale = (mGamma * zprime + 1.) / mLx;
2142 const double scale2 = mGamma * mDepthOnLz / mLx;
2143
2144 const Vec3d tmp(scale * in.x() + scale2 * centered.x()* in.z(),
2145 scale * in.y() + scale2 * centered.y()* in.z(),
2146 mDepthOnLz * in.z());
2147
2148 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 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 Vec3d centered(isloc);
2163 centered = centered - mBBox.min();
2164 centered.x() -= mXo;
2165 centered.y() -= mYo;
2166
2167 // scale the z-direction on depth / K count
2168 const double zprime = centered.z()*mDepthOnLz;
2169
2170 const double scale = (mGamma * zprime + 1.) / mLx;
2171 const double scale2 = mGamma * mDepthOnLz / mLx;
2172
2173
2174 Vec3d out = mSecondMap.applyInverseJacobian(in);
2175
2176 out.x() = (out.x() - scale2 * centered.x() * out.z() / mDepthOnLz) / scale;
2177 out.y() = (out.y() - scale2 * centered.y() * out.z() / mDepthOnLz) / scale;
2178 out.z() = out.z() / mDepthOnLz;
2179
2180 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 Vec3d applyIJT(const Vec3d& d1_is, const Vec3d& ijk) const override
2223 {
2224 const Vec3d loc = applyFrustumMap(ijk);
2225 const double s = mGamma * loc.z() + 1.;
2226
2227 // verify that we aren't at the singularity
2228 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 const double sinv = 1.0/s; // 1/(z*gamma + 1)
2234 const double pt0 = mLx * sinv; // Lx / (z*gamma +1)
2235 const double pt1 = mGamma * pt0; // gamma * Lx / ( z*gamma +1)
2236 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 Mat3d gradE(Mat3d::zero());
2242 for (int j = 0; j < 3; ++j ) {
2243 gradE(0,j) = pt0 * jacinv(0,j) - pt2 * loc.x()*jacinv(2,j);
2244 gradE(1,j) = pt0 * jacinv(1,j) - pt2 * loc.y()*jacinv(2,j);
2245 gradE(2,j) = (1./mDepthOnLz) * jacinv(2,j);
2246 }
2247
2248 Vec3d result;
2249 for (int i = 0; i < 3; ++i) {
2250 result(i) = d1_is(0) * gradE(0,i) + d1_is(1) * gradE(1,i) + d1_is(2) * gradE(2,i);
2251 }
2252
2253 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 Mat3d applyIJC(const Mat3d& d2_is, const Vec3d& d1_is, const Vec3d& ijk) const override
2264 {
2265 const Vec3d loc = applyFrustumMap(ijk);
2266
2267 const double s = mGamma * loc.z() + 1.;
2268
2269 // verify that we aren't at the singularity
2270 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 const double sinv = 1.0/s; // 1/(z*gamma + 1)
2277 const double pt0 = mLx * sinv; // Lx / (z*gamma +1)
2278 const double pt1 = mGamma * pt0; // gamma * Lx / ( z*gamma +1)
2279 const double pt2 = pt1 * sinv; // gamma * Lx / ( z*gamma +1)**2
2280 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 Mat3d matE0(Mat3d::zero());
2287 Mat3d matE1(Mat3d::zero()); // matE2 = 0
2288 for(int j = 0; j < 3; j++) {
2289 for (int k = 0; k < 3; k++) {
2290
2291 const double pt4 = 2. * jacinv(2,j) * jacinv(2,k) * pt3;
2292
2293 matE0(j,k) = -(jacinv(0,j) * jacinv(2,k) + jacinv(2,j) * jacinv(0,k)) * pt2 +
2294 pt4 * loc.x();
2295
2296 matE1(j,k) = -(jacinv(1,j) * jacinv(2,k) + jacinv(2,j) * jacinv(1,k)) * pt2 +
2297 pt4 * loc.y();
2298 }
2299 }
2300
2301 // compute \frac{\partial E_i}{\partial x_j}
2302 Mat3d gradE(Mat3d::zero());
2303 for (int j = 0; j < 3; ++j ) {
2304 gradE(0,j) = pt0 * jacinv(0,j) - pt2 * loc.x()*jacinv(2,j);
2305 gradE(1,j) = pt0 * jacinv(1,j) - pt2 * loc.y()*jacinv(2,j);
2306 gradE(2,j) = (1./mDepthOnLz) * jacinv(2,j);
2307 }
2308
2309 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 for (int m = 0; m < 3; ++m ) {
2313 for ( int n = 0; n < 3; ++n) {
2314 for (int i = 0; i < 3; ++i ) {
2315 for (int j = 0; j < 3; ++j) {
2316 result(m, n) += gradE(j, m) * gradE(i, n) * d2_is(i, j);
2317 }
2318 }
2319 }
2320 }
2321
2322 for (int m = 0; m < 3; ++m ) {
2323 for ( int n = 0; n < 3; ++n) {
2324 result(m, n) +=
2325 matE0(m, n) * d1_is(0) + matE1(m, n) * d1_is(1);// + matE2(m, n) * d1_is(2);
2326 }
2327 }
2328
2329 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 Vec3d voxelSize() const override
2346 {
2347 const Vec3d loc( 0.5*(mBBox.min().x() + mBBox.max().x()),
2348 0.5*(mBBox.min().y() + mBBox.max().y()),
2349 mBBox.min().z());
2350
2351 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 Vec3d voxelSize(const Vec3d& loc) const override
2360 {
2361 Vec3d out, pos = applyMap(loc);
2362 out(0) = (applyMap(loc + Vec3d(1,0,0)) - pos).length();
2363 out(1) = (applyMap(loc + Vec3d(0,1,0)) - pos).length();
2364 out(2) = (applyMap(loc + Vec3d(0,0,1)) - pos).length();
2365 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 double getDepth() const { return mDepth; }
2378 // gamma a non-dimensional number: nearplane x-width / camera to near plane distance
2379 double getGamma() const { return mGamma; }
2380
2381 /// Return the bounding box that defines the frustum in pre-image space
2382 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 bool hasSimpleAffine() const { return mHasSimpleAffine; }
2392
2393 /// read serialization
2394 void read(std::istream& is) override
2395 {
2396 // for backward compatibility with earlier version
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 MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const override
2448 {
2449 return MapBase::Ptr(
2450 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 MapBase::Ptr preTranslate(const Vec3d& t) const override
2455 {
2456 return MapBase::Ptr(
2457 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 MapBase::Ptr preScale(const Vec3d& s) const override
2462 {
2463 return MapBase::Ptr(
2464 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 MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
2469 {
2471 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 MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const override
2477 {
2478 return MapBase::Ptr(
2479 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 MapBase::Ptr postTranslate(const Vec3d& t) const override
2484 {
2485 return MapBase::Ptr(
2486 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 MapBase::Ptr postScale(const Vec3d& s) const override
2491 {
2492 return MapBase::Ptr(
2493 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 MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
2498 {
2500 mBBox, mTaper, mDepth, mSecondMap.postShear(shear, axis0, axis1)));
2501 }
2502
2503private:
2504 void init()
2505 {
2506 // set up as a frustum
2507 mLx = mBBox.extents().x();
2508 mLy = mBBox.extents().y();
2509 mLz = mBBox.extents().z();
2510
2511 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 mXo = 0.5* mLx;
2517 mYo = 0.5* mLy;
2518
2519 // mDepth is non-dimensionalized on near
2520 mGamma = (1./mTaper - 1) / mDepth;
2521
2522 mDepthOnLz = mDepth/mLz;
2523 mDepthOnLzLxLx = mDepthOnLz/(mLx * mLx);
2524
2525 /// test for shear and non-uniform scale
2526 mHasSimpleAffine = true;
2527 Vec3d tmp = mSecondMap.voxelSize();
2528
2529 /// false if there is non-uniform scale
2530 if (!isApproxEqual(tmp(0), tmp(1))) { mHasSimpleAffine = false; return; }
2531 if (!isApproxEqual(tmp(0), tmp(2))) { mHasSimpleAffine = false; return; }
2532
2533 Vec3d trans = mSecondMap.applyMap(Vec3d(0,0,0));
2534 /// look for shear
2535 Vec3d tmp1 = mSecondMap.applyMap(Vec3d(1,0,0)) - trans;
2536 Vec3d tmp2 = mSecondMap.applyMap(Vec3d(0,1,0)) - trans;
2537 Vec3d tmp3 = mSecondMap.applyMap(Vec3d(0,0,1)) - trans;
2538
2539 /// false if there is shear
2540 if (!isApproxEqual(tmp1.dot(tmp2), 0., 1.e-7)) { mHasSimpleAffine = false; return; }
2541 if (!isApproxEqual(tmp2.dot(tmp3), 0., 1.e-7)) { mHasSimpleAffine = false; return; }
2542 if (!isApproxEqual(tmp3.dot(tmp1), 0., 1.e-7)) { mHasSimpleAffine = false; return; }
2543 }
2544
2545 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 Vec3d out(in);
2551 out = out - mBBox.min();
2552 out.x() -= mXo;
2553 out.y() -= mYo;
2554
2555 // scale the z-direction on depth / K count
2556 out.z() *= mDepthOnLz;
2557
2558 double scale = (mGamma * out.z() + 1.)/ mLx;
2559
2560 // scale the x-y on the length I count and apply tapper
2561 out.x() *= scale ;
2562 out.y() *= scale ;
2563
2564 return out;
2565 }
2566
2567 Vec3d applyFrustumInverseMap(const Vec3d& in) const
2568 {
2569 // invert taper and resize: scale = 1/( (z+1)/2 (mt-1) + 1)
2570 Vec3d out(in);
2571 double invScale = mLx / (mGamma * out.z() + 1.);
2572 out.x() *= invScale;
2573 out.y() *= invScale;
2574
2575 out.x() += mXo;
2576 out.y() += mYo;
2577
2578 out.z() /= mDepthOnLz;
2579
2580 // move back
2581 out = out + mBBox.min();
2582 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.
2610template<typename FirstMapType, typename SecondMapType>
2612{
2613public:
2615
2618
2619
2620 CompoundMap() { updateAffineMatrix(); }
2621
2622 CompoundMap(const FirstMapType& f, const SecondMapType& s): mFirstMap(f), mSecondMap(s)
2623 {
2624 updateAffineMatrix();
2625 }
2626
2627 CompoundMap(const MyType& other):
2628 mFirstMap(other.mFirstMap),
2629 mSecondMap(other.mSecondMap),
2630 mAffineMap(other.mAffineMap)
2631 {}
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 {
2660 return mAffineMap.isIdentity();
2661 } else {
2662 return mFirstMap.isIdentity()&&mSecondMap.isIdentity();
2663 }
2664 }
2665
2666 bool isDiagonal() const {
2668 return mAffineMap.isDiagonal();
2669 } else {
2670 return mFirstMap.isDiagonal()&&mSecondMap.isDiagonal();
2671 }
2672 }
2673
2675 {
2677 AffineMap::Ptr affine(new AffineMap(mAffineMap));
2678 return affine;
2679 } else {
2681 "Constant affine matrix representation not possible for this nonlinear map");
2682 }
2683 }
2684
2685 // direct decompotion
2686 const FirstMapType& firstMap() const { return mFirstMap; }
2687 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
2705private:
2706 void updateAffineMatrix()
2707 {
2709 // both maps need to be linear, these methods are only defined for linear maps
2710 AffineMap::Ptr first = mFirstMap.getAffineMap();
2711 AffineMap::Ptr second= mSecondMap.getAffineMap();
2712 mAffineMap = AffineMap(*first, *second);
2713 }
2714 }
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
ValueT value
Definition: GridBuilder.h:1287
#define OPENVDB_MAP_CLASS_SPECIFIER
Definition: Maps.h:298
#define OPENVDB_MAP_FUNC_SPECIFIER
Definition: Maps.h:299
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_API
Definition: Platform.h:254
Definition: Exceptions.h:56
Definition: Exceptions.h:59
Definition: Exceptions.h:61
A general linear transform using homogeneous coordinates to perform rotation, scaling,...
Definition: Maps.h:310
MapBase::Ptr postScale(const Vec3d &s) const override
Definition: Maps.h:612
void accumPostShear(Axis axis0, Axis axis1, double shear)
Definition: Maps.h:533
static void registerMap()
Definition: Maps.h:374
AffineMap()
Definition: Maps.h:315
void write(std::ostream &os) const override
write serialization
Definition: Maps.h:544
Vec3d voxelSize(const Vec3d &) const override
Definition: Maps.h:476
AffineMap(const Mat3d &m)
Definition: Maps.h:327
bool isDiagonal() const
Return true if the underylying matrix is diagonal.
Definition: Maps.h:482
Vec3d applyJT(const Vec3d &in, const Vec3d &) const override
Definition: Maps.h:447
MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:618
MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:588
void accumPostRotation(Axis axis, double radians)
Modify the existing affine map by post-applying the given operation.
Definition: Maps.h:518
void accumPreShear(Axis axis0, Axis axis1, double shear)
Definition: Maps.h:508
MapBase::Ptr postTranslate(const Vec3d &t) const override
Definition: Maps.h:606
Vec3d applyIJT(const Vec3d &in) const override
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:459
AffineMap(const AffineMap &first, const AffineMap &second)
constructor that merges the matrixes for two affine maps
Definition: Maps.h:357
Mat4d getMat4() const
Return the matrix representation of this AffineMap.
Definition: Maps.h:627
Name type() const override
Return the name of this map's concrete type (e.g., "AffineMap").
Definition: Maps.h:381
AffineMap::Ptr getAffineMap() const override
Return AffineMap::Ptr to a deep copy of the current AffineMap.
Definition: Maps.h:561
double determinant(const Vec3d &) const override
Return the determinant of the Jacobian, ignores argument.
Definition: Maps.h:468
bool operator!=(const AffineMap &other) const
Definition: Maps.h:410
bool hasUniformScale() const override
Return false ( test if this is unitary with translation )
Definition: Maps.h:388
bool operator==(const AffineMap &other) const
Definition: Maps.h:402
MapBase::Ptr postRotate(double radians, Axis axis=X_AXIS) const override
Return a MapBase::Ptr to a new map that is the result of postfixing the appropraite operation.
Definition: Maps.h:600
Vec3d applyJT(const Vec3d &in) const override
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:449
double determinant() const override
Return the determinant of the Jacobian.
Definition: Maps.h:470
Vec3d applyJacobian(const Vec3d &in, const Vec3d &) const override
Return the Jacobian of the map applied to in.
Definition: Maps.h:430
Mat3d applyIJC(const Mat3d &in, const Vec3d &, const Vec3d &) const override
Definition: Maps.h:464
MapBase::Ptr copy() const override
Return a MapBase::Ptr to a deep copy of this map.
Definition: Maps.h:368
Vec3d applyJacobian(const Vec3d &in) const override
Return the Jacobian of the map applied to in.
Definition: Maps.h:432
std::string str() const override
string serialization, useful for debugging
Definition: Maps.h:546
AffineMap::Ptr inverse() const
Return AffineMap::Ptr to the inverse of this map.
Definition: Maps.h:564
bool isLinear() const override
Return true (an AffineMap is always linear).
Definition: Maps.h:385
const Mat3d & getConstJacobianInv() const
Definition: Maps.h:629
Vec3d applyInverseJacobian(const Vec3d &in, const Vec3d &) const override
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:436
Vec3d applyInverseJacobian(const Vec3d &in) const override
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:441
MapBase::Ptr preTranslate(const Vec3d &t) const override
Definition: Maps.h:576
Vec3d voxelSize() const override
Return the lengths of the images of the segments (0,0,0)-(1,0,0), (0,0,0)-(0,1,0) and (0,...
Definition: Maps.h:475
MapBase::Ptr preScale(const Vec3d &s) const override
Definition: Maps.h:582
static bool isRegistered()
Definition: Maps.h:372
bool isScaleTranslate() const
Return true if the map is equivalent to a ScaleTranslateMap.
Definition: Maps.h:486
AffineMap(const AffineMap &other)
Definition: Maps.h:344
MapBase::Ptr preRotate(double radians, Axis axis=X_AXIS) const override
Return a MapBase::Ptr to a new map that is the result of prepending the appropraite operation.
Definition: Maps.h:570
const Mat4d & getConstMat4() const
Definition: Maps.h:628
AffineMap & operator=(const AffineMap &other)
Definition: Maps.h:412
Mat3d applyIJC(const Mat3d &m) const override
Return the Jacobian Curvature: zero for a linear map.
Definition: Maps.h:461
Vec3d applyIJT(const Vec3d &in, const Vec3d &) const override
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:457
Vec3d applyMap(const Vec3d &in) const override
Return the image of in under the map.
Definition: Maps.h:425
MapBase::Ptr inverseMap() const override
Return a new map representing the inverse of this map.
Definition: Maps.h:370
bool isIdentity() const
Return true if the underlying matrix is approximately an identity.
Definition: Maps.h:480
void read(std::istream &is) override
read serialization
Definition: Maps.h:542
void accumPreRotation(Axis axis, double radians)
Modify the existing affine map by pre-applying the given operation.
Definition: Maps.h:493
bool isScale() const
Return true if the map is equivalent to a ScaleMap.
Definition: Maps.h:484
Vec3d applyInverseMap(const Vec3d &in) const override
Return the pre-image of in under the map.
Definition: Maps.h:427
void accumPreScale(const Vec3d &v)
Definition: Maps.h:498
void accumPreTranslation(const Vec3d &v)
Definition: Maps.h:503
static MapBase::Ptr create()
Return a MapBase::Ptr to a new AffineMap.
Definition: Maps.h:366
SharedPtr< FullyDecomposedMap > createDecomposedMap()
on-demand decomposition of the affine map
Definition: Maps.h:555
SharedPtr< AffineMap > Ptr
Definition: Maps.h:312
void accumPostScale(const Vec3d &v)
Definition: Maps.h:523
~AffineMap() override=default
static Name mapType()
Definition: Maps.h:382
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:400
void accumPostTranslation(const Vec3d &v)
Definition: Maps.h:528
AffineMap(const Mat4d &m)
Definition: Maps.h:335
Creates the composition of two maps, each of which could be a composition. In the case that each comp...
Definition: Maps.h:2612
SharedPtr< MyType > Ptr
Definition: Maps.h:2616
const SecondMapType & secondMap() const
Definition: Maps.h:2687
const FirstMapType & firstMap() const
Definition: Maps.h:2686
void setSecondMap(const SecondMapType &second)
Definition: Maps.h:2690
bool isDiagonal() const
Definition: Maps.h:2666
SharedPtr< const MyType > ConstPtr
Definition: Maps.h:2617
void write(std::ostream &os) const
Definition: Maps.h:2698
void setFirstMap(const FirstMapType &first)
Definition: Maps.h:2689
AffineMap::Ptr getAffineMap() const
Definition: Maps.h:2674
CompoundMap()
Definition: Maps.h:2620
bool operator==(const MyType &other) const
Definition: Maps.h:2639
bool operator!=(const MyType &other) const
Definition: Maps.h:2647
Name type() const
Definition: Maps.h:2633
CompoundMap(const FirstMapType &f, const SecondMapType &s)
Definition: Maps.h:2622
bool isIdentity() const
Definition: Maps.h:2657
MyType & operator=(const MyType &other)
Definition: Maps.h:2649
static Name mapType()
Definition: Maps.h:2634
CompoundMap(const MyType &other)
Definition: Maps.h:2627
void read(std::istream &is)
Definition: Maps.h:2692
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
const Coord & min() const
Definition: Coord.h:320
const Coord & max() const
Definition: Coord.h:321
void read(std::istream &is)
Unserialize this bounding box from the given stream.
Definition: Coord.h:495
Int32 ValueType
Definition: Coord.h:32
Vec3d asVec3d() const
Definition: Coord.h:143
Abstract base class for maps.
Definition: Maps.h:135
virtual Vec3d voxelSize() const =0
Method to return the local size of a voxel. When a location is specified as an argument,...
virtual Vec3d applyInverseMap(const Vec3d &in) const =0
static bool isEqualBase(const MapT &self, const MapBase &other)
Definition: Maps.h:250
virtual Vec3d applyMap(const Vec3d &in) const =0
virtual SharedPtr< AffineMap > getAffineMap() const =0
SharedPtr< MapBase > Ptr
Definition: Maps.h:137
bool isType() const
Return true if this map is of concrete type MapT (e.g., AffineMap).
Definition: Maps.h:150
virtual double determinant() const =0
virtual MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const =0
virtual Mat3d applyIJC(const Mat3d &m) const =0
virtual Vec3d applyJT(const Vec3d &in) const =0
Apply the Jacobian transpose of this map to a vector. For a linear map this is equivalent to applying...
virtual std::string str() const =0
virtual Mat3d applyIJC(const Mat3d &m, const Vec3d &v, const Vec3d &domainPos) const =0
virtual Vec3d applyJT(const Vec3d &in, const Vec3d &domainPos) const =0
virtual MapBase::Ptr copy() const =0
virtual void read(std::istream &)=0
virtual ~MapBase()=default
virtual Vec3d voxelSize(const Vec3d &) const =0
virtual bool isLinear() const =0
Return true if this map is linear.
virtual bool hasUniformScale() const =0
Return true if the spacing between the image of latice is uniform in all directions.
virtual MapBase::Ptr preScale(const Vec3d &) const =0
virtual Vec3d applyInverseJacobian(const Vec3d &in) const =0
Apply the InverseJacobian of this map to a vector. For a linear map this is equivalent to applying th...
virtual Vec3d applyIJT(const Vec3d &in) const =0
Apply the Inverse Jacobian Transpose of this map to a vector. For a linear map this is equivalent to ...
SharedPtr< const MapBase > ConstPtr
Definition: Maps.h:138
virtual double determinant(const Vec3d &) const =0
MapBase()
Definition: Maps.h:247
virtual Vec3d applyIJT(const Vec3d &in, const Vec3d &domainPos) const =0
MapBase(const MapBase &)=default
virtual MapBase::Ptr postTranslate(const Vec3d &) const =0
virtual Name type() const =0
Return the name of this map's concrete type (e.g., "AffineMap").
virtual Vec3d applyInverseJacobian(const Vec3d &in, const Vec3d &domainPos) const =0
virtual void write(std::ostream &) const =0
virtual Vec3d applyJacobian(const Vec3d &in) const =0
Apply the Jacobian of this map to a vector. For a linear map this is equivalent to applying the map e...
virtual MapBase::Ptr preTranslate(const Vec3d &) const =0
virtual MapBase::Ptr postRotate(double radians, Axis axis=X_AXIS) const =0
virtual MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const =0
virtual MapBase::Ptr postScale(const Vec3d &) const =0
virtual Vec3d applyJacobian(const Vec3d &in, const Vec3d &domainPos) const =0
virtual MapBase::Ptr inverseMap() const =0
Return a new map representing the inverse of this map.
Ptr(*)() MapFactory
Definition: Maps.h:139
virtual bool isEqual(const MapBase &other) const =0
Return true if this map is equal to the given map.
virtual MapBase::Ptr preRotate(double radians, Axis axis=X_AXIS) const =0
Methods to update the map.
Threadsafe singleton object for accessing the map type-name dictionary. Associates a map type-name wi...
Definition: Maps.h:263
static MapBase::Ptr createMap(const Name &)
Create a new map of the given (registered) type name.
static void clear()
Clear the map type registry.
static void unregisterMap(const Name &)
Remove a map type from the registry.
static bool isRegistered(const Name &)
Return true if the given map type name is registered.
std::map< Name, MapBase::MapFactory > MapDictionary
Definition: Maps.h:265
static MapRegistry * instance()
static void registerMap(const Name &, MapBase::MapFactory)
Register a map type along with a factory function.
void setToRotation(const Quat< T > &q)
Set this matrix to the rotation matrix specified by the quaternion.
Definition: Mat3.h:267
Mat3 inverse(T tolerance=0) const
Definition: Mat3.h:479
void setCol(int j, const Vec3< T > &v)
Set jth column to vector v.
Definition: Mat3.h:173
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:468
T det() const
Determinant of matrix.
Definition: Mat3.h:493
Vec3< T > col(int j) const
Get jth column, e.g. Vec3d v = m.col(0);.
Definition: Mat3.h:182
void setRow(int i, const Vec3< T > &v)
Set ith row to vector v.
Definition: Mat3.h:155
Mat4 inverse(T tolerance=0) const
Definition: Mat4.h:499
Mat3< T > getMat3() const
Definition: Mat4.h:311
void setToRotation(Axis axis, T angle)
Sets the matrix to a rotation about the given axis.
Definition: Mat4.h:797
Vec4< T0 > transform(const Vec4< T0 > &v) const
Transform a Vec4 by post-multiplication.
Definition: Mat4.h:1012
void setTranslation(const Vec3< T > &t)
Definition: Mat4.h:328
void setMat3(const Mat3< T > &m)
Set upper left to a Mat3.
Definition: Mat4.h:304
This map is composed of three steps. First it will take a box of size (Lx X Ly X Lz) defined by a mem...
Definition: Maps.h:1911
MapBase::Ptr postScale(const Vec3d &s) const override
Return a MapBase::Ptr to a new map that is the result of appending the given scale to the linear part...
Definition: Maps.h:2490
NonlinearFrustumMap()
Definition: Maps.h:1916
NonlinearFrustumMap(const BBoxd &bb, double taper, double depth, const MapBase::Ptr &secondMap)
Constructor that takes an index-space bounding box to be mapped into a frustum with a given depth and...
Definition: Maps.h:1939
void setTaper(double t)
set the taper value, the ratio of nearplane width / far plane width
Definition: Maps.h:2371
static void registerMap()
Definition: Maps.h:2052
const BBoxd & getBBox() const
Return the bounding box that defines the frustum in pre-image space.
Definition: Maps.h:2382
void write(std::ostream &os) const override
write serialization
Definition: Maps.h:2424
bool operator!=(const NonlinearFrustumMap &other) const
Definition: Maps.h:2113
const AffineMap & secondMap() const
Return MapBase::Ptr& to the second map.
Definition: Maps.h:2385
double getGamma() const
Definition: Maps.h:2379
double getDepth() const
Return the unscaled frustm depth.
Definition: Maps.h:2377
Vec3d applyIJT(const Vec3d &d1_is, const Vec3d &ijk) const override
Definition: Maps.h:2222
MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
Return a MapBase::Ptr to a new map that is the result of appending the given shear to the linear part...
Definition: Maps.h:2497
MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given shear to the linear par...
Definition: Maps.h:2468
MapBase::Ptr postTranslate(const Vec3d &t) const override
Return a MapBase::Ptr to a new map that is the result of appending the given translation to the linea...
Definition: Maps.h:2483
Vec3d applyIJT(const Vec3d &in) const override
Return the transpose of the inverse Jacobian of the linear second map applied to in.
Definition: Maps.h:2212
bool operator==(const NonlinearFrustumMap &other) const
Definition: Maps.h:2091
bool isValid() const
Definition: Maps.h:2388
Name type() const override
Return NonlinearFrustumMap.
Definition: Maps.h:2059
AffineMap::Ptr getAffineMap() const override
Definition: Maps.h:2368
NonlinearFrustumMap(const Vec3d &position, const Vec3d &direction, const Vec3d &up, double aspect, double z_near, double depth, Coord::ValueType x_count, Coord::ValueType z_count)
Constructor from a camera frustum.
Definition: Maps.h:1977
bool hasUniformScale() const override
Return false (by convention false)
Definition: Maps.h:2067
MapBase::Ptr postRotate(double radians, Axis axis=X_AXIS) const override
Return a MapBase::Ptr to a new map that is the result of appending the given rotation to the linear p...
Definition: Maps.h:2476
Vec3d applyJT(const Vec3d &in) const override
Return the Jacobian Transpose of the second map applied to in.
Definition: Maps.h:2207
double determinant() const override
Return the determinant of the Jacobian of linear second map.
Definition: Maps.h:2333
MapBase::Ptr copy() const override
Return a MapBase::Ptr to a deep copy of this map.
Definition: Maps.h:2040
Vec3d applyJacobian(const Vec3d &in) const override
Return the Jacobian of the linear second map applied to in.
Definition: Maps.h:2127
std::string str() const override
string serialization, useful for debuging
Definition: Maps.h:2435
bool isLinear() const override
Return false (a NonlinearFrustumMap is never linear).
Definition: Maps.h:2064
Vec3d applyJT(const Vec3d &in, const Vec3d &isloc) const override
Return the Jacobian Transpose of the map applied to vector in at indexloc.
Definition: Maps.h:2185
Vec3d applyInverseJacobian(const Vec3d &in) const override
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:2154
MapBase::Ptr preTranslate(const Vec3d &t) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given translation to the line...
Definition: Maps.h:2454
Vec3d voxelSize() const override
Return the size of a voxel at the center of the near plane.
Definition: Maps.h:2345
MapBase::Ptr preScale(const Vec3d &s) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given scale to the linear par...
Definition: Maps.h:2461
static bool isRegistered()
Definition: Maps.h:2050
double determinant(const Vec3d &loc) const override
Definition: Maps.h:2337
NonlinearFrustumMap(const NonlinearFrustumMap &other)
Definition: Maps.h:1951
NonlinearFrustumMap(const BBoxd &bb, double taper, double depth)
Constructor that takes an index-space bounding box to be mapped into a frustum with a given depth and...
Definition: Maps.h:1928
MapBase::Ptr preRotate(double radians, Axis axis=X_AXIS) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given rotation to the linear ...
Definition: Maps.h:2447
Mat3d applyIJC(const Mat3d &d2_is, const Vec3d &d1_is, const Vec3d &ijk) const override
Definition: Maps.h:2263
Vec3d applyInverseJacobian(const Vec3d &in, const Vec3d &isloc) const override
Return the Inverse Jacobian defined at isloc of the map applied to in.
Definition: Maps.h:2158
Vec3d applyMap(const Vec3d &in) const override
Return the image of in under the map.
Definition: Maps.h:2116
MapBase::Ptr inverseMap() const override
Not implemented, since there is currently no map type that can represent the inverse of a frustum.
Definition: Maps.h:2045
bool isIdentity() const
Return true if the map is equivalent to an identity.
Definition: Maps.h:2070
void read(std::istream &is) override
read serialization
Definition: Maps.h:2394
double getTaper() const
Return the taper value.
Definition: Maps.h:2373
Vec3d applyInverseMap(const Vec3d &in) const override
Return the pre-image of in under the map.
Definition: Maps.h:2122
Vec3d voxelSize(const Vec3d &loc) const override
Returns the lengths of the images of the three segments from loc to loc + (1,0,0),...
Definition: Maps.h:2359
static MapBase::Ptr create()
Return a MapBase::Ptr to a new NonlinearFrustumMap.
Definition: Maps.h:2038
void setDepth(double d)
set the frustum depth: distance between near and far plane = frustm depth * frustm x-width
Definition: Maps.h:2375
Mat3d applyIJC(const Mat3d &in) const override
Return the Jacobian Curvature for the linear second map.
Definition: Maps.h:2258
static Name mapType()
Return NonlinearFrustumMap.
Definition: Maps.h:2061
Vec3d applyJacobian(const Vec3d &in, const Vec3d &isloc) const override
Return the Jacobian defined at isloc applied to in.
Definition: Maps.h:2129
bool hasSimpleAffine() const
Return true if the second map is a uniform scale, Rotation and translation.
Definition: Maps.h:2391
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:2089
A specialized Affine transform that scales along the principal axis the scaling need not be uniform i...
Definition: Maps.h:670
Vec3d voxelSize() const final
Return the lengths of the images of the segments (0,0,0) − 1,0,0), (0,0,0) − (0,1,...
Definition: Maps.h:822
const Vec3d & getScale() const
Return the scale values that define the map.
Definition: Maps.h:809
Vec3d applyInverseMap(const Vec3d &in) const final
Return the pre-image of in under the map.
Definition: Maps.h:748
static void registerMap()
Definition: Maps.h:716
void write(std::ostream &os) const override
write serialization
Definition: Maps.h:836
Vec3d applyMap(const Vec3d &in) const final
Return the image of in under the map.
Definition: Maps.h:740
MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:904
MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:884
ScaleMap(const Vec3d &scale)
Definition: Maps.h:679
double determinant(const Vec3d &) const final
Return the product of the scale values, ignores argument.
Definition: Maps.h:802
Vec3d applyIJT(const Vec3d &in) const final
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:785
Vec3d applyIJT(const Vec3d &in, const Vec3d &) const final
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:781
const Vec3d & getInvScale() const
Return 1/(scale)
Definition: Maps.h:816
Vec3d applyJacobian(const Vec3d &in, const Vec3d &) const final
Return the Jacobian of the map applied to in.
Definition: Maps.h:756
bool isLinear() const final
Return true (a ScaleMap is always linear).
Definition: Maps.h:727
Name type() const override
Return the name of this map's concrete type (e.g., "AffineMap").
Definition: Maps.h:723
AffineMap::Ptr getAffineMap() const override
Return a AffineMap equivalent to this map.
Definition: Maps.h:865
MapBase::Ptr postRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of prepending the appropraite operation to the ...
Definition: Maps.h:896
MapBase::Ptr copy() const override
Return a MapBase::Ptr to a deep copy of this map.
Definition: Maps.h:708
std::string str() const override
string serialization, useful for debuging
Definition: Maps.h:845
Vec3d applyInverseJacobian(const Vec3d &in, const Vec3d &) const final
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:764
Vec3d applyJacobian(const Vec3d &in) const final
Return the Jacobian of the map applied to in.
Definition: Maps.h:760
Mat3d applyIJC(const Mat3d &in) const final
Return the Jacobian Curvature: zero for a linear map.
Definition: Maps.h:787
~ScaleMap() override=default
MapBase::Ptr preRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of prepending the appropraite operation to the ...
Definition: Maps.h:875
Vec3d applyJT(const Vec3d &in) const final
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:777
Vec3d voxelSize(const Vec3d &) const final
Definition: Maps.h:823
bool operator==(const ScaleMap &other) const
Definition: Maps.h:855
static bool isRegistered()
Definition: Maps.h:714
ScaleMap()
Definition: Maps.h:675
double determinant() const final
Return the product of the scale values.
Definition: Maps.h:804
Vec3d applyJT(const Vec3d &in, const Vec3d &) const final
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:775
const Vec3d & getInvTwiceScale() const
Return 1/(2 scale). Used to optimize some finite difference calculations.
Definition: Maps.h:814
ScaleMap(const ScaleMap &other)
Definition: Maps.h:693
bool hasUniformScale() const final
Return true if the values have the same magitude (eg. -1, 1, -1 would be a rotation).
Definition: Maps.h:730
Mat3d applyIJC(const Mat3d &in, const Vec3d &, const Vec3d &) const final
Definition: Maps.h:798
MapBase::Ptr inverseMap() const override
Return a new map representing the inverse of this map.
Definition: Maps.h:710
const Vec3d & getInvScaleSqr() const
Return the square of the scale. Used to optimize some finite difference calculations.
Definition: Maps.h:812
void read(std::istream &is) override
read serialization
Definition: Maps.h:827
bool operator!=(const ScaleMap &other) const
Definition: Maps.h:862
static MapBase::Ptr create()
Return a MapBase::Ptr to a new ScaleMap.
Definition: Maps.h:706
static Name mapType()
Definition: Maps.h:724
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:853
Vec3d applyInverseJacobian(const Vec3d &in) const final
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:769
A specialized Affine transform that scales along the principal axis the scaling need not be uniform i...
Definition: Maps.h:1179
Vec3d voxelSize() const final
Return the absolute values of the scale values.
Definition: Maps.h:1349
const Vec3d & getScale() const
Returns the scale values.
Definition: Maps.h:1354
bool operator==(const ScaleTranslateMap &other) const
Definition: Maps.h:1397
ScaleTranslateMap(const ScaleTranslateMap &other)
Definition: Maps.h:1223
Vec3d applyInverseMap(const Vec3d &in) const final
Return the pre-image of under the map.
Definition: Maps.h:1281
static void registerMap()
Definition: Maps.h:1248
bool operator!=(const ScaleTranslateMap &other) const
Definition: Maps.h:1405
void write(std::ostream &os) const override
write serialization
Definition: Maps.h:1376
Vec3d applyMap(const Vec3d &in) const final
Return the image of under the map.
Definition: Maps.h:1273
MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:1459
MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:1435
double determinant(const Vec3d &) const final
Return the product of the scale values, ignores argument.
Definition: Maps.h:1343
Vec3d applyIJT(const Vec3d &in) const final
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:1319
const Vec3d & getTranslation() const
Returns the translation.
Definition: Maps.h:1356
MapBase::Ptr postTranslate(const Vec3d &t) const override
Definition: Maps.h:1452
Vec3d applyIJT(const Vec3d &in, const Vec3d &) const final
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:1315
const Vec3d & getInvScale() const
Return 1/(scale)
Definition: Maps.h:1363
Vec3d applyJacobian(const Vec3d &in, const Vec3d &) const final
Return the Jacobian of the map applied to in.
Definition: Maps.h:1290
bool isLinear() const final
Return true (a ScaleTranslateMap is always linear).
Definition: Maps.h:1259
Name type() const override
Return the name of this map's concrete type (e.g., "AffineMap").
Definition: Maps.h:1255
AffineMap::Ptr getAffineMap() const override
Return AffineMap::Ptr to an AffineMap equivalent to *this.
Definition: Maps.h:1408
MapBase::Ptr postRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of postfixing the appropraite operation.
Definition: Maps.h:1446
MapBase::Ptr copy() const override
Return a MapBase::Ptr to a deep copy of this map.
Definition: Maps.h:1238
std::string str() const override
string serialization, useful for debuging
Definition: Maps.h:1386
Vec3d applyInverseJacobian(const Vec3d &in, const Vec3d &) const final
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:1298
Vec3d applyJacobian(const Vec3d &in) const final
Return the Jacobian of the map applied to in.
Definition: Maps.h:1294
Mat3d applyIJC(const Mat3d &in) const final
Return the Jacobian Curvature: zero for a linear map.
Definition: Maps.h:1327
ScaleTranslateMap(const Vec3d &scale, const Vec3d &translate)
Definition: Maps.h:1195
MapBase::Ptr preRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of prepending the appropraite operation.
Definition: Maps.h:1418
Vec3d applyJT(const Vec3d &in) const final
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:1311
Vec3d voxelSize(const Vec3d &) const final
Return the absolute values of the scale values, ignores argument.
Definition: Maps.h:1351
MapBase::Ptr preTranslate(const Vec3d &t) const override
Definition: Maps.h:1424
static bool isRegistered()
Definition: Maps.h:1246
double determinant() const final
Return the product of the scale values.
Definition: Maps.h:1345
Vec3d applyJT(const Vec3d &in, const Vec3d &) const final
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:1309
ScaleTranslateMap(const ScaleMap &scale, const TranslationMap &translate)
Definition: Maps.h:1210
const Vec3d & getInvTwiceScale() const
Return 1/(2 scale). Used to optimize some finite difference calculations.
Definition: Maps.h:1361
bool hasUniformScale() const final
Return true if the scale values have the same magnitude (eg. -1, 1, -1 would be a rotation).
Definition: Maps.h:1263
Mat3d applyIJC(const Mat3d &in, const Vec3d &, const Vec3d &) const final
Definition: Maps.h:1338
ScaleTranslateMap()
Definition: Maps.h:1184
MapBase::Ptr inverseMap() const override
Return a new map representing the inverse of this map.
Definition: Maps.h:1240
const Vec3d & getInvScaleSqr() const
Return the square of the scale. Used to optimize some finite difference calculations.
Definition: Maps.h:1359
void read(std::istream &is) override
read serialization
Definition: Maps.h:1366
static MapBase::Ptr create()
Return a MapBase::Ptr to a new ScaleTranslateMap.
Definition: Maps.h:1236
static Name mapType()
Definition: Maps.h:1256
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:1395
Vec3d applyInverseJacobian(const Vec3d &in) const final
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:1303
A specialized linear transform that performs a translation.
Definition: Maps.h:994
TranslationMap(const TranslationMap &other)
Definition: Maps.h:1002
static void registerMap()
Definition: Maps.h:1017
void write(std::ostream &os) const override
write serialization
Definition: Maps.h:1086
Vec3d voxelSize(const Vec3d &) const override
Return (1,1,1).
Definition: Maps.h:1078
Vec3d applyJT(const Vec3d &in, const Vec3d &) const override
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:1054
MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:1157
MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
Definition: Maps.h:1132
const Vec3d & getTranslation() const
Return the translation vector.
Definition: Maps.h:1081
MapBase::Ptr postTranslate(const Vec3d &t) const override
Definition: Maps.h:1150
Vec3d applyIJT(const Vec3d &in) const override
Return the transpose of the inverse Jacobian (Identity for TranslationMap) of the map applied to in.
Definition: Maps.h:1063
Name type() const override
Return the name of this map's concrete type (e.g., "AffineMap").
Definition: Maps.h:1024
AffineMap::Ptr getAffineMap() const override
Return AffineMap::Ptr to an AffineMap equivalent to *this.
Definition: Maps.h:1106
double determinant(const Vec3d &) const override
Return 1.
Definition: Maps.h:1071
bool hasUniformScale() const override
Return false (by convention true)
Definition: Maps.h:1031
MapBase::Ptr postRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of postfixing the appropriate operation.
Definition: Maps.h:1143
TranslationMap()
Definition: Maps.h:1000
Mat3d applyIJC(const Mat3d &mat) const override
Return the Jacobian Curvature: zero for a linear map.
Definition: Maps.h:1065
Vec3d applyJT(const Vec3d &in) const override
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:1056
double determinant() const override
Return 1.
Definition: Maps.h:1073
Vec3d applyJacobian(const Vec3d &in, const Vec3d &) const override
Return the Jacobian of the map applied to in.
Definition: Maps.h:1038
Mat3d applyIJC(const Mat3d &mat, const Vec3d &, const Vec3d &) const override
Definition: Maps.h:1066
MapBase::Ptr copy() const override
Return a MapBase::Ptr to a deep copy of this map.
Definition: Maps.h:1009
Vec3d applyJacobian(const Vec3d &in) const override
Return the Jacobian of the map applied to in.
Definition: Maps.h:1040
std::string str() const override
string serialization, useful for debuging
Definition: Maps.h:1088
bool isLinear() const override
Return true (a TranslationMap is always linear).
Definition: Maps.h:1028
TranslationMap(const Vec3d &t)
Definition: Maps.h:1001
MapBase::Ptr preRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of prepending the appropriate operation.
Definition: Maps.h:1118
Vec3d applyInverseJacobian(const Vec3d &in, const Vec3d &) const override
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:1044
Vec3d applyInverseJacobian(const Vec3d &in) const override
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:1049
bool operator==(const TranslationMap &other) const
Definition: Maps.h:1097
MapBase::Ptr preTranslate(const Vec3d &t) const override
Definition: Maps.h:1125
Vec3d voxelSize() const override
Return (1,1,1).
Definition: Maps.h:1076
static bool isRegistered()
Definition: Maps.h:1015
Vec3d applyIJT(const Vec3d &in, const Vec3d &) const override
Return the transpose of the inverse Jacobian (Identity for TranslationMap) of the map applied to in,...
Definition: Maps.h:1060
Vec3d applyMap(const Vec3d &in) const override
Return the image of in under the map.
Definition: Maps.h:1034
MapBase::Ptr inverseMap() const override
Return a new map representing the inverse of this map.
Definition: Maps.h:1011
void read(std::istream &is) override
read serialization
Definition: Maps.h:1084
Vec3d applyInverseMap(const Vec3d &in) const override
Return the pre-image of in under the map.
Definition: Maps.h:1036
static MapBase::Ptr create()
Return a MapBase::Ptr to a new TranslationMap.
Definition: Maps.h:1007
static Name mapType()
Definition: Maps.h:1025
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:1095
bool operator!=(const TranslationMap &other) const
Definition: Maps.h:1103
A specialized Affine transform that scales along the principal axis the scaling is uniform in the thr...
Definition: Maps.h:921
bool operator==(const UniformScaleMap &other) const
Definition: Maps.h:955
static void registerMap()
Definition: Maps.h:943
bool operator!=(const UniformScaleMap &other) const
Definition: Maps.h:956
UniformScaleMap(double scale)
Definition: Maps.h:927
Name type() const override
Return the name of this map's concrete type (e.g., "AffineMap").
Definition: Maps.h:950
MapBase::Ptr copy() const override
Return a MapBase::Ptr to a deep copy of this map.
Definition: Maps.h:934
UniformScaleMap()
Definition: Maps.h:926
static bool isRegistered()
Definition: Maps.h:942
MapBase::Ptr inverseMap() const override
Return a new map representing the inverse of this map.
Definition: Maps.h:936
static MapBase::Ptr create()
Return a MapBase::Ptr to a new UniformScaleMap.
Definition: Maps.h:932
UniformScaleMap(const UniformScaleMap &other)
Definition: Maps.h:928
static Name mapType()
Definition: Maps.h:951
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:953
A specialized Affine transform that uniformaly scales along the principal axis and then translates th...
Definition: Maps.h:1496
bool operator==(const UniformScaleTranslateMap &other) const
Definition: Maps.h:1538
static void registerMap()
Definition: Maps.h:1527
UniformScaleTranslateMap(const UniformScaleTranslateMap &other)
Definition: Maps.h:1507
MapBase::Ptr postTranslate(const Vec3d &t) const override
Return a MapBase::Ptr to a UniformScaleTranslateMap that is the result of postfixing translation on t...
Definition: Maps.h:1555
Name type() const override
Return the name of this map's concrete type (e.g., "AffineMap").
Definition: Maps.h:1533
MapBase::Ptr copy() const override
Return a MapBase::Ptr to a deep copy of this map.
Definition: Maps.h:1513
UniformScaleTranslateMap(double scale, const Vec3d &translate)
Definition: Maps.h:1502
bool operator!=(const UniformScaleTranslateMap &other) const
Definition: Maps.h:1542
MapBase::Ptr preTranslate(const Vec3d &t) const override
Return a MapBase::Ptr to a UniformScaleTranslateMap that is the result of prepending translation on t...
Definition: Maps.h:1546
static bool isRegistered()
Definition: Maps.h:1522
UniformScaleTranslateMap(const UniformScaleMap &scale, const TranslationMap &translate)
Definition: Maps.h:1504
MapBase::Ptr inverseMap() const override
Return a new map representing the inverse of this map.
Definition: Maps.h:1515
static MapBase::Ptr create()
Return a MapBase::Ptr to a new UniformScaleTranslateMap.
Definition: Maps.h:1511
UniformScaleTranslateMap()
Definition: Maps.h:1501
static Name mapType()
Definition: Maps.h:1534
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:1536
A specialized linear transform that performs a unitary maping i.e. rotation and or reflection.
Definition: Maps.h:1639
static void registerMap()
Definition: Maps.h:1725
bool operator==(const UnitaryMap &other) const
Definition: Maps.h:1745
void write(std::ostream &os) const override
write serialization
Definition: Maps.h:1813
Vec3d voxelSize(const Vec3d &) const override
Returns the lengths of the images of the segments (0,0,0) − (1,0,0), (0,0,0) − (0,...
Definition: Maps.h:1803
Vec3d applyJT(const Vec3d &in, const Vec3d &) const override
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:1775
MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override
Return a MapBase::Ptr to a new map that is the result of appending the given shear.
Definition: Maps.h:1888
UnitaryMap(const Mat4d &m)
Definition: Maps.h:1675
MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given shear.
Definition: Maps.h:1855
MapBase::Ptr postTranslate(const Vec3d &t) const override
Return a MapBase::Ptr to a new map that is the result of appending the given translation.
Definition: Maps.h:1872
Vec3d applyIJT(const Vec3d &in) const override
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:1786
MapBase::Ptr postScale(const Vec3d &v) const override
Return a MapBase::Ptr to a new map that is the result of appending the given scale.
Definition: Maps.h:1880
Name type() const override
Return UnitaryMap.
Definition: Maps.h:1733
AffineMap::Ptr getAffineMap() const override
Return AffineMap::Ptr to an AffineMap equivalent to *this.
Definition: Maps.h:1825
double determinant(const Vec3d &) const override
Return the determinant of the Jacobian, ignores argument.
Definition: Maps.h:1794
bool hasUniformScale() const override
Return false (by convention true)
Definition: Maps.h:1741
MapBase::Ptr postRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of appending the given rotation.
Definition: Maps.h:1864
Vec3d applyJT(const Vec3d &in) const override
Return the Jacobian Transpose of the map applied to in.
Definition: Maps.h:1777
double determinant() const override
Return the determinant of the Jacobian.
Definition: Maps.h:1796
Vec3d applyJacobian(const Vec3d &in, const Vec3d &) const override
Definition: Maps.h:1758
Mat3d applyIJC(const Mat3d &in, const Vec3d &, const Vec3d &) const override
Definition: Maps.h:1789
MapBase::Ptr copy() const override
Returns a MapBase::Ptr to a deep copy of *this.
Definition: Maps.h:1716
~UnitaryMap() override=default
Vec3d applyJacobian(const Vec3d &in) const override
Return the Jacobian of the map applied to in.
Definition: Maps.h:1760
std::string str() const override
string serialization, useful for debuging
Definition: Maps.h:1818
bool isLinear() const override
Return true (a UnitaryMap is always linear).
Definition: Maps.h:1738
MapBase::Ptr preRotate(double radians, Axis axis) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given rotation.
Definition: Maps.h:1831
MapBase::Ptr preScale(const Vec3d &v) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given scale.
Definition: Maps.h:1847
Vec3d applyInverseJacobian(const Vec3d &in, const Vec3d &) const override
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:1764
Vec3d applyInverseJacobian(const Vec3d &in) const override
Return the Inverse Jacobian of the map applied to in (i.e. inverse map with out translation)
Definition: Maps.h:1769
UnitaryMap(const Vec3d &axis, double radians)
Definition: Maps.h:1649
MapBase::Ptr preTranslate(const Vec3d &t) const override
Return a MapBase::Ptr to a new map that is the result of prepending the given translation.
Definition: Maps.h:1839
Vec3d voxelSize() const override
Returns the lengths of the images of the segments (0,0,0) − (1,0,0), (0,0,0) − (0,...
Definition: Maps.h:1802
static bool isRegistered()
Definition: Maps.h:1723
UnitaryMap(Axis axis, double radians)
Definition: Maps.h:1656
UnitaryMap(const UnitaryMap &other)
Definition: Maps.h:1700
Vec3d applyIJT(const Vec3d &in, const Vec3d &) const override
Return the transpose of the inverse Jacobian of the map applied to in.
Definition: Maps.h:1784
Vec3d applyMap(const Vec3d &in) const override
Return the image of in under the map.
Definition: Maps.h:1754
MapBase::Ptr inverseMap() const override
Return a new map representing the inverse of this map.
Definition: Maps.h:1718
UnitaryMap()
default constructor makes an Idenity.
Definition: Maps.h:1645
void read(std::istream &is) override
read serialization
Definition: Maps.h:1807
Vec3d applyInverseMap(const Vec3d &in) const override
Return the pre-image of in under the map.
Definition: Maps.h:1756
static MapBase::Ptr create()
Return a MapBase::Ptr to a new UnitaryMap.
Definition: Maps.h:1714
bool operator!=(const UnitaryMap &other) const
Definition: Maps.h:1752
Mat3d applyIJC(const Mat3d &in) const override
Return the Jacobian Curvature: zero for a linear map.
Definition: Maps.h:1788
SharedPtr< UnitaryMap > Ptr
Definition: Maps.h:1641
static Name mapType()
Return UnitaryMap.
Definition: Maps.h:1735
UnitaryMap(const Mat3d &m)
Definition: Maps.h:1663
UnitaryMap(const UnitaryMap &first, const UnitaryMap &second)
Definition: Maps.h:1706
bool isEqual(const MapBase &other) const override
Return true if this map is equal to the given map.
Definition: Maps.h:1743
Definition: Vec3.h:24
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:89
T length() const
Length of the vector.
Definition: Vec3.h:204
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:195
T * asPointer()
Definition: Vec3.h:98
T & y()
Definition: Vec3.h:90
T & z()
Definition: Vec3.h:91
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:366
Vec3< double > Vec3d
Definition: NanoVDB.h:1174
CoordT Round(const Vec3T< RealT > &xyz)
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
bool hasTranslation(const Mat4< T > &m)
Definition: Mat4.h:1323
Mat3< double > Mat3d
Definition: Mat3.h:848
OPENVDB_API SharedPtr< SymmetricMap > createSymmetricMap(const Mat3d &m)
Utility methods.
bool isAffine(const Mat4< T > &m)
Definition: Mat4.h:1318
bool isInvertible(const MatType &m)
Determine if a matrix is invertible.
Definition: Mat.h:891
bool isUnitary(const MatType &m)
Determine if a matrix is unitary (i.e., rotation or reflection).
Definition: Mat.h:911
CompoundMap< CompoundMap< UnitaryMap, ScaleMap >, UnitaryMap > SpectralDecomposedMap
Definition: Maps.h:45
Vec3< typename MatType::value_type > getScale(const MatType &mat)
Return a Vec3 representing the lengths of the passed matrix's upper 3×3's rows.
Definition: Mat.h:655
MatType shear(Axis axis0, Axis axis1, typename MatType::value_type shear)
Set the matrix to a shear along axis0 by a fraction of axis1.
Definition: Mat.h:710
OPENVDB_API SharedPtr< MapBase > simplify(SharedPtr< AffineMap > affine)
reduces an AffineMap to a ScaleMap or a ScaleTranslateMap when it can
OPENVDB_API SharedPtr< PolarDecomposedMap > createPolarDecomposedMap(const Mat3d &m)
Decomposes a general linear into translation following polar decomposition.
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:407
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
Mat4< double > Mat4d
Definition: Mat4.h:1368
Axis
Definition: Math.h:904
@ X_AXIS
Definition: Math.h:905
bool isDiagonal(const MatType &mat)
Determine if a matrix is diagonal.
Definition: Mat.h:924
OPENVDB_API Mat4d approxInverse(const Mat4d &mat)
Returns the left pseudoInverse of the input matrix when the 3x3 part is symmetric otherwise it zeros ...
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:477
OPENVDB_API SharedPtr< FullyDecomposedMap > createFullyDecomposedMap(const Mat4d &m)
General decomposition of a Matrix into a Unitary (e.g. rotation) following a Symmetric (e....
bool isIdentity(const MatType &m)
Determine if a matrix is an identity matrix.
Definition: Mat.h:882
std::string Name
Definition: Name.h:17
void writeString(std::ostream &os, const Name &name)
Definition: Name.h:31
Name readString(std::istream &is)
Definition: Name.h:20
math::BBox< Vec3d > BBoxd
Definition: Types.h:84
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
@ OPENVDB_FILE_VERSION_FLOAT_FRUSTUM_BBOX
Definition: version.h.in:245
Definition: Exceptions.h:13
Definition: Coord.h:586
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Tolerance for floating-point comparison.
Definition: Math.h:147
Map traits.
Definition: Maps.h:55
Definition: Maps.h:79
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202