[Geoserver-devel] Geoserver and crs

Hi list,
I have been working lately on a new version of the
wcs-wms_with_rasters and I ran into an annoying problem.

In the getmap request, if I am right, the envelope is lon-lat
regardless the crs. This means that if I request a map with SRS
epsg:4326 we receive a bbox with lon first but we should internally
handle with lat first.

Despite of this in RenderUtilities the worldToScreenTransform assumes
that the crs is always lon,lat, is this an error or it is stupid me?

I found other minor issues which I would like (in conjunction with
alessio) fix but this is an interesting/annoying one and I wanted to
hear someone else's opinion.

Simone.

On 2/17/06, Jody Garnett <jgarnett@anonymised.com> wrote:

Simone Giannecchini wrote:
> ---------- Forwarded message ----------
> From: Simone Giannecchini <simboss1@anonymised.com>
> Date: Feb 17, 2006 4:07 PM
> Subject: Geoserver and crs
> To: geoserver-devel@lists.sourceforge.net
>
>
> Hi list,
> I have been working lately on a new version of the
> wcs-wms_with_rasters and I ran into an annoying problem.
>
> In the getmap request, if I am right, the envelope is lon-lat
> regardless the crs. This means that if I request a map with SRS
> epsg:4326 we receive a bbox with lon first but we should internally
> handle with lat first.
>
For WFS the request is always in the target coordinate system (which
means client code has to convert from the advertised lon-lat bounds to
the traget crs in order to make a request.

What WMS can do depends a little bit on what version you are using, talk
to richard and look at the different WMS strategies for the exact details.
For example in WMS 1.3 your request can include the CRS and your
bounding box in a GetMap request.

What I am talking about is basically wat follows.

If you take a look at the RendereUtilities class and you check the
worldToScreenTransform method you can see that it makes the assumption
that your crs is always Lon,Lat but if the underlying crs is lat,lon
it fails to compute the transform. This happens if you use EPSG:4326
for example.

When we parse the request parameters for a getmap in geoserver we
build a JTS Envelope object which is correctly lat, lan but when we
set the CRS using CRS.decode the axis order can be different as it
happens regularly with EPSG:4236 (see GetMapRequest file in geoserver
code). Hence when we build the worldToScreenTransform inside the
Streaming renderer the transform is uncorrect as I sasid above. I am
investigating the part of the renderer where features are rendered in
order to understand how this problem has been overcome.

I fixed it creating a new worldToScreenTransform method which takes
into account the crs.

I hope that someon can tell me something about it, in the meanwhile I .

Simone.

> Despite of this in RenderUtilities the worldToScreenTransform assumes
> that the crs is always lon,lat, is this an error or it is stupid me?
>
Um we use StreamingRenderer all the time with all sorts of projections.
> I found other minor issues which I would like (in conjunction with
> alessio) fix but this is an interesting/annoying one and I wanted to
> hear someone else's opinion.
>

I am ansering the two previous email from Martin.
On 2/18/06, Martin Desruisseaux <martin.desruisseaux@anonymised.com> wrote:

Simone Giannecchini a écrit :
> In the getmap request, if I am right, the envelope is lon-lat
> regardless the crs. This means that if I request a map with SRS
> epsg:4326 we receive a bbox with lon first but we should internally
> handle with lat first.

If I'm understanding right, the WMS specification always put longitude
first. But I was at the OGC meeting last September, and the CRS working
group insisted loudly that the WMS specification is wrong in this
regards, and the official order should really be (latitude,longitude). I
don't know how they plan to do that.

The confusion exists in the EPSG factories too. In Geotools, epsg-wkt
always use (longitude,latitude) order as in WMS usage, while epsg-hsql,
epsg-access and epsg-postgresql use the official (latitude,longitude)
order. However, this confusion is not particular to Geotools. In the OGC
meeting, it has been reported that (longitude,latitude) and
(latitude,longitude) orders are found in different products for the same
EPSG code.

In Geotools 2.2, the following class has been added as a partial attempt
to adress this problem:

    org.geotools.referencing.factory.OrderedAxisAuthorityFactory

This class creates CRS using an arbitrary factory (e.g. epsg-hsql) and
reorder axis in (longitude,latitude) order before to returns it to the
user. This provided as an attempt to bring epsg-hsql to users expecting
the same axis order than epsg-wkt.

Cool, I will take a look at it.

> Despite of this in RenderUtilities the worldToScreenTransform assumes
> that the crs is always lon,lat, is this an error or it is stupid me?

I have not yet looked at RenderUtilities, but if it assumes that CRS is
always (longitude,latitude), than I think that RendererUtilities would
need to be improved. A good renderer should always work with arbitrary
axis order for every operations.

Coudl you spend 5 minutes and take a look? I am trying to improve the
rendering of raster in our GeoServer and all this confusion about axis
order is a real pain for me. I fixed the problem writing a new
worldToScreenTransform method which takes into account the CRS without
making any assumptions.

I think the source of all my problems is the usage of the JTS envelope
plus epsg_wkt. The JTS envelope does not carry along a crs while the
espg_wkt uses lon,lat instead of lat,lon. In the version of the WCS we
are building right now we have removed dependecies from JTS.Envelope
everywhere but a lot of them remain in the WMS for features. The point
of all this discussion is see if we can reamove this depency and adopt
the GeneralEnvelope as we do in the WCS.

       Martin.

On 2/18/06, Martin Desruisseaux <martin.desruisseaux@anonymised.com> wrote:

Jody Garnett a écrit :
>> Despite of this in RenderUtilities the worldToScreenTransform assumes
>> that the crs is always lon,lat, is this an error or it is stupid me?
>>
> Um we use StreamingRenderer all the time with all sorts of projections.

Yes, but if the projections come from epsg-wkt, lets remind that this
factory uses (longitude,latitude) axis order for every CRS, in
disagrement with the official EPSG database. Was StreamingRenderer tried
with CRS created by epsg-hsql?

       Martin.

All the test I have done were performed using epsg-hsql. I can
confidently state that if the crs is EPSG:4326 and comes from
ESPG-HSQL the actual worldToScreen Transform failes. Let's see how
this happens:

   /**
    * Sets up the affine transform <p/>
    * ((Taken from the old LiteRenderer))
    *
    * @param mapExtent the map extent
    * @param paintArea the size of the rendering output area
    * @return a transform that maps from real world coordinates to the screen
    */
    public static AffineTransform worldToScreenTransform( Envelope
mapExtent, Rectangle paintArea ) {
        double scaleX = paintArea.getWidth() / mapExtent.getWidth();
        double scaleY = paintArea.getHeight() / mapExtent.getHeight();

        double tx = -mapExtent.getMinX() * scaleX ;
        double ty = (mapExtent.getMinY() * scaleY) + paintArea.getHeight();

        AffineTransform at = new AffineTransform(scaleX, 0.0d, 0.0d,
-scaleY, tx, ty);
        AffineTransform
originTranslation=AffineTransform.getTranslateInstance(paintArea.x,
paintArea.y);
        originTranslation.concatenate(at);

        return originTranslation!=null?originTranslation:at;
    }

This is the incriminated method. As you can easily see from the
computation of scaleX, the assumption that the CRS for the supplied
ampExtent (a JTS Envelope) is LON,LAT hence this method fails if the
CRS is LAT,LON.

Tomorrow I will investigate how this problem has been overcome in the
features rendering part of the StreamingRenderer, in order if possible
to provide the same solution in the GridCoverageRenderer I am
refactoring for the Coverage branch.

Anyway, it might be tht I am wrong and the problem I see does not
exist. I would like one of the active developers of the Geserver to
take 5 minutes to read these emails in order to hear what they say
about this.

Simone.

Simone Giannecchini a écrit :

Coudl you spend 5 minutes and take a look? I am trying to improve the
rendering of raster in our GeoServer and all this confusion about axis
order is a real pain for me. I fixed the problem writing a new
worldToScreenTransform method which takes into account the CRS without
making any assumptions.

I looked at RenderUtilities.worldToScreenTransform and you are right, this method do not take axis order in account. This method expect a JTS envelope, which do not carry CRS information, so this method had to assumes a (longitude,latitude) order (unless we had an explicit CRS argument to this method).

Proposed solutions lower in this email.

I think the source of all my problems is the usage of the JTS envelope
plus epsg_wkt. The JTS envelope does not carry along a crs while the
espg_wkt uses lon,lat instead of lat,lon. In the version of the WCS we
are building right now we have removed dependecies from JTS.Envelope
everywhere but a lot of them remain in the WMS for features. The point
of all this discussion is see if we can reamove this depency and adopt
the GeneralEnvelope as we do in the WCS.

I believe too that JTS + epsg-wkt is contributing to the axis order mismatch. Using the OpenGIS envelope instead of JTS would probably be safer. If a user need interoperability between JTS Envelope and GeoAPI Envelope, he may consider ReferencedEnvelope, which is a JTS envelope implementing the GeoAPI interface:

http://javadoc.geotools.fr/2.2/org/geotools/geometry/jts/ReferencedEnvelope.html

So if we don't want to break our JTS dependency right now, we could replace JTS envelope by ReferencedEnvelope as a migration path.

Note that we should encourage usage of GeoAPI's Envelope interface when possible instead of some specific implementation like GeneralEnvelope. If the GeoAPI interface need to be expanded with some more API in order to make it more usable, the timing is good for proposing it. We can expand section 3.3 in the document attached there:

     http://jira.codehaus.org/browse/GEO-76

All the test I have done were performed using epsg-hsql. I can
confidently state that if the crs is EPSG:4326 and comes from
ESPG-HSQL the actual worldToScreen Transform failes. Let's see how
this happens:

public static AffineTransform worldToScreenTransform(Envelope mapExtent, Rectangle paintArea) {
[...snip...]

This is the incriminated method. As you can easily see from the
computation of scaleX, the assumption that the CRS for the supplied
mapExtent (a JTS Envelope) is LON,LAT hence this method fails if the
CRS is LAT,LON.

Right. Possible fixes are:

1) Add a CoordinateReferenceSystem argument (or replace the Envelope
    argument by ReferencedEnvelope). Inspect the coordinate system axis.
    If an axis with AxisOrientation.SOUTH | NORTH appears before an axis
    with AxisOrientation.EAST | WEST, replace the following line:

    new AffineTransform(scaleX, 0.0d, 0.0d, -scaleY, tx, ty);

    by

    new AffineTransform(0.0d, -scaleY, scaleX, 0.0d, tx, ty);

2) Add a CoordinateReferenceSystem argument for *both* the Envelope and
    the Rectangle arguments. This is closer to the GO-1 specification.
    In GO-1 vocabulary, the Envelope CRS is the "objective CRS" while
    the Rectangle CRS is the "display CRS". Axis swapping can be
    determined by the following code:

    CoordinateSytsem objectiveCS = objectiveCRS.getCoordinateSystem();
    CoordinateSystem displayCS = displayCRS.getCoordinateSystem();
    Matrix swap = AbstractCS.swapAndScaleAxis(objectiveCS, displayCS);

    This is more generic than #1 above; it work for an arbitrary number
    of dimensions, can handle non-geographic cases like (latitude,time)
    axis (we sometime use that in oceanography), and can performs unit
    conversions as well as axis swaping. In the specific case of 2D CRS,
    the matrix need to be converted into an AffineTransform (Matrix3 in
    the org.geotools.referencing.operation.matrix may be of some help)
    and concatenated with the AffineTransform computed by
    worldToScreenTransform. Note that the later should be renamed
    objectiveToDisplayTransform for GO-1 compliance.

    The drawnback is that this approach requires that the renderer carry
    around the concept of display CRS as well as objective CRS. I'm not
    sure that the StreamingRenderer do that.

