Shear6

The Shear6 class template represent a 3D shear transformation, with predefined typedefs for float and double.

Example:

#include <Imath/ImathShear.h>
#include <Imath/ImathMatrix.h>

void
shear6_example()
{
    Imath::Shear6f s (0.330f, 0.710f, 0.010f, 0.999f, -0.531f, -0.012f);

    Imath::M44f M;
    M.setShear (s);
}
typedef Shear6<float> Imath::Shear6f

Shear6 of type float.

template<class T>
class Shear6

Shear6 class template.

A shear matrix is technically defined as having a single nonzero off-diagonal element; more generally, a shear transformation is defined by those off-diagonal elements, so in 3D, that means there are 6 possible elements/coefficients:

| X' |   |  1  YX  ZX  0 |   | X |
| Y' |   | XY   1  ZY  0 |   | Y |
| Z' | = | XZ  YZ   1  0 | = | Z |
| 1  |   |  0   0   0  1 |   | 1 |

X' =      X + YX * Y + ZX * Z
Y' = YX * X +      Y + ZY * Z
Z` = XZ * X + YZ * Y +      Z
See https://www.cs.drexel.edu/~david/Classes/CS430/Lectures/L-04_3DTransformations.6.pdf

Those variable elements correspond to the 6 values in a Shear6. So, looking at those equations, “Shear YX”, for example, means that for any point transformed by that matrix, its X values will have some of their Y values added. If you’re talking about “Axis A has values from Axis B added to it”, there are 6 permutations for A and B (XY, XZ, YX, YZ, ZX, ZY).

Not that Maya has only three values, which represent the lower/upper (depending on column/row major) triangle of the matrix. Houdini is the same as Maya (see https://www.sidefx.com/docs/houdini/props/obj.html) in this respect.

There’s another way to look at it. A general affine transformation in 3D has 12 degrees of freedom - 12 “available” elements in the 4x4 matrix since a single row/column must be (0,0,0,1). If you add up the degrees of freedom from Maya:

  • 3 translation
  • 3 rotation
  • 3 scale
  • 3 shear

You obviously get the full 12. So technically, the Shear6 option of having all 6 shear options is overkill; Imath/Shear6 has 15 values for a 12-degree-of-freedom transformation. This means that any nonzero values in those last 3 shear coefficients can be represented in those standard 12 degrees of freedom. Here’s a python example of how to do that:

>>> import imath
>>> M = imath.M44f()
>>> s = imath.V3f()
>>> h = imath.V3f()
>>> r = imath.V3f()
>>> t = imath.V3f()
# Use Shear.YX (index 3), which is an "extra" shear value
>>> M.setShear((0,0,0,1,0,0))
M44f((1, 1, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1))
>>> M.extractSHRT(s, h, r, t)
1
>>> s
V3f(1.41421354, 0.707106769, 1)
>>> h
V3f(1, 0, 0)
>>> r
V3f(0, -0, 0.785398185)
>>> t
V3f(0, 0, 0)
That shows how to decompose a transform matrix with one of those “extra” shear coefficients into those standard 12 degrees of freedom. But it’s not necessarily intuitive; in this case, a single non-zero shear coefficient resulted in a transform that has non-uniform scale, a single “standard” shear value, and some rotation.

So, it would seem that any transform with those extra shear values set could be translated into Maya to produce the exact same transformation matrix; but doing this is probably pretty undesirable, since the result would have some surprising values on the other transformation attributes, despite being technically correct.

This usage of “degrees of freedom” is a bit hand-wavey here; having a total of 12 inputs into the construction of a standard transformation matrix doesn’t necessarily mean that the matrix has 12 true degrees of freedom, but the standard translation/rotation/scale/shear matrices have the right construction to ensure that.

Direct access to members

T xy
T xz
T yz
T yx
T zx
T zy

Constructors and Assignment

constexpr Shear6()

Initialize to 0.

constexpr Shear6(T XY, T XZ, T YZ)

Initialize to the given XY, XZ, YZ values.

constexpr Shear6(const Vec3<T> &v)

Initialize to the given XY, XZ, YZ values held in (v.x, v.y, v.z)

template<class S>
constexpr Shear6(const Vec3<S> &v)

Initialize to the given XY, XZ, YZ values held in (v.x, v.y, v.z)

constexpr Shear6(T XY, T XZ, T YZ, T YX, T ZX, T ZY)

Initialize to the given (XY XZ YZ YX ZX ZY) values.

constexpr Shear6(const Shear6 &h)

Copy constructor.

template<class S>
constexpr Shear6(const Shear6<S> &h)

Construct from a Shear6 object of another base type.

constexpr const Shear6<T> &operator=(const Shear6 &h)

Assignment.

template<class S>
constexpr const Shear6 &operator=(const Vec3<S> &v)

Assignment from vector.

~Shear6()

Destructor.

Compatibility with Sb

template<class S>
void setValue(S XY, S XZ, S YZ, S YX, S ZX, S ZY)

Set the value.

template<class S>
void setValue(const Shear6<S> &h)

Set the value.

template<class S>
void getValue(S &XY, S &XZ, S &YZ, S &YX, S &ZX, S &ZY) const

Return the values.

template<class S>
void getValue(Shear6<S> &h) const

Return the value in h

T *getValue()

Return a raw pointer to the array of values.

const T *getValue() const

Return a raw pointer to the array of values.

Arithmetic and Comparison

template<class S>
constexpr bool operator==(const Shear6<S> &h) const

Equality.

template<class S>
constexpr bool operator!=(const Shear6<S> &h) const

Inequality.

constexpr bool equalWithAbsError(const Shear6<T> &h, T e) const

Compare two shears and test if they are “approximately equal”:

Return
True if the coefficients of this and h are the same with an absolute error of no more than e, i.e., for all i abs (this[i] - h[i]) <= e

constexpr bool equalWithRelError(const Shear6<T> &h, T e) const

Compare two shears and test if they are “approximately equal”:

Return
True if the coefficients of this and h are the same with a relative error of no more than e, i.e., for all i abs (this[i] - h[i]) <= e * abs (this[i])

constexpr const Shear6<T> &operator+=(const Shear6 &h)

Component-wise addition.

constexpr Shear6<T> operator+(const Shear6 &h) const

Component-wise addition.

constexpr const Shear6<T> &operator-=(const Shear6 &h)

Component-wise subtraction.

constexpr Shear6<T> operator-(const Shear6 &h) const

Component-wise subtraction.

constexpr Shear6<T> operator-() const

Component-wise multiplication by -1.

constexpr const Shear6<T> &negate()

Component-wise multiplication by -1.

constexpr const Shear6<T> &operator*=(const Shear6 &h)

Component-wise multiplication.

constexpr const Shear6<T> &operator*=(T a)

Scalar multiplication.

constexpr Shear6<T> operator*(const Shear6 &h) const

Component-wise multiplication.

constexpr Shear6<T> operator*(T a) const

Scalar multiplication.

constexpr const Shear6<T> &operator/=(const Shear6 &h)

Component-wise division.

constexpr const Shear6<T> &operator/=(T a)

Scalar division.

constexpr Shear6<T> operator/(const Shear6 &h) const

Component-wise division.

constexpr Shear6<T> operator/(T a) const

Scalar division.

Numerical Limits

static constexpr T baseTypeLowest()

Largest possible negative value.

static constexpr T baseTypeMax()

Largest possible positive value.

static constexpr T baseTypeSmallest()

Smallest possible positive value.

static constexpr T baseTypeEpsilon()

Smallest possible e for which 1+e != 1.

Public Types

typedef T BaseType

The base type: In templates that accept a parameter V (could be a Color4), you can refer to T as V::BaseType

Public Functions

constexpr T &operator[](int i)

Element access.

constexpr const T &operator[](int i) const

Element access.

template<class S>
constexpr const Shear6<T> &operator=(const Vec3<S> &v)

Public Static Functions

static constexpr unsigned int dimensions()

Return the number of dimensions, i.e. 6.

Warning

doxygenfunction: Unable to resolve multiple matches for function “operator<<” with arguments (std::ostream& s, const Shear6<T>& h) in doxygen xml output for project “Imath” from directory: /build/ilmbase-TFRjEc/ilmbase-3.1.11/obj-x86_64-linux-gnu/website/doxygen/xml. Potential matches:

- std::ostream &operator<<(std::ostream&, Imath::half)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Color4<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Euler<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Interval<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Line3<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Matrix22<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Matrix33<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Matrix44<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Plane3<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Quat<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Shear6<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Vec2<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Vec3<T>&)
- template<class T>
  std::ostream &Imath::operator<<(std::ostream&, const Vec4<T>&)