Affine transforms - matrix algebra

Pavel Safrata pavel.safrata at
Tue Jul 17 01:22:12 PDT 2012

Hi Jim,

On 17.7.2012 6:08, Jim Graham wrote:
> 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?

Nobody sad "X confused some people so Y must be the right answer". Just 
the opposite, we agreed that this new approach will cause some confusion 
as well. The thing is that we cannot reuse J2D API because the method 
names are not available to us and this is the best thing we could come 
up with. My impression right now is that any names we choose might be 
expected to work both ways, because people are used to J2D which really 
seems to work illogically - you need to add your transformations in the 
reverse order to get their natural concatenation. Still, I'm open to any 
better naming if you have one.

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

So we can switch append/prepend semantics to be illogical consistently 
with the rest of the java world. Seems that everywhere else if you 
"scale then translate" the system translates and then scales. It is well 
possible that consistency wins over being intuitive.

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

Do you have names that are not ambiguous and don't have ten words each? ;-)

> - get(row, col) - I like it
> - toArray() - what about getMatrix()?

I would probably expect getMatrix to return double[[]] or some Matrix. 
The toArray seems more clear to me.

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

How about leaving Affine(double[] matrix) as proposed and add
Affine(double[] array, MatrixArrayType type, int beginIndex)

> - what about getRow(row, array) and getColumn(col, array) which can be 
> combined with vector methods to do fast custom matrix operations?

Sounds good!
I would again introduce both variants:
double[] getRow(int row),
double[] getRow(int row, double[] array)

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

I would probably wait for some requests from users to be sure that they 
really want it and to get some list of transform "classes" they want to 
recognize. Right now I'm afraid of introducing a complex logic for 
maintaining this classification that will miss its point.


> There's some food for thought, I'll let that simmer and come back to 
> it tomorrow...
>             ...jim
> 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