3) An other possible approach is to help me with the implementation of
    GO-1 renderer. The GO-1 renderer (in ext/go module) is a refactoring
    of the old J2D-renderer, which was fast (except for startup time) and
    have some features not found in StreamingRenderer (like displaying a
    map scale), but had a number of inconvenient like complexity, lack of
    SLD support, memory usage, etc. This renderer was designed with great
    attention to CRS (understandably, since it was wrote by the same
    author than the referencing module) and was handling axis swapping
    right. Javadoc for the GO-1 port:

http://maven.geotools.fr/reports/go/apidocs/org/geotools/display/canvas/package-summary.html

    Note that the base classes are designed for supporting 3D rendering
    engines as well as 2D :). The inconvenient of working on GO-1
    renderer is that it may take a while before it get the same set of
    functionalities than StreamingRenderer for non-rasters graphics.
    I plan to "steal" code for StreamingRenderer, but help from someone
    who know the StreamingRenderer would certainly make the work faster.

  Martin.

Simone Giannecchini a écrit :

Coudl you spend 5 minutes and take a look? I am trying to improve the
rendering of raster in our GeoServer and all this confusion about axis
order is a real pain for me. I fixed the problem writing a new
worldToScreenTransform method which takes into account the CRS without
making any assumptions.

I looked at RenderUtilities.worldToScreenTransform and you are right,
this method do not take axis order in account. This method expect a JTS
envelope, which do not carry CRS information, so this method had to
assumes a (longitude,latitude) order (unless we had an explicit CRS
argument to this method).

