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