nmea2xyzt Perl Script

#!/usr/bin/perl
# takes data logged with optional timestamp on each data string and
# produces an tab delimited xyzt file using lat/long for xy and meters
# for 
# Ben Smith - S/V Mother of Perl, January 2006
#######################################################################

use strict;
use Getopt::Long;
use NMEAfields;

my $scan = 1; # scan each line for the begining of the NMEA string
my $I = NMEAfields->new(); # one one interpreter needed
my $line;
my $dataP;
my $lastLong = 0;
my $Long = 0;
my $lastLat = 0;
my $Lat = 0;
my $lastGPStime = 0;
    my $GPStime = 0;
my $Depth;

my $timestamp = 0;
my $nmeastr = "";
our @zList = ();

our $useFeet;
our $Timestamp = undef;
our $Verbose = 0;
our $Debug = 0;

my $result = GetOptions("timestamp=i" => \$Timestamp, #numeric
			"verbose" => \$Verbose,
			"feet" => \$useFeet,
			"debug" => \$Debug);

$|=1;

while($line = <>){
    $line =~ s/^\s*//; # remove leading whitespace
    $line =~ s/\s*$//; # remove trailing whitespace
    next if $line =~ /^$/;  # skip blank lines
    print "\nProcessing line: \"$line\"\n" if $Verbose & 2;
    
    my(@fields) = split(/\s+/,$line); # break out any leading fields

    $nmeastr = pop(@fields) ; # the last field
    if($Timestamp) {
	$timestamp = $fields[$Timestamp];
    }
    if($dataP = $I->Interp($nmeastr)) { # get a data object
	if($dataP->ElementCode eq 'RMC') {
	    # RMC contains a time and position in one string
	    $lastLong = $Long;
	    $Long = sprintf("%.6f",$dataP->{LongDecDeg});
	    $lastLat = $Lat;
	    $Lat = sprintf("%.6f",$dataP->{LatDecDeg});
	    $lastGPStime = $GPStime;
	    $GPStime = $dataP->UNIXtime;
	    if($lastLat && $lastLong && scalar @zList) {
		my $items = scalar @zList;
		# interpolate positions and times for each depth
		for(my $n = 0; $n < $items; ++ $n) {
		    my $thisLat = 
		        ($n/$items) * ($Lat - $lastLat) + $lastLat;
		    my $thisLong = 
			($n/$items) * ($Long - $lastLong) + $lastLong;
		    my $thisGPStime = 
			($n/$items) * ($GPStime - $lastGPStime) + $lastGPStime;
		    if($Timestamp) {
			print join("\t",$thisLong,$thisLat,
				   $zList[$n],$timestamp,"\n");
		    } else {
			print join("\t",$thisLong,$thisLat,
				   $zList[$n],$thisGPStime,"\n");
		    }
		}
	    }
	    @zList = ();
	}elsif($dataP->{DBTmeters}) {
	    if($useFeet) {
		$Depth = sprintf("%.2f",$dataP->{DBTmeters}*3.28084);
	    } else {
		$Depth = sprintf("%.2f",$dataP->{DBTmeters});
	    }
	    push(@zList,$Depth);
	}
    }			       
}