findap02.pl to HTML.

index -|- end

Generated: Sun Aug 21 11:10:59 2011 from findap02.pl 2010/11/15 58.8 KB.

#!/usr/bin/perl
# NAME: findap02.pl
# AIM: Read FlightGear apt.dat, and find an airport given the name,
# 12/11/2010-11/11/2010 - check out... reduce noise...
# 09/11/2010 - Some UI enhancements... Skip NAV version line, ... FIX20101109
# 17/08/2010 - Fix for windows command -latlon=5,10 becomes -latlon 5 10
# 13/02/2010 - Change to using C:\FGCVS\FLightGear\data files...
# 18/11/2009 - Added Bucket2.pm, to show bucket details - OOPS, would NOT work
# 18/12/2008 - Used tested include 'fg_wsg84.pl' for distance services
# 12/12/2008 - Switch to using DISTANCE, rather than DEGREES, for searching
# for close NAVAIDS ... Add a -range=nn Kilometers
# 19/11/2008 - Added $tryharder, when NO navaid found
# updated 20070526 fixes to run from command line
# Updated 20070405 to parse inputs, added help, 
# 20061127 - Use gz (gzip) files directly from $FG_ROOT
# geoff mclane - http://geoffmclane.com/mperl/index.htm - 20061127
use strict;
use warnings;
use Time::HiRes qw( gettimeofday tv_interval );
my $perl_dir = 'C:/GTools/perl'; 
unshift(@INC, $perl_dir);
require 'logfile.pl' or die "Error: Unable to locate logfile.pl ...\n";
require 'fg_wsg84.pl' or die "Unable to load fg_wsg84.pl ...\n";
require "Bucket2.pm" or die "Unable to load Bucket2.pm ...\n";
# =============================================================================
# This NEEDS to be adjusted to YOUR particular default location of these files.
my $FGROOT = (exists $ENV{'FG_ROOT'})? $ENV{'FG_ROOT'} : "C:/FGCVS/FlightGear/data";
#my $FGROOT = (exists $ENV{'FG_ROOT'})? $ENV{'FG_ROOT'} : "C:/FG/27/data";
my $APTFILE      = "$FGROOT/Airports/apt.dat.gz";   # the airports data file
my $NAVFILE      = "$FGROOT/Navaids/nav.dat.gz";   # the NAV, NDB, etc. data file
##my $FIXFILE      = "$FGROOT/Navaids/fix.dat.gz";   # the FIX data file
# =============================================================================
my $VERS="Nov 12, 2010. version 1.0.1";
# log file stuff
my ($LF);
my $pgmname = $0;
if ($pgmname =~ /\w{1}:\\.*/) {
    my @tmpsp = split(/\\/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $perl_dir."\\temp.$pgmname.txt";
open_log($outfile);
my $t0 = [gettimeofday];

# program variables - set during running
# different searches -icao=LFPO, -latlon=1,2, or -name="airport name"
# KSFO San Francisco Intl (37.6208607739872,-122.381074803838)
my $aptdat = $APTFILE;
my $navdat = $NAVFILE;

my $SRCHICAO = 0;   # search using icao id ... takes precedence
my $SRCHONLL = 0;   # search using lat,lon
my $SRCHNAME = 0;   # search using name
my $SHOWNAVS = 0;   # show navaids around airport found

my $g_max_name_len = 32; # was 24
my $aptname = "strasbourg";
my $apticao = 'KSFO';
my $g_lat = 37.6;
my $g_lon = -122.4;
my $maxlatd = 0.5;
my $maxlond = 0.5;
my $nmaxlatd = 0.1;
my $nmaxlond = 0.1;
my $max_cnt = 0;   # maximum airport count - 0 = no limit
my $max_range_km = 5;   # range search using KILOMETERS

# features
my $tryharder = 0;  # Expand the search for NAVAID, until at least 1 found
my $usekmrange = 0; # search using KILOMETER range - see $max_range_km
my $sortbyfreq = 1; # sort NAVAIDS by FREQUENCY
my $verbosity = 0; # just info neeeded...
my $vor_only = 0;
my $loadlog = 0;

# variables for range using distance calculation
my $PI = 3.1415926535897932384626433832795029;
my $D2R = $PI / 180;
my $R2D = 180 / $PI;
my $ERAD = 6378138.12;
my $DIST_FACTOR = $ERAD;

# debug tests
# ===================
my $test_name = 0;   # to TEST a NAME search
my $def_name = "hong kong";
my $test_ll = 0;   # to TEST a LAT,LON search
my $def_lat = 37.6;
my $def_lon = -122.4;
my $test_icao = 0;   # to TEST an ICAO search
my $def_icao = 'VHHH'; ## 'KHAF';  ## LFPO'; ## 'KSFO';
my $dbg1 = 0;   # show airport during finding ...
my $dbg_fa02 = 0;   # show navaid during finding ...
my $dbg3 = 0;   # show count after finding
my $verb3 = 0;
my $dbg_fa04 = 0; # show NAV center search...

# ===================

my $av_apt_lat = 0;   # later will be $tlat / $ac;
my $av_apt_lon = 0; # later $tlon / $ac;

# apt.dat.gz CODES - see http://x-plane.org/home/robinp/Apt810.htm for DETAILS
my $aln =     '1';   # airport line
my $rln =    '10';   # runways/taxiways line
my $sealn'16'; # Seaplane base header data.
my $heliln = '17'; # Heliport header data.  
my $twrln'14'; # Tower view location. 
my $rampln = '15'; # Ramp startup position(s) 
my $bcnln'18'; # Airport light beacons  
my $wsln =   '19'; # windsock
my $minatc = '50';
my $twrfrq = '54';   # like 12210 TWR
my $appfrq = '55'# like 11970 ROTTERDAM APP
my $maxatc = '56';
my $lastln = '99'; # end of file

# nav.dat.gz CODES
my $navNDB = '2';
my $navVOR = '3';
my $navILS = '4';
my $navLOC = '5';
my $navGS  = '6';
my $navOM  = '7';
my $navMM  = '8';
my $navIM  = '9';
my $navVDME = '12';
my $navNDME = '13';
my @navset = ($navNDB, $navVOR, $navILS, $navLOC, $navGS, $navOM, $navMM, $navIM, $navVDME, $navNDME);
my @navtypes = qw( NDB VOR ILS LOC GS OM NM IM VDME NDME );

my $maxnnlen = 4;

# global program variables
my $actnav = '';
my @g_aptlist = (); # ALL airports found, for research, if needed
my @aptlist2 = ();
my @navlist = ();
my @navlist2 = ();
my @g_navlist3 = ();
my $totaptcnt = 0;
my $g_acnt = 0;
my $outcount = 0;
my @tilelist = ();
my $in_input_file = 0;

#program variables
my @warnings = ();
my %g_dupe_shown = ();
my $nav_file_version = 0;
my $got_center_latlon = 0; # 1 if latlon given in command, or ...
my $g_total_aps = 0; # push(@g_aptlist, [$diff, $icao, $name, $alat, $alon]);

sub VERB1() { return $verbosity >= 1; }
sub VERB2() { return $verbosity >= 2; }
sub VERB5() { return $verbosity >= 5; }
sub VERB9() { return $verbosity >= 9; }

sub prtw {
    my ($tx) = shift;
    $tx =~ s/\n$//;
    prt("$tx\n");
    push(@warnings,$tx);
}

sub show_warnings {
   my ($dbg) = shift;
    if (@warnings) {
        prt( "\nGot ".scalar @warnings." WARNINGS ...\n" );
        foreach my $line (@warnings) {
            prt("$line\n" );
        }
        prt("\n");
    } elsif ($dbg) {
        prt("\nNo warnings issued.\n\n");
    }
}

sub pgm_exit($$) {
    my ($val,$msg) = @_;
    show_warnings(0);
    if (length($msg)) {
        $msg =~ s/\n$//;
        prt("$msg\n");
    }
    $loadlog = 1 if ($outcount > 30);
    close_log($outfile,$loadlog);
    unlink($outfile);
    exit($val);
}

sub get_bucket_info {
   my ($lon,$lat) = @_;
   my $b = Bucket2->new();
   $b->set_bucket($lon,$lat);
   return $b->bucket_info();
}

sub show_scenery_tiles() {
    my ($name);
    my $cnt = scalar @tilelist;
    if ($cnt) {
        if (VERB9()) {
            prt( "Scenery Tile" );
            if ($cnt > 1) {
                prt( "s" );
            }
            prt( ": " );
            foreach $name (@tilelist) {
                prt( "$name " );
            }
            prt( "\n" );
        } elsif (VERB5()) {
            prt( "Scenery Tile Count $cnt\n" );
        }
    }
}

#======================================================
### MAIN ###
# ==========

parse_args(@ARGV);   # collect command line arguments ...

prt( "$pgmname ... Hello, World ... ".scalar localtime(time())."\n" ) if (VERB9());

load_apt_data();

set_average_apt_latlon();

#my @aptsort = sort mycmp_ascend @aptlist;
show_airports_found($max_cnt);
#if ($acnt && $SHOWNAVS) {
if ($SHOWNAVS) {
   search_nav();
   show_navaids_found();
    show_airports_found($max_cnt) if (VERB9());
}

show_scenery_tiles();


my $elapsed = tv_interval ( $t0, [gettimeofday]);
prt( "Ran for $elapsed seconds ...\n" );
pgm_exit(0,"");

########################################################################
### ONLY SUBS BELOW HERE
sub elim_the_dupes($) {
    my ($name) = @_;
    my @arr = split(/\s+/,$name);
    my %dupes = ();
    my @narr = ();
    my ($itm);
    foreach $itm (@arr) {
        if (!defined $dupes{$itm}) {
            $dupes{$itm} = 1;
            push(@narr,$itm);
        }
    }
    return join(" ",@narr);
}

sub show_airports_found {
   my ($mx) = shift;   # limit the AIRPORT OUTPUT
   my $scnt = $g_acnt;
   my $tile = '';
    my ($dist,$az,$adkm,$ahdg,$alat,$alon,$line,$diff,$icao,$name,$msg);
    $msg = "";
   if ($mx && ($mx < $scnt)) {
      $scnt = $mx;
      $msg .= "Listing $scnt of $g_acnt aiports ";
   } else {
      $msg .= "Listing $scnt aiport(s) ";
   }

   if ($SRCHICAO) {
      $msg .= "with ICAO [$apticao] ...";
   } elsif ($SRCHONLL) {
      $msg .= "around lat,lon [$g_lat,$g_lon], using diff [$maxlatd,$maxlond] ...";
   } else {
      $msg .= "matching [$aptname] ...";
   }
    prt("$msg\n") if (VERB1());
    # search the airport list
    #                  0=typ, 1=lat, 2=lon, 3=alt, 4=frq, 5-rng, 6-frq2, 7=nid, 8=name, 9=off, 10=dist, 11=az);
    #push(@g_navlist3, [$typ,              $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off, $dist, $az]);
    #                 0      1      2      3      4      5   6  7  8  9      10     11    12     13
    #push(@aptlist2, [$diff, $icao, $name, $alat, $alon, -1, 0, 0, 0, $icao, $name, $off, $dist, $az]);
    @aptlist2 = sort mycmp_decend_ap_dist @aptlist2 if ($got_center_latlon);
   for (my $i = 0; $i < $scnt; $i++) {
      $diff = $aptlist2[$i][0];
      $icao = $aptlist2[$i][1];
      $name = $aptlist2[$i][2];
        $name = elim_the_dupes($name);

        # locations
      $alat = $aptlist2[$i][3];
      $alon = $aptlist2[$i][4];

        # from center point
        $dist = $aptlist2[$i][12];
        $az   = $aptlist2[$i][13];

      $tile = get_bucket_info( $alon, $alat );
        $adkm = sprintf( "%0.2f", ($dist / 1000.0));    # get kilometers
        $ahdg = sprintf( "%0.1f", $az );    # and azimuth


      while (length($icao) < 4) {
         $icao .= ' ';
      }
      $line = $diff;
      while (length($line) < 6) {
         $line = ' '.$line;
      }
        # name length = 'Chavenay Villepreux ' - say 24 for unique
        $name .= " " while (length($name) < 24);
        # expand to standard
        $alat = sprintf("%2.9f",$alat);
        $alon = sprintf("%3.9f",$alon);
        #$alat = ' '.$alat while (length($alat) < 12);
        #$alon = ' '.$alon while (length($alon) < 13);
      #$line .= ' '.$icao.' '.$name.' ('.$alat.','.$alon.") tile=$tile";
      $line .= ' '.$icao.' '.$name.' '.$alat.','.$alon;
        $line .= " (";
        $line .= "fg=".get_tile($alon,$alat);
        # more information on a/p found...
        $line .= ", ".$adkm."Km on $ahdg";
        $line .= ")"; # close

        # show it
      prt("$line\n"); # print
      $outcount++;
      add_2_tiles($tile);
   }
   prt( "[v2] Done $scnt list ...\n" ) if (VERB2());
}


sub get_tile { # $alon, $alat
   my ($lon, $lat) = @_;
   my $tile = 'e';
   if ($lon < 0) {
      $tile = 'w';
      $lon = -$lon;
   }
   my $ilon = int($lon / 10) * 10;
   if ($ilon < 10) {
      $tile .= "00$ilon";
   } elsif ($ilon < 100) {
      $tile .= "0$ilon";
   } else {
      $tile .= "$ilon"
   }
   if ($lat < 0) {
      $tile .= 's';
      $lat = -$lat;
   } else {
      $tile .= 'n';
   }
   my $ilat = int($lat / 10) * 10;
   if ($ilat < 10) {
      $tile .= "0$ilat";
   } elsif ($ilon < 100) {
      $tile .= "$ilat";
   } else {
      $tile .= "$ilat"
   }
   return $tile;
}

sub add_2_tiles {   # $tile
   my ($tl) = shift;
   if (@tilelist) {
      foreach my $t (@tilelist) {
         if ($t eq $tl) {
            return 0;
         }
      }
   }
   push(@tilelist, $tl);
   return 1;
}

sub is_valid_nav {
   my ($t) = shift;
    if ($t && length($t)) {
        my $txt = "$t";
        my $cnt = 0;
        foreach my $n (@navset) {
            if ($n eq $txt) {
                $actnav = $navtypes[$cnt];
                return 1;
            }
            $cnt++;
        }
    }
   return 0;
}

sub set_average_apt_latlon {
    $g_acnt = scalar @aptlist2;
    $g_total_aps = scalar @g_aptlist;
   my $ac = $g_acnt;
   my $tlat = 0;
   my $tlon = 0;
    my ($alat,$alon);
    prt( "Found $$g_acnt, of $totaptcnt, airports ...getting average...\n" ) if ($dbg3 || VERB9());
   if ($ac) {
      for (my $i = 0; $i < $ac; $i++ ) {
         $alat = $aptlist2[$i][3];
         $alon = $aptlist2[$i][4];
         $tlat += $alat;
         $tlon += $alon;
      }
      $av_apt_lat = $tlat / $ac;
      $av_apt_lon = $tlon / $ac;
        if ($SRCHICAO) {
            prt( "Found $g_acnt matching $apticao ...(av. $av_apt_lat,$av_apt_lon)\n" ) if ($dbg3 || VERB9());
        } elsif ($SRCHONLL) {
            prt( "Found $g_acnt matching $g_lat, $g_lon ...(av. $av_apt_lat,$av_apt_lon)\n" ) if ($dbg3 || VERB9());
        } else {
            prt( "Found $g_acnt matching $aptname ... (av. $av_apt_lat,$av_apt_lon)\n" ) if ($dbg3 || VERB9());
        }
   }
}

# push(@aptlist2, [$diff, $icao, $name, $alat, $alon]);
# my $nmaxlatd = 1.5;
# my $nmaxlond = 1.5;
sub near_an_airport {
   my ($lt, $ln, $dist, $az) = @_;
    my ($az1, $az2, $s, $ret);
   my $ac = scalar @aptlist2;
    my ($x,$y,$z) = fg_ll2xyz($ln,$lt);    # get cart x,y,z
    my $d2 = $max_range_km * 1000;      # get meters
    my ($alat,$alon,$diff,$icao,$name);
   for (my $i = 0; $i < $ac; $i++ ) {
      $diff = $aptlist2[$i][0];
      $icao = $aptlist2[$i][1];
      $name = $aptlist2[$i][2];
      $alat = $aptlist2[$i][3];
      $alon = $aptlist2[$i][4];
        if ($usekmrange) {
            my ($xb, $yb, $yz) = fg_ll2xyz($alon, $alat);
            my $dst = sqrt( fg_coord_dist_sq( $x, $y, $z, $xb, $yb, $yz ) ) * $DIST_FACTOR;
            if ($dst < $d2) {
                $s = -1;
                $az1 = -1;
                $ret = fg_geo_inverse_wgs_84($alat, $alon, $lt, $ln, \$az1, \$az2, \$s);
                $$dist = $s;
                $$az = $az1;
                return ($i + 1);
            }
        } else {
          my $td = abs($lt - $alat);
          my $nd = abs($ln - $alon);
          if (($td < $nmaxlatd)&&($nd < $nmaxlond)) {
                $s = -1;
                $az1 = -1;
                $ret = fg_geo_inverse_wgs_84($alat, $alon, $lt, $ln, \$az1, \$az2, \$s);
                $$dist = $s;
                $$az = $az1;
             return ($i + 1);
          }
        }
   }
   return 0;
}

sub not_in_world_range($$) {
    my ($lt,$ln) = @_;
    return 1 if ($lt < -90);
    return 1 if ($lt >  90);
    return 1 if ($ln < -180);
    return 1 if ($ln >  180);
    return 0;
}

# like sub near_an_airport {
sub near_given_point {
   my ($lt, $ln, $dist, $az) = @_;
    return 0 if (not_in_world_range($lt,$ln));
    my ($az1, $az2, $s, $ret);
    my ($x,$y,$z) = fg_ll2xyz($ln,$lt);    # get cart x,y,z
    my $d2 = $max_range_km * 1000;      # get meters
    my $ngp_ret = 0;
    my ($alat,$alon);
    if ($SRCHONLL) {
   # for (my $i = 0; $i < $ac; $i++ ) {
   #   $diff = $aptlist2[$i][0];
   #   $icao = $aptlist2[$i][1];
   #   $name = $aptlist2[$i][2];
      $alat = $g_lat;
      $alon = $g_lon;
        if ($usekmrange) {
            my ($xb, $yb, $yz) = fg_ll2xyz($alon, $alat);
            my $dst = sqrt( fg_coord_dist_sq( $x, $y, $z, $xb, $yb, $yz ) ) * $DIST_FACTOR;
            if ($dst < $d2) {
                $s = -1;
                $az1 = -1;
                $ret = fg_geo_inverse_wgs_84($alat, $alon, $lt, $ln, \$az1, \$az2, \$s);
                ${$dist} = $s;
                ${$az}   = $az1;
                $ngp_ret = 1;
            }
        } else {
          my $td = abs($lt - $alat);
          my $nd = abs($ln - $alon);
          if (($td < $nmaxlatd)&&($nd < $nmaxlond)) {
                $s = -1;
                $az1 = -1;
                $ret = fg_geo_inverse_wgs_84($alat, $alon, $lt, $ln, \$az1, \$az2, \$s);
                ${$dist} = $s;
                ${$az} = $az1;
             $ngp_ret = 1;
          }
        }
   }
   return $ngp_ret;
}

sub show_navaids_found {
   my ($ic, $in, $line, $lcnt, $dnone);
   my ($diff, $icao, $alat, $alon);
   my ($typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off);
    my ($dist, $az, $adkm, $ahdg);
    my ($apds,$apaz,$dist_hdg,$add);
    my $msg = '';
    my $hdr = "Type  Latitude     Logitude        Alt.  Freq.  Range  Frequency2    ID  Name";
   #prt( "$actnav, $typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name ($off)\n");
   #push(@navlist2, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off]);
    my $nearna = scalar @g_navlist3;
   my $ac = scalar @aptlist2;
    @navlist2 = sort mycmp_ascend_n4 @navlist2 if ($sortbyfreq);
   my $nc = scalar @navlist2;
    my $tot = $nc + $nearna;
    my $dspcnt = 0;
    $msg = "For ";
    $msg .= "$nearna 'near' aids, " if ($nearna);
    $msg .= "$ac airports, found $tot NAVAIDS, ";
    if ($usekmrange) {
       $msg .= "within [$max_range_km] Km ...";
    } else {
       $msg .= "within [$nmaxlatd,$nmaxlond] degrees ...";
    }
    prt("$msg\n");
   $lcnt = 0;
    prt("List $nearna NEAR $g_lat,$g_lon...\n") if ($nearna);
    #my @navlist3 = sort mycmp_decend_dist @g_navlist3;
    #my $rnavlist3 = \@navlist3;
    @g_navlist3 = sort mycmp_decend_dist @g_navlist3;
    my $rnavlist3 = \@g_navlist3;
    $dspcnt = 0;
   for ($ic = 0; $ic < $nearna; $ic++) {
      $typ = ${$rnavlist3}[$ic][0];
      $nlat = ${$rnavlist3}[$ic][1];
      $nlon = ${$rnavlist3}[$ic][2];
      $nalt = ${$rnavlist3}[$ic][3];
      $nfrq = ${$rnavlist3}[$ic][4];
      $nrng = ${$rnavlist3}[$ic][5];
      $nfrq2 = ${$rnavlist3}[$ic][6];
      $nid = ${$rnavlist3}[$ic][7];
      $name = ${$rnavlist3}[$ic][8];
      $off = ${$rnavlist3}[$ic][9];
        $dist = ${$rnavlist3}[$ic][10];
        $az = ${$rnavlist3}[$ic][11];
      is_valid_nav($typ);
        if ($vor_only) {
            if (($actnav =~ /VOR/) || ($actnav =~ /NBD/)) {
                # these are OK
            } else {
                next;
            }
        }
        $dspcnt++;
        $line = $actnav;
        $line .= ' ' while (length($line) < $maxnnlen);

        $line .= ' ';
        $nalt = ' '.$nalt while (length($nalt) < 5);

        $nfrq = ' '.$nfrq while (length($nfrq) < 5);
        $nrng = ' '.$nrng while (length($nrng) < 5);
        $nfrq2 = ' '.$nfrq2 while (length($nfrq2) < 10);
        $nid = ' '.$nid while (length($nid) < 4);
        $nlat = ' '.$nlat while (length($nlat) < 12);
        $nlon = ' '.$nlon while (length($nlon) < 13);
        $adkm = sprintf( "%0.2f", ($dist / 1000.0));    # get kilometers
        $ahdg = sprintf( "%0.1f", $az );    # and azimuth
        $name = elim_the_dupes($name);
        $name .= ' ' while (length($name) < $g_max_name_len);
        $dist_hdg = "(".$adkm."Km on $ahdg, ap$off)";
        $line .= "$nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name";
        if ($dnone == 0) {
            #prt( "Type  Latitude     Logitude        Alt.  Freq.  Range  Frequency2    ID  Name\n" );
            prt( "$hdr\n" );
            $dnone++;
        }
        if (defined $g_dupe_shown{$line}) {
            prt( "[v5] DupeNR: Shown [$actnav $nlat,$nlon $name] - SHOWN\n") if (VERB5());
        } else {
            prt( "$line $dist_hdg\n" );
            $outcount++;
            $lcnt++;
            $g_dupe_shown{$line} = 1;
        }
    }
    prt("Done $dspcnt of $nearna NEAR $g_lat,$g_lon...\n") if ($nearna);
   $lcnt = 0;
    # count objects for display...
    $dspcnt = 0;
   for ($ic = 0; $ic < $ac; $ic++) {
      $diff = $aptlist2[$ic][0];
      $icao = $aptlist2[$ic][1];
      $name = $aptlist2[$ic][2];
      $alat = $aptlist2[$ic][3];
      $alon = $aptlist2[$ic][4];
        $apds = $aptlist2[$ic][12];
        $apaz = $aptlist2[$ic][13];
      $icao .= ' ' while (length($icao) < 4);
      $line = $diff;
      $line = ' '.$line while (length($line) < 6);
      $line .= ' '.$icao.' '.$name.' ('.$alat.','.$alon.')';
      $dnone = 0;
      for ( $in = 0; $in < $nc; $in++ ) {
         $typ = $navlist2[$in][0];
         $nlat = $navlist2[$in][1];
         $nlon = $navlist2[$in][2];
         $nalt = $navlist2[$in][3];
         $nfrq = $navlist2[$in][4];
         $nrng = $navlist2[$in][5];
         $nfrq2 = $navlist2[$in][6];
         $nid = $navlist2[$in][7];
         $name = $navlist2[$in][8];
         $off = $navlist2[$in][9];
            $dist = $navlist2[$in][10];
            $az = $navlist2[$in][11];
         if ($off == ($ic + 1)) {
            # it is FOR this airport
            is_valid_nav($typ);
                if ($vor_only) {
                    if (($actnav =~ /VOR/) || ($actnav =~ /NBD/)) {
                        # these are OK
                    } else {
                        next;
                    }
                }
             #     NDB  50.049000, 008.328667,   490,   399,    25,      0.000,  WBD, Wiesbaden NDB (ap=2 nnnKm on 270.1)
                #     Type Latitude   Logitude     Alt.  Freq.  Range  Frequency2    ID  Name
                #     VOR  37.61948300, -122.37389200,    13, 11580,    40,       17.0,  SFO, SAN FRANCISCO VOR-DME (ap=1 nnnKm on 1.1)
            #prt( "$actnav, $typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name ($off)\n");
                $dspcnt++;
         }
      }
      # prt( "$hdr\n" ) if ($dnone);
   }
    prt("List for $ac airports... near $g_lat,$g_lon... display $dspcnt...\n") if ($ac);
    $lcnt = 0;
   for ($ic = 0; $ic < $ac; $ic++) {
      $diff = $aptlist2[$ic][0];
      $icao = $aptlist2[$ic][1];
      $name = $aptlist2[$ic][2];
      $alat = $aptlist2[$ic][3];
      $alon = $aptlist2[$ic][4];
        $apds = $aptlist2[$ic][12];
        $apaz = $aptlist2[$ic][13];

      $icao .= ' ' while (length($icao) < 4);

        # start with 'offset' from center point
      $line = $diff;
      $line = ' '.$line while (length($line) < 6);
      $line .= ' '.$icao.' '.$name.' ('.$alat.','.$alon.')';

        $dspcnt = 0;
        # check the LIST of viable items to DISPLAY
      for ( $in = 0; $in < $nc; $in++ ) {
         $typ = $navlist2[$in][0];
         $off = $navlist2[$in][9];
         if ($off == ($ic + 1)) {
            is_valid_nav($typ);
                if ($vor_only) {
                    if (($actnav =~ /VOR/) || ($actnav =~ /NBD/)) {
                        $dspcnt++; # these are OK
                    }
                } else {
                    $dspcnt++;
                }
            }
        }
        $line .= " ($dspcnt)";
        prt("\n") if ($ic && $dspcnt);
      prt("$line\n");
      $outcount++;
      $dnone = 0;
        $line = '';
      for ( $in = 0; $in < $nc; $in++ ) {
         $typ = $navlist2[$in][0];
         $nlat = $navlist2[$in][1];
         $nlon = $navlist2[$in][2];
         $nalt = $navlist2[$in][3];
         $nfrq = $navlist2[$in][4];
         $nrng = $navlist2[$in][5];
         $nfrq2 = $navlist2[$in][6];
         $nid = $navlist2[$in][7];
         $name = $navlist2[$in][8];
         $off = $navlist2[$in][9];
            $dist = $navlist2[$in][10];
            $az = $navlist2[$in][11];
         if ($off == ($ic + 1)) {
            # it is FOR this airport
            is_valid_nav($typ);
                if ($vor_only) {
                    if (($actnav =~ /VOR/) || ($actnav =~ /NBD/)) {
                        # these are OK
                    } else {
                        next;
                    }
                }
             #     NDB  50.049000, 008.328667,   490,   399,    25,      0.000,  WBD, Wiesbaden NDB (ap=2 nnnKm on 270.1)
                #     Type Latitude   Logitude     Alt.  Freq.  Range  Frequency2    ID  Name
                #     VOR  37.61948300, -122.37389200,    13, 11580,    40,       17.0,  SFO, SAN FRANCISCO VOR-DME (ap=1 nnnKm on 1.1)
            #prt( "$actnav, $typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name ($off)\n");
                # start line
            $line = $actnav;
            $line .= ' ' while (length($line) < $maxnnlen);
            $line .= ' ';

            $nalt = ' '.$nalt while (length($nalt) < 5);
            $nfrq = ' '.$nfrq while (length($nfrq) < 5);
            $nrng = ' '.$nrng while (length($nrng) < 5);
            $nfrq2 = ' '.$nfrq2 while (length($nfrq2) < 10);
            $nid = ' '.$nid while (length($nid) < 4);
                $nlat = ' '.$nlat while (length($nlat) < 12);
                $nlon = ' '.$nlon while (length($nlon) < 13);
                $adkm = sprintf( "%0.2f", ($dist / 1000.0));    # get kilometers
                $ahdg = sprintf( "%0.1f", $az );    # and azimuth
                $name = elim_the_dupes($name);
                $name .= ' ' while (length($name) < $g_max_name_len);
                $dist_hdg .= "(".$adkm."Km on $ahdg, ap$off)";
            $line .= "$nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name";
                $add = 0;
                if (defined $g_dupe_shown{$line}) {
                    if (VERB5()) {
                        $add = 1;
                    }
                } else {
                    $add = 1;
                }

            if ($add && ($dnone == 0)) {
               #prt( "Type  Latitude     Logitude        Alt.  Freq.  Range  Frequency2    ID  Name\n" );
               prt( "$hdr\n" );
               $dnone = 1;
            }
              $outcount++;
             $lcnt++;
                if (defined $g_dupe_shown{$line}) {
                    if (VERB5()) {
                        prt( "DupeAID: Shown [$actnav $nlat,$nlon $name] - SHOWN\n");
                    }
                } else {
                    prt( "$line $dist_hdg\n" );
                    $g_dupe_shown{$line} = 1;
                add_2_tiles( get_bucket_info( $nlon, $nlat ) );
                }
         }
      }
      prt( "$hdr\n" ) if ($dnone);
   }
   prt( "[v5] Listed $lcnt NAVAIDS ...\n" ) if (VERB5());
}

sub load_apt_data {
    my ($cnt,$msg);
    prt("[v9] Loading $aptdat file ...\n") if (VERB9());
    mydie("ERROR: Can NOT locate $aptdat ...$!...\n") if ( !( -f $aptdat) );
    ###open IF, "<$aptdat" or mydie("OOPS, failed to open [$aptdat] ... check name and location ...\n");
    open IF, "gzip -d -c $aptdat|" or mydie( "ERROR: CAN NOT OPEN $aptdat...$!...\n" );
    my @lines = <IF>;
    close IF;
    $cnt = scalar @lines;
    $msg = '';
    if ($SRCHICAO) {
        $msg .= "Search ICAO [$apticao]...";
    } elsif ($SRCHONLL) {
        $msg .= "Search LAT,LON [$g_lat,$g_lon], w/diff [$maxlatd,$maxlond]...";
    } else {
        $msg .= "Search NAME [$aptname]...";
    }
    $msg .= " got $cnt lines, FOR airports,rwys,txwys... ";
    prt("$msg\n") if (VERB1());
    my ($add,$alat,$alon);
    # ================
    # SEARCH THE LINES
    # search ICAO, POSITION, NAME...
    # ================
    $add = 0;
    my ($off,$dist,$az,@arr2,$rwyt,$glat,$glon,$dlat,$dlon,$rlat,$rlon);
    my ($line,$apt,$diff,$rwycnt,$icao,$name);
    $off = 0;
    $dist = 0;
    $az = 0;
    $glat = 0;
    $glon = 0;
    $apt = '';
    $rwycnt = 0;
    foreach $line (@lines) {
        $line = trimall($line);
        ###prt("$line\n");
        my @arr = split(/ /,$line);
        if ($line =~ /^$aln\s+/) {   # start with '1'
            if (length($apt) && ($rwycnt > 0)) {
                # average position
                $alat = $glat / $rwycnt;
                $alon = $glon / $rwycnt;
                $off = -1;
                $dist = 999999;
                $az = 400;
                #$off = near_given_point( $alat, $alon, \$dist, \$az );
                $dlat = abs( $g_lat - $alat );
                $dlon = abs( $g_lon - $alon );
                $diff = int( ($dlat * 10) + ($dlon * 10) );
                @arr2 = split(/ /,$apt);
                $icao = $arr2[4];
                $name = join(' ', splice(@arr2,5));
                ##prt("$diff [$apt] (with $rwycnt runways at [$alat, $alon]) ...\n");
                ##prt("$diff [$icao] [$name] ...\n");
                #push(@g_aptlist, [$diff, $icao, $name, $alat, $alon, -1, 0, 0, 0, $icao, $name, $off, $dist, $az]);
                push(@g_aptlist, [$diff, $icao, $name, $alat, $alon]);
                $add = 0;
                if ($SRCHICAO) {
                    $add = 1 if ($icao =~ /$apticao/);
                } else {
                    if ($SRCHONLL) {
                        # searching by LAT,LON position
                        if (($dlat < $maxlatd) && ($dlon < $maxlond)) {
                            $add = 1;
                        }
                    } else {
                        # searching by airport name
                        $add = 1 if ($name =~ /$aptname/i);
                    }
                }
                if ($add) {
                    $off = near_given_point( $alat, $alon, \$dist, \$az );
                    prt("$icao, $name, $alat, $alon, rwys $rwycnt...\n") if ($dbg1);
                #                  0=typ, 1=lat, 2=lon, 3=alt, 4=frq, 5-rng, 6-frq2, 7=nid, 8=name, 9=off, 10=dist, 11=az);
                #push(@g_navlist3, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off, $dist, $az]);
                    push(@aptlist2, [$diff, $icao, $name, $alat, $alon, -1, 0, 0, 0, $icao, $name, $off, $dist, $az]);
                }
            }
            $apt = $line;
            $rwycnt = 0;
            $glat = 0;
            $glon = 0;
            $totaptcnt++;   # count another AIRPORT
        } elsif ($line =~ /^$rln\s+/) {
            # 10  36.962213  127.031071 14x 131.52  8208 1595.0620 0000.0000   150 321321  1 0 3 0.25 0 0300.0300
            # 10  36.969145  127.020106 xxx 221.51   329 0.0 0.0    75 161161  1 0 0 0.25 0 
            $rlat = $arr[1];
            $rlon = $arr[2];
            $rwyt = $arr[3];
            ###prt( "$line [$rlat, $rlon]\n" );
            if ( $rwyt ne "xxx" ) {
                $glat += $rlat;
                $glon += $rlon;
                $rwycnt++;
            }
        } elsif ($line =~ /^$lastln\s?/) {   # 99, followed by space, count 0 or more ...
            prt( "Reached END OF FILE ... \n" ) if ($dbg1);
            last;
        }
    }

    # do any LAST entry
    $add = 0;
    $off = -1;
    $dist = 0;
    $az = 0;
    if ($rwycnt > 0) {
        $alat = $glat / $rwycnt;
        $alon = $glon / $rwycnt;
        $off = -1;
        $dist = 999999;
        $az = 400;
        #$off = near_given_point( $alat, $alon, \$dist, \$az );
        $dlat = abs( $g_lat - $alat );
        $dlon = abs( $g_lon - $alon );
        $diff = int( ($dlat * 10) + ($dlon * 10) );
        @arr2 = split(/ /,$apt);
        $icao = $arr2[4];
        $name = join(' ', splice(@arr2,5));
        ###prt("$diff [$apt] (with $rwycnt runways at [$alat, $alon]) ...\n");
        ###prt("$diff [$icao] [$name] ...\n");
        ###push(@g_aptlist, [$diff, $icao, $name, $alat, $alon]);
        ##push(@g_aptlist, [$diff, $icao, $name, $alat, $alon, -1, 0, 0, 0, $icao, $name, $off, $dist, $az]);
        push(@g_aptlist, [$diff, $icao, $name, $alat, $alon]);
        $totaptcnt++;   # count another AIRPORT
        $add = 0;
        if ($SRCHICAO) {
            $add = 1 if ($name =~ /$apticao/);
        } else {
            if ($SRCHONLL) {
                if (($dlat < $maxlatd) && ($dlon < $maxlond)) {
                    $add = 1;
                }
            } else {
                $add = 1 if ($name =~ /$aptname/i);
            }
        }
        if ($add) {
             $off = near_given_point( $alat, $alon, \$dist, \$az );
             prt("$icao, $name, $alat, $alon, rwycnt $rwycnt - LAST\n") if ($dbg1);
             # push(@aptlist2, [$diff, $icao, $name, $alat, $alon]);
           #                  0=typ, 1=lat, 2=lon, 3=alt, 4=frq, 5-rng, 6-frq2, 7=nid, 8=name, 9=off, 10=dist, 11=az);
           #push(@g_navlist3, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off, $dist, $az]);
             push(@aptlist2, [$diff, $icao, $name, $alat, $alon, -1, 0, 0, 0, $icao, $name, $off, $dist, $az]);
        }
    }
}

sub load_nav_file {
   prt("\n[v9] Loading $navdat file ...\n") if (VERB9());
   mydie("ERROR: Can NOT locate [$navdat]!\n") if ( !( -f $navdat) );
   open NIF, "gzip -d -c $navdat|" or mydie( "ERROR: CAN NOT OPEN $navdat...$!...\n" );
   my @nav_lines = <NIF>;
   close NIF;
    return @nav_lines;
}

sub search_nav {
   my ($typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off);
    my ($alat, $alon);
    my ($dist, $az,$msg);
    my $cnt = 0;
    my @nav_lines = load_nav_file();
   my $nav_cnt = scalar @nav_lines;
   my $ac = scalar @aptlist2;
    $msg = '';
    $msg .= "Search FOR [$g_lat,$g_lon]... ";
    if ($ac == 1) {
         $alat = $aptlist2[0][3];
      $alon = $aptlist2[0][4];
        if ($usekmrange) {
            $msg .= "Use max [$max_range_km] Km from $ac ap at $alat,$alon.";
        } else {
            $msg .= "Use dev [$nmaxlatd,$nmaxlond] from $ac ap at $alat,$alon.";
        }
    } else {
        if ($usekmrange) {
            $msg .= "Use max dist [$max_range_km] Km from $ac apts.";
        } else {
            $msg .= "Use dev [$nmaxlatd,$nmaxlond] from $ac apts.";
        }
    }
    $msg .= " in $nav_cnt NAV lines...";

    prt("$msg\n") if (VERB1());
   my $vcnt = 0;
    my $navs_found = 0;
    my (@arr,$nc,$lnn,$len,$dnvers,$line);
    $lnn = 0;
    $lnn = 0;
    $dnvers = 0;
    $cnt = 0;
   foreach $line (@nav_lines) {
        $cnt++;
      $line = trimall($line);
        $len = length($line);
        $lnn++;
        # 810 Version - data cycle 2009.12, build 20091080, metadata NavXP810
        if ($line =~ /\s+Version\s+/i) {
            if ($line =~ /\s*(\n+)\s+Version\s+/) {
                $nav_file_version = $1;
            }
            $typ = length($line) > 80 ? substr($line,0,80) : $line;
            prt( "[v2] NAVAID: $typ\n" ) if (VERB2());
            $dnvers = 1;
            last;
        }
    }
    $lnn = 0;
    $cnt = scalar @nav_lines;
   prt( "[04] Doing 'center' search... $cnt NAV objects\n") if ($dbg_fa04);
    $cnt = 0;
    $vcnt = 0;
   foreach $line (@nav_lines) {
      $line = trimall($line);
        $len = length($line);
        $lnn++;
        next if ($line =~ /\s+Version\s+/i);
      @arr = split(/ /,$line);
      $nc = scalar @arr;
      $typ = $arr[0];
        # Check for type number in @navset, and set $actnav to name, like VOR, NDB, etc
        $off = 0;
      if ( is_valid_nav($typ) ) {
         $vcnt++;
         $nlat = $arr[1];
         $nlon = $arr[2];
         $nalt = $arr[3];
         $nfrq = $arr[4];
         $nrng = $arr[5];
         $nfrq2 = $arr[6];
         $nid = $arr[7];
         $name = '';
         for (my $i = 8; $i < $nc; $i++) {
            $name .= ' ' if length($name);
            $name .= $arr[$i];
         }
            $off = near_given_point( $nlat, $nlon, \$dist, \$az );
         if ($off) {
                $off = 2;
            prt( "[04] $actnav, $typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name ($off)\n") if ($dbg_fa04);

            #                 0=typ, 1=lat, 2=lon, 3=alt, 4=frq, 5-rng, 6-frq2, 7=nid, 8=name, 9=off, 10=dist, 11=az);
            push(@g_navlist3, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off, $dist, $az]);
                $cnt++;
         }
        }
    }
     prt( "[04] Done 'center' search, $vcnt valid, found $cnt...\n") if ($dbg_fa04);

    $lnn = 0;
    $vcnt = 0;
   foreach $line (@nav_lines) {
      $line = trimall($line);
        $len = length($line);
        $lnn++;
        my ($tmp);
        # 810 Version - data cycle 2009.12, build 20091080, metadata NavXP810
        if ($line =~ /\s+Version\s+/i) {
            if ($line =~ /\s*(\n+)\s+Version\s+/) {
                $nav_file_version = $1;
            }
            $typ = length($line) > 80 ? substr($line,0,80) : $line;
            prt( "[v2] NAVAID: $typ\n" ) if (VERB2() && !$dnvers);
            next;
        }
      ###prt("$line\n");
      @arr = split(/ /,$line);
      # 0   1 (lat)   2 (lon)        3     4   5           6   7  8++
      # 2   38.087769 -077.324919  284   396  25       0.000 APH  A P Hill NDB
      # 3   57.103719  009.995578   57 11670 100       1.000 AAL  Aalborg VORTAC
      # 4   39.980911 -075.877814  660 10850  18     281.662 IMQS 40N 29 ILS-cat-I
      # 4  -09.458922  147.231225  128 11010  18     148.650 IWG  AYPY 14L ILS-cat-I
      # 5   40.034606 -079.023281 2272 10870  18     236.086 ISOZ 2G9 24 LOC
      # 5   67.018506 -050.682072  165 10955  18      61.600 ISF  BGSF 10 LOC
      # 6   39.977294 -075.860275  655 10850  10  300281.205 ---  40N 29 GS
      # 6  -09.432703  147.216444  128 11010  10  302148.785 ---  AYPY 14L GS
      # 7   39.960719 -075.750778  660     0   0     281.205 ---  40N 29 OM
      # 7  -09.376150  147.176867  146     0   0     148.785 JSN  AYPY 14L OM
      # 8  -09.421875  147.208331   91     0   0     148.785 MM   AYPY 14L MM
      # 8  -09.461050  147.232544  146     0   0     328.777 PY   AYPY 32R MM
      # 9   65.609444 -018.052222   32     0   0      22.093 ---  BIAR 01 IM
      # 9   08.425319  004.475597 1126     0   0      49.252 IL   DNIL 05 IM
      # 12 -09.432703  147.216444   11 11010  18       0.000 IWG  AYPY 14L DME-ILS
      # 12 -09.449222  147.226589   11 10950  18       0.000 IBB  AYPY 32R DME-ILS
      $nc = scalar @arr;
      $typ = $arr[0];
        # Check for type number in @navset, and set $actnav to name, like VOR, NDB, etc
      if ( is_valid_nav($typ) ) {
         $vcnt++;
         $nlat = $arr[1];
         $nlon = $arr[2];
         $nalt = $arr[3];
         $nfrq = $arr[4];
         $nrng = $arr[5];
         $nfrq2 = $arr[6];
         $nid = $arr[7];
         $name = '';
         for (my $i = 8; $i < $nc; $i++) {
            $name .= ' ' if length($name);
            $name .= $arr[$i];
         }
         push(@navlist, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name]);
            # Using $nmaxlatd, $nmaxlond, check airports in @aptlist2;
         $off = near_an_airport( $nlat, $nlon, \$dist, \$az );
            $off = near_given_point( $nlat, $nlon, \$dist, \$az ) if (!$off);
         if ($off) {
            prt( "[02] $actnav, $typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name ($off)\n") if ($dbg_fa02);
                #                0     1      2      3      4      5      6       7     8      9     10     11
            push(@navlist2, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off, $dist, $az]);
         }
        #} elsif ($line =~ /^\d+\s+Version\s+-\s+DAFIF\s+/) {
        #    my $ind = index($line,',');
        #    prt( "NAVAID: ".substr($line, 0, (($ind > 0) ? $ind : 50) )."\n" );   # 810 Version - DAFIF ...
        } elsif (($line eq 'I')||($line eq '99')) {
            # ignore these
      } elsif (length($line)) {
            #$typ = $line;
            $typ = length($line) > 80 ? substr($line,0,80) : $line;
            prtw("WARNING: What is this line? [$typ]???\n".
                "from $navdat file ...\n");
        }
   }
    $navs_found = scalar @navlist2;
    if (($navs_found == 0) && $tryharder) {
        my $def_latd = $nmaxlatd;
        my $def_lond = $nmaxlond;
        my $def_dist = $max_range_km;
        while ($navs_found == 0) {
            $nmaxlatd += 0.1;
            $nmaxlond += 0.1;
            $max_range_km += 0.1;
            if ($usekmrange) {
                prt("Expanded to [$max_range_km] Km from $ac airport(s)...\n" );
            } else {
                prt("Expanded to [$nmaxlatd,$nmaxlond] from $ac airport(s)...\n" );
            }
            foreach $line (@nav_lines) {
                $line = trimall($line);
                ###prt("$line\n");
                @arr = split(/ /,$line);
                $nc = scalar @arr;
                $typ = $arr[0];
                # Check for type number in @navset, and set $actnav to name, like VOR, NDB, etc
                if ( is_valid_nav($typ) ) {
                    $nlat = $arr[1];
                    $nlon = $arr[2];
                    $nalt = $arr[3];
                    $nfrq = $arr[4];
                    $nrng = $arr[5];
                    $nfrq2 = $arr[6];
                    $nid = $arr[7];
                    $name = '';
                    for (my $i = 8; $i < $nc; $i++) {
                        $name .= ' ' if length($name);
                        $name .= $arr[$i];
                    }
                    # Using $nmaxlatd, $nmaxlond, check airports in @aptlist2;
                    $off = near_an_airport( $nlat, $nlon, \$dist, \$az );
                    if ($off) {
                        prt( "[02] $actnav, $typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name ($off)\n") if ($dbg_fa02);
                        push(@navlist2, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $off, $dist, $az]);
                    }
                }
            }
            $navs_found = scalar @navlist2;
        }
        prt("Found $navs_found nearby NAVAIDS, ");
        if ($usekmrange) {
            prt("using distance $max_range_km Km...\n" );
        } else {
            prt("using difference $nmaxlatd, $nmaxlond...\n" );
        }
        $nmaxlatd = $def_latd;
        $nmaxlond = $def_lond;
        $max_range_km = $def_dist;
    }
   prt("[v5] Done - Found $navs_found nearby NAVAIDS, of $vcnt searched...\n" ) if (VERB5());
}