Proposed solutions lower in this email.

I think the source of all my problems is the usage of the JTS envelope
plus epsg_wkt. The JTS envelope does not carry along a crs while the
espg_wkt uses lon,lat instead of lat,lon. In the version of the WCS we
are building right now we have removed dependecies from JTS.Envelope
everywhere but a lot of them remain in the WMS for features. The point
of all this discussion is see if we can reamove this depency and adopt
the GeneralEnvelope as we do in the WCS.

I believe too that JTS + epsg-wkt is contributing to the axis order
mismatch. Using the OpenGIS envelope instead of JTS would probably be
safer. If a user need interoperability between JTS Envelope and GeoAPI
Envelope, he may consider ReferencedEnvelope, which is a JTS envelope
implementing the GeoAPI interface:

http://javadoc.geotools.fr/2.2/org/geotools/geometry/jts/ReferencedEnvelope.html

So if we don't want to break our JTS dependency right now, we could
replace JTS envelope by ReferencedEnvelope as a migration path.

Note that we should encourage usage of GeoAPI's Envelope interface when
possible instead of some specific implementation like GeneralEnvelope.
If the GeoAPI interface need to be expanded with some more API in order
to make it more usable, the timing is good for proposing it. We can
expand section 3.3 in the document attached there:

     http://jira.codehaus.org/browse/GEO-76

