LocalToScene Transformation (related to Affine Transforms)

Pavel Safrata pavel.safrata at oracle.com
Fri May 11 01:14:53 PDT 2012


Hi Jim,

On 11.5.2012 8:25, Jim Graham wrote:
> Hi Pavel,
>
> On 5/9/2012 8:16 AM, Pavel Safrata wrote:
>> Hello,
>> I've been working on the local-to-scene transform
>> (http://javafx-jira.kenai.com/browse/RT-520). I have a prototype that
>> makes it an observable (read-only) property, registering for
>> invalidation notifications to parent only when somebody registers a
>> listener to it. This is nicer than a simple "compute" method - it looks
>> like a standard observable lazy property from user's point of view.
>>
>> The big question now is what the type of the property should be. The
>> first candidate is javafx.scene.transform.Affine. Unfortunately this
>> class has each element of the matrix as a property, which makes it
>> pretty impractical for that purpose. There are two options there:
>> - We can create a new Affine instance each time the transformation
>> changes (and somebody calls the getter). This way all the elements would
>> have to be immutable, so all their setters would need to throw
>> exceptions (ugly) and whole their observability would be just a useless
>> slowdown.
>
> Why do we need to make them read only?  As long as the Affine we hand 
> out is a copy and we make that clear, then let them muck with the 
> value they get back.

Do we have any precedent for such copy-out property? I think it is 
highly confusing. Users are used to do getSomething().modifyIt() all the 
time and everywhere it makes an effect on the node. Where it is not 
possible, we always return something immutable or "unmodifiable". I 
think that proper javadoc doesn't really justify making one property 
behaving differently from all the others. Another thing is that the 
object property notifies you each time its reference changes, telling 
you the old reference and new reference. Returning a different reference 
every time doesn't really fit there. Not mentioning that instead of 
creating the matrix each time it changes, we will create it each time 
someone calls getter, which may be much more often.

>
>> - Or we can keep the single instance and modify its elements. This way
>> user would have to register twelve listeners to be notified of
>> transformation changes.
>> None of those options seems good enough.
>
> That second option definitely doesn't seem very good.

Agreed, unless we introduce a new mechanism for notifying about object 
state changes.

>
>> We considered another option: creating a new class TransformationMatrix.
>> This class would be immutable and would contain various methods for work
>> with matrices. All the transforms would have a getter that would return
>> an instance of this class, the Affine class would have also a setter.
>> Now the localToSceneTransformation property could be of type
>> TransformationMatrix. This would spare us the above problems and provide
>> an independent class for matrix operations, but on the other hand,
>> converting transformations to the matrix and back may be an unnecessary
>> burden, also doing some complex matrix computation with an immutable
>> matrix class would result in pretty huge garbage production (slowing
>> down the computation).
>
> If we created a matrix class it would be an excellent place to put all 
> of the methods that people have been asking for for doing matrix math. 
> If we wanted an immutable matrix class for this purpose then we'd end 
> up with needing the immutable matrix for the property and a mutable 
> matrix for doing actual matrix work.
>
> What's wrong with having the property return a mutable matrix?  Is 
> there some rule that the value of a property has to be "==" identical 
> between notifications?

As I wrote above, I believe this would be the only property whatsoever 
that would be mutable but whose changes would be ignored by the node. 
This alone is enough for me to tell I really don't like it. Did I miss 
something?

>
>> So we propose yet another approach. In the base Transform class,
>> introduce getters for all the elements of the transformation matrix (not
>> observable, just getters). Each transformation would be able to return
>> the values according to its current state. Our property would then be of
>> type Transform, allowing only for getting the matrix values. This would
>> make the property observable as a whole (creating a new instance each
>> time), unmodifiable, and would leave us with a nicely open way to
>> introduce the methods for matrix operations on the Transform class, most
>> of them probably returning the Affine instance as a result, and the
>> Affine class could then have a bunch of methods to be modified in place.
>
> How important is immutability in the values of properties?  Because 
> you say that the Transform value here would be "unmodifiable", but it 
> would be unmodifiable only in terms of its declared type and if you 
> choose to return an Affine then it can be cast and modified which 
> would mean we don't really care about the mutability of property 
> values...?

I think I never told I would choose to return Affine. Just the opposite, 
I would probably boost the performance by returning something that 
doesn't have twelve property objects that take ages to even construct.

>
> Also, in your last point, it sounds like you want the value used to be 
> modifiable in place, but you claim that it would be unmodifiable 
> earlier as if it was a "feature".

I want Affine to be modifiable in place, but not Transform, which I want 
to use for the property.

>
> I'm a little confused as to the constraints here in terms of 
> mutability of property values...?

I hope the above explained my view of this..
Thanks,
Pavel

>
>             ...jim


More information about the openjfx-dev mailing list