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