All the test I have done were performed using epsg-hsql. I can
confidently state that if the crs is EPSG:4326 and comes from
ESPG-HSQL the actual worldToScreen Transform failes. Let's see how
this happens:

public static AffineTransform worldToScreenTransform(Envelope mapExtent, Rectangle paintArea) {
[...snip...]

This is the incriminated method. As you can easily see from the
computation of scaleX, the assumption that the CRS for the supplied
mapExtent (a JTS Envelope) is LON,LAT hence this method fails if the
CRS is LAT,LON.

Right. Possible fixes are:

1) Add a CoordinateReferenceSystem argument (or replace the Envelope
    argument by ReferencedEnvelope). Inspect the coordinate system axis.
    If an axis with AxisOrientation.SOUTH | NORTH appears before an axis
    with AxisOrientation.EAST | WEST, replace the following line:

    new AffineTransform(scaleX, 0.0d, 0.0d, -scaleY, tx, ty);

    by

    new AffineTransform(0.0d, -scaleY, scaleX, 0.0d, tx, ty);

2) Add a CoordinateReferenceSystem argument for *both* the Envelope and
    the Rectangle arguments. This is closer to the GO-1 specification.
    In GO-1 vocabulary, the Envelope CRS is the "objective CRS" while
    the Rectangle CRS is the "display CRS". Axis swapping can be
    determined by the following code:

    CoordinateSytsem objectiveCS = objectiveCRS.getCoordinateSystem();
    CoordinateSystem displayCS = displayCRS.getCoordinateSystem();
    Matrix swap = AbstractCS.swapAndScaleAxis(objectiveCS, displayCS);

    This is more generic than #1 above; it work for an arbitrary number
    of dimensions, can handle non-geographic cases like (latitude,time)
    axis (we sometime use that in oceanography), and can performs unit
    conversions as well as axis swaping. In the specific case of 2D CRS,
    the matrix need to be converted into an AffineTransform (Matrix3 in
    the org.geotools.referencing.operation.matrix may be of some help)
    and concatenated with the AffineTransform computed by
    worldToScreenTransform. Note that the later should be renamed
    objectiveToDisplayTransform for GO-1 compliance.

    The drawnback is that this approach requires that the renderer carry
    around the concept of display CRS as well as objective CRS. I'm not
    sure that the StreamingRenderer do that.

3) An other possible approach is to help me with the implementation of
    GO-1 renderer. The GO-1 renderer (in ext/go module) is a refactoring
    of the old J2D-renderer, which was fast (except for startup time) and
    have some features not found in StreamingRenderer (like displaying a
    map scale), but had a number of inconvenient like complexity, lack of
    SLD support, memory usage, etc. This renderer was designed with great
    attention to CRS (understandably, since it was wrote by the same
    author than the referencing module) and was handling axis swapping
    right. Javadoc for the GO-1 port:

http://javadoc.geotools.fr/2.2/org/geotools/display/canvas/package-summary.html

    Note that the base classes are designed for supporting 3D rendering
    engines as well as 2D :). The inconvenient of working on GO-1
    renderer is that it may take a while before it get the same set of
    functionalities than StreamingRenderer for non-rasters graphics.
    I plan to "steal" code for StreamingRenderer, but help from someone
    who know the StreamingRenderer would certainly make the work faster.

  Martin.

