Garmin Contour Maps from USGS National Elevation Dataset

Overview

  1. Download pre-packaged NED tiles from USGS, 1 degree square each.
  2. Split tiles into subtiles.
  3. Generate contour shapefiles from each subtile.
  4. Convert contours to OSM.
  5. Create Garmin map from OSM files.

Contour Generator Script

#!/usr/bin/perl

use strict;

my %apps = (
            gdalwarp => 'gdalwarp',
            gdal_contour => 'gdal_contour',
            ogr2osm => '/path/to/ogr2osm.py',
            mkgmap => '/path/to/mkgmap.jar',
           );
my $interval = 5;
# family ID must match TYP file
my $fam = 3758;
my $typ = '/path/to/M0000eae.TYP';
my $style = ['/path/to/mkgmap/resources/styles/', 'style-name'];

my @tiles;

my $mapid = shift;
my $desc = shift;

print "map: $mapid\n";

my ($xtiles, $ytiles) = (8,8);

mkdir for qw/work-tiles work-contour work-osm/;

while (my $source = shift)
{
    my ($tile) = $source =~ /(n\d{2}w\d{3})/;
    my ($oy, $ox) = $tile =~ /n(\d{2})w(\d{3})/;
    $ox = -$ox;
    $oy--;

    for my $tx(1..$xtiles)
    {
        for my $ty(1..$ytiles)
        {
            my @box = ($ox + ($tx-1)/$xtiles, $oy + ($ty-1)/$ytiles,
                       $ox + ($tx  )/$xtiles, $oy + ($ty  )/$ytiles);
            my $newtile = "${tile}_${tx}_${ty}";
            print "$newtile -> @box\n";
            unlink "work-tiles/$newtile.tif";
            system($apps{gdalwarp}, '-t_srs', 'EPSG:4326', '-te', @box,
                   $source, "work-tiles/$newtile.tif") and die;
            push @tiles, $newtile;
        }
    }
}

open my $template, '>', 'work-osm/template.args';

for my $tile(@tiles)
{
    print "$tile contours\n";
    unlink "work-contour/$tile-ele.$_" for qw/shp shx prj dbf/;
    system($apps{gdal_contour}, '-a', 'ele', '-i', $interval, "work-tiles/$tile.tif", "work-contour/$tile-ele.shp")
        and die;
    system('python', $apps{ogr2osm},
           '-t', 'elevation', '-o', "work-osm/$tile-ele.osm",
           "work-contour/$tile-ele.shp") and die;
    print $template "mapname: $mapid\n";
    print $template "input-file: $tile-ele.osm\n\n";
    $mapid++;
}

chdir 'work-osm';

system('java', '-jar', $apps{mkgmap}, "--family-id=$fam",
       "--description=NED Contours $desc",
       "--style-file=$style->[0]", "--style=$style->[1]",
       '--reduce-point-density=8', '--remove-short-arcs',
       '--draw-priority=40', '--transparent',
       '--gmapsupp', '--tdbfile', $typ, '-c', 'template.args');

Edit the variables at the top of the script to point to your mkgmap jar, style file, TYP file and family ID, and desired contour interval in meters. When called as nedosm.pl mapid description tile ... this script will divide each NED tile into 64 subtiles, create a contour shapefile for each one, and convert these to OSM format. The osm files can be converted to a garmin map with mkgmap. mapid should be an 8-digit Garmin map number, description is a map description to show on the GPS.

Translation module for ogr2osm.py

This simply sorts the contours into major, medium, and minor intervals that can be displayed at different zoom levels. Save as translations/elevation.py in the current directory (ogr2osm.py does NOT look in its own install directory for this)

def translateAttributes(attrs):
    if not attrs: return

    tags = {'contour': 'elevation'}
    if 'ele' in attrs:
        ele = attrs['ele']
        tags['ele'] = str(int(float(ele)))

        if (float(ele) % 100) == 0:
            tags['contour_ext'] = 'elevation_major';
        elif (float(ele) % 25) == 0:
            tags['contour_ext'] = 'elevation_medium';
        else:
            tags['contour_ext'] = 'elevation_minor';

    return tags

TYP file for custom rendering

A Garmin TYP format file can be added to the map to customize the rendering on the GPS.

Limitations

ogr2osm.py runs somewhat slowly because it performs much more processing than necessary for this simple data.

The translation module has the contour intervals for major/minor har-dcoded.

Artifacts will appear at the borders between subtiles (discontinuous contour lines).

-- StephenCavilia - 05 Aug 2011
Topic revision: r3 - 19 Oct 2011, StephenCavilia
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding CodenamePending? Send feedback