Affine transforms - matrix algebra

Jim Graham james.graham at
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 :-)


>>> 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?)...


More information about the openjfx-dev mailing list