Hi Martin, hi all,
I checked deeply the part of the GeoServer and GeoTools which is responsible for rendering features and I think I might have found myself the answer to my doubts. As I wrote in one previous email, I think that the worldToScreenTransform of the org.geotools.renderer.lite.RendererUtilities class makes an erroneus assumption about the CRS and the same thing happens for the createMapEnvelope method. I was wondering how things could work smoothly when rendering features in StreamingRenderer therefore I tracked down a complete WMS request from the GetMapRequest to the pain method in the StreamingRenderer using the states shapefile as target. I rely on the EPSG-HSQL crs datastore.

When requesting the states layer from Geoserver with crs set to EPSG:4326 in parseMandatoryParameters of the GetMapKvpReader we parse the WMS BBOX parameters (which is by default lon,lat) and wew set up a lon,lat JTS Envelope (which has no information about the crs) but in the subsequent parseOptionalParameters method of the same class we do as follows:

          CoordinateReferenceSystem mapcrs = CRS.decode(epsgCode);
          request.setCrs(mapcrs);
The resulting mapcrs WKT is

GEOGCS["WGS 84",
  DATUM["World Geodetic System 1984",
    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]],
    AUTHORITY["EPSG","6326"]],
  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]],
  UNIT["degree", 0.017453292519943295],
  AXIS["Geodetic latitude", NORTH],
  AXIS["Geodetic longitude", EAST],
  AUTHORITY["EPSG","4326"]]
As you can see the axes are swapped with respect to the envelope we set up before.

In the execute method of the GetMapResponse we set up the StreamingRenderer for producing the map. We get the JTS Envelope and the CRS we set up before when parsing the GetMap request, we load all the layers with the respective styles, we get a map producer, depending on the output format (png, jpeg, etc..) and we produce the map.

Now we are in the DefaultRastermapProducer. In the produceMap method we do, more or less, as follows,

    final int width = map.getMapWidth();
    final int height = map.getMapHeight();
    BufferedImage curImage = new BufferedImage(width, height,BufferedImage.TYPE_4BYTE_ABGR);
    Rectangle paintArea = new Rectangle(width, height);
    Envelope dataArea = map.getAreaOfInterest();
    AffineTransform at = RendererUtilities.worldToScreenTransform(dataArea, paintArea);
    renderer.paint(graphic, paintArea, at);

In my opinion the affine tranform we build in worldToScreenTransform is wrong since the associated CRS is lat,lon but the Envelope is lon,lat. Despite to what I just said features are rendered smoothly and I also would like to say that performances are dramatically improved! In order to clarify things better, I dag deeper into the StreamingRenderer for features.

The interesting method is the paintprocessSymbolizers method of the StreamingrRenderer class. Here I have the features to render along with the styels and the worldToScreenTransform. In my case I was rendering two multypoligons.
When inspecting the geometry associated I noticed that they were MultyPoligon as expected but I aso noticed the the coordinates of the objects where in lon,lat while again the associated crs was the canonical EPSG:4326 with lat,lon.

Someone, plsease, correct me if I am wrong here, but I think that everything works smoothly because basically when features are involved we ALWAYS make the assumption that we have lon,lat regardless of the CRS. Is this right or there exists another explanation?

