# Copyright (C) 1996 Thomas R. Metcalf # # This software is provided "as is" and is subject to change without # notice. No warranty of any kind is made with regard to this software, # including, but not limited to, the implied warranties of # merchantability and fitness for a particular purpose. The author shall # not be liable for any errors or for direct, indirect, special, # incidental or consequential damages in connection with the furnishing, # performance, or use of this software: use it at your own risk. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this library; if not, write to the Free # Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # sub ACOS { # Compute the arc cosine # Input: Cosine (forced to -1 <= cosine <= 1) # Output: Angle in radians (0 0) {0;} else {$pi;} } else { $piover2 - atan2($cosine/(sqrt($argument)),1); } } sub tan { sin($_[0]) / cos($_[0]) } sub GCDISTANCE { # Compute Great Circle distance between positions # Input: lat1, lon1, lat2, lon, all in decimal degrees # Output: Distance in Nautical Miles, Initial Course my($latitude1,$longitude1,$latitude2,$longitude2) = @_; $latitude1 *= $dtor; $latitude2 *= $dtor; $longitude1 *= $dtor; $longitude2 *= $dtor; my $dlon = $longitude1-$longitude2; (&ACOS(sin($latitude1)*sin($latitude2) + cos($latitude1)*cos($latitude2) * cos($dlon))*60/$dtor, atan2(sin($dlon), cos($latitude1)*tan($latitude2)-sin($latitude1)*cos($dlon))/$dtor); } sub LOCATIONS { my %locations; $locations{""} = ""; $locations{"Acapulco, Mexico"} = "+16.50 +099.56 NEP 99999"; $locations{"Agana, Guam"} = "+13.29 -144.48 NWP 99999"; $locations{"Ahmenabad, India"} = "+23.02 -072.35 NIN 99999"; $locations{"Apalachicola, FL"} = "+29.43 +085.01 NAT 250"; $locations{"Atlantic City, NJ"} = "+39.45 +074.57 NAT 99999"; $locations{"Auckland, New Zealand"} = "-37.01 -174.48 SWP 99999"; $locations{"Baguio City, Philippines"}= "+16.25 -120.36 NWP 250"; $locations{"Balboa, Panama"} = "+08.57 +079.34 NEP 500"; $locations{"Baltimore, MD"} = "+39.11 +076.40 NAT 250"; $locations{"Bangkok, Thailand"} = "+13.23 -100.36 NIN 99999"; $locations{"Barahona, Dom. Rep."} = "+18.13 +071.06 NAT 250"; $locations{"Baton Rouge, LA"} = "+30.30 +091.10 NAT 250"; $locations{"Beaumont, TX"} = "+30.00 +094.00 NAT 250"; $locations{"Beef Island, BVI"} = "+18.27 +064.32 NAT 99999"; $locations{"Biloxi, MS"} = "+30.24 +088.55 NAT 99999"; $locations{"Boca Raton, FL"} = "+26.23 +080.09 NAT 250"; $locations{"Bombay, India"} = "+19.07 -072.51 NIN 99999"; $locations{"Boston, MA"} = "+42.00 +071.00 NAT 99999"; $locations{"Bridgetown, Barbados"} = "+13.06 +059.36 NAT 99999"; $locations{"Broome, Australia"} = "-17.56 -122.10 SIN 99999"; $locations{"Brownsville, TX"} = "+25.54 +097.30 NAT 99999"; $locations{"Cabo San Lucas, Mexico"} = "+22.52 +109.54 NEP 99999"; $locations{"Cairns, Australia"} = "-16.53 -145.45 SWP 99999"; $locations{"Calcutta, India"} = "+22.32 -088.20 NIN 99999"; $locations{"Campeche, Mexico"} = "+19.51 +090.33 NAT 250"; $locations{"Cancun, Mexico"} = "+21.09 +086.45 NAT 99999"; $locations{"Caracas, Venezuela"} = "+10.36 +066.59 NAT 99999"; $locations{"Cebu City, Philippines"} = "+10.18 -123.54 NWP 99999"; $locations{"Charleston, SC"} = "+32.47 +079.55 NAT 99999"; $locations{"Chittagong, Bangledesh"} = "+22.21 -091.50 NIN 99999"; $locations{"Coatzacoalcos, Mexico"} = "+18.09 +094.25 NAT 99999"; $locations{"Colon, Panama"} = "+09.22 +079.54 NAT 500"; $locations{"Da Nang, Vietnam"} = "+16.04 -108.13 NWP 99999"; $locations{"Diego Garcia"} = "-07.18 -072.24 SIN 99999"; $locations{"Fort de France, Martinique"}= "+14.37 +061.05 NAT 99999"; $locations{"Freeport, Bahamas"} = "+26.33 +078.42 NAT 99999"; $locations{"Galveston, TX"} = "+29.17 +094.48 NAT 99999"; $locations{"George Town, Malaysia"} = "+05.25 -100.20 NIN 99999"; $locations{"Grand Cayman, Cayman Is."}= "+19.17 +081.21 NAT 99999"; $locations{"Guantanamo Bay, Cuba"} = "+19.54 +075.09 NAT 99999"; $locations{"Guatemala City, Guatemala"}= "+14.37 +090.31 NEP 99999"; $locations{"Halifax, Nova Scotia"} = "+44.40 +063.35 NAT 99999"; $locations{"Hamilton, Bermuda"} = "+32.00 +064.00 NAT 99999"; $locations{"Hamilton, New Zealand"} = "-37.51 -175.20 SWP 99999"; $locations{"Hanoi, Vietnam"} = "+21.02 -105.52 NWP 99999"; $locations{"Havana, Cuba"} = "+23.07 +082.25 NAT 99999"; $locations{"Hartford, CN"} = "+41.56 +072.41 NAT 99999"; $locations{"Hilo, HI"} = "+19.43 +155.04 NEP 250"; $locations{"Ho Chi Minh, Vietnam"} = "+10.47 -106.42 NWP 99999"; $locations{"Hong Kong"} = "+22.30 -114.18 NWP 99999"; $locations{"Honolulu, HI"} = "+21.21 +157.56 CNP 99999"; $locations{"Jacksonville, FL"} = "+30.03 +081.42 NAT 99999"; $locations{"Kadena AB, Okinawa"} = "+26.21 -127.46 NWP 99999"; $locations{"Kagoshima, Japan"} = "+31.33 -130.33 NWP 99999"; $locations{"Kahului, HI"} = "+20.54 +156.26 NEP 250"; $locations{"Karachi, Pakistan"} = "+24.48 -066.59 NIN 99999"; $locations{"Kennedy S.C., FL"} = "+28.62 +080.68 NAT 99999"; $locations{"Key West, FL"} = "+24.33 +081.45 NAT 99999"; $locations{"Kingston, Jamaica"} = "+17.58 +076.48 NAT 99999"; $locations{"Kitty Hawk, NC"} = "+36.06 +075.42 NAT 250"; $locations{"Kona, HI"} = "+20.38 +156.00 NEP 250"; $locations{"Kuala Terengganu, Malaysia"} = "+05.20 -103.08 NWP 99999"; $locations{"Maracaibo, Venezuela"} = "+10.39 +071.36 NAT 99999"; $locations{"Mazatlan, Mexico"} = "+23.12 +106.25 NEP 99999"; $locations{"Melbourne, FL"} = "+28.04 +080.36 NAT 250"; $locations{"Kwajalein, Marshall Is."} = "+08.44 -167.44 NWP 99999"; $locations{"Lajes, Azores"} = "+38.45 +027.05 NAT 99999"; $locations{"La Paz, Mexico"} = "+24.16 +110.25 NEP 250"; $locations{"Lihue, HI"} = "+21.59 +159.21 NEP 250"; $locations{"Limon, Costa Rica"} = "+10.00 +083.02 NAT 500"; $locations{"Managua, Nicaragua"} = "+12.10 +086.15 NEP 500"; $locations{"Manila, Philippines"} = "+14.35 -120.59 NWP 99999"; $locations{"Manzanillo, Mexico"} = "+19.03 +104.20 NEP 250"; $locations{"Miami, FL"} = "+25.45 +080.23 NAT 99999"; $locations{"Mobile, AL"} = "+30.40 +088.05 NAT 99999"; $locations{"Nantucket, MA"} = "+41.17 +070.05 NAT 250"; $locations{"Nassau, Bahamas"} = "+25.03 +077.28 NAT 99999"; $locations{"New Orleans, LA"} = "+30.00 +090.03 NAT 99999"; $locations{"New York, NY"} = "+40.39 +073.47 NAT 99999"; $locations{"Norfolk, VA"} = "+36.54 +076.12 NAT 99999"; $locations{"Ocean City, MD"} = "+38.20 +075.05 NAT 99999"; $locations{"Panama City, FL"} = "+30.10 +085.41 NAT 250"; $locations{"Pensacola, FL"} = "+30.26 +087.12 NAT 99999"; $locations{"Perth, Australia"} = "-31.56 -115.57 SIN 99999"; $locations{"Plaisance, Mauritius"} = "-20.26 -057.40 SIN 250"; $locations{"Port Au Prince, Haiti"} = "+18.33 +072.20 NAT 99999"; $locations{"Port Hedland, Australia"} = "-20.19 -118.35 SIN 250"; $locations{"Port Louis, Mauritius"} = "-20.00 -057.00 SIN 99999"; $locations{"Port of Spain, Trinidad"} = "+10.40 +061.31 NAT 99999"; $locations{"Puerto Cortes, Honduras"} = "+15.48 +087.56 NAT 500"; $locations{"Puerto Vallarta, Mexico"} = "+20.40 +105.15 NEP 99999"; $locations{"Puerto Lempira, Honduras"}= "+15.13 +083.47 NAT 500"; $locations{"Pyongyang, Korea"} = "+39.02 -125.41 NWP 99999"; $locations{"Rangoon, Burma"} = "+16.47 -096.09 NIN 99999"; $locations{"Saint Pierre, Reunion"} = "-21.20 -055.29 SIN 99999"; $locations{"Saipan, N. Mariana Is."} = "+15.10 -145.40 NWP 99999"; $locations{"Salina Cruz, Mexico"} = "+16.10 +095.12 NEP 99999"; $locations{"San Diego, CA"} = "+32.51 +117.07 NEP 500"; $locations{"San Jose, Costa Rica"} = "+09.56 +084.05 NEP 500"; $locations{"San Juan, Puerto Rico"} = "+18.29 +066.08 NAT 99999"; $locations{"Santo Domingo, Dom. Rep."}= "+18.26 +069.40 NAT 99999"; $locations{"San Salvador, El Salvador"}= "+13.42 +089.13 NEP 99999"; $locations{"Savannah, GA"} = "+32.08 +081.12 NAT 99999"; $locations{"Seoul, Korea"} = "+37.34 -126.58 NWP 99999"; $locations{"St. Thomas, USVI"} = "+18.20 +064.58 NAT 99999"; $locations{"Subic Bay, Philippines"} = "+14.48 -120.16 NWP 99999"; $locations{"Sydney, Australia"} = "-33.52 -151.12 SWP 99999"; $locations{"Taipei, Taiwan"} = "+25.20 -121.31 NWP 99999"; $locations{"Tampico, Mexico"} = "+22.18 +097.52 NAT 99999"; $locations{"Tehuantepec, Mexico"} = "+16.20 +095.14 NEP 60"; $locations{"Tokyo, Japan"} = "+35.33 -139.47 NWP 99999"; $locations{"Townsville, Australia"} = "-19.15 -146.45 SWP 99999"; $locations{"Wellington, New Zealand"} = "-41.20 -174.48 SWP 99999"; $locations{"Wilmington, NC"} = "+34.10 +077.50 NAT 99999"; $locations{"Yap, Caroline Is."} = "+09.29 -138.05 NWP 99999"; %locations; } sub DEG2DIRECTION { my ($c) = @_; my $tcourse; while ($c > 180) {$c -= 360;} while ($c < -180) {$c += 360;} if ($c > -11.25 && $c <= +11.25) {$tcourse = "N";} if ($c > +11.25 && $c <= +33.75) {$tcourse = "NNE";} if ($c > +33.75 && $c <= +56.25) {$tcourse = "NE";} if ($c > +56.25 && $c <= +78.75) {$tcourse = "ENE";} if ($c > +78.75 && $c <= +101.75) {$tcourse = "E";} if ($c > +101.75 && $c <= +123.75) {$tcourse = "ESE";} if ($c > +123.75 && $c <= +146.25) {$tcourse = "SE";} if ($c > +146.25 && $c <= +168.75) {$tcourse = "SSE";} if ($c > +168.75 || $c <= -168.75) {$tcourse = "S";} if ($c <= -146.25 && $c > -168.75) {$tcourse = "SSW";} if ($c <= -123.75 && $c > -146.25) {$tcourse = "SW";} if ($c <= -101.25 && $c > -123.75) {$tcourse = "WSW";} if ($c <= -78.75 && $c > -101.25) {$tcourse = "W";} if ($c <= -56.25 && $c > -78.75) {$tcourse = "WNW";} if ($c <= -33.75 && $c > -56.25) {$tcourse = "NW";} if ($c <= -11.25 && $c > -33.75) {$tcourse = "NNW";} #print "$c $tcourse\n"; $tcourse; } sub GetLocString { my($lat,$lon) = @_; my $dmin = 999999.; my $locstring = ""; my $locstring1 = ""; my $locstringtemp= ""; my $location,$obest,%secondbest,%dminsecond; foreach $location (keys(%locations)) { my ($lat,$lon,$o,$dthresh) = split(/\s+/,$locations{$location},4); $lat = int($lat) + ($lat-int($lat))*100.0/60.0; $lon = int($lon) + ($lon-int($lon))*100.0/60.0; my ($d,$c) = &GCDISTANCE($lat,$lon,$latnum,$lonnum); if ($d < $dthresh) { my $tcourse = &DEG2DIRECTION($c); my $dint = int($d + 0.5); my $locstringtemp = "$dint nmi $tcourse of $location"; if ($obest eq "" || $d < $dmin) { # save old as the second best if ($obest ne "") { $secondbest{$obest} = $locstring; $dminsecond{$obest} = $dmin; } # set up best $dmin = $d; $obest = $o; $locstring = $locstringtemp; } elsif ($secondbest{$o} eq "" || $d < $dminsecond{$o}) { $secondbest{$o} = $locstringtemp; $dminsecond{$o} = $d; } } } $locstring1 = $secondbest{$obest}; ($locstring,$locstring1); } 1