LocalToScene Transformation (related to Affine Transforms)

Martin Desruisseaux martin.desruisseaux at geomatys.fr
Thu May 10 08:30:25 PDT 2012

Hello all

Le 09/05/12 17:16, Pavel Safrata a écrit :
> 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 this approach was selected, maybe a plain "Matrix" class name, with 
'getNumRows()', 'getNumColumns()' and 'get(i,j)' methods would be 
sufficient. This would allow usage in two-dimensional cases (as 3×3 
matrices), three-dimensional cases (as 4×4 matrices), perspective 
transform (which is not affine, but still represented by 3×3 matrices) 
or other matrix operations not necessarily related to coordinate 

For example, when dealing with generic (not necessarily affine) 
coordinate transformations - for example map projections -, transforming 
a point is not always sufficient. Some time we need the mathematical 
derivative of the transform at a given point. In the particular case of 
affine transforms, the derivative is trivially the same everywhere, 
which may explain why Java2D has never feel a need for it (note however 
that java.awt.geom.AffineTransform has something close: the 
deltaTransform(...) method). But in the general case the transform 
derivative may vary at any point, and the result of a transform 
derivative can be express as a matrix. See for example:


The derivatives are useful for example because a map projection may 
change straight lines into curved lines, and the derivative are useful 
for computing Bézier curves that approximate those curves. They are also 
useful for helping some iterative algorithms to converge faster. If the 
matrix class name was "TransformMatrix", we would need a 
"DerivativeMatrix" for the above case, and likewise for all other matrix 
usage. I think that a plain "Matrix" class of arbitrary dimension would 
fit better the need.

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

If this approach was selected, the "Transform" class name would become 
unfortunate, because the class name suggests arbitrary transform, while 
the above-cited getters would in practice restrict the transform to the 
affine case. This would be yet more confusing since an Affine class 
already exist. If we were allowed to rename the classes, it seems to me 
that the "Transform" class would need to be renamed "Affine" (because 
"Translate", "Scale", "Shear" and "Rotate" are special cases of affine 
transforms) and the current "Affine" would have to be renamed into 
something else, maybe "GeneralAffine".

I would like to propose a mix of those two approaches: the 
'localToSceneTransformation' property would be of kind "Transform" like 
the second proposal, but instead of individual getter methods for 
various matrix coefficients, provide the following method in the 
Transform class:

     public abstract Matrix getMatrix(Point3D location);

For every current JavaFX implementations, the Point3D argument would be 
ignored and can be null. For custom implementations, e.g. map 
projections (or anything which is non-linear), the result vary for each 
points. This method would copy the current Transform state in a new 
Matrix object (i.e. take a snapshot) - so no need for new Transform 
instance when the state change, and no need for new Matrix instance when 
performing matrix operations (the operations could be applied in-place 
in the existing Matrix instance).


More information about the openjfx-dev mailing list