I would like one of the lead developer of the GeoServer to spend 10 minutes on this issue because it might be important especially if someone (like me :wink: ) tries to extend geoserver to serve raster which makes NO assumptions on the order of the axes for the CRS. I think those 10 minutes would be well spent (I have to admit that, especially after Martin's email, I am quite surprised that no GeoServer developer dropped even 2 lines to answer).

Thanks everybody, and sorry for stealing your time wth such a long email.

Simone.

PS
Martin I will respond to your email in a successive email.

----- Original Message ----- From: "Martin Desruisseaux" <martin.desruisseaux@anonymised.com>
To: "Simone Giannecchini" <simboss1@anonymised.com>
Cc: "Jody Garnett" <jgarnett@anonymised.com>; <geotools-devel@lists.sourceforge.net>; <geoserver-devel@lists.sourceforge.net>
Sent: Sunday, February 19, 2006 9:07 AM
Subject: Re: [Geotools-devel] Fwd: Geoserver and crs

Simone Giannecchini a écrit :

Coudl you spend 5 minutes and take a look? I am trying to improve the
rendering of raster in our GeoServer and all this confusion about axis
order is a real pain for me. I fixed the problem writing a new
worldToScreenTransform method which takes into account the CRS without
making any assumptions.

I looked at RenderUtilities.worldToScreenTransform and you are right,
this method do not take axis order in account. This method expect a JTS
envelope, which do not carry CRS information, so this method had to
assumes a (longitude,latitude) order (unless we had an explicit CRS
argument to this method).

Proposed solutions lower in this email.

I think the source of all my problems is the usage of the JTS envelope
plus epsg_wkt. The JTS envelope does not carry along a crs while the
espg_wkt uses lon,lat instead of lat,lon. In the version of the WCS we
are building right now we have removed dependecies from JTS.Envelope
everywhere but a lot of them remain in the WMS for features. The point
of all this discussion is see if we can reamove this depency and adopt
the GeneralEnvelope as we do in the WCS.

I believe too that JTS + epsg-wkt is contributing to the axis order
mismatch. Using the OpenGIS envelope instead of JTS would probably be
safer. If a user need interoperability between JTS Envelope and GeoAPI
Envelope, he may consider ReferencedEnvelope, which is a JTS envelope
implementing the GeoAPI interface:

http://javadoc.geotools.fr/2.2/org/geotools/geometry/jts/ReferencedEnvelope.html

So if we don't want to break our JTS dependency right now, we could
replace JTS envelope by ReferencedEnvelope as a migration path.

Note that we should encourage usage of GeoAPI's Envelope interface when
possible instead of some specific implementation like GeneralEnvelope.
If the GeoAPI interface need to be expanded with some more API in order
to make it more usable, the timing is good for proposing it. We can
expand section 3.3 in the document attached there:

    http://jira.codehaus.org/browse/GEO-76

All the test I have done were performed using epsg-hsql. I can
confidently state that if the crs is EPSG:4326 and comes from
ESPG-HSQL the actual worldToScreen Transform failes. Let's see how
this happens:

public static AffineTransform worldToScreenTransform(Envelope mapExtent, Rectangle paintArea) {
[...snip...]

This is the incriminated method. As you can easily see from the
computation of scaleX, the assumption that the CRS for the supplied
mapExtent (a JTS Envelope) is LON,LAT hence this method fails if the
CRS is LAT,LON.

Right. Possible fixes are:

1) Add a CoordinateReferenceSystem argument (or replace the Envelope
   argument by ReferencedEnvelope). Inspect the coordinate system axis.
   If an axis with AxisOrientation.SOUTH | NORTH appears before an axis
   with AxisOrientation.EAST | WEST, replace the following line:

   new AffineTransform(scaleX, 0.0d, 0.0d, -scaleY, tx, ty);

   by

   new AffineTransform(0.0d, -scaleY, scaleX, 0.0d, tx, ty);

2) Add a CoordinateReferenceSystem argument for *both* the Envelope and
   the Rectangle arguments. This is closer to the GO-1 specification.
   In GO-1 vocabulary, the Envelope CRS is the "objective CRS" while
   the Rectangle CRS is the "display CRS". Axis swapping can be
   determined by the following code:

   CoordinateSytsem objectiveCS = objectiveCRS.getCoordinateSystem();
   CoordinateSystem displayCS = displayCRS.getCoordinateSystem();
   Matrix swap = AbstractCS.swapAndScaleAxis(objectiveCS, displayCS);

   This is more generic than #1 above; it work for an arbitrary number
   of dimensions, can handle non-geographic cases like (latitude,time)
   axis (we sometime use that in oceanography), and can performs unit
   conversions as well as axis swaping. In the specific case of 2D CRS,
   the matrix need to be converted into an AffineTransform (Matrix3 in
   the org.geotools.referencing.operation.matrix may be of some help)
   and concatenated with the AffineTransform computed by
   worldToScreenTransform. Note that the later should be renamed
   objectiveToDisplayTransform for GO-1 compliance.

   The drawnback is that this approach requires that the renderer carry
   around the concept of display CRS as well as objective CRS. I'm not
   sure that the StreamingRenderer do that.

3) An other possible approach is to help me with the implementation of
   GO-1 renderer. The GO-1 renderer (in ext/go module) is a refactoring
   of the old J2D-renderer, which was fast (except for startup time) and
   have some features not found in StreamingRenderer (like displaying a
   map scale), but had a number of inconvenient like complexity, lack of
   SLD support, memory usage, etc. This renderer was designed with great
   attention to CRS (understandably, since it was wrote by the same
   author than the referencing module) and was handling axis swapping
   right. Javadoc for the GO-1 port:

http://javadoc.geotools.fr/2.2/org/geotools/display/canvas/package-summary.html

   Note that the base classes are designed for supporting 3D rendering
   engines as well as 2D :). The inconvenient of working on GO-1
   renderer is that it may take a while before it get the same set of
   functionalities than StreamingRenderer for non-rasters graphics.
   I plan to "steal" code for StreamingRenderer, but help from someone
   who know the StreamingRenderer would certainly make the work faster.

