# Affine transforms - matrix algebra

Pavel Safrata pavel.safrata at oracle.com
Tue Aug 28 09:58:24 PDT 2012

```Hello,
assuming all the stuff that remained unanswered is quietly agreed, I
hope this proposal could be the final one.
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
public int rows()
public int columns()
public int elements()
public boolean is2D()

New NonInvertibleTransformException

New TransformChangedEvent with single event type TRANSFORM_CHANGED

On Point3D class:
public double distance(double x, double y, double z)
public double distance(Point3D point)
// Gets distance from the given point
public Point3D add(double x, double y, double z)
// Creates a point with distances from origin added (adds a vector)
public Point3D subtract(double x, double y, double z)
public Point3D subtract(Point3D point)
// Creates a point with the given point's distances from origin
subtracted
// (subtracts a vector)
public Point3D normalize()
// Gets a point in the same direction from the origin with
distance from the origin equal to one
// (normalizes a vector)
public Point3D midpoint(double x, double y, double z)
public Point3D midpoint(Point3D point)
// Gets center between the two points
public double angle(double x, double y, double z)
public double angle(Point3D)
// Gets angle between the two points when observed from the origin
// (angle between vectors)
public double angle(Point3D p1, Point3D p2)
// Gets angle between the given points when observed from this
point
public double magnitude()
// Gets distance from the origin (lenght of a vector)
public Point3D crossProduct(double x, double y, double z)
public Point3D crossProduct(Point3D point)
public double dotProduct(double x, double y, double z)
public double dotProduct(Point3D point)
// Compute product of the two vectors

On Point2D:
// similar to Point3D mapped to 2D (except of crossProduct still
returning 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(double x, double y, double z)
public Point3D transform(Point3D point)
// Transforms the point
public Point2D transform(double x, double y)
public Point2D transform(Point2D point)
// throws IllegalArgument for 3D transform
public Bounds transform(Bounds bounds)
// Transforms the bounds
public void transform2DPoints(double[] srcPts, int srcOffset,
double[] dstPts, int dstOffset, int numPts)
// similar to J2D
public void transform3DPoints(double[] srcPts, int srcOffset,
double[] dstPts, int dstOffset, int numPts)
// similar to the above but with tree coordinates per point
public inverseTransform* // 7 methods
// one counterpart for each transform*
public Point3D deltaTransform(double x, double y, double z)
public Point3D deltaTransform(Point3D point)
public Point2D deltaTransform(double x, double y)
public Point2D deltaTransform(Point2D point)
// transformation without translation (transformation of a vector)
public inverseDeltaTransform // 4 methods
// inverse transformation without translation

public double determinant()
public boolean isType2D()
public boolean isIdentity()
public Transform.similarTo(Transform t, Bounds range, double
maximumDelta)
// Test similarity to the given transform
// Returns true if all points inside range are translated to
points no farther than maximumDelta

public double getElement(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[] row(MatrixType type, int row)
public double[] row(MatrixType type, int row, double[] array)
public double[] column(MatrixType type, int column)
public double[] column(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 void setOnTransformChanged(EventHandler<? super
TransformChangedEvent> value)
public EventHandler<? super TransformChangedEvent>
getOnTransformChanged()
public ObjectProperty<EventHandler<? super TransformChangedEvent>>
onTransformChangedProperty()

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 offset)
// reads number of elements specified by "type"
// from index specified by "offset"
// throws IndexOutOfBounds 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 offset)
// 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 offset)
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, Point2D pivot)
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 appendScale(double sx, double sy, double sz, Point3D pivot)
public void appendRotation(double angle)
public void appendRotation(double angle, double pivotX, double pivotY)
public void appendRotation(double angle, Point2D pivot)
public void appendRotation(double angle,
double pivotX, double pivotY, double pivotZ,
double axisX, double axisY, double axisZ)
public void appendRotation(double angle,
double pivotX, double pivotY, double pivotZ,
Point3D axis)
public void appendRotation(double angle, Point3D pivot, Point3D axis)
public void appendShear(double shx, double shy)
public void appendShear(double shx, double shy, double pivotX,
double pivotY)
public void appendShear(double shx, double shy, Point2D pivot)

// "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* // 20 methods
// Every append* method has its prepend* counterpart,
// adding the transformation before the existing one,
// multiplying on the left

public void setElement(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

```