Affine transforms - matrix algebra

Jim Graham james.graham at
Mon Jul 16 21:08:27 PDT 2012

Oh my!  What a discussion!

OK, here are my thoughts after having perused most of the discussion:

- Canning setToFoo() - I agree, it encouraged too many people to delete 
an existing transform simply due to thinking that was the method they 
wanted and I'd rather force them to use "setToIdentity" so it is obvious 
that they are destroying information.  To the person who said "our 
Affine objects won't contain a transform" - ummm, which Affine objects? 
  Yes, if you construct one it will have identity, but as we add methods 
to get Affine objects from the environment, those objects will not be 
identity, so this issue remains real.

- append/prepend are problematical.  I don't think 2D got it "wrong", I 
think it did it one way that was actually based on prior work, but there 
are a number of developers who came from a different background that had 
the reverse expectation.  Simply saying "X confused some people so Y 
must be the right answer" misses the point that some people were not 
confused by X and might be confused by Y.  Also, if that was a problem, 
we've already fought that battle getting people used to 2D's system so 
if we reverse course now then we simply rub everyone's face in it. 
Sigh.  Is there some new terminology that we could use that doesn't 
trigger expectations?

- We already have GraphicsContext in 2.2 that has "translate, scale, 
etc."  I would hope that the "appendFoo()" methods would work like 
those, but I have the sneaky suspicion that I read in the discussion 
that actually the prepend methods are closer to those.  Consider how a 
developer that was used to "I scaled then I translated" would view 
append/prepend?  That sounds to me like the scale happened and then the 
translate was "appended to the list of operations as if one called it 
after scale in some Canvas code".  Also, append should probably reflect 
what happens when you get the list of Transform objects from a Node and 
then append some new Transform objects to the end of that list.  Prepend 
should match what happens when you place new Transform objects at the 
head of that same Node.getTransforms() list.

- append might mean a matrix operation with the math going one way, but 
it might also mean "then after you step into that coordinate system, you 
do this operation from that perspective", and it might also mean "after 
you move everything around and you are staring at the transformed 
objects from outside (i.e. the point of view of the universe), you then 
move it again like this" and all of those will result in different math.

- get(row, col) - I like it
- toArray() - what about getMatrix()?
- 2x3, 3x4, etc - I would make those explicit in the method name rather 
than side effected from the array length (which I think someone was 
suggesting, but maybe I read it wrong) - because someone might have a 
nice scratch array laying around that is really long and they want to 
use it to grab the matrix, but they don't really want all of its values 
to be used.  So, if they can call "double scratch[] = new double[1024]; 
t.getMatrix2x3(scratch);" then that would be nice.
- what about getRow(row, array) and getColumn(col, array) which can be 
combined with vector methods to do fast custom matrix operations?

- what about classification methods so they can special case "uniform 
scaling", "unrotated", "translation-only", etc. matrix cases?

There's some food for thought, I'll let that simmer and come back to it 


On 7/16/2012 11:25 AM, Richard Bair wrote:
> Hi Pavel,
> Before approving I want Jim Graham to have a look. He's been on vacation, I think he either gets back today or next week.
> Thanks!
> Richard
> On Jul 16, 2012, at 4:37 AM, Pavel Safrata wrote:
>> Hi Kirill,
>> it is just for convenience. The point is that if you have algorithms or other libraries that use the fourth row, you can work with the array right away.
>> Regards,
>> Pavel
>> On 16.7.2012 13:28, Kirill.Prazdnikov wrote:
>>> Hi Pavel,
>>>>     public Affine(double[] matrix)
>>>>         // accepts arrays of length 6, 12 and 16.
>>>>         // In case of 16 members the last four numbers must be 0, 0, 0, 1
>>>>         // throws IllegalArgument if the above conditions are not met
>>> What is the point of setting 4x4 matrix of the last row must be 0,0,0,1 ?
>>> Should we remove 4x4 case at all ?
>>> Thanks

More information about the openjfx-dev mailing list