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