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