Martin.

There are all sorts of assumptions that come together to cause things to work virtuously (if not correctly) most of the time.

1 - Every shape file in geographic coordinate that I have ever seen has had its ordinates in lon/lat order.
2 - Geotools will, when parsing a WKT string that does *not* specify axis order, use lon/lat order, which is virtuous, because it matches with the reality of (1) above.
3 - The WMS specification prior to 1.3 assumed (and then stated) that the envelopes provided would be in lon/lat order only.
4 - The WMS specification 1.3 stated that envelopes would be in the order specified by the CRS.
5 - The EPSG ordering for most geographic coordinate systems is lat/lon.
6 - The epsg-wkt factory uses a properties file of WKT, without explicit axis order, which means all the geographic coordinate systems are constructed with lon/lat order (see (2) above).
7 - The epsg-hsql factory uses the EPSG database directly and constructs CRS with the axis order from EPSG (lat/lon in geographic cases).

In general, if you ignore axis order *everywhere* things work, because the raw data tends to be in lon/lat order. It is only when axis order gets explicit (like in WMS 1.3) that things start to break down. We "fixed" this problem in the uDig WMS client by simply not negotiating up to WMS version 1.3.

Not an answer for you, but more grist for the mill...

P

On 19-Feb-06, at 8:11 AM, Simone Giannecchini wrote:

Someone, plsease, correct me if I am wrong here, but I think that everything works smoothly because basically when features are involved we ALWAYS make the assumption that we have lon,lat regardless of the CRS. Is this right or there exists another explanation?

Simone Giannecchini wrote:

I am ansering the two previous email from Martin.
On 2/18/06, Martin Desruisseaux <martin.desruisseaux@anonymised.com> wrote:
  

Simone Giannecchini a écrit :
    

In the getmap request, if I am right, the envelope is lon-lat
regardless the crs. This means that if I request a map with SRS
epsg:4326 we receive a bbox with lon first but we should internally
handle with lat first.
      

If I'm understanding right, the WMS specification always put longitude
first. But I was at the OGC meeting last September, and the CRS working
group insisted loudly that the WMS specification is wrong in this
regards, and the official order should really be (latitude,longitude). I
don't know how they plan to do that.
    

I do - for OWS-3 we did the following (after much discussion)...

For the SRS URI:
- EPSG:4326 - traditional WMS use easting/esting
- urn:ogc:def:crs:EPSG:6.6:4979 use what the EPSG database says

Thus the client/server can tell what is going on (if I have the 2nd uri format wrong it is simply a mistake)....

I have not yet looked at RenderUtilities, but if it assumes that CRS is
always (longitude,latitude), than I think that RendererUtilities would
need to be improved. A good renderer should always work with arbitrary
axis order for every operations.
    

I think the source of all my problems is the usage of the JTS envelope
plus epsg_wkt. The JTS envelope does not carry along a crs while the
espg_wkt uses lon,lat instead of lat,lon.

User ReferencedEnvelope, created to solve this problem.

of all this discussion is see if we can reamove this depency and adopt
the GeneralEnvelope as we do in the WCS.
  

In geoapi/geoserver1.4/geotools we just created BoundingBox (extrends Envelope) to solve this api problem ... please check a revent WMS or WFS specification for the details.

Jody

Hi Jody,
I have to admit that I have not had much time to follow the discussion
for GeoServer 1.4 (my fault). I will take a look as soon as possible
and I will also try to participate the IRC meetings.

Just a clarification, with these emails, I am trying to understand how
management of features works inside geoserver, I am not focusing on
WMS or WFS specifications. Assumptions made which work for features
might not work for coverages (and in fact they do not work).
The past versions of the WCS branch have been based on too many tricks
in order to bypass problems, I personally hate that but there was no
time (and not enough knowledge on our side I have to confess) to make
things better. What I am trying to do now, since now I am responsible
for the two branches (geoserver and geotools), is understanding
clearly how the official geoserver works otherwise the time spent on
the coverage branch will be wasted.

Thanks a lot,
   Simone.
On 2/20/06, Jody Garnett <jgarnett@anonymised.com> wrote:

