#!/bin/perl # dms2ll.pl - Oct 2005 - geoff mclane # AIM: To accept an input DEGREES MINUTES (SECONDS DECIMAL) [NSEW] # and convert to a single decimal degrees ... 47 28 0 N # 28/03/2014 - some improvements # 13/03/2014 - some more improvements BUT STILL VERY UGLY ;=(( # 24/09/2013 - some improvements # 21/07/2011 - Fix bug when entered # 12/11/2010 - Attempt to reconstitute the same FORM # 20061206 - Later added conversion back to DEG MIN SECS as a check ... # Mt Everest 27 59 17 N = 27.9880555555556 - 86 55 31 E = 86.9252777777778 = N27E086.hgt use strict; use warnings; # print "Hello, World ... Arguments are ...\n"; my $g_argcnt = 0; my $arg = ''; my $arg2 = ''; my $g_args = ''; # out of array, into string my $degs = 0; my $deg1 = 0; my $quad = ''; my $g_degs = 0; # first argment # functions my $sdeg = ' '; # options my $add_reverse_calc = 0; sub prt($) { printf shift; } sub deg2dms2f { my ($pos, $neg, $deg) = @_; my $sign = $pos; if ($deg < 0) { $sign = $neg; $deg = -$deg; } my $d = int($deg * 360000 + 0.5); my $s = ($d % 6000) / 100; $d = int($d / 6000); my $m = $d % 60; $d = int($d / 60); return ($sign, $d, $m, $s); } sub deg2dm { my ($pos, $neg, $deg) = @_; my $sign = $pos; if ($deg < 0) { $sign = $neg; $deg = -$deg; } my $d = int($deg * 60 + 0.5); my $m = $d % 60; $d = int($d / 60); return ($sign, $d, $m); } sub coords2str { my ($lat, $lon) = @_; my $form ="%s%02d${sdeg}%02d'%05.2f\", %s%03d${sdeg}%02d'%05.2f\" (%.7f, %.7f)"; sprintf($form, deg2dms2f('N', 'S', $lat), deg2dms2f('E', 'W', $lon), $lat, $lon); } sub lat2str { my ($lat) = @_; my $form ="%s%02d${sdeg}%02d'%05.2f\" (%.7f)"; sprintf($form, deg2dms2f('N', 'S', $lat), $lat ); } sub lon2str { my ($lon) = @_; my $form ="%s%02d${sdeg}%02d'%05.2f\" (%.7f)"; sprintf($form, deg2dms2f('E', 'W', $lon), $lon ); } sub lon2strdm { my ($md) = @_; my $form = "%s%d${sdeg}%02d' (%.2f)"; sprintf($form, deg2dm('E', 'W', $md), $md); } sub lat2strdm { my ($md) = @_; my $form = "%s%d${sdeg}%02d' (%.2f)"; sprintf($form, deg2dm('N', 'S', $md), $md); } sub give_help() { prt("\nHELP: Give quadrant, N, S, E, W immediately followed by degs [mins [secs]]\n"); prt("Like E13 50 or S15 30 22.456\n"); } parse_args(@ARGV); print "Found $g_argcnt arguments ... [$g_args]\n"; if ($g_argcnt < 2) { give_help(); prt("Insufficient arguments\n"); exit(1); } if (length($quad)==0) { if ($g_args =~ /(N|E)/i) { # nothing $quad = $1; print "Quadrant: $quad ...\n"; } elsif ($g_args =~ /(S|W)/i) { $degs *= -1; $quad = $1; print "Quadrant: $quad ...(negative)\n"; } else { print "No quadrant NSEW found ... assumed positive ...[$g_args]\n"; } } print "Degrees = $degs\n"; # now to convert is back if ($add_reverse_calc) { my $nquad = 'N|E'; if ($degs < 0) { $nquad = 'S|W'; $degs *= -1; } my $idegs = int($degs); my $rmins = ($degs - $idegs) * 60; my $imins = int($rmins); my $rsecs = ($rmins - $imins) * 60; if ($g_argcnt == 1) { print "dms = [$g_degs $nquad] ... from [$g_args]\n"; } elsif ($g_argcnt == 2) { print "dms = [$idegs $rmins $nquad] ... from [$g_args]\n"; } elsif ($g_argcnt == 3) { print "dms = [$idegs $imins $rsecs $nquad] ... from [$g_args]\n"; } else { print "dms = [$idegs $imins $rsecs $nquad] ... from [$g_args]\n"; } if (($quad eq 'N')||($quad eq 'S')) { print "Latitude: dms=".lat2str($degs)." dm=".lat2strdm($degs)."\n"; } elsif (($arg eq 'E')||($arg eq 'W')) { print "Longitude: dms=".lon2str($degs)." dm:".lon2strdm($degs)."\n"; } } exit(0); sub next_arg { my ($arg,@av) = @_; return 0 if (! @av); return 1; } sub parse_args { my @av = @_; my $cnt = 0; $g_argcnt = scalar @av; $g_args = join(" ",@av); while (@av) { $arg = $av[0]; if (($arg eq '-?')||($arg eq '-h')||($arg eq '--help')) { give_help(); exit(1); } if ($cnt == 0) { if ($arg =~ /^\d/) { # start with a number } else { $arg = substr($arg,1) if ($arg =~ /^\w/); } $arg = substr($arg,0,length($arg)-1) if ($arg =~ /\D$/); $deg1 = $arg; $degs += $arg; print "Arg 1 Degrees = $arg ($deg1) = $degs\n"; $g_degs = $arg; if (next_arg(@av)) { $arg = $av[1]; if ($arg =~ /^\d/) { # starts with digit - leave it } else { shift @av; } } } elsif ($cnt == 1) { $arg = substr($arg,0,length($arg)-1) if ($arg =~ /\D$/); $arg2 = $arg; $arg2 =~ s/\'//; $degs += ($arg2 / 60); $deg1 = ($arg2 / 60); print "Arg 2 Minutes = $arg ($deg1) = $degs\n"; if (next_arg(@av)) { $arg = $av[1]; if ($arg =~ /^\d/) { # starts with digit - leave it } else { shift @av; } } } elsif ($cnt == 2) { $arg2 = $arg; $arg2 =~ s/\"//; $arg2 = substr($arg2,0,length($arg2)-1) while ($arg2 =~ /\D$/); $arg2 = substr($arg2,0,length($arg2)-1) while ($arg2 =~ /\s$/); $degs += ($arg2 / (60*60)); $deg1 = ($arg2 / (60*60)); print "Arg 3 Seconds = $arg ($deg1) = $degs\n"; #if (next_arg(@av)) { # $arg = $av[1]; # if ($arg =~ /^\d/) { # # starts with digit - leave it # } else { # shift @av; # } #} } else { if (($arg eq 'N')||($arg eq 'S')||($arg eq 'E')||($arg eq 'W')) { $quad = $arg; $arg2 = int($degs); if ($quad =~ /(S|W)/) { print "Quadrant: $quad ...(negative) "; $degs *= -1; } else { print "Quadrant: $quad ... "; } print "$degs ($quad$arg2)\n"; } else { ###$deg1 = 0; print "Arg $g_argcnt: Unknown argument [$arg]...\n"; #exit(1); } } shift @av; $cnt++; } } # eof = dms2ll.pl