# Affine transforms - matrix algebra

Jim Graham james.graham at oracle.com
Tue Aug 14 11:50:57 PDT 2012

```Hi Pavel,

On 8/14/2012 12:41 AM, Pavel Safrata wrote:
>> Also, in many cases we provide:
>>
>> Foo Foo.operate(Foo_operand, Foo_result_container)
>>
>> so that code can reuse objects. I think that makes sense here as well.
>
> I generally agree but Point3D is immutable so it's not possible here.

D'oh!  You learn something new every day.  My apologies as I'm not
familiar with the FX API versions of these objects - I tend to work on
the implementation and we have internal versions of many of these
objects with different design constraints...

>>> public double getAngle(Point3D)
>>> // Gets angle between the two points when observed from the origin
>>> // (angle between vectors)
>>
>> What about the static variant "getAngle(po, p1, p2)"?
>
> Again the immutable point..

Not an issue.  My suggestion was for a getAngle() method that took 3
input points for calculating the angle "p1 -> po -> p2" and returning
it.  None of those arguments was for storing the result.

For that matter we could consider "angle(p1, p2)" which returned the
angle  of one corner of the triangle "this, p1, p2", but the question is
which of those 3 points should be used as the vertex of the triangle for
maximum utility and maximum "being able to remember which 2 of the 3
points are in the argument list".  Barring some obvious and easily
remembered way of specing that method I'm suggesting a static method
that requires you to provide all 3 points (see above) and then it is
easy enough to either specify that the "origin/vertex" point is the
first one since it is the most important one, or perhaps it should be
the middle one so that the argument list is in the order that reads
along the angle?

>> I think we discussed it before, but do we want "void transform(p1,
>> presult)"?
>
> I don't think we discussed this before, but you know by now, point is
> immutable :-)

OK, I deserve that... :(

>>> 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
>>
>> Would there be a "getMatrixType"?
>
> The transform has no matrix type. You can request any matrix type from
> any transform.

A given transform may only have some elements, though, so at any given
time it may have non-default elements for its 2x3 positions even though
it might return full 4x4 values if you ask it.  If you are wondering how
complex an operation that has arbitrary Transforms specified will be
then you have to assume the worst, that they are all 4x4 transforms.
The is2D() method would help for optimizing the 2D 2x3 only case, and
that may be the most important case in the end.  This could be a more
general form of that convenience method, though.  It would be important
to make sure it is well understood that it is returning "the current
state of the matrix elements".

>> I hope someone involved more in FX events can review this.
>
> I discussed this with Lubo who is our greatest event expert :-)

Yay...

>>> 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)
>>
>> The appendRotation(... Point3D axis) stands out. Should we have
>> variants for all of the pivotXYZ methods that take a Point2D/3D?
>
> Pivot is always represented as three doubles, even with rotation.
> Point3D can be used only for the axis (which is unique property to
> rotation) and the reason is that for the orthogonal rotations you can
> use Rotate's X_AXIS, Y_AXIS and Z_AXIS.

I see.  I am aware of the convenience values for the axis, and that
makes the Point3D for axis doubly useful, but is that a reason not to
consider variants that use Point3D for pivot as well?  (One reason I can
think is that the overloads might run into each other if we aren't
careful, but if we can find a sensible overload set then it would be
nice to allow specifying the "pivot point" with an actual point, no?)...

...jim
```