Ticket #11 (closed task: onhold)

Opened 9 years ago

Last modified 8 years ago

How to encode coordinate reference systems in CSML-XML?

Reported by: jonblower Owned by: cbyrom
Priority: blocker Milestone:
Component: java-xml Version:
Keywords: Cc: j.d.blower@…

Description

Need a way to encode CRSs as strings that are parseable by software tools. The EPSG database of CRS codes is parseable by GeoTools?, which (I think) parses CRS codes by URN (e.g. "urn:ogc:def:CRS:84"). Perhaps we could adopt this method for the "standard" GIS projections?

What about CRSs that don't appear in this database? Is there an NDG namespace that contains known CRS codes?

Change History

comment:1 Changed 9 years ago by jonblower

  • Cc j.d.blower@… added

comment:2 Changed 9 years ago by cbyrom

Initial investigations not entirely conclusive. Added method, CSMLExporter.getCRSCode() to get the CRS code for a specified CRS. This uses the geotools library to do the lookup - via some plugin DBs. NB, the default DB didn't work and the HSQL one caused stackoverflows. Got things working with the derby db jar, but this only seems to return codes for a few CRSs. Have left with Martin Desruisseaux to investigate the problem.

If we can get this library to reliably work, should be straightforward to construct URLs - and to add our own authority for unavailable codes. NB, also can use URNs effectively for parameterised and compound CRSs.

comment:3 Changed 9 years ago by cbyrom

NB, notes from meeting discussing this with Dome Lowe and Jon Blower:

 http://proj.badc.rl.ac.uk/csml/wiki/CSMLEncodings/CoordinateReferenceSystems

comment:4 Changed 9 years ago by cbyrom

Investigation incomplete at present:

Full email communication as follows:

Hello Jon

Jon Blower a écrit :

Is there any way in which I can find out the corresponding CRS code (e.g. the EPSG code), or better still, an OGC URN, from a CoordinateReferenceSystem? object? That is, I want to do the reverse of CRS.decode(String crsCode).

Yes, the following method is there exactly for that. You need an EPSG database however, either the embedded JavaDB or a database on PostgreSQL, at your choice.

 http://www.geotoolkit.org/apidocs/org/geotoolkit/referencing/CRS.html#lookupIdentifier(org.opengis.referencing.IdentifiedObject,%20boolean)

Please let me know if you have any issue.

Regards,

Martin


Jon Blower a écrit :

Excellent! Was that method present in GeoTools?? If so I must have missed it. We plan to migrate to Geotoolkit anyway when we have a chance.

Yes it was in Geotools as well. Actually this is documented with the following convention, which is applied consistently in the whole library: when the @since javadoc tag gives any number in the 2.x range, it was in that Geotools version. So in this particular case the method was introduced in Geotools 2.4. Everything flagged "@since 3.00" or above is new in Geotoolkit.

Just as a side note, anything in the "@since 1.x" range come from pre-geotools age.

So I guess the WKT database doesn't support this?

Actually I think it would work but I'm not sure; we need to try (and idealy add a JUnit test for making sure we will not have a regression). An advantage of the EPSG database is that this method takes advantage of database indexes for faster search, while the WKT database requires a sequential scan of all CRS. However if the WKT database is not big, it should not be a big issue.

And of course I'm very pleased if Geotoolkit can suit your need :). Please let me know or create a JIRA task ( http://jira.geotoolkit.org) if the above method doesn't work or need to be extended.

Martin


Hello

Calum.Byrom@… a écrit :

I've been trying to get this to work but have hit some problems. If I try running without the backend DB, and do:

crsCode = CRS.lookupIdentifier(null, crs, true);