Simone Giannecchini wrote:
> I am ansering the two previous email from Martin.
> On 2/18/06, Martin Desruisseaux <martin.desruisseaux@anonymised.com> wrote:
>
>> Simone Giannecchini a écrit :
>>
>>> In the getmap request, if I am right, the envelope is lon-lat
>>> regardless the crs. This means that if I request a map with SRS
>>> epsg:4326 we receive a bbox with lon first but we should internally
>>> handle with lat first.
>>>
>> If I'm understanding right, the WMS specification always put longitude
>> first. But I was at the OGC meeting last September, and the CRS working
>> group insisted loudly that the WMS specification is wrong in this
>> regards, and the official order should really be (latitude,longitude). I
>> don't know how they plan to do that.
>>
I do - for OWS-3 we did the following (after much discussion)...

For the SRS URI:
- EPSG:4326 - traditional WMS use easting/esting
- urn:ogc:def:crs:EPSG:6.6:4979 use what the EPSG database says

Thus the client/server can tell what is going on (if I have the 2nd uri
format wrong it is simply a mistake)....
>> I have not yet looked at RenderUtilities, but if it assumes that CRS is
>> always (longitude,latitude), than I think that RendererUtilities would
>> need to be improved. A good renderer should always work with arbitrary
>> axis order for every operations.
>>
> I think the source of all my problems is the usage of the JTS envelope
> plus epsg_wkt. The JTS envelope does not carry along a crs while the
> espg_wkt uses lon,lat instead of lat,lon.
User ReferencedEnvelope, created to solve this problem.
> of all this discussion is see if we can reamove this depency and adopt
> the GeneralEnvelope as we do in the WCS.
>
In geoapi/geoserver1.4/geotools we just created BoundingBox (extrends
Envelope) to solve this api problem ... please check a revent WMS or WFS
specification for the details.

Jody

Simone Giannecchini wrote:

Hi Jody,
I have to admit that I have not had much time to follow the discussion
for GeoServer 1.4 (my fault). I will take a look as soon as possible
and I will also try to participate the IRC meetings.

Just a clarification, with these emails, I am trying to understand how
management of features works inside geoserver, I am not focusing on
WMS or WFS specifications. Assumptions made which work for features
might not work for coverages (and in fact they do not work).
The past versions of the WCS branch have been based on too many tricks
in order to bypass problems, I personally hate that but there was no
time (and not enough knowledge on our side I have to confess) to make
things better. What I am trying to do now, since now I am responsible
for the two branches (geoserver and geotools), is understanding
clearly how the official geoserver works otherwise the time spent on
the coverage branch will be wasted.
  

I had an email/jira back in September that really is *what we must do* - from a doc that will come out in March:

The interpretation of this SRS tag is divided depending on the format returned:

· EPSG:4326
The interpretation of this SRS is ambiguous in practice. The pragmatic solution is to interpret the ordinates in eastward/northward order, ignoring the specified order in the EPSG database.

This follows industry practice, and the use of EPSG codes by the early WMS services. This is only a problem for a small percentage of the allowable codes.
The approach is in conflict with the latest Web Map Server specification, and represents a difference between practice and correctness.

    * URI
      Understood to indicate CRS information directly as specified by
      the European Petroleum Standards Group.
    * WKT
      Provides the WKT representation of the information retrieved.
    * AUTO:42000,0,0,0
      Reference to the AUTO projections maintained by the Web Map
      Server specifications (both AUTO, and AUTO2 are in use). The
      numbers used are “units”, “lat” and “long”. Please consult
      document the WMS 1.1.1 specification for more information.

The best advice we were offered over the course of our integrated client work was to treat “EPSG:1234” in the historical manner. Use the new URI format wherever possible (as its meaning is clear and consistent).

In short "EPSG:####" will always be ill defined, and needs be we must revert to the easting/northing access order. This
effects both WMS and WFS 1.0. These OGC specifications are kinda messed and their is nothing we can do to untangle it
(except provide a swap access button on the configuration page). I do not know if WCS is effected but I suspect so.

Enough cold hard truth.

What we can do is use the proper shiny new SRS URI format, it means the same thing everywhere and is not effected
by mistakes from the past.

In short if you are using coverages at the geotools level - I never want to hear us talk about "EPSG:4326" again. That is a
problem we can leave at the GeoServer side of the fence.

Since I have wasted weeks on this issue, I am going to go look up the new format for you.

- OGC document 04-077, which defines URN's for Coordinate Reference Systems in GML
- urn:ogc:def:crs:OGC:1.3:CRS84 is lon/lat WGS 84
- urn:ogc:crs:EPSG:6.7:4326 is lat/lon WGS 84

So the OGC steps in as their own authority here and defines "OGC:CRS84".

Once again the move to WFS1.1 and URI for SRS will solve this problem.
Jody