# Affine transforms - matrix algebra

Pavel Safrata pavel.safrata at oracle.com
Mon Aug 13 08:19:14 PDT 2012

```On 13.8.2012 16:48, Pavel Safrata wrote:
> Hello,
> here is my new proposal. The list of changes would be pretty long so
> I'm going to ask you to read the whole thing once more.
> 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

Oh, I've just realized that we already have
distance(Point3D)
...

> public Point3D add(Point3D point)
>         // Creates a point with distances from origin added (adds two
> 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?

.. so maybe we should rather have center(Point3D), angle(Point3D),
length()/distance()
Pavel

> 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
>

```