# Affine transforms - matrix algebra

Pavel Safrata pavel.safrata at oracle.com
Tue Jul 10 08:00:14 PDT 2012

```Hello,
based on previous discussions, we're going to propose a set of new
methods to our transforms.

Tracking Jira issue: http://javafx-jira.kenai.com/browse/RT-17942

I hope the names are self-explanatory, otherwise please let me know and
I'll provide some description.

On Transform class:
public Transform getConcatenation(Transform transform) //
multiplication
public Transform getInverse() throws
NoninvertibleTransformException // negation
public Transform copy()

Note: in subclasses these methods will be overridden and will return
more specific types where possible.

On Affine class:

Constructors:
public Affine(Transform transform)
public Affine(double mxx, double mxy, double mxz, double tx,
double myx, double myy, double myz, double ty,
double mzx, double mzy, double mzz, double tz)

Setters of the entire matrix:
public void setToTransform(Transform t)
public void setToTransform(double mxx, double mxy, double mxz,
double mxt,
double myx, double myy, double myz, double
myt,
double mzx, double mzy, double mzz, double
mzt)
public void setToIdentity()
public void setToTranslation(double tx, double ty)
public void setToTranslation(double tx, double ty, double tz)
public void setToScale(double sx, double sy)
public void setToScale(double sx, double sy, double pivotX, double
pivotY)
public void setToScale(double sx, double sy, double sz)
public void setToScale(double sx, double sy, double sz,
double pivotX, double pivotY, double pivotZ)
public void setToRotation(double theta)
public void setToRotation(double theta, double pivotX, double pivotY)
public void setToRotation(double theta,
double axisX, double axisY, double axisZ,
double pivotX, double pivotY, double pivotZ)
public void setToShear(double shx, double shy)
public void setToShear(double shx, double shy, double pivotX,
double pivotY)

Operations on the matrix (modifying it in place):
public void invert() throws NoninvertibleTransformException
public void concatenate(Transform t)
public void concatenate(double Txx, double Txy, double Txz, double Txt,
double Tyx, double Tyy, double Tyz, double Tyt,
double Tzx, double Tzy, double Tzz, double Tzt)
public void preConcatenate(Transform t) // left multiplication
public void preConcatenate(double Txx, double Txy, double Txz,
double Txt,
double Tyx, double Tyy, double Tyz, double Tyt,
double Tzx, double Tzy, double Tzz, double Tzt)
public void concatWithTranslation(double tx, double ty)
public void concatWithTranslation(double tx, double ty, double tz)
public void concatWithScale(double sx, double sy)
public void concatWithScale(double sx, double sy, double pivotX,
double pivotY)
public void concatWithScale(double sx, double sy, double sz)
public void concatWithScale(double sx, double sy, double sz,
double pivotX, double pivotY, double
pivotZ)
public void concatWithRotation(double theta)
public void concatWithRotation(double theta, double pivotX, double
pivotY)
public void concatWithRotation(double theta,
double axisX, double axisY, double axisZ,
double pivotX, double pivotY, double pivotZ)
public void concatWithShear(double shx, double shy)
public void concatWithShear(double shx, double shy, double pivotX,
double pivotY)
public void preTranslate(double mxt, double myt)
public void preTranslate(double mxt, double myt, double mzt)

Other methods:
public double getDeterminant()

Notes:

Instead of "concatWithTranslation" it would be more natural to use just
"translate" (and similarly for the others), but unfortunately these
method names are already taken by the static factory methods on
Transform class. This is unpleasant but we need to be backward
compatible so we have to introduce different names. We'll be happy to
hear better naming suggestions than the concatWith* (which is pretty
descriptive I think but not really nice).

To avoid even bigger method explosion this proposal doesn't contain all
the convenience "preConcatWith*" methods. However, we added
preTranslate, because it is needed quite often (and
preConcatWithTranslation looks quite horrible). Any comments to that?

Should rotation axis be passed as Point3D (rather than the three
doubles), consistently with Rotate transform?

Would you want static factory methods on Affine (creating Affine
instances with the simple transforms)?

Would it be important to you whether or not matrix changes are atomic?
If you call one of the methods that modify the entire matrix, can be
listeners for each member called immediately as the members are set, or
do they need to be called after all the members are updated?

Any missing operations?

Thanks,
Pavel
```