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