Relations/Relations to GPX

From OpenStreetMap Wiki
Jump to navigation Jump to search

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 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


#!/usr/bin/perl -w

	use LWP::Simple;
	use XML::Tiny qw(parsefile);
	use IO::Scalar;
	# Which relations do you want to map?

	# What's the destination filename?

	%lat=(); %lon=();

	# -----------------------------------------
	# Which ways are included in the relations?
	foreach $relation (@relations) {

		# Read relation

		print "Reading $relation\n";
		$XMLFILE=new IO::Scalar \$rel;
		$first=@{$xml}[0];			# get first element of array
		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

	$maxlon=-180; $minlon=180;
	$maxlat= -90; $minlat= 90;
	foreach $wayid (@waylist) {
		print "Reading way $s of $#waylist\n";
		$XMLFILE=new IO::Scalar \$way;

		foreach $t (@{$first->{'content'}}) {
			if ($t->{'name'} eq 'node') {
				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') {
				foreach $nd (@{$t->{'content'}}) {
					next unless ($nd->{'name'} eq 'nd');
					$polyline.="<trkpt lat='$lat{$id}' lon='$lon{$id}' />\n";
				push @polylines,$polyline;
		close $XMLFILE;

	# --------------
	# 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"?>
creator="GPSBabel -"
<bounds minlat="$minlat" minlon="$minlon" maxlat="$maxlat" maxlon="$maxlon"/>
	close OUTFILE;