Relations/Relations to GPX
From OpenStreetMap Wiki
Contents |
What it does
This little Perl script takes a bunch of route relations, and writes them out as a single GPX file.
The idea is that you use it in conjunction with a GPX visualiser. Just for example, if you were a ranger for your local cycle route, and wanted to embed a map of the route on your website, you could use this.
Example
http://www.systemeD.net/osm/routes/ is an example of the National Byway relations highlighted on the map. (OL code taken from [1] with grateful thanks.)
Possible future development
- a web interface
- the ability to load a list of ways, or the results of a XAPI query
- investigate using GML rather than GPX, which with OpenLayers' BBOX strategy should work better for big datasets
Code
#!/usr/bin/perl -w
use LWP::Simple;
use XML::Tiny qw(parsefile);
use IO::Scalar;
# Which relations do you want to map?
@relations=(9327,9333,34610,47904);
# What's the destination filename?
$fn='test.gpx';
@waylist=();
%lat=(); %lon=();
# -----------------------------------------
# Which ways are included in the relations?
foreach $relation (@relations) {
# Read relation
print "Reading $relation\n";
$rel=get("http://www.openstreetmap.org/api/0.6/relation/$relation");
$XMLFILE=new IO::Scalar \$rel;
$xml=parsefile($XMLFILE);
$first=@{$xml}[0]; # get first element of array
$members=$first->{'content'}[0]->{'content'};
close $XMLFILE;
# Parse members
foreach $member (@{$members}) {
next unless ($member->{'name'} eq 'member');
next unless ($member->{'attrib'}->{'type'} eq 'way');
push @waylist,$member->{'attrib'}->{'ref'};
}
}
# -----------------------------------------
# Download ways, lats and longs from server
@polylines=();
$maxlon=-180; $minlon=180;
$maxlat= -90; $minlat= 90;
$s=0;
foreach $wayid (@waylist) {
print "Reading way $s of $#waylist\n";
$way=get("http://www.openstreetmap.org/api/0.6/way/$wayid/full");
$XMLFILE=new IO::Scalar \$way;
$xml=parsefile($XMLFILE);
$first=@{$xml}[0];
foreach $t (@{$first->{'content'}}) {
if ($t->{'name'} eq 'node') {
$id=$t->{'attrib'}->{'id'};
$lat{$id}=$t->{'attrib'}->{'lat'};
$lon{$id}=$t->{'attrib'}->{'lon'};
if ($lat{$id}>$maxlat) { $maxlat=$lat{$id}; }
if ($lon{$id}>$maxlon) { $maxlon=$lon{$id}; }
if ($lat{$id}<$minlat) { $minlat=$lat{$id}; }
if ($lon{$id}<$minlon) { $minlon=$lon{$id}; }
} elsif ($t->{'name'} eq 'way') {
$polyline="<trkseg>\n";
foreach $nd (@{$t->{'content'}}) {
next unless ($nd->{'name'} eq 'nd');
$id=$nd->{'attrib'}->{'ref'};
$polyline.="<trkpt lat='$lat{$id}' lon='$lon{$id}' />\n";
}
$polyline.="</trkseg>\n";
push @polylines,$polyline;
}
}
close $XMLFILE;
$s++;
}
# --------------
# Write GPX file
print "Writing GPX file\n";
open (OUTFILE, ">$fn") or die "Can't open $fn for writing: $!\n";
print OUTFILE <<EOF;
<?xml version="1.0" encoding="UTF-8"?>
<gpx
version="1.0"
creator="GPSBabel - http://www.gpsbabel.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.topografix.com/GPX/1/0"
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
<bounds minlat="$minlat" minlon="$minlon" maxlat="$maxlat" maxlon="$maxlon"/>
<trk>
@polylines
</trk>
</gpx>
EOF
close OUTFILE;