(i.e. with a null Citation - since I'm not sure what this needs to be set to) then I get back a code - although this is the same code that can be found via

crs.getName().getCode()

  • so I guess it's just doing a default fall back on this?

The current implementation is to look at this crs.getName().getCode() first, and only if there is nothing found there, look in the database.

If the value returned by crs.getName().getCode() is something else than "EPSG:xxxx" and the value for the Citation argument is Citations.EPSG, then the method should realize that the code is not appropriate and looks in the database.

If I use the simpler interface, i.e.:

crsCode = CRS.lookupIdentifier(crs, true);

then this returns only nulls.

Could you post the output of crs.toString() please? It would help to see what is going on. Also, do you noticed a slight delay during the execution of the above method (something long enough to suggest that a search is actually running, something like 1 or 2 seconds).

I then tried adding the supporting DBs by including the jar files on the classpath - I tried the following two:

*epsg-wkt-2.5-SNAPSHOT.jar*

  • produces identical results to before

*epsg-hsql-2.5-SNAPSHOT.jar *- which requires the hsql.jar too (although this isn't actually specified anywhere).

  • this only runs occasionally - usually falling over with a StackOverflow?:

java.lang.StackOverflowError?

(...snip...)

at org.geotoolkit.referencing.factory.DatumAliases?.createPrimeMeridian(DatumAliases?.java:605) at org.geotools.referencing.factory.DatumAliases?.createPrimeMeridian(DatumAliases?.java:572) at org.geotoolkit.referencing.factory.DatumAliases?.createPrimeMeridian(DatumAliases?.java:605) at org.geotoolkit.referencing.factory.DatumAliases?.createPrimeMeridian(DatumAliases?.java:605) at org.geotools.referencing.factory.DatumAliases?.createPrimeMeridian(DatumAliases?.java:572)

The stack trace shows a mix of Geotools and Geotoolkit. Because the factories are registered as "plugins", each project has detected the factory of the other project and try to use it, which is apparently causing confusion here.

I will investigate this bug (I would like those two projects to be able to live together). In the main time it is safer to make sure that your classpath contains the JAR of only one project (GeoTools? or Geotoolkit) and avoid putting both of them on the same classpath.

In order to use the EPSG database with Geotoolkit, try to put the following JAR on your classpath:

  • geotk-epsg.jar
  • derby-10.4.2.0.jar

I have put a first draft of documentation there. I will try to complete it progressively according the questions or comments:

 http://www.geotoolkit.org/modules/referencing/geotk-epsg/index.html

Please let me known if it is any better.

Martin


Hello Calum

Calum.Byrom@… a écrit :

Thanks for the quick response. As requested, crs.toString() gives:

GEOGCS["ED50",

DATUM["European Datum 1950",

SPHEROID["International 1924", 6378388.0, 297.0]],

PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH]]

(...snip...)

the test data returns 'null' for CRS.lookupIdentifier(Citations.EPSG, crs, true) - and for any combinations of the input parameters;

In the EPSG database, the axis order for geographic CRS is (latitude, longitude). The CRS posted above has the opposite axis order (as we can see from the AXIS[...] elements). Consequently by default the lookupIdentifier methods consider that the given CRS doesn't match the definition in the EPSG database.

It is possible to force the library to treat axis order as if it was (longitude, latitude) despite what EPSG define. There is two way of doing that: you can set the (longitude, latitude) axis order on a system-wide basis (convenient if you are sure that all your data are that way, but not recommanded if you need to deal with latest OGC standards like WMS 1.3.0 and above):

Hints.putSystemDefault(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);

or you can force the (longitude, latitude) axis order on a case-by-case basis:

String code = ((AbstractAuthorityFactory?)

CRS.getAuthorityFactory(true)).getIdentifiedObjectFinder(CoordinateReferenceSystem?.class).findIdentifier(crs);

the 'real' data returns 'CRS:84' (what I'm actually looking for!) for CRS.lookupIdentifier(crs, true) but 'null' for any other combination of inputs.

CRS:84 is defined by the WMS specification as (longitude, latitude) - at the opposite of what EPSG define - so this matches your CRS. Other combinaison of parameters will consider that there is no match if the specified authority is Citations.EPSG, unless axis order has been forced as described above.

Martin


Thanks Martin - I've tried your suggestions. Results as follows:

Setting:

Hints.putSystemDefault(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);

doesn't appear to have any effect on produced results.

Using:

String code = ((AbstractAuthorityFactory?) CRS.getAuthorityFactory(true)).getIdentifiedObjectFinder(CoordinateReferenceSystem?.class).findIdentifier(crs);

reliably produces the same result as CRS.lookupIdentifier(crs, true); - I still can't get back any valid results when specifying the Citations object.

I've noticed for other CRS objects (e.g. DefaultVerticalCRS.GEOIDAL_HEIGHT), as well as the test object, I also get back null values - is this as you'd expect?

NB, I've tried the various different combinations of using the above with the different inputs to lookupIdentifier, and get the same results as per my last email.

Regards,

Calum.


Hello Calum

Calum.Byrom@… a écrit :

Sorry to trouble you again - I was wondering if you'd had a chance to look into the problem I was having below?

I commited a partial fix last week, but it was more related to Coverage reprojection - I'm not sure it applied to your issue. Could you confirm me that the problem is still present? If so, would it be possible to provide a small test case please? I would investigate it this afternoon.


Not had a chance to fully test things from this point.

comment:5 Changed 9 years ago by jonblower

comment:6 Changed 8 years ago by domlowe

  • Status changed from new to closed
  • Resolution set to onhold
Note: See TracTickets for help on using tickets.