[Java-collab] Re: CRS axis issues (Was: Introduction and a few suggestions on recent topics)

Matthias Basler matthiasbasler at earthflight.org
Mon Aug 24 06:56:58 EDT 2009


> 4) The most efficient way to handle the axis order issue in a
>     GeoTools/Geotk-like implementation is to impose the desired order
> right
>     at the CRS creation time. Rather than having DirectPosition accepting
>     arbitrary axis order and have its getX()/getY() methods perform
> analysis
>     on the CRS axes, it is better to let the referencing module provides
> the
>     MathTransform from the arbitrary CRS to the "XYZ-ordered" CRS.
> 
>     Advantages:
>       * This avoid duplication of code since the referencing module
>         already performs analysis of axes when infering MathTransform.
> 
>       * A MathTransform performing axes swapping is an AffineTransform.
>         AffineTransforms can be efficiently concatenated with other kind
>         of conversions like unit conversions or "scaling", "false
> easting",
>         "false northing" after a map projection. Consequently in many
> cases
>         the cost of performing axis swapping is absolutly null, because
>         we just updated the coefficients of an affine transform that
>         would have been applied anyway.

My opinion is different here.
Imposing the desired axis order at the CRS construction surely has some advantages, but also a serious disadvantage:

As mentioned by Markus it is vital to retain the original CRS or at least the information which CRS it was so that round tripping is possible, e.g. in the case of a pure GML2.0 import -> GML3.x export or a similar scenario.


However, your suggestion to include axis swapping in CRS transformation wherever possible is definitely a good one.
I must admit I have overlooked this shortcut when creating such implementations. The overhead to spare is not big, but the code will be much cleaner if it is possible to just call

CRS swappedCRS = CRS.swapXY() 

or the like and then create the transform for that.

>     For now lets assume that "target" is null, which means
>     than MathTransform will return a newly allocated object. In the
>     particular case where the target CRS is one having XYZ axis order,
>     MathTransform could return a DirectPositionXYZ object.
> 
>     Advantage:
>     * User can know if he is allowed to use the getX(), getY() methods
>       by performing an "if (p instanceof DirectPositionXYZ)" check.
> 
>     * The check proposed by Mathias (where getX() throw an exception
>       if the point doesn't have a legal CRS) is replaced by a cast to
>       DirectPositionXYZ, which throw a ClassCastException if we are
>       not allowed to. The advantage is that this check is performed
>       only once for the DirectPosition as a whole, instead than for
>       each individual ordinate.

Not sure this will fit all possibilities ...

(a) You can equally call getX(), getY() and getZ() equally well on a geometry with YXZ or a theoretical ZXY coordinate system, which are not covered by your DirectPositionXYZ interface.

(b) A CRS might have X and Y axes, but not Z or the other way round.

> In summary this approach is:
> 
> * Type safe, since the getX() / getY() methods are defined only
>    in an sub-interface where the meaning of those methods is
>    garanteed to be the expected one. This allow API who want
>    a XYZ position to enforce this restriction in their method
>    signature.

Is this "type safety" really so important, I wonder? 
Having "hasXY()" or "hasZ()" methods or similar around can do the same trick, if it a goal to avoid throwing exceptions.

> * Highly performant, since 1) in a majority of cases the axis
>    swapping has been concatenated in an affine transform
>    which already existed anyway, and 2) the check for validity
>    of getX() / getY() method call is performed only once for
>    the DirectPosition as a whole (and is not performed any more
>    once we have casted to DirectPositionXYZ), instead than every
>    time a get[X|Y] method is invoked.

In my CRSInfo solution the "computation" whether an X/Y/Z axis exists is done only once for every CRS too, so it is equally efficient. Plus, it is done separately for each axis and therefore imho more flexible.


Speaking of the axis order...
... the usual orthogonal ones are XY, YX, XYZ and YXZ. However I wonder if there are (in practice) any CRS that define axis order as e.g. ZYX or XZY and if it makes sense to care about such exotic cases?

In my own library I chose to do so in order to stay as general as possible, but I wonder if the bit of additional code is really needed...

-- 
Matthias Basler
matthiasbasler at earthflight.org



More information about the Java-collab mailing list