# put least first
sub mycmp_ascend_n4 {
   if (${$a}[4] < ${$b}[4]) {
      return -1;
   }
   if (${$a}[4] > ${$b}[4]) {
      return 1;
   }
   return 0;
}

# put least first
sub mycmp_ascend {
   if (${$a}[0] < ${$b}[0]) {
      prt( "-[".${$a}[0]."] < [".${$b}[0]."]\n" ) if $verb3;
      return -1;
   }
   if (${$a}[0] > ${$b}[0]) {
      prt( "+[".${$a}[0]."] < [".${$b}[0]."]\n" ) if $verb3;
      return 1;
   }
   prt( "=[".${$a}[0]."] == [".${$b}[0]."]\n" ) if $verb3;
   return 0;
}

sub mycmp_decend {
   if (${$a}[0] < ${$b}[0]) {
      prt( "+[".${$a}[0]."] < [".${$b}[0]."]\n" ) if $verb3;
      return 1;
   }
   if (${$a}[0] > ${$b}[0]) {
      prt( "-[".${$a}[0]."] < [".${$b}[0]."]\n" ) if $verb3;
      return -1;
   }
   prt( "=[".${$a}[0]."] == [".${$b}[0]."]\n" ) if $verb3;
   return 0;
}

# 0=typ, 1=lat, 2=lon, 3=alt, 4=frq, 5-rng, 6-frq2, 7=nid, 8=name, 9=off, 10=dist, 11=az);
sub mycmp_decend_dist {
   return -1 if (${$a}[10] < ${$b}[10]);
   return 1 if (${$a}[10] > ${$b}[10]);
   return 0;
}

