Not that anyone is going to read this (nothing else to do at 11:30pm but sleep, but why do that when I could learn something about UTM which I'll use ... but I digress), but it turns out that I needed to learn a few things about UTM. Below is the latest version that I think would actually work. The issue before is that I was not taking into account the zone and not handling the zero that could be possible with the denominator of the atan2. I think the easiest approach is to convert from UTM to lat/lon and then find the angle using the lat/lon. I pick Clarke 1866 but I don't think it matters, any conversion should work. I think (I'll spend more time thinking about that one). But change it if you think it will make a difference or change it and run some tests to see if it matters (as I typed it I figured, well check it out). I was correct it only changes the answer in the 1.0e-6.
#!/usr/bin/perl
# This script prints out the bearing in degrees between to point given in UTM format.
#
#
use strict;
use warnings;
use Geo::Coordinates::UTM;
use Math::Trig;
my ($x1,$y1,$x2,$y2) = (0,0,0,0);
my @names = ellipsoid_names;
# I don't think the ellipsoid makes a difference
($y1,$x1)=utm_to_latlon('clarke 1866','30V',512543.0,6406592.0);
($y2,$x2)=utm_to_latlon('clarke 1866','30V',514543.0,6406592.0);
my $ans1 = getAngleBetweenPoints($x1,$y1,$x2,$y2);
print "Bearing using \'$names[5]\': $ans1\n";
($y1,$x1)=utm_to_latlon('Australian National','30V',512543.0,6406592.0);
($y2,$x2)=utm_to_latlon('Australian National','30V',514543.0,6406592.0);
my $ans2 = getAngleBetweenPoints($x1,$y1,$x2,$y2);
print "Bearing using \'$names[1]\': $ans2\n";
print "Difference between \'$names[5]\' and \'$names[1]\': ".($ans1-$ans2)."\n";
#
# Ported from: http://stackoverflow.com/questions/642555/how-do-i-calculate-the-azimuth-angle-to-north-between-two-wgs84-coordinates
#
#
sub getAngleBetweenPoints {
my ($X1,$Y1,$X2,$Y2) = @_;
my ($dx,$dy,$result) = (($X2 - $X1),($Y2 - $Y1),0);
if ($dx > 0) {
$result = (pi*0.5) - atan2($dy,$dx);
}
elsif ($dx < 0 ) {
$result = (pi*1.5) - atan2($dy,$dx);
}
elsif ($dy > 0) {
$result = 0;
}
elsif ($dy < 0) {
$result = pi;
}
else {
$result = -999;
}
$result = rad2deg($result) if ( $result != -999 );
return $result;
}
Output:
Bearing using 'Clarke 1880': 90.1029398115509
Bearing using 'Australian National': 90.1029387649392
Difference between 'Clarke 1880' and 'Australian National': 1.0466117288388e-06