Sunday, 19 September 2010

Convert easting northing to latitude longitude

The solution to this depends on how many places you'd like to convert. To be clear though, I'm talking about converting British Ordnance survey easting northing coordinates (EPSG:27700) into WGS84 latitude longitude coordinates (EPSG:4326). This blog entry can easily be adapted to do the inverse - or other coordinates systems.

Converting just a few?
Use a website. Like this one: http://www.nearby.org.uk/conversions.cgi

Converting a big batch?
Say you have a text file (CSV maybe) with 1.7 million entries (for example, all the postcodes in the UK from the Ordnance Survey Code Point data, which is now free and downloadable here).
You want to convert them all but don't fancy doing them one by one because you have a life.

To do this, I've used Python and Mapnik. You'll need some (very) basic programming skills to do this example. I'm in Linux (Ubuntu to be precise), so you might have to adapt this slightly if you're using something else.

You'll need Python and Mapnik installed. In Ubuntu, I installed the following packages:
  • mapnik-utils
  • python
  • python-dev
  • python-mapnik
  • libmapnik-0.6
  • libmapnik-dev
You might not need all of them, but I have them installed. Then, download a little example I put together here. Don't worry, even if you don't know Python. It's really simple.

Decompress it into a folder, then in a command line type:
python en_to_latlng.py input.txt

The input.txt file is just an example to get you started. Notice it just dumps the output to the console. To save it to a file:
python en_to_latlng.py input.txt > output.txt

The "greater than" symbol just pushes all the output into output.txt using output redirection.



Doing it in Java?
Yes, I like Java too. I used GeoTools to do this conversion in Java. If you use Maven, it's fantastically easy to add the dependencies. You'll need to add 3 things to your pom.xml:


  1. Property which defines which version you're using
  2. The dependencies themselves
  3. The repository (from which to download the geotools JARs and POMs)




<properties>
        <geotools.version>2.7.0.1</geotools.version>
 </properties>
...


<dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-epsg-hsql</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <!-- include WarpAffine to prevent ClassLoader error -->
            <groupId>org.geotools</groupId>
            <artifactId>gt-xml</artifactId>
            <version>
${geotools.version}</version>
        </dependency>

...


<repositories>
        <repository>
            <id>maven2-repository.dev.java.net</id>
            <name>Java.net repository</name>
            <url>http://download.java.net/maven/2</url>
        </repository>
        <repository>
            <id>osgeo</id>
            <name>Open Source Geospatial Foundation Repository</name>
            <url>http://download.osgeo.org/webdav/geotools/</url>
        </repository>
</repositories>








As for the code itself, it's pretty straightforward:




CRSAuthorityFactory crsFac =
                    ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null);


            CoordinateReferenceSystem wgs84crs = crsFac.createCoordinateReferenceSystem("4326");
            CoordinateReferenceSystem osgbCrs = crsFac.createCoordinateReferenceSystem("27700");


            CoordinateOperation op = new DefaultCoordinateOperationFactory().createOperation(osgbCrs, wgs84crs);


            DirectPosition eastNorth = new GeneralDirectPosition(easting, northing);
            DirectPosition latLng = op.getMathTransform().transform(eastNorth, eastNorth);


            System.out.println("lat: " + latLng.getOrdinate(0));
            


System.out.println("lng: " + latLng.getOrdinate(1));






Doing it in Javascript?

The key here is Proj4, an Open Source library originally written in C but it's been ported to plenty of other languages, including Javascript. Basically, it allows easy conversions between coordinate systems and projections. What you're looking for is Proj4JS, Pro4J's Javascript brother. See the website for details - I'll add an example here if I get time.

3 comments:

  1. Thanks. I found the mapnik conversion slightly inaccurate

    ReplyDelete
  2. I get a RuntimeError: failed to initialize projection with: '+init=epsg:27700'. Any ideas why?

    ReplyDelete