A projected version of an OSM extract
Projection
Most slippy maps, including OSM's main slippy map layer, are projected in EPSG:3857.
Raw OSM Data (found in extracts, planet.osm), is in EPSG:4326, aka WGS84.
For clarification on projections, see: <http://trac.osgeo.org/proj/wiki/FAQ> <http://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/> For information on the projection and converting between lon/lat and tile formats, see Slippy map tilenames.
Projection of OSM data
Here's what I did to add 'x' and 'y' (XML) attributes to my OSM data in my local national grid (OSGB, aka EPSG:27700):
#!/usr/bin/perl use warnings; use strict; use Geo::Proj4; use XML::LibXSLT; use XML::LibXML; use XML::DOM; my $osgb36 = Geo::Proj4->new(init => "epsg:27700") or die Geo::Proj4->error; project_xsl(); sub project_dom { my $parser = new XML::DOM::Parser; my $doc = $parser->parse(\*STDIN); my $nodes = $doc->getElementsByTagName ("node"); my $n = $nodes->getLength; for (my $i = 0; $i < $n; $i++) { my $node = $nodes->item($i); my $lat = $node->getAttributeNode("lat")->getValue(); my $lon = $node->getAttributeNode("lon")->getValue(); my ($x, $y) = $osgb36->forward($lat, $lon) or die; $node->setAttribute("x", $x); $node->setAttribute("y", $y); } print $doc->toString(); } sub project_xsl { XML::LibXSLT->register_function("urn:proj", "toosgb", sub { # args: lat, lon my ($x, $y) = $osgb36->forward(@_) or die; my $result = XML::LibXML::NodeList->new; $result->push(XML::LibXML::Attr->new("x", $x)); $result->push(XML::LibXML::Attr->new("y", $y)); return $result; }); XML::LibXSLT->register_function("urn:proj", "bounds", sub { # args: bbox string my @b = split ',', shift; my $result = XML::LibXML::NodeList->new; if ($#b == 3) { $result->push(XML::LibXML::Attr->new("minlat", $b[0])); $result->push(XML::LibXML::Attr->new("minlon", $b[1])); $result->push(XML::LibXML::Attr->new("maxlat", $b[2])); $result->push(XML::LibXML::Attr->new("maxlon", $b[3])); } return $result; }); my $xslt = XML::LibXSLT->new(); my $doc = get_stylesheet(); my $stylesheet = $xslt->parse_stylesheet($doc); my $osm = XML::LibXML->load_xml(IO=>\*STDIN, no_cdata=>1); my $output = $stylesheet->transform($osm) or die; print $stylesheet->output_as_chars($output); } sub get_stylesheet { return XML::LibXML->load_xml(string=><<'EOF', no_cdata=>1); <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:proj="urn:proj" version="1.0"> <xsl:output method="xml" encoding="utf-8" indent="yes"/> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="*"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match="bound[@box]"> <xsl:copy-of select="."/> <bounds> <xsl:copy-of select="proj:bounds(@box)"/> </bounds> </xsl:template> <xsl:template match="way|relation"> <xsl:copy> <xsl:copy-of select="@id"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match="node"> <xsl:copy> <xsl:copy-of select="@id|@lat|@lon"/> <xsl:copy-of select="proj:toosgb(@lat,@lon)"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet> EOF }
I hope this is useful to others wanting to use a projected version of an OSM extract.
The above code includes two working methods - the stylesheet version, though longer, may be useful if you're already processing OSM with XSLT.