# $dist = $aptlist2[$i][12];
#                 0      1      2      3      4      5   6  7  8  9      10     11    12     13
#push(@aptlist2, [$diff, $icao, $name, $alat, $alon, -1, 0, 0, 0, $icao, $name, $off, $dist, $az]);
sub mycmp_decend_ap_dist {
   return -1 if (${$a}[12] < ${$b}[12]);
   return 1 if (${$a}[12] > ${$b}[12]);
   return 0;
}


##############
### functions
sub trimall {   # version 20061127
   my ($ln) = shift;
   chomp $ln;         # remove CR (\n)
   $ln =~ s/\r$//;      # remove LF (\r)
   $ln =~ s/\t/ /g;   # TAB(s) to a SPACE
   while ($ln =~ /\s\s/) {
      $ln =~ s/\s\s/ /g;   # all double space to SINGLE
   }
   while ($ln =~ /^\s/) {
      $ln = substr($ln,1); # remove all LEADING space
   }
   while ($ln =~ /\s$/) {
      $ln = substr($ln,0, length($ln) - 1); # remove all TRAILING space
   }
   return $ln;
}

# 12/12/2008 - Additional distance calculations
# from 'signs' perl script
# Melchior FRANZ <mfranz # aon : at>
# $Id: signs,v 1.37 2005/06/01 15:53:00 m Exp $

