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