# Affine transforms - matrix algebra

Pavel Safrata pavel.safrata at oracle.com
Mon Aug 13 07:48:49 PDT 2012

```Hello,
here is my new proposal. The list of changes would be pretty long so I'm
Thanks,
Pavel

New enum MatrixType { MT_2D_2x3, MT_2D_3x3, MT_3D_3x4, MT_3D_4x4 }
// specifies type of matrix
// causes IllegalArgumentException whenever a 2D type is requested
for a 3D transform

New NoninvertibleTransformException

New TransformChangedEvent with single event type TRANSFORM_CHANGED

On Point3D class:
public double getDistance(Point3D point)
// Gets distance from the given point
vectors)
public Point3D subtract(Point3D point)
// Creates a point with the given point's distances from origin
subtracted
// (subtracts two vectors)
public Point3D normalize()
// Gets a point in the same direction from the origin with
distance from the origin equal to one
// (normalizes a vector)
? should the above three methods be named getSomething to stress that
the operation doesn't modify the object?
public Point3D getCenter(Point3D)
// Gets center between the two points
public double getAngle(Point3D)
// Gets angle between the two points when observed from the origin
// (angle between vectors)
public double getLength()
// Gets distance from the origin (lenght of a vector)
? should it be named getDistance() not to look that weird on Point?
public Point3D crossProduct(Point3D point)
public double dotProduct(Point3D point)
// Compute product of the two vectors (I don't think we can
reasonably document those as point operations)

On Point2D:
// similar to Point3D

On Transform class:
public Transform createConcatenation(Transform transform)
// Creates new concatenated transform that is equivalent to
// this transform being first in a transformation list and the
given transform second
// Means multiplication on the right by the given transform
public Transform createInverse() throws NoninvertibleTransformException
// Creates a negated transform
public Transform clone()
// Of course Transform implementing Cloneable

// in subclasses the above methods will be overridden and will
return more specific types where possible

public Point3D transform(Point3D point)
// Transforms the point
public Point2D transform(Point2D point)
// throws IllegalArgument for 3D transform
public Bounds transform(Bounds bounds)
// Transforms the bounds
public void transform2D(double[] srcPts, int srcOffset, double[]
dstPts, int dstOffset, int numPts)
// similar to J2D
public void transform3D(double[] srcPts, int srcOffset, double[]
dstPts, int dstOffset, int numPts)
// similar to the above but with tree coordinates per point
public inverseTransform* // 6 methods
// one counterpart for each transform*
public Point3D deltaTransform(Point3D point)
public Point2D deltaTransform(Point2D point)
// transformation without translation (transformation of a vector)

public double getDeterminant()
public boolean is2D()
public boolean is3D()

public double get(MatrixType type, int row, int column)
// Convenience getter for the individual elements
// throws IndexOutOfBounds if index out of the range specified
by type
public double[] toArray(MatrixType type)
// Returns flattened matrix specified by type
public double[] toArray(MatrixType type, double[] array)
// Similar to the above, just uses the passed array if it is
big enough
public double[] getRow(MatrixType type, int row)
public double[] getRow(MatrixType type, int row, double[] array)
public double[] getColumn(MatrixType type, int column)
public double[] getColumn(MatrixType type, int column, double[] array)
// Similar to toAarray returning the particular tuples
// throw IndexOutOfBounds if index out of the range specified
by type

// Support for the transform changed event:
// Transform will implement EventTarget interface
protected void transformChanged()
// for the subclasses to call when the transform changes
public <T extends Event> void addEventFilter(EventType<T> eventType,
EventHandler<? super
T> eventHandler)
public <T extends Event> void removeEventFilter(EventType<T> eventType,
EventHandler<? super T> eventHandler)
public <T extends Event> void addEventHandler(final EventType<T>
eventType,
final EventHandler<?
super T> eventHandler)
public <T extends Event> void removeEventHandler(EventType<T>
eventType,
EventHandler<? super T> eventHandler)
public final void setOnTransformChanged(EventHandler<? super
TransformChangedEvent> value)

On Affine class:

public Affine(Transform transform)
public Affine(double mxx, double mxy, double tx,
double myx, double myy, double ty)
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)
public Affine(double[] array, MatrixType type, int beginIndex)
// reads number of elements specified by "type"
// from index specified by "beginIndex"
// throws IllegalArgument if the array is not long enough or
// if the last 3x3 or 4x4 matrix row is set to something
different than 0, 0, (0,) 1

public void setToTransform(Transform t)
public void setToTransform(double mxx, double mxy, double tx,
double myx, double myy, double ty)
public void setToTransform(double mxx, double mxy, double mxz,
double tx,
double myx, double myy, double myz,
double ty,
double mzx, double mzy, double mzz,
double tz)
public void setToTransform(double[] array, MatrixType type, int
beginIndex)
// the same acceptance criteria as the constructor
public void setToIdentity()

public void invert() throws NoninvertibleTransformException
public void append(Transform t) // multiplying on the right
public void append(double mxx, double mxy, double tx,
double myx, double myy, double ty)
public void append(double mxx, double mxy, double mxz, double tx,
double myx, double myy, double myz, double ty,
double mzx, double mzy, double mzz, double tz)
public void append(double[] array, MatrixType type, int beginIndex)

public void appendTranslation(double tx, double ty)
public void appendTranslation(double tx, double ty, double tz)
public void appendScale(double sx, double sy)
public void appendScale(double sx, double sy, double pivotX, double
pivotY)
public void appendScale(double sx, double sy, double sz)
public void appendScale(double sx, double sy, double sz,
double pivotX, double pivotY, double pivotZ)
public void appendRotation(double theta)
public void appendRotation(double theta, double pivotX, double pivotY)
public void appendRotation(double theta,
double pivotX, double pivotY, double pivotZ,
double axisX, double axisY, double axisZ)
public void appendRotation(double theta,
double pivotX, double pivotY, double pivotZ,
Point3D axis)
public void appendShear(double shx, double shy)
public void appendShear(double shx, double shy, double pivotX,
double pivotY)

// "append" means "add the transformation after the existing one", so
// "append" means multiply this matrix on the right by the given matrix

public void prepend* // 16 methods
// Every append* method has its prepend* counterpart,
// adding the transformation before the existing one,
// multiplying on the left

public void set(MatrixType type, int row, int col, double value)
// convenience setter for the individual elements
// allows to set the last row of 3x3 or 4x4 matrix only to 0,
0, (0,) 1
// throws IllegalArgument if the above condition is not met
// trows IndexOutOfBounds if one of the indices out of
specified matrix type

```