Relations/Relations to GPX

From OpenStreetMap Wiki
Jump to: navigation, 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

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;