# sub ll2xyz($$) {
sub ll2xyz {
   my $lon = (shift) * $D2R;
   my $lat = (shift) * $D2R;
   my $cosphi = cos $lat;
   my $di = $cosphi * cos $lon;
   my $dj = $cosphi * sin $lon;
   my $dk = sin $lat;
   return ($di, $dj, $dk);
}


# sub xyz2ll($$$) {
sub xyz2ll {
   my ($di, $dj, $dk) = @_;
   my $aux = $di * $di + $dj * $dj;
   my $lat = atan2($dk, sqrt $aux) * $R2D;
   my $lon = atan2($dj, $di) * $R2D;
   return ($lon, $lat);
}

# sub coord_dist_sq($$$$$$) {
sub coord_dist_sq {
   my ($xa, $ya, $za, $xb, $yb, $zb) = @_;
   my $x = $xb - $xa;
   my $y = $yb - $ya;
   my $z = $zb - $za;
   return $x * $x + $y * $y + $z * $z;
}


sub give_help {
   prt( "FLIGHTGEAR AIRPORT SEARCH UTILITY - $VERS\n" );
   prt( "Usage: $pgmname options\n" );
   prt( "Options: A ? anywhere for this help.\n" );
    prt( " --file <file>   (-f) = Load commands from this 'file' of commands...\n");
   prt( " -icao=$apticao           - Search using icao.\n" );
   prt( " -latlon=$g_lat,$g_lon  - Search using latitude, longitude.\n" );
   prt( " -maxout=$max_cnt            - Limit the airport output. A 0 for ALL.\n" );
   prt( " -maxll=$maxlatd,$maxlond       - Maximum difference, when searching ariports using lat,lon.\n" );
   prt( " -name=\"$aptname\"   - Search using airport name. (A -name=. would match all.)\n" );
   prt( " -shownavs (or -s)    - Show NAVAIDS around airport found, if any. " );
    prt( "(Def=". ($SHOWNAVS ? "On" : "Off") . ")\n" );
   prt( " -nmaxll=$nmaxlatd,$nmaxlond      - Maximum difference, when searching NAVAID lat,lon.\n" );
   prt( " -aptdata=$aptdat  - Use a specific AIRPORT data file.\n" );
   prt( " -navdata=$navdat  - Use a specific NAVAID data file.\n" );
    prt( " -range=$max_range_km             - Set Km range when checking for NAVAIDS.\n" );
    prt( " -r                   - Use above range ($max_range_km Km) for searching.\n" );
    prt( " -tryhard (or -t)     - Expand search if no NAVAIDS found in range. " );
    prt( "(Def=". ($tryharder ? "On" : "Off") . ")\n" );
    prt( " --verbosity (-v[nn]) - Increase or set verbosity.\n");
    prt( " --VOR           (-V) - List only VOR (+NDB)\n");
    prt( " --loadlog       (-l) - Load log at end of display.\n");
   mydie( "                                     Happy Searching.\n" );
}

# Ensure argument exists, or die.
sub require_arg {
    my ($arg, @arglist) = @_;
    mydie( "ERROR: no argument given for option '$arg' ...\n" ) if ! @arglist;
}

sub deal_with_verbosity($) {
    my @av = @_;
    my ($arg,$sarg);
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /^-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /^-/);
            if ($sarg =~ /^v/) {
                if ($sarg =~ /^v.*(\n+)$/) {
                    $verbosity = $1;
                } else {
                    while ($sarg =~ /^v/i) {
                        $verbosity++;
                        $sarg = substr($sarg,1)
                    }
                }
                prt( "[v1] Set verbosity to $verbosity\n") if (VERB1());
            }

        }
        shift @av;
    }
}

sub local_strip_both_quotes($) {
    my $txt = shift;
    if ($txt =~ /^'(.+)'$/) {
        return $1;
    }
    if ($txt =~ /^"(.+)"$/) {
        return $1;
    }
    return '' if ($txt eq '""');
    return '' if ($txt eq "''");
    #prt("Stripping [$txt] FAILED\n");
    return $txt;
}


sub load_input_file($$) {
    my ($arg,$file) = @_;
    if (open INF, "<$file") {
        my @lines = <INF>;
        close INF;
        my @carr = ();
        my ($line,@arr,$tmp,$i);
        my $lncnt = scalar @lines;
        for ($i = 0; $i < $lncnt; $i++) {
            $line = $lines[$i];
            $line = trim_all($line);
            next if (length($line) == 0);
            next if ($line =~ /^\#/);
            # load CONTINUATION lines - ends in '\' back-slash
            while (($line =~ /\\$/)&&(($i+1) < $lncnt)) {
                $i++;
                $line =~ s/\\$//;
                $line .= trim_all($lines[$i]);
            }
            @arr = split(/\s/,$line);
            foreach $tmp (@arr) {
                $tmp = local_strip_both_quotes($tmp);
                push(@carr,$tmp);
            }
        }
        $in_input_file++;
        parse_args(@carr);
        $in_input_file--;
    } else {
        pgm_exit(1,"ERROR: Unable to 'open' file [$file]!\n")
    }
}

# set $SRCHICAO on/off
# set $SRCHONLL on/off
sub parse_args {
   my (@av) = @_;
   my (@arr,$arg,$sarg,$lcarg,$ch);
    deal_with_verbosity(@av);
   while(@av) {
      $arg = $av[0]; # shift @av;
        $lcarg = lc($arg);
        $ch = substr($arg,0,1);
        $sarg = $arg;
        $sarg = substr($sarg,1) while ($sarg =~ /^-/);
      if ($arg =~ /\?/) {
         give_help();
        } elsif ($ch eq '-') {
            if ($sarg =~ /^v/) {
                # done verbosity
            } elsif ($sarg =~ /^f/) {
                require_arg(@av);
                shift @av;
                $sarg = $av[0];
                load_input_file($arg,$sarg);
            } elsif ($sarg =~ /^V/) {
                $vor_only = 1;
                prt( "Set VOR (NBD) ONLY flag\n") if (VERB1());
            } elsif (( $sarg =~ /^loadlog$/ )||($sarg =~ /^l$/)) {
                prt("Set load log at end of display.\n") if (VERB1());
                $loadlog = 1;
            } elsif ( $arg =~ /-icao=(.+)/i ) {
                # BY ICAO
                $apticao = $1;
                $SRCHICAO = 1;
                $SRCHONLL = 0;
                $SRCHNAME = 0;
                prt( "Search using ICAO of [$apticao] ...\n" ) if (VERB1());
            } elsif ( $lcarg eq '-icao' ) {
                require_arg(@av);
                shift @av;
                $SRCHICAO = 1;
                $SRCHONLL = 0;
                $SRCHNAME = 0;
                $apticao = $av[0];
                prt( "Search using ICAO of [$apticao] ...\n" ) if (VERB1());

            # BY LAT,LON
            } elsif ( $arg =~ /-latlon=(.+)/i ) {
                $SRCHICAO = 0;
                $SRCHONLL = 1;
                $SRCHNAME = 0;
                @arr = split(',', $1);
                if (scalar @arr == 2) {
                    $g_lat = $arr[0];
                    $g_lon = $arr[1];
                    prt( "Search using LAT,LON of [$g_lat,$g_lon] ...\n" ) if (VERB1());
                } else {
                    # 17/08/2010 - assume lat and lon also split, and try harder
                    $g_lat = $arr[0];
                    require_arg(@av);
                    shift @av;
                    $g_lon = $av[0];
                    if (($g_lat =~ /^(\d|-|\+|\.)+$/) && ($g_lon =~ /^(\d|-|\+|\.)+$/)) {
                        prt( "Search using LAT,LON of [$g_lat,$g_lon] ...\n" ) if (VERB1());
                    } else {
                        mydie( "ERROR: Failed to find lat,lon in [$arg] [$g_lat,$g_lon]...\n" );
                    }
                }
            } elsif ( $lcarg eq '-latlon' ) {
                # set a center LAT,LON
                require_arg(@av);
                shift @av;
                $SRCHICAO = 0;
                $SRCHONLL = 1; # search using lat,lon input...
                $SRCHNAME = 0;
                @arr = split(',', $av[0]);
                if (scalar @arr == 2) {
                    $g_lat = $arr[0];
                    $g_lon = $arr[1];
                    prt( "Search using LAT,LON of [$g_lat,$g_lon] ...\n" ) if (VERB1());
                } else {
                    # 17/08/2010 - assume lat and lon also split, and try harder
                    $g_lat = $arr[0];
                    require_arg(@av);
                    shift @av;
                    $g_lon = $av[0];
                    if (($g_lat =~ /^(\d|-|\+|\.)+$/) && ($g_lon =~ /^(\d|-|\+|\.)+$/)) {
                        prt( "Search using LAT,LON of [$g_lat,$g_lon] ...\n" ) if (VERB1());
                    } else {
                        mydie( "ERROR: Failed to find lat,lon in [$arg] [$g_lat,$g_lon]...\n" );
                    }
                }
                $got_center_latlon = 1; # given *** CENTER OF WORLD *** position -latlon lat lon
            # By NAME
            } elsif ( $arg =~ /-name=(.+)/i ) {
                $aptname = $1;
                $SRCHICAO = 0;
                $SRCHONLL = 0;
                $SRCHNAME = 1;
                prt( "Search using NAME of [$aptname] ...\n" ) if (VERB1());
            } elsif ( $lcarg eq '-name' ) {
                require_arg(@av);
                shift @av;
                $SRCHICAO = 0;
                $SRCHONLL = 0;
                $SRCHNAME = 1;
                $aptname = $av[0];
                prt( "Search using NAME of [$aptname] ...\n" ) if (VERB1());
            } elsif ( $arg =~ /^-loadlog$/i ) {
                $loadlog = 1;
                prt( "Load log into wordpad.\n" ) if (VERB1());
            } elsif ( $arg =~ /^-shownavs$/i ) {
                $SHOWNAVS = 1;
                prt( "And show NAVAIDS around airport, if any.\n" ) if (VERB1());
            } elsif ( $arg =~ /^-s$/i ) {
                $SHOWNAVS = 1;
                prt( "And show NAVAIDS around airport, if any.\n" ) if (VERB1());
            } elsif ( $arg =~ /-maxll=(.+)/i ) {
                @arr = split(',', $1);
                if (scalar @arr == 2) {
                    $maxlatd = $arr[0];
                    $maxlond = $arr[1];
                    prt( "Search maximum difference LAT,LON of [$maxlatd,$maxlond] ...\n" ) if (VERB1());
                } else {
                    # 17/08/2010 - assume lat and lon also split, and try harder
                    $maxlatd = $arr[0];
                    require_arg(@av);
                    shift @av;
                    $maxlond = $av[0];
                    if (($maxlatd =~ /^(\d|-|\+|\.)+$/) && ($maxlond =~ /^(\d|-|\+|\.)+$/)) {
                        prt( "Search maximum difference LAT,LON of [$maxlatd,$maxlond] ...\n" ) if (VERB1());
                    } else {
                        mydie( "ERROR: Failed to find maximum lat,lon difference in [$arg] [$maxlatd,$maxlond]...\n" );
                    }
                }
            } elsif ( $lcarg eq '-maxll' ) {
                require_arg(@av);
                shift @av;
                @arr = split(',', $av[0]);
                if (scalar @arr == 2) {
                    $maxlatd = $arr[0];
                    $maxlond = $arr[1];
                    prt( "Search maximum difference LAT,LON of [$maxlatd,$maxlond] ...\n" ) if (VERB1());
                } else {
                    # 17/08/2010 - assume lat and lon also split, and try harder
                    $maxlatd = $arr[0];
                    require_arg(@av);
                    shift @av;
                    $maxlond = $av[0];
                    if (($maxlatd =~ /^(\d|-|\+|\.)+$/) && ($maxlond =~ /^(\d|-|\+|\.)+$/)) {
                        prt( "Search maximum difference LAT,LON of [$maxlatd,$maxlond] ...\n" ) if (VERB1());
                    } else {
                        mydie( "ERROR: Failed to find maximum lat,lon difference in [$arg] [$maxlatd,$maxlond]...\n" );
                    }
                }
            } elsif ( $arg =~ /-nmaxll=(.+)/i ) {
                @arr = split(',', $1);
                if (scalar @arr == 2) {
                    $nmaxlatd = $arr[0];
                    $nmaxlond = $arr[1];
                    prt( "Search maximum NAV difference LAT,LON of [$nmaxlatd,$nmaxlond] ...\n" ) if (VERB1());
                } else {
                    # 17/08/2010 - assume lat and lon also split, and try harder
                    $nmaxlatd = $arr[0];
                    require_arg(@av);
                    shift @av;
                    $nmaxlond = $av[0];
                    if (($nmaxlatd =~ /^(\d|-|\+|\.)+$/) && ($nmaxlond =~ /^(\d|-|\+|\.)+$/)) {
                        prt( "Search maximum NAV difference LAT,LON of [$nmaxlatd,$nmaxlond] ...\n" ) if (VERB1());
                    } else {
                        mydie( "ERROR: Failed to find maximum lat,lon NAV difference in [$arg] [$nmaxlatd,$nmaxlond]...\n" );
                    }
                }
            } elsif ( $lcarg eq '-nmaxll' ) {
                require_arg(@av);
                shift @av;
                @arr = split(',', $av[0]);
                if (scalar @arr == 2) {
                    $nmaxlatd = $arr[0];
                    $nmaxlond = $arr[1];
                    prt( "Search maximum NAV difference LAT,LON of [$nmaxlatd,$nmaxlond] ...\n" ) if (VERB1());
                } else {
                    # 17/08/2010 - assume lat and lon also split, and try harder
                    $nmaxlatd = $arr[0];
                    require_arg(@av);
                    shift @av;
                    $nmaxlond = $av[0];
                    if (($nmaxlatd =~ /^(\d|-|\+|\.)+$/) && ($nmaxlond =~ /^(\d|-|\+|\.)+$/)) {
                        prt( "Search maximum NAV difference LAT,LON of [$nmaxlatd,$nmaxlond] ...\n" ) if (VERB1());
                    } else {
                        mydie( "ERROR: Failed to find maximum lat,lon NAV difference in [$arg] [$nmaxlatd,$nmaxlond]...\n" );
                    }
                }
            } elsif ( $arg =~ /-aptdata=(.+)/i ) {
                $aptdat = $1;   # the airports data file
                prt( "Using AIRPORT data file [$aptdat] ...\n" ) if (VERB1());
            } elsif ( $lcarg eq '-aptdata' ) {
                require_arg(@av);
                shift @av;
                $aptdat = $av[0];   # the airports data file
                prt( "Using AIRPORT data file [$aptdat] ...\n" ) if (VERB1());
            } elsif ( $arg =~ /-navdata=(.+)/i ) {
                $navdat = $1;
                prt( "Using NAVAID data file [$navdat] ...\n" ) if (VERB1());
            } elsif ( $lcarg eq '-navdata' ) {
                require_arg(@av);
                shift @av;
                $navdat = $av[0];
                prt( "Using NAVAID data file [$navdat] ...\n" ) if (VERB1());
            } elsif ( $arg =~ /-maxout=(.+)/i ) {
                $max_cnt = $1;
                prt( "Airport output limited to $max_cnt. A zero (0), for no limit\n" ) if (VERB1());
            } elsif ( $lcarg eq '-maxout' ) {
                require_arg(@av);
                shift @av;
                $max_cnt = $av[0];
                prt( "Airport output limited to $max_cnt. A zero (0), for no limit\n" ) if (VERB1());
            } elsif ( $arg =~ /-range=(.+)/i ) {
                $max_range_km = $1;
                prt( "Navaid search using $max_range_km Km. A zero (0), for no limit\n" ) if (VERB1());
                $usekmrange = 1;
                prt( "Navaid search using $max_range_km Km.\n" ) if (VERB1());
            } elsif ( $lcarg eq '-range' ) {
                require_arg(@av);
                shift @av;
                $max_range_km = $av[0];
                prt( "Navaid search using $max_range_km Km. A zero (0), for no limit\n" ) if (VERB1());
                $usekmrange = 1;
                prt( "Navaid search using $max_range_km Km.\n" ) if (VERB1());
            } elsif ( $lcarg eq '-r' ) {
                $usekmrange = 1;
                prt( "Navaid search using $max_range_km Km.\n" ) if (VERB1());
            } elsif (( $lcarg eq '-tryhard' )||( $lcarg eq '-t' )) {
                $tryharder = 1;  # Expand the search for NAVAID, until at least 1 found
                prt( "Navaid search 'tryharder' set.\n" ) if (VERB1());
            } else {
                mydie( "ERROR: Unknown argument [$arg]. Try ? for HELP ...\n" );
            }
        } else {
            # ASSUME AN AIRPORT NAME
            $SRCHICAO = 0;
            $SRCHONLL = 0;
            $SRCHNAME = 1;
            $aptname = $av[0];
            prt( "Search using NAME of [$aptname] ...\n" ) if (VERB1());
        }
      shift @av;
   }

    if ( ! $in_input_file ) {
        # NOT in an INPUT file
        # *** ONLY FOR TESTING ***
        if ($test_name) {
            $SRCHICAO = 0;
            $SRCHONLL = 0;
            $SRCHNAME = 1;
            $SHOWNAVS = 1;
            $usekmrange = 1;
            $max_range_km = 5;
            $aptname = $def_name;
        } elsif ($test_ll) {
            $g_lat = $def_lat;
            $g_lon = $def_lon;
            $maxlatd = 0.1;
            $maxlond = 0.1;
            $SRCHICAO = 0;
            $SRCHONLL = 1;
            $SRCHNAME = 0;
        } elsif ($test_icao) {
            $SRCHICAO = 1;
            $SRCHONLL = 0;
            $SRCHNAME = 0;
            $SHOWNAVS = 1;
            $apticao = $def_icao;
            # now have $tryharder to expand this, if NO NAVAIDS found
            $tryharder = 1;
            $usekmrange = 1;
        }


        if ( ($SRCHICAO == 0) && ($SRCHONLL == 0) && ($SRCHNAME == 0) ) {
            prt( "ERROR: No valid command action found, like -\n" );
            prt( "By ICAO '-icao=KSFO', by LAT/LON '-latlon=21,-122', or '-name=something'!\n" );
            give_help();
        }
    }

}

# eof - findap02.pl

index -|- top

checked by tidy  Valid HTML 4.01 Transitional