User:Ewmjc/PGS 2 OSM Conversion Script

From OpenStreetMap Wiki
Jump to navigation Jump to search
#!/usr/bin/perl

use strict;
use Geo::ShapeFile;

=pod

=head1 NAME

Prototype Global Shoreline Data (PGS) Shapefile to OSM XML conversion script.

=head1 DESCRIPTION

Converts specified lat/lon windows of

National Geospatial-Intelligence Agency (US)

Prototype Global Shoreline Data (Satellite Derived High Water Line Data) file

to

OpenStreetMap (OSM) Nodes and Segments file suitable for editing in JOSM.

Author: Based on "Shapefile upload script" by OJW http://wiki.openstreetmap.org/index.php/Shapefile_upload_script
and adapted by Mike Collinson, Aug 2006

=head1 TO RUN

1) Download and install Geo::ShapeFile package from CPAN or ppm.

1) Download appropriate PGS file from http://www.nga.mil/portal/site/nga01/index.jsp?epi-content=GENERIC&itemID=9328fbd8dcc4a010VgnVCMServer3c02010aRCRD&beanID=1629630080&viewID=Article

2) Unzip the file

3) Enter your local configuration parameters below

4) perl coastline.pl

=cut

## YOUR CONFIGURATION

# Where you  want your output file to be written

open (OSMFILE,'>c:/temp/coastline.osm');

# Change the following for the location you want to process
# Name and relative location of your downloaded, uzipped PGS file (don't
# specify any root file type
# Min Lon (decimal)
# Min Lat (decimal)
# Max Lon (decimal)
# Max Lat (decimal)

&createCoasts("coastline/NGA_GlobalShoreline_cd5", 150.40, -34.20, 151.35, -33.75);

## -- END OF YOUR CONFIGURATION

print "Done\n";

sub createCoasts(){

  my ($Filename, $X1, $Y1, $X2, $Y2) = @_;

  open(LOG, ">coastline_log.txt");
  print LOG "Area $X1 to $X2, $Y1 to $Y2\n";

  my $shapefile = new Geo::ShapeFile($Filename);
  printf "%d shapes in input file\n", $shapefile->shapes();

  print OSMFILE  "<?xml version=\"1.0\"?>\n<osm version=\"0.3\">";

  my $CountA = my $CountB = my $Node = my $SegmentID = 0;
  for(1 .. $shapefile->shapes()) {
    my $shape = $shapefile->get_shp_record($_);
    my $LastValid = 0;
    #debug print LOG "Shape\n";
    my $firstshape = 1;

    my $LastNode = '';
    foreach my $Point($shape->points()){
        my $Long = $Point->X();
        my $Lat = $Point->Y();

        my $InArea = ($Lat > $Y1 && $Lat < $Y2 && $Long > $X1 && $Long < $X2);

        if($InArea){
            $Node--;
            writeNode($Lat, $Long, $Node);
            if ($firstshape) {
                print LOG "Shape\n";
                $firstshape = 0;
            }
            printf LOG "Node #%d: %f, %f\n", $Node, $Lat, $Long;

            if($LastValid){
                $SegmentID--;
                my $Segment = writeSegment($LastNode, $Node, $SegmentID);
                printf LOG "Segment #%d: %d, %d\n", $Segment, $LastNode, $Node;
            }
            $LastNode = $Node;
            $CountB++;
            $LastValid = 1;
        } else {
            $LastValid = 0;
        }
        $CountA++;

      }
    }

    print OSMFILE "</osm>";

    print "Writing $CountB points out of $CountA in input file\n";
    print LOG "Complete\n";
    close LOG;
    print "Complete\n";

}

sub writeSegment(){

  my ($NodeID_1,$NodeID_2, $SegmentID) = @_;
  my $Tags = "<tag k=\"created_by\" v=\"almien_coastlines\"/>";
  $Tags   .= "<tag k=\"natural\" v=\"coastline\"/>";
  $Tags   .= "<tag k=\"source\" v=\"PGS\"/>";

  my $Segment = sprintf("<segment id=\"%d\" from=\"%d\" to=\"%d\">$Tags</segment>\n", $SegmentID, $NodeID_1,$NodeID_2);
  print OSMFILE $Segment;

  return;
}

sub writeNode(){
  my ($Lat, $Long, $Node) = @_;
  my $Tags = "<tag k=\"created_by\" v=\"almien_coastlines\"/>";
  $Tags .= "<tag k=\"source\" v=\"PGS\"/>";

  my $NodeTag = sprintf("<node id=\"%d\" lon=\"%f\" lat=\"%f\">$Tags</node>", $Node, $Long, $Lat);

  print OSMFILE $NodeTag;

  return;
}