#!/usr/bin/perl -w # NAME: test-bearing.pl # AIM: Just some test on getting a bearing from 2 lat,lon positions use strict; use warnings; use Math::Trig; my $startlat = 43.6822; my $startlon = -70.450769; my $endlat = 43.682211; my $endlon = -70.45070; my $DiffLat = 0.000011; my $distLat = 1.22; # m my $DiffLon = 0.000069; my $distLon = 7.68; # m sub prt($) { print shift; } my $pi = atan2(1,1) * 4; my $pi2 = $pi + $pi; my $d2r = $pi / 180; my $r2d = 180 / $pi; my $R = 6371; # earth's mean radius in km my $Rm = 6370137; my $Latitude1deg = 110.54; # km my $Longitude1deg = 111.320; # *cos(latitude) km # my $D2M = 111000; # m sub distHaversine($$$$) { my ($lat1, $lon1, $lat2, $lon2) = @_; my $dLat = $d2r * ($lat2-$lat1); my $dLon = $d2r * ($lon2-$lon1); $lat1 = $d2r * $lat1; $lat2 = $d2r * $lat2; my $a = sin($dLat/2) * sin($dLat/2) + cos($lat1) * cos($lat2) * sin($dLon/2) * sin($dLon/2); my $c = 2 * atan2(sqrt($a), sqrt(1-$a)); my $d = $R * $c; return $d; # km } sub distPythag($$$$) { my ($x1, $y1, $x2, $y2) = @_; my $d = sqrt((($x2 - $x1) ** 2) + (($y2 - $y1) ** 2)); return $d * 110.54; # km } sub showBearing($$$$) { my ($lat1,$lon1,$lat2,$lon2) = @_; my ($alat,$alon,$dlat,$dlon); my ($angl1,$angl2,$angl3); my $distH = 1000 * distHaversine($lat1,$lon1,$lat2,$lon2); my $distP = 1000 * distPythag($lat1,$lon1,$lat2,$lon2); $alat = sprintf("%.6f",$distH); $alon = sprintf("%.6f",$distP); prt("distH $alat ($distH), distP $alon ($distP)\n"); my $diflat = $lat1 - $lat2; my $diflon = $lon1 - $lon2; my $dlat2m = 1.22 / ($diflat * 1000); my $dlon2m = 7.68 / ($diflon * 1000); $alat = sprintf("%.6f",$diflat); $alon = sprintf("%.6f",$diflon); $dlat = $diflat * $Latitude1deg * 1000; $dlon = $diflon * $Latitude1deg * 1000; prt("dif lat $alat ($diflat) dlat $dlat dlat2m $dlat2m\n"); prt("dif lon $alon ($diflon) dlon $dlon dlon2m $dlon2m\n"); $angl1 = atan( $dlon / $dlat ); $angl2 = atan( $dlat / $dlon ); $angl3 = atan( 7.68 / 1.22 ); ### prt("angle $angl1 $angl2 $angl3\n"); $angl1 = atan( ($d2r * $dlon) / ($d2r * $dlat) ); $angl2 = atan( ($d2r * $dlat) / ($d2r * $dlon) ); $angl3 = atan( ($d2r * 7.68) / ($d2r * 1.22) ); ### prt("angle $angl1 $angl2 $angl3\n"); $angl1 = $r2d * atan( ($d2r * $dlon) / ($d2r * $dlat) ); ### $angl2 = $r2d * atan( ($d2r * $dlat) / ($d2r * $dlon) ); $angl3 = $r2d * atan( ($d2r * 7.68) / ($d2r * 1.22) ); ### prt("angle $angl1 $angl2 $angl3\n"); prt("angle $angl1 $angl3\n"); } my $D2M = 111000; # m sub porkypigBearing($$$$) { my ($lat1,$lon1,$lat2,$lon2) = @_; my $diflat = ($lat1 - $lat2) * $D2M; my $diflon = ($lon1 - $lon2) * $D2M; my $b = $r2d * atan( ($d2r * $diflon) / ($d2r * $diflat) ); return int($b); } sub getBearing($$$$) { my ($Lat1,$Lon1,$Lat2,$Lon2) = @_; #// convert to radians my $startLat = $Lat1 * $d2r; my $startLon = $Lon1 * $d2r; my $endLat = $Lat2 * $d2r; my $endLon = $Lon2 * $d2r; my $dLon = $endLon - $startLon; my $dPhi = log(tan($endLat/2.0+$pi/4.0)/tan($startLat/2.0+$pi/4.0)); if (abs($dLon) > $pi) { if ($dLon > 0.0) { $dLon = -($pi2 - $dLon); } else { $dLon = ($pi2 + $dLon); } } my $d = atan2($dLon, $dPhi) * $r2d; return ($d + 360.0) % 360.0; } #showBearing($startlat,$startlon,$endlat,$endlon); my $b1 = getBearing($startlat,$startlon,$endlat,$endlon); prt("From $startlat,$startlon to $endlat,$endlon is $b1 degrees\n"); my $b2 = porkypigBearing($startlat,$startlon,$endlat,$endlon); prt("From $startlat,$startlon to $endlat,$endlon is $b2 degrees\n"); # eof