#!/usr/bin/perl -w # NAME: flightplan.pl # AIM: Given a starting and ending airport, try to develop a flight plan # Method: Construct a bounding box # have a bgn_lat,bgn_lon,bgn_alt, and an end_lat,end_lon,end_alt # Have a FULL array of ALL airports loaded # Have a FULL array of ALL navaids loaded # need to construct a quadrilateral, from bgn towards end, # min max # -----|----------| # / | need | # / | navaids | # B -> E | in this | # \ | box | # \ | | # -----|----------| # # 29/09/2014 geoff mclane http://geoffair.net/mperl use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Time::HiRes qw( gettimeofday tv_interval ); use Cwd; my $os = $^O; my $perl_dir = '/home/geoff/bin'; my $PATH_SEP = '/'; my $temp_dir = '/tmp'; if ($os =~ /win/i) { $perl_dir = 'C:\GTools\perl'; $temp_dir = $perl_dir; $PATH_SEP = "\\"; } unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n"; require 'fg_wsg84.pl' or die "Unable to load fg_wsg84.pl ...\n"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt"; my $out_xg = $temp_dir.$PATH_SEP."tempout.xg"; my $out_xml = $temp_dir.$PATH_SEP."tempout.xml"; open_log($outfile); my $t0 = [gettimeofday]; # user variables my $VERS = "0.0.3 2014-11-09"; ###my $VERS = "0.0.2 2014-09-26"; my $load_log = 0; my $in_file = ''; my $verbosity = 0; my $out_file = ''; my $track_color = 'green'; my $runway_color = 'red'; my $bbox_color = 'gray'; my $stdalt = 5000; # feet my $bgn_icao = ''; my $end_icao = ''; my ($bgn_lat,$bgn_lon,$bgn_alt); my ($end_lat,$end_lon,$end_alt); my ($bgn_az,$tot_dist); # offset into @g_aptlist my $bgn_off = -1; my $end_off = -1; my ($actnav); ########################################################################### ### This should depends of the aircraft type AND VFR or IFR ########################################################################### my $fp_type = 'VFR'; my $min_dist = 40; # nm my $max_dist = 100; # nm my $max_max_dist = 400; # 350; # 300; # 250; # 200; # nm my $deg_spread = 10; my $max_deg_spread = 46; # 40; # 30; my $extension_nm = 40; #nm ########################################################################### sub set_defs() { # YGIL 1050 ft -31.69684576,148.63677076 Gilgandra, 345 km on 137, to # YSSY 21 ft -33.94927300,151.18134683 Sydney Intl $bgn_lat = -31.69684576; $bgn_lon = 148.63677076; $bgn_alt = 1050; $end_lat = -33.94927300; $end_lon = 151.18134683; $end_alt = 21; $bgn_az = 137; $tot_dist = 345000; prt("YGIL 1050 ft -31.69684576,148.63677076 Gilgandra, 345 km on 137, to\n"); prt("YSSY 21 ft -33.94927300,151.18134683 Sydney Intl\n"); } # ============================================================================= # This NEEDS to be adjusted to YOUR particular default location of these files. my $CDATROOT="F:/fgdata"; # 20140127 - 3.1 if (-d "X:/fgdata") { $CDATROOT = "X:/fgdata"; } my $FGROOT = (exists $ENV{'FG_ROOT'})? $ENV{'FG_ROOT'} : $CDATROOT; my $APTFILE = "$FGROOT/Airports/apt.dat.gz"; # the airports data file my $NAVFILE = "$FGROOT/Navaids/nav.dat.gz"; # the NAV, NDB, etc. data file # add these files my $FIXFILE = "$FGROOT/Navaids/fix.dat.gz"; # the FIX data file my $AWYFILE = "$FGROOT/Navaids/awy.dat.gz"; # Airways data my $g_aptdat = $APTFILE; my $g_navdat = $NAVFILE; my $g_fixfile = $FIXFILE; my $g_awyfile = $AWYFILE; # ### DEBUG ### my $debug_on = 0; my $def_bgn = 'YPPH'; # Perth ###my $def_bgn = 'YGIL'; my $def_end = 'YSSY'; # Sydney #my $def_end = 'YSDU'; ### program variables my @warnings = (); my $cwd = cwd(); sub VERB1() { return $verbosity >= 1; } sub VERB2() { return $verbosity >= 2; } sub VERB5() { return $verbosity >= 5; } sub VERB9() { return $verbosity >= 9; } sub show_warnings($) { my ($val) = @_; if (@warnings) { prt( "\nGot ".scalar @warnings." WARNINGS...\n" ); foreach my $itm (@warnings) { prt("$itm\n"); } prt("\n"); } else { prt( "\nNo warnings issued.\n\n" ) if (VERB9()); } } sub pgm_exit($$) { my ($val,$msg) = @_; if (length($msg)) { $msg .= "\n" if (!($msg =~ /\n$/)); prt($msg); } show_warnings($val); close_log($outfile,$load_log); exit($val); } sub prtw($) { my ($tx) = shift; $tx =~ s/\n$//; prt("$tx\n"); push(@warnings,$tx); } sub process_in_file($) { my ($inf) = @_; if (! open INF, "<$inf") { pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); } my @lines = ; close INF; my $lncnt = scalar @lines; prt("Processing $lncnt lines, from [$inf]...\n"); my ($line,$inc,$lnn); $lnn = 0; foreach $line (@lines) { chomp $line; $lnn++; if ($line =~ /\s*#\s*include\s+(.+)$/) { $inc = $1; prt("$lnn: $inc\n"); } } } my @apt_lines = (); my @g_naptlist = (); my @g_aptlist = (); my @g_nav_lines = (); my @g_navlist = (); # 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 MM IM VDME NDME ); # VDME - VOR (VHF (Very High Frequency) Omni-directional Radio-range) with Distance Measuring Equipment - usually belongs to Government & Military. # NDB - European from 280 kHz to 530 kHz # with a gap between 495 and 505 kHz because 500 kHz was the international maritime distress (emergency) frequency. sub in_world_range($$) { my ($lt,$ln) = @_; return 0 if ($lt < -90); return 0 if ($lt > 90); return 0 if ($ln < -180); return 0 if ($ln > 180); return 1; } sub load_nav_data() { my $t1 = [gettimeofday]; prt("\n[v9] Loading $g_navdat file ...\n") if (VERB9()); mydie("ERROR: Can NOT locate [$g_navdat]!\n") if ( !( -f $g_navdat) ); open NIF, "gzip -d -c $g_navdat|" or mydie( "ERROR: CAN NOT OPEN $g_navdat...$!...\n" ); @g_nav_lines = ; close NIF; my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("[v9] Got ".scalar @g_nav_lines." lines in $elap...\n") if (VERB9()); } sub load_apt_data() { my ($cnt,$msg); prt("[v9] Loading $g_aptdat file... moment... 15-20 secs...\n") if (VERB9()); pgm_exit(1,"ERROR: Can NOT locate $g_aptdat ...$!...\n") if ( !( -f $g_aptdat) ); open IF, "gzip -d -c $g_aptdat|" or mydie( "ERROR: CAN NOT OPEN $g_aptdat...$!...\n" ); @apt_lines = ; close IF; $cnt = scalar @apt_lines; my $elapsed = tv_interval ( $t0, [gettimeofday]); $elapsed = secs_HHMMSS($elapsed); prt("[v9] Done in $elapsed, got $cnt lines to scan... 20-30 secs\n") if (VERB9()); } 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 get_nav_type($) { my ($t) = shift; my $txt = "$t"; my $cnt = 0; foreach my $n (@navset) { if ($n eq $txt) { $txt = $navtypes[$cnt]; last; } $cnt++; } $txt .= ' ' while (length($txt) < 4); return $txt; } sub search_nav_lines() { my $rnls = \@g_nav_lines; my $nav_cnt = scalar @{$rnls}; prt("Processing $nav_cnt navaid records, getting distances to $bgn_lat,$bgn_lon and $end_lat,$end_lon...\n"); my ($ln,$line,$len,$lnn,@arr,$typ,$nc,$i,$res); my ($nlat,$nlon,$nalt,$nfrq,$nrng,$nfrq2,$nid,$name,$km,$az); my ($dist1,$az11,$az12); my ($dist2,$az21,$az22); for ($ln = 0; $ln < $nav_cnt; $ln++) { $lnn = $ln + 1; $line = ${$rnls}[$ln]; $line = trim_all($line); $len = length($line); next if ($line =~ /\s+Version\s+/i); next if ($line =~ /^I/); next if ($len == 0); # 0 1 (lat) 2 (lon) 3(alt) 4(feq) 5(rng) 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 @arr = split(/\s+/,$line); $nc = scalar @arr; $typ = $arr[0]; last if ($typ == 99); if ($nc < 8) { prt("Type: [$typ] - Handle this line [$line] - count = $nc...\n"); pgm_exit(1,"ERROR: FIX ME FIRST!\n"); } 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 ($i = 8; $i < $nc; $i++) { $name .= ' ' if length($name); $name .= $arr[$i]; } $res = fg_geo_inverse_wgs_84 ($bgn_lat,$bgn_lon,$nlat,$nlon,\$az11,\$az12,\$dist1); $res = fg_geo_inverse_wgs_84 ($end_lat,$end_lon,$nlat,$nlon,\$az21,\$az22,\$dist2); #$km = $dist / 1000; #$km = (int(($km + 0.05) * 10) / 10); #$az = (int(($az1 + 0.05) * 10) / 10); #prt( "[v5] $actnav, $typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $km, $az\n") if (VERB5()); # 0=typ,1=lat, 2=lon, 3=alt, 4=frq, 5-rng, 6-frq2, 7=nid,8=name,9=dist,10=az1,11=az2 push(@g_navlist, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $dist1, $az11, $dist2, $az21] ); } else { pgm_exit(1,"ERROR: FIX ME! Unknown type [$line]\n"); } } $nc = scalar @g_navlist; prt("Loaded $nc navaids... from $g_navdat\n"); } sub load_all_navaids() { my $t1 = [gettimeofday]; load_nav_data(); search_nav_lines(); my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("Loaded full navaid array in $elap\n"); } sub find_airports() { my ($line,$len,$type,@arr,@arr2); my ($trwycnt,$version); my ($alat,$alon,$aalt,$actl,$abld,$icao,$name); my ($rlat,$rlon,$rwyt,$add); my ($rlat1,$rlon1,$rlat2,$rlon2); my ($ftyp,$cfrq,$frqn); my $rwycnt = 0; my $wwcnt = 0; my $helicnt = 0; my $lncnt = 0; my @line_array = (); my $glat = 0; my $glon = 0; my $apt = ''; my $totaptcnt = 0; my @runways = (); # clear RUNWAY list my @waterways = (); # clear RUNWAY list my @heliways = (); # clear RUNWAY list my @freqs = (); # clear frequencies my $fndcnt = 0; foreach $line (@apt_lines) { $lncnt++; $line = trim_all($line); $len = length($line); next if ($len == 0); next if ($line =~ /^I/); @arr = split(/\s+/,$line); if ($line =~ /^\d+\s+Version\s+/) { # my $ind = index($line,','); $version = $arr[0]; $len = index($line,','); $len = 80 if ($len <= 0); prt(substr($line,0,$len)." ($version) file: $g_aptdat\n"); next; } ###prt("$line\n"); push(@line_array,$line); $type = $arr[0]; # if 1=Airport, 16=SeaPlane, 17=Heliport if (($type == 1)||($type == 16)||($type == 17)) { # start with 1, 16, 17 # 0 1 2 3 4 # 17 126 0 0 EH0001 [H] VU medisch centrum # ID ALT C B NAME++ $trwycnt = $rwycnt; $trwycnt += $wwcnt; $trwycnt += $helicnt; if (length($apt) && ($trwycnt > 0)) { # average position $alat = $glat / $trwycnt; $alon = $glon / $trwycnt; @arr2 = split(/\s+/,$apt); # split airport line $aalt = $arr2[1]; # Airport (general) ALTITUDE AMSL $actl = $arr2[2]; # control tower $abld = $arr2[3]; # buildings $icao = $arr2[4]; # ICAO $name = join(' ', splice(@arr2,5)); # Name my @ra = @runways; my @wa = @waterways; my @ha = @heliways; my @fa = @freqs; if (($icao eq $bgn_icao)||($icao eq $end_icao)) { # 0 1 2 3 4 5 6 7 8 push(@g_aptlist, [$icao, $name, $alat, $alon, $aalt, \@ra, \@wa, \@ha, \@fa ]); $fndcnt++; # show_frequencies(\@fa); } else { # 0 1 2 3 4 5 6 7 8 push(@g_naptlist, [$icao, $name, $alat, $alon, $aalt, \@ra, \@wa, \@ha, \@fa ]); } } @line_array = (); # clear ALL lines of this AIRPORT push(@line_array,$line); $apt = $line; $rwycnt = 0; $wwcnt = 0; $helicnt = 0; @runways = (); # clear RUNWAY list @waterways = (); # clear RUNWAY list @heliways = (); # clear RUNWAY list @freqs = (); # clear frequencies $glat = 0; $glon = 0; $totaptcnt++; # count another AIRPORT ###} elsif ($line =~ /^$rln\s+/) { } elsif ($type == 10) { # 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]; # text 'xxx'=taxiway, 'H1x'=heleport, else a runway ###prt( "$line [$rlat, $rlon]\n" ); if ( $rwyt ne "xxx" ) { # $rwyt =~ s/x//g; # remove trailing 'x' $glat += $rlat; $glon += $rlon; $rwycnt++; push(@runways, \@arr); } ###} elsif ($line =~ /^5(\d+)\s+/) { } elsif ( ($type >= 50) && ($type <= 56) ) { # frequencies # 50 12775 ATIS $ftyp = $type - 50; $cfrq = $arr[1]; $frqn = $arr[2]; $add = 0; if ($ftyp == 0) { $add = 1; # ATIS } elsif ($ftyp == 1) { $add = 1; # Unicom } elsif ($ftyp == 2) { $add = 1; # clearance } elsif ($ftyp == 3) { $add = 1; # ground } elsif ($ftyp == 4) { $add = 1; # tower } elsif ($ftyp == 5) { $add = 1; # approach } elsif ($ftyp == 6) { $add = 1; # departure } else { pgm_exit(1,"Unknown [$line]\n"); } if ($add) { my @fa3 = @arr; push(@freqs, \@fa3); # save the freq array } else { pgm_exit(1, "WHAT IS THIS [5$ftyp $cfrq $frqn] [$line]\n FIX ME!!!"); } } elsif ($type == 14) { # tower location } elsif ($type == 15) { # ramp startup } elsif ($type == 18) { # Airport light beacon } elsif ($type == 19) { # Airport windsock # ============================================================================= # 20140110 - Switch to LATEST git fgdata - IE 1000 Version - data cycle 2013.10 # So must ADD all the NEW 'types', just like x-plane } elsif ($type == 20) { # 20 22.32152700 114.19750500 224.10 0 3 {@Y,^l}31-13{^r} } elsif ($type == 21) { # 21 22.31928000 114.19800800 3 134.09 3.10 13 PAPI-4R } elsif ($type == 100) { # See full version 1000 specs below # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 100 29.87 3 0 0.00 1 2 1 16 43.91080605 004.90321905 0.00 0.00 2 0 0 0 34 43.90662331 004.90428974 0.00 0.00 2 0 0 0 $rlat1 = $arr[9]; # $of_lat1 $rlon1 = $arr[10]; # $of_lon1 $rlat2 = $arr[18]; # $of_lat2 $rlon2 = $arr[19]; # $of_lon2 $rlat = ($rlat1 + $rlat2) / 2; $rlon = ($rlon1 + $rlon2) / 2; ###prt( "$line [$rlat, $rlon]\n" ); $glat += $rlat; $glon += $rlon; my @a2 = @arr; push(@runways, \@a2); $rwycnt++; } elsif ($type == 101) { # Water runways # 0 1 2 3 4 5 6 7 8 # 101 243.84 0 16 29.27763293 -089.35826258 34 29.26458929 -089.35340410 # 101 22.86 0 07 29.12988952 -089.39561501 25 29.13389936 -089.38060001 # prt("$.: $line\n"); $rlat1 = $arr[4]; $rlon1 = $arr[5]; $rlat2 = $arr[7]; $rlon2 = $arr[8]; $rlat = sprintf("%.8f",(($rlat1 + $rlat2) / 2)); $rlon = sprintf("%.8f",(($rlon1 + $rlon2) / 2)); if (!in_world_range($rlat,$rlon)) { prtw( "WARNING: $.: $line [$rlat, $rlon] NOT IN WORLD\n" ); next; } $glat += $rlat; $glon += $rlon; my @a2 = @arr; push(@waterways, \@a2); $wwcnt++; } elsif ($type == 102) { # Heliport # my $heli = '102'; # Helipad # 0 1 2 3 4 5 6 7 8 9 10 11 # 102 H2 52.48160046 013.39580674 355.00 18.90 18.90 2 0 0 0.00 0 # 102 H3 52.48071507 013.39937648 2.64 13.11 13.11 1 0 0 0.00 0 # prt("$.: $line\n"); $rlat = sprintf("%.8f",$arr[2]); $rlon = sprintf("%.8f",$arr[3]); if (!in_world_range($rlat,$rlon)) { prtw( "WARNING: $.: $line [$rlat, $rlon] NOT IN WORLD\n" ); next; } $glat += $rlat; $glon += $rlon; my @a2 = @arr; push(@heliways, \@a2); $helicnt++; } elsif ($type == 110) { # 110 2 0.00 134.10 runway sholder } elsif ($type == 111) { # 111 22.30419700 114.21613100 } elsif ($type == 112) { # 112 22.30449500 114.21644400 22.30480900 114.21677000 51 102 } elsif ($type == 113) { # 113 22.30370300 114.21561700 } elsif ($type == 114) { # 114 43.29914799 -008.38013558 43.29965322 -008.37970933 } elsif ($type == 115) { # 115 22.31009400 114.21038500 } elsif ($type == 116) { # 116 43.30240028 -008.37799316 43.30271076 -008.37878407 } elsif ($type == 120) { # 120 hold lines W A13 } elsif ($type == 130) { # 130 Airport Boundary } elsif ($type == 1000) { # 1000 Northerly flow } elsif ($type == 1001) { # 1001 KGRB 270 020 999 } elsif ($type == 1002) { # 1002 KGRB 0 } elsif ($type == 1003) { # 1003 KGRB 0 } elsif ($type == 1004) { # 1004 0000 2400 } elsif ($type == 1100) { # 1100 36 12654 all heavy|jets|turboprops|props 000360 000360 Northerly } elsif ($type == 1101) { # 1101 36 left } elsif ($type == 1200) { # ???? } elsif ($type == 1201) { # 1201 42.75457409 -073.80880021 both 2110 _start } elsif ($type == 1202) { # 1202 2110 2112 twoway taxiway } elsif ($type == 1204) { # 1204 arrival 01,19 } elsif ($type == 1300) { # 1300 30.32875704 -009.41140596 323.85 misc jets|props Ramp # =============================================================================== } elsif ($type == 99) { ### } elsif ($line =~ /^$lastln\s?/) { # 99, followed by space, count 0 or more ... prt( "Reached END OF FILE ... \n" ) if (VERB9()); last; } else { my $cnt = scalar @apt_lines; my $elapsed = tv_interval ( $t0, [gettimeofday]); $elapsed = secs_HHMMSS($elapsed); prt("FIX ME - LINE UNCASED $type - Line ".get_nn($lncnt)." of ".get_nn($cnt)." - $elapsed\n"); prt("$line\n"); pgm_exit(1,""); } } } sub process_inputs() { load_apt_data(); my $t1 = [gettimeofday]; find_airports(); my $max = scalar @g_aptlist; my $acnt = scalar @g_naptlist; my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("From $acnt airports, found $max in $elap...\n"); my ($ra); # 0 1 2 3 4 5 6 7 8 #push(@g_naptlist, [$icao, $name, $alat, $alon, $aalt, \@ra, \@wa, \@ha, \@fa ]); my ($i,$rlat,$rlon,$calt); my ($icao1,$name1,$alat1,$alon1,$aalt1,$rra1,$rwa1,$rha1,$rfa1); my ($icao2,$name2,$alat2,$alon2,$aalt2,$rra2,$rwa2,$rha2,$rfa2); my ($dist,$az1,$az2,$s,$ret); for ($i = 0; $i < $max; $i++) { $ra = $g_aptlist[$i]; $icao1 = ${$ra}[0]; if ($icao1 eq $bgn_icao) { $bgn_off = $i; } elsif ($icao1 eq $end_icao) { $end_off = $i; } } $ret = 0; if ($bgn_off == -1) { prt("icao $bgn_icao NOT FOUND! "); $ret++; } if ($end_off == -1) { prt("icao $end_icao NOT FOUND! "); $ret++; } if ($ret > 0) { prt("FAILED!\n"); return; } $ra = $g_aptlist[$bgn_off]; $icao1 = ${$ra}[0]; $name1 = ${$ra}[1]; $alat1 = ${$ra}[2]; $alon1 = ${$ra}[3]; $aalt1 = ${$ra}[4]; $rra1 = ${$ra}[5]; $rwa1 = ${$ra}[6]; $rha1 = ${$ra}[7]; $rfa1 = ${$ra}[8]; $ra = $g_aptlist[$end_off]; $icao2 = ${$ra}[0]; $name2 = ${$ra}[1]; $alat2 = ${$ra}[2]; $alon2 = ${$ra}[3]; $aalt2 = ${$ra}[4]; $rra2 = ${$ra}[5]; $rwa2 = ${$ra}[6]; $rha2 = ${$ra}[7]; $rfa2 = ${$ra}[8]; $bgn_lat = $alat1; $bgn_lon = $alon1; $bgn_alt = $aalt1; $end_lat = $alat2; $end_lon = $alon2; $end_alt = $aalt2; $ret = fg_geo_inverse_wgs_84($bgn_lat, $bgn_lon, $end_lat, $end_lon, \$az1, \$az2, \$s); $bgn_az = $az1; $tot_dist = $s; # just for display $rlat = sprintf("%.8f",$alat1); $rlon = sprintf("%.8f",$alon1); $calt = sprintf("%5d",$aalt1). " ft"; #$ret = fg_geo_inverse_wgs_84($alat1, $alon1, $alat2, $alon2, \$az1, \$az2, \$s); $az2 = int( $az1 + 0.5 ); $dist = int( ($s + 0.5) / 1000 )." km"; prt("$icao1 $calt $rlat,$rlon $name1, $dist on $az2, to\n"); $rlat = sprintf("%.8f",$alat2); $rlon = sprintf("%.8f",$alon2); $calt = sprintf("%5d",$aalt2). " ft"; prt("$icao2 $calt $rlat,$rlon $name2\n"); } # FLight Plan # # US FCC Type # 1. Type - VFR (I), IFR (V), DVFR - mixed Y - init IFR, Z - init VFR # Type of flight - S=Sceduled, N=Non-sceduled, G=General Aviation, M=Militry, X=Other? # 2. Aircraft - IDENT # 3. Aircraft Type / Special Equipment: H=Heavy (136K kg or more), M=Medium (7K kg +), L-Light (<7K kg) # Radio communication, navigation and approach aid equipment and capabilities # N=No COM/NAV/approach, S=standard COM/NAV/Approach + A=GBAS landing system, B=LPV (APV with SBAS) # C=Loran, D=DME, E1=FMC WPR ACARS, E2=D-FIS ACARS, E3=PDC ACARS, F=ADF, G=GNSS, # H=HF RTF, I=Intertial Navigation, J1=CPDLC ATN VDL Mode 2, J2=CPDLC FANS 1/A HFDL, # J3=CPDLC FANS 1/A VDL Mode A, J4=CPDLC FANS 1/A VDL Mode 2, J5=CPDLC FANS 1/A SATCOM(INMARSAT), # J6=CPDLC FANS 1/A SATCOM (MTSAT), J7=CPDLC FANS 1/A SATCOM (Iridium), K=MLS, L=ILS, # M1=ATC RTF SATCOM (INMARSAT), M2=ATC RTF (MTSAT), M3=ATC RTF (Iridium), O=VOR P1�P9 Reserved for RCP # R=PBN approved, S=VHF RTF, VOR, and ILS, T=TACAN, U=UHF RTF, V=VHF RTF, W=RVSM approved, X=MNPS approved, # Y=VHF with 8.33 kHz channel spacing capability, Z=Other equipment with COM/, NAV/ and/or DAT/, as appropriate. # 4. True Airspeed - KTS # 5. Departure Point - SID, ICAO, ALT # 6. Departure Time - Zulu - Proposed/Actual # 7. Crusing Altitude - feet or FL - Flight level, expressed as F followed by 3 figures (for example, F085; F330), or # Standard Metric Level in tens of meters, expressed as S followed by 4 figures (for example, S1130), or # Altitude in hundreds of feet, expressed as A followed by 3 figures (for example, A045; A100), or # Altitude in tens of meters, expressed as M followed by 4 figures (for example, M0840), or # for uncontrolled VFR flights, the letters VFR. # 8. ROUTE OF FLIGHT - Each waypoint # The identification of the significant point, followed by the bearing from the point in the form # of 3 figures giving degrees magnetic, followed by the distance from the point in the form of 3 # figures expressing nautical miles. For example, a point 180 magnetic at a distance of 40 nautical # miles from VOR DUB should be expressed as DUB180040. # 9. Destination - STAR, ICAO, ALT #10. Est. Time Enroute - HH:MM #11. Remarks #12. Fuel on Board - in HH:MM #13. Alternate Airports #14. Pilot - Name, address, telephone #15. Number on board: #16. Color of aircraft # sub show_airport($) { my $ra = shift; my ($icao, $name, $alat, $alon, $aalt, $rrwa, $wa, $ha, $fa); $icao = ${$ra}[0]; $name = ${$ra}[1]; $alat = ${$ra}[2]; $alon = ${$ra}[3]; $aalt = ${$ra}[4]; $rrwa = ${$ra}[5]; $wa = ${$ra}[6]; $ha = ${$ra}[7]; $fa = ${$ra}[0]; # for display $alon = sprintf("%.8f",$alon); $alat = sprintf("%.8f",$alat); $aalt = sprintf("%5d",$aalt)." ft"; prt("$icao $alat,$alon,$aalt $name\n"); } #/** Feet to Meters */ my $FEET_TO_METER = 0.3048; # offset 10 in runway array my %runway_surface = ( 1 => 'Asphalt', 2 => 'Concrete', 3 => 'Turf/grass', 4 => 'Dirt', 5 => 'Gravel', 6 => 'H-Asphalt', # helepad (big 'H' in the middle). 7 => 'H-Concrete', # helepad (big 'H' in the middle). 8 => 'H-Turf', # helepad (big 'H' in the middle). 9 => 'H-Dirt', # helepad (big 'H' in the middle). 10 => 'T-Asphalt', # taxiway - with yellow hold line across long axis (not available from WorldMaker). 11 => 'T-Concrete', # taxiway - with yellow hold line across long axis (not available from WorldMaker). 12 => 'Dry Lakebed', # (eg. at KEDW Edwards AFB). 13 => 'Water' # runways (marked with bobbing buoys) for seaplane/floatplane bases (available in X-Plane 7.0 and later). ); sub get_ll_stg($$) { my ($lat,$lon) = @_; my $stg = sprintf("%.8f,%.8f",$lat,$lon); $stg .= ' ' while (length($stg) < 23); return $stg; } # radio frequency listing # Radio Frequencies # AWOS (Automatic Weather Observation System), ASOS (Automatic Surface Observation System) my $minatc = '50'; # ATIS (Automated Terminal Information System). AWIS (Automatic Weather Information Service) my $unicom = '51'; # Unicom or CTAF (USA), radio (UK) - open channel for pilot position reporting at uncontrolled airports. my $cleara = '52'; # Clearance delivery. my $goundf = '53'; # ground my $twrfrq = '54'; # like 12210 TWR my $appfrq = '55'; # like 11970 ROTTERDAM APP my $maxatc = '56'; # Departure. my %off2name = ( 0 => 'ATIS', 1 => 'Unicom', 2 => 'Clearance', 3 => 'Ground', 4 => 'Tower', 5 => 'Approach', 6 => 'Departure' ); my %off2name2 = ( 0 => 'ATIS', 1 => 'UNICOM', 2 => 'CLR', 3 => 'GRD', 4 => 'TWR', 5 => 'APP', 6 => 'DEP' ); my $use_full_list = 0; # seems better to GROUP frequencies my $add_name_show = 0; # does NOT seem helpful my $use_short_names = 1; # Use APP instead of Approach sub show_frequencies($) { my $rfa = shift; my $rfc = scalar @{$rfa}; my ($tmp,$rtlen); my ($rfna,$line,$block,$len,$ra); my ($ev,$fr,$fn,$evnm,$ftyp); my %names = (); my $max_line = 100; my $info = ''; if ($rfc) { $tmp = "radio:".$rfc." ["; $rtlen = length($tmp); $info .= $tmp; foreach $ra (@{$rfa}) { # 50 12775 ATIS $ev = ${$ra}[0]; # number in file 50, 51, ...., 56 $fr = ${$ra}[1]; # frequency x 100 $fn = ${$ra}[2]; # type AWIS, CTAF, ... if ($ev && $fr && $fn) { #### prt("$ev $fr $fn\n"); $fr /= 100; } else { pgm_exit(1,"ERROR: Frequency array FAILED\n"); } # prepare information $evnm = 'UNK'.$ev.'?'; $ftyp = $ev - 50; if ( ($ftyp >= 0) && ($ftyp <= 6) ) { if ($use_short_names) { $evnm = $off2name2{$ftyp}; } else { $evnm = $off2name{$ftyp}; } } #$info .= " $ev $fr $fn"; #$info .= " $evnm $fn $fr"; if ($use_full_list) { $info .= " $evnm $fr ($fn)"; } else { $names{$evnm} = [] if (!defined $names{$evnm}); $rfna = $names{$evnm}; if ($add_name_show) { push(@{$rfna}, "$fr ($fn)"); } else { push(@{$rfna},$fr); } } } if (!$use_full_list) { my ($key,$val,$wrap); if ($add_name_show) { $wrap = 0; foreach $key (sort keys %names) { $rfna = $names{$key}; $info .= " $key:"; foreach $val (@{$rfna}) { $info .= " $val"; } $wrap++; if ($wrap == 3) { $wrap = 0; $info .= "\n"; } } } else { $line = $info; # start the line $info = ''; foreach $key (sort keys %names) { $rfna = $names{$key}; $block = ''; foreach $val (@{$rfna}) { $block .= ' ' if (length($block)); $block .= $val; } $block = "$key: $block"; $len = length($line) + length($block); #prt("got len $len\n"); if ($len > $max_line) { $info .= "$line\n" if (length($line)); $line = ' ' x $rtlen; #prt("wrapped line\n"); } $line .= "$block "; } $info .= $line if (length($line)); $info =~ s/\s+$//; } } $info .= ']'; } else { $info .= " [No freq. info]"; } prt("$info\n"); } sub show_runways($$$) { my ($rrwys,$rwater,$rheli) = @_; my $rwycnt = scalar @{$rrwys}; my $info = "runway:$rwycnt: "; my ($ra,$type,$tmp,$rtyp,$hdg,$rlen,$disp1,$disp2,$rwid,$rlit,$surf,$rhdg); my ($displ1,$displ2,$stopw1,$stopw2,$rwy1,$rwy2); my ($elon1,$elon2,$elat1,$elat2,$s,$az1,$az2); my ($rwlen,$rwlen2,$hdgr,$eaz1,$eaz2,$hdg1,$hdg2); my $annoxg = ''; foreach $ra (@{$rrwys}) { $tmp = scalar @{$ra}; $type = ${$ra}[0]; # get first 'type' entry ###prt(join(" ",@{$ra})." t=$type c=$tmp\n"); ###next; if ($type == 10) { # 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 if ($tmp < 15) { foreach $hdg (@{$ra}) { $info .= "[$hdg] "; } pgm_exit(1,"ERROR: Invalid runway array cnt $tmp! $info\n"); } $rtyp = ${$ra}[3]; $hdg = ${$ra}[4]; $rlen = ${$ra}[5]; # length, in feet # For example, for displaced threshold lengths of 543 feet and 1234 feet, # the code would be 543.1234. $tmp = ${$ra}[6]; # get displacements - feet - threshold $displ1 = int($tmp); $displ2 = ($tmp - $displ1) * 10000; $tmp = ${$ra}[7]; # get stopway - feet $stopw1 = int($tmp); $stopw2 = ($tmp - $stopw1) * 10000; $rwid = ${$ra}[8]; # WIDTH in feet $rlit = ${$ra}[9]; # LIGHTS $surf = ${$ra}[10]; # add surface type $rtyp =~ s/x+$//; # REMOVE any TRAILIN 'x', but may have 'L', 'R', 'C', 'S' appended if ($rtyp =~ /^\d+$/) { $rhdg = $rtyp * 10; # 2010-12-15 - get opposite end numbers } else { $rhdg = $hdg; # get opp heading, but may NOT be per numbers } $rhdg += 180; # reverse it $rhdg -= 360 if ($rhdg >= 360); # drop wrap $rwy1 = $rtyp; $rwy2 = int($rhdg / 10); $rhdg = int($rhdg / 10); $rhdg = "0$rhdg" if ($rhdg < 10); # display it ####################################################### $info .= "\n"; # if (VERB1()); # new line $info .= " $rtyp/$rhdg ($hdg) "; $info .= $rlen." ft."; # length in FEET if (defined $runway_surface{$surf}) { $info .= " (s=".$runway_surface{$surf}.")"; } $rwlen2 = (${$ra}[5] * $FEET_TO_METER) / 2; $hdgr = $hdg + 180; $hdgr -= 360 if ($hdgr >= 360); fg_geo_direct_wgs_84( ${$ra}[1], ${$ra}[2], $hdg , $rwlen2, \$elat1, \$elon1, \$eaz1 ); fg_geo_direct_wgs_84( ${$ra}[1], ${$ra}[2], $hdgr, $rwlen2, \$elat2, \$elon2, \$eaz2 ); $hdg1 = $hdg; $hdg2 = $hdgr; $az1 = $hdg1; $az2 = $hdg2; if (VERB1()) { $info .= " ".${$ra}[1].",".${$ra}[2]; if (VERB2()) { # show ENDS of runway $info .= "\n $rtyp: $elat1,$elon1 $rhdg: $elat2,$elon2"; $info .= " th=$displ1/$displ2 sp=$stopw1/$stopw2"; } } } elsif ($type == 100) { # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 100 29.87 3 0 0.00 1 2 1 16 43.91080605 004.90321905 0.00 0.00 2 0 0 0 34 43.90662331 004.90428974 0.00 0.00 2 0 0 0 $rwid = ${$ra}[1]; # WIDTH in meters? NOT SHOWN $surf = ${$ra}[2]; # add surface type $rwy1 = ${$ra}[8]; $elat1 = ${$ra}[9]; $elon1 = ${$ra}[10]; $rwy2 = ${$ra}[17]; $elat2 = ${$ra}[18]; $elon2 = ${$ra}[19]; my $res = fg_geo_inverse_wgs_84 ($elat1,$elon1,$elat2,$elon2,\$az1,\$az2,\$s); # display it # ========================================================================== $info .= "\n"; # if (VERB1()); # new line $s = (int(($s + 0.05) * 10) / 10); $az1 = (int(($az1 + 0.05) * 10) / 10); $rwy1 .= ' ' while (length($rwy1) < 3); $rwy2 .= ' ' while (length($rwy2) < 3); $info .= " $rwy1: ".get_ll_stg($elat1,$elon1)." $rwy2: ".get_ll_stg($elat2,$elon2)." b=$az1 l=$s m."; if (defined $runway_surface{$surf}) { $info .= " (s=".$runway_surface{$surf}.")"; } } else { pgm_exit(1,"Uncoded RUNWAY type $type - FIX ME!\n".join(" ",@{$ra})."\n"); } $annoxg .= "$elon1 $elat1\n"; $annoxg .= "$elon2 $elat2\n"; $annoxg .= "NEXT\n"; } $info .= "\n"; # 0 1 2 3 4 5 6 7 8 # 101 243.84 0 16 29.27763293 -089.35826258 34 29.26458929 -089.35340410 # 101 22.86 0 07 29.12988952 -089.39561501 25 29.13389936 -089.38060001 # from : http://data.x-plane.com/file_specs/XP%20APT1000%20Spec.pdf # 0 101 - Raw code for waterway # 1 22.86 - width in meters # 2 0 - perimeter buoys # 3 16 - runway number # 4 29.129 - lat # 5 -089.39 - lon # 6 25 - runway number # 7 29.133 - lat # 8 -089.38 - lon $rwycnt = scalar @{$rwater}; if ($rwycnt) { $info .= "waterway:$rwycnt:\n"; foreach $ra (@{$rwater}) { $rwid = ${$ra}[1]; # WIDTH in meters? NOT SHOWN $surf = ${$ra}[2]; # buoys $rwy1 = ${$ra}[3]; $elat1 = ${$ra}[4]; $elon1 = ${$ra}[5]; $rwy2 = ${$ra}[6]; $elat2 = ${$ra}[7]; $elon2 = ${$ra}[8]; my $res = fg_geo_inverse_wgs_84 ($elat1,$elon1,$elat2,$elon2,\$az1,\$az2,\$s); # display it # ========================================================================== $s = (int(($s + 0.05) * 10) / 10); $az1 = (int(($az1 + 0.05) * 10) / 10); $rwy1 .= ' ' while (length($rwy1) < 3); $rwy2 .= ' ' while (length($rwy2) < 3); $info .= " $rwy1: ".get_ll_stg($elat1,$elon1)." $rwy2: ".get_ll_stg($elat2,$elon2)." b=$az1 l=$s m."; $info .= "\n"; # if (VERB1()); # new line } } $rwycnt = scalar @{$rheli}; if ($rwycnt) { # 0 1 2 3 4 5 6 7 8 9 10 11 # 102 H1 47.53918248 -122.30722302 2.00 10.06 10.06 1 0 0 0.25 0 # 102 Helipad # 0 102 Row code for a helipad # 1 H1 Designator for a helipad. Must be unique at an airport. Usually “H” suffixed by an integer (eg. “H1”, “H3”) # 2 47.53918248 Latitude of helipad centre # 3 -122.30722302 Longitude of helipad centre in decimal degrees # 4 2.00 Orientation (true heading) of helipad in degrees # 5 10.06 Helipad length in metres Two decimal places recommended (metres), must be >=1.00 # 6 10.06 Helipad width in metres Two decimal places recommended (metres), must be >= 1.00 # 7 1 Helipad surface code Integer value for a Surface Type Code (see below) # 8 0 Helipad markings 0 (other values not yet supported) # 9 0 Code defining a helipad shoulder surface type 0=no shoulder, 1=asphalt shoulder, 2=concrete shoulder #10 0.25 Helipad smoothness (not used by X-Plane yet) 0.00 (smooth) to 1.00 (very rough). Default is 0.25 #11 0 Helipad edge lighting 0=no edge lights, 1=yellow edge lights $info .= "helipad:$rwycnt:\n"; $rwy1 = ${$ra}[1]; $elat1 = ${$ra}[2]; $elon1 = ${$ra}[3]; $rwlen = ${$ra}[5]; $rwlen2= ${$ra}[6]; $info .= " $rwy1: ".get_ll_stg($elat1,$elon1)." $rwlen x $rwlen2 m."; $info .= "\n"; # if (VERB1()); # new line } prt($info); } sub get_runways_xg($) { my $ra = shift; my ($rrwa, $wa, $ha, $fa); my ($tmp,$type,$rlat1,$rlat2,$rlon1,$rlon2,$rlat3,$rlon3,$rlat4,$rlon4); my ($elat1,$elon1,$elat2,$elon2,$rwid2,$res,$rcnt); my ($az1,$az2,$dist,$az); show_airport($ra); $rrwa = ${$ra}[5]; $wa = ${$ra}[6]; $ha = ${$ra}[7]; $rcnt = scalar @{$rrwa}; my $xg = ''; if ($rcnt > 0) { $xg .= "color $runway_color\n"; foreach $ra (@{$rrwa}) { $tmp = scalar @{$ra}; $type = ${$ra}[0]; # get first 'type' entry if ($type == 10) { # 0 1 2 3 # 10 36.962213 127.031071 14x 131.52 8208 1595.0620 0000.0000 150 321321 1 0 3 0.25 0 0300.0300 } elsif ($type == 100) { # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 100 29.87 3 0 0.00 1 2 1 16 43.91080605 004.90321905 0.00 0.00 2 0 0 0 34 43.90662331 004.90428974 0.00 0.00 2 0 0 0 $rwid2 = ${$ra}[1] / 2; $elat1 = ${$ra}[9]; $elon1 = ${$ra}[10]; $elat2 = ${$ra}[18]; $elon2 = ${$ra}[19]; $res = fg_geo_inverse_wgs_84 ($elat1,$elon1,$elat2,$elon2,\$az1,\$az2,\$dist); $az2 = $az1 + 90; $az2 -= 360 if ($az2 >= 360); $res = fg_geo_direct_wgs_84($elat1,$elon1,$az2,$rwid2,\$rlat1, \$rlon1,\$az); $res = fg_geo_direct_wgs_84($elat2,$elon2,$az2,$rwid2,\$rlat3, \$rlon3,\$az); $az2 = $az1 - 90; $az2 += 360 if ($az2 < 0); $res = fg_geo_direct_wgs_84($elat1,$elon1,$az2,$rwid2,\$rlat2, \$rlon2,\$az); $res = fg_geo_direct_wgs_84($elat2,$elon2,$az2,$rwid2,\$rlat4, \$rlon4,\$az); # got the 4 corners $xg .= "$rlon1 $rlat1\n"; $xg .= "$rlon2 $rlat2\n"; $xg .= "$rlon3 $rlat3\n"; $xg .= "$rlon4 $rlat4\n"; $xg .= "NEXT\n"; } } } return $xg; } sub show_airport_all($) { my $ra = shift; my ($rrwa, $wa, $ha, $fa); show_airport($ra); $rrwa = ${$ra}[5]; $wa = ${$ra}[6]; $ha = ${$ra}[7]; $fa = ${$ra}[8]; show_runways($rrwa,$wa,$ha); show_frequencies($fa); } # BBOX lef_lon, bot_lat, rit_lon, top_lat sub find_apts($$) { my ($bbox,$rapts) = @_; my ($lef_lon, $bot_lat, $rit_lon, $top_lat); my @arr = split(",",$bbox); my $cnt = scalar @arr; return 0 if ($cnt != 4); $lef_lon = $arr[0]; $bot_lat = $arr[1]; $rit_lon = $arr[2]; $top_lat = $arr[3]; @arr = (); ## 0 1 2 3 4 5 6 7 8 #push(@g_naptlist, [$icao, $name, $alat, $alon, $aalt, \@ra, \@wa, \@ha, \@fa ]); my ($ra, $icao, $name, $alat, $alon, $aalt, $rrwa, $wa, $ha, $fa); foreach $ra (@g_naptlist) { $icao = ${$ra}[0]; $name = ${$ra}[1]; $alat = ${$ra}[2]; $alon = ${$ra}[3]; $aalt = ${$ra}[4]; $rrwa = ${$ra}[5]; $wa = ${$ra}[6]; $ha = ${$ra}[7]; $fa = ${$ra}[0]; if (($alon >= $lef_lon)&& ($alon <= $rit_lon)&& ($alat >= $bot_lat)&& ($alat <= $top_lat)) { push(@arr,$ra); } } $cnt = scalar @arr; if ($cnt > 0) { @{$rapts} = @arr; } return $cnt; } sub show_navaid($) { my $ra = shift; # 0 1 2 3 4 5 6 7 8 9 10 11 12 # push(@g_navlist, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $dist1, $az11, $dist2, $az21] ); my ($typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $dist1, $az11, $dist2, $az21); $typ = ${$ra}[0]; $nlat = ${$ra}[1]; $nlon = ${$ra}[2]; $nalt = ${$ra}[3]; $nfrq = ${$ra}[4]; $nrng = ${$ra}[5]; $nfrq2 = ${$ra}[6]; $nid = ${$ra}[7]; $name = ${$ra}[8]; $dist1 = ${$ra}[9]; $az11 = ${$ra}[10]; $dist2 = ${$ra}[11]; $az21 = ${$ra}[12]; # for display $nlon = sprintf("%.8f",$nlon); $nlat = sprintf("%.8f",$nlat); $nalt = sprintf("%5d",$nalt)." ft"; $dist1 = int(($dist1 + 0.5) / 1000). " km"; $dist2 = int(($dist2 + 0.5) / 1000). " km"; $az11 = int($az11 + 0.5); $az21 = int($az21 + 0.5); prt("$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $dist1, $az11, $dist2, $az21\n"); } # BBOX lef_lon, bot_lat, rit_lon, top_lat # 20140930 - Find ONLY VOR and NDB unless $all flag is ON sub find_wpts($$$) { my ($bbox,$rwpts,$all) = @_; # 0 1 2 3 4 5 6 7 8 9 10 11 12 # push(@g_navlist, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $dist1, $az11, $dist2, $az21] ); my ($ra,$nlat,$nlon,$ntyp); my ($lef_lon, $bot_lat, $rit_lon, $top_lat); my @arr = split(",",$bbox); my $cnt = scalar @arr; return 0 if ($cnt != 4); $lef_lon = $arr[0]; $bot_lat = $arr[1]; $rit_lon = $arr[2]; $top_lat = $arr[3]; @arr = (); foreach $ra (@g_navlist) { $ntyp = ${$ra}[0]; if ($all || (($ntyp == 2)||($ntyp == 3))) { $nlat = ${$ra}[1]; $nlon = ${$ra}[2]; if (($nlon >= $lef_lon)&& ($nlon <= $rit_lon)&& ($nlat >= $bot_lat)&& ($nlat <= $top_lat)) { push(@arr,$ra); } } } $cnt = @arr; if ($cnt > 0) { @{$rwpts} = @arr; return $cnt; } return 0; } # BBOX left lon, bottom lat, right lon, top lat sub latlon_2_bbox($$$$$$$$) { my ($min_lat1,$min_lon1,$max_lat1,$max_lon1,$min_lat2,$min_lon2,$max_lat2,$max_lon2) = @_; my $left_lon = $min_lon1; $left_lon = $max_lon1 if ($max_lon1 < $left_lon); $left_lon = $min_lon2 if ($min_lon2 < $left_lon); $left_lon = $max_lon2 if ($max_lon2 < $left_lon); my $bot_lat = $min_lat1; $bot_lat = $max_lat1 if ($max_lat1 < $bot_lat); $bot_lat = $min_lat2 if ($min_lat2 < $bot_lat); $bot_lat = $max_lat2 if ($max_lat2 < $bot_lat); my $rit_lon = $min_lon1; $rit_lon = $max_lon1 if ($max_lon1 > $rit_lon); $rit_lon = $min_lon2 if ($min_lon2 > $rit_lon); $rit_lon = $max_lon2 if ($max_lon2 > $rit_lon); my $top_lat = $min_lat1; $top_lat = $max_lat1 if ($max_lat1 > $top_lat); $top_lat = $min_lat2 if ($min_lat2 > $top_lat); $top_lat = $max_lat2 if ($max_lat2 > $top_lat); if (VERB9()) { prt("Polgon ($min_lat1,$min_lon1,$max_lat1,$max_lon1,$min_lat2,$min_lon2,$max_lat2,$max_lon2)\n". "BBOX = $left_lon,$bot_lat,$rit_lon,$top_lat\n"); } return "$left_lon,$bot_lat,$rit_lon,$top_lat"; } # BBOX left lon, bottom lat, right lon, top lat sub bbox_2_xg($) { my $bbox = shift; my @arr = split(",",$bbox); my $cnt = scalar @arr; return "# bbox $bbox FAILED ($cnt)\n" if ($cnt != 4); my $lef_lon = $arr[0]; my $bot_lat = $arr[1]; my $rit_lon = $arr[2]; my $top_lat = $arr[3]; my $xg = "# BBOX LBRT $lef_lon,$bot_lat,$rit_lon,$top_lat\n"; $xg .= "$lef_lon $bot_lat\n"; $xg .= "$lef_lon $top_lat\n"; $xg .= "$rit_lon $top_lat\n"; $xg .= "$rit_lon $bot_lat\n"; $xg .= "$lef_lon $bot_lat\n"; $xg .= "NEXT\n"; return $xg; } my ($g_min_lat,$g_min_lon,$g_max_lat,$g_max_lon); sub set_extended_bbox($$) { my ($lat,$lon) = @_; $g_min_lon = $lon if ($lon < $g_min_lon); $g_max_lon = $lon if ($lon > $g_max_lon); $g_min_lat = $lat if ($lat < $g_min_lat); $g_max_lat = $lat if ($lat > $g_max_lat); } sub set_initial_bbox($$$$) { my ($bgn_lat,$bgn_lon,$end_lat,$end_lon) = @_; $g_min_lon = $bgn_lon; $g_min_lon = $end_lon if ($end_lon < $g_min_lon); $g_max_lon = $bgn_lon; $g_max_lon = $end_lon if ($end_lon > $g_max_lon); $g_min_lat = $bgn_lat; $g_min_lat = $end_lat if ($end_lat < $g_min_lat); $g_max_lat = $bgn_lat; $g_max_lat = $end_lat if ($end_lat > $g_max_lat); # but this is just the start point and end point # need to extend this by say 10 nm around each point # $extension_nm my ($res,$elat,$elon,$s,$az); $s = nm_2_meter($extension_nm); $res = fg_geo_direct_wgs_84( $bgn_lat, $bgn_lon, 0, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); $res = fg_geo_direct_wgs_84( $bgn_lat, $bgn_lon, 90, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); $res = fg_geo_direct_wgs_84( $bgn_lat, $bgn_lon, 180, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); $res = fg_geo_direct_wgs_84( $bgn_lat, $bgn_lon, 270, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); $res = fg_geo_direct_wgs_84( $end_lat, $end_lon, 0, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); $res = fg_geo_direct_wgs_84( $end_lat, $end_lon, 90, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); $res = fg_geo_direct_wgs_84( $end_lat, $end_lon, 180, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); $res = fg_geo_direct_wgs_84( $end_lat, $end_lon, 270, $s, \$elat, \$elon, \$az ); set_extended_bbox($elat,$elon); } sub get_flight_plan() { my $dist_rem = $tot_dist; my $dist_nm = meter_2_nm($dist_rem); my $nxt_az = $bgn_az; # ok, try to get NEXT waypoint # $min_dist = 40; # nm # $max_dist = 100; # nm my $min_m = nm_2_meter($min_dist); my $max_m = nm_2_meter($max_dist); #sub fg_geo_direct_wgs_84 { #my ( $lat1, $lon1, $az1, $s, $lat2, $lon2, $az2 ) = @_; my ($min_lat1,$min_lon1,$max_lat1,$max_lon1); my ($min_lat2,$min_lon2,$max_lat2,$max_lon2); my ($res,$az,$ind,$bbox,$ra,$cnt,$nxtwpt,$acnt); my $nxt_lat = $bgn_lat; my $nxt_lon = $bgn_lon; my $home = 0; my $wpt_cnt = 0; my ($nlat2,$nlon2,$wpts_fnd,$apts_fnd); my ($finding,$nxt_max_m,$icao); my ($typ, $typ2, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, $dist1, $az11, $az12, $dist2, $az21, $az22); my $xcnt = 0; my $total_dist = 0; my $tmpxg = ''; my @track = (); my $flag = 0; # offset into @g_aptlist $bgn_off, $end_off = -1; #my ($icao,$alat,$alon,$aalt,$rra,$rwa,$rha,$rfa); $ra = $g_aptlist[$bgn_off]; my $id = ${$ra}[0]; my $alt = ${$ra}[4]; show_airport_all($ra); set_initial_bbox($bgn_lat,$bgn_lon,$end_lat,$end_lon); # add BEGIN of track push(@track,[$bgn_lat,$bgn_lon,$id,$alt]); prt("BEGIN: $bgn_icao ($bgn_lat,$bgn_lon), dist ".int($dist_nm)." nm, bearing ".int($nxt_az)."\n"); if ($dist_nm < $max_dist) { # too short - just a direct flight $ra = $g_aptlist[$end_off]; $alt = ${$ra}[4]; prt("On bearing ".int($bgn_az+0.5)." degrees, distance ".int($dist_nm + 0.5)." nm\n"); prt("END: $end_icao ($end_lat,$end_lon,$alt)\n"); # add END of track push(@track,[$end_lat,$end_lon,$end_icao,$alt]); $home = 1; } $tmpxg .= "color $bbox_color\n"; while (!$home) { my @wpts = (); my @apts = (); # $deg_spread = 10; my $az1 = $nxt_az + $deg_spread; $az1 -= 360 if ($az1 >= 360); my $az2 = $nxt_az - $deg_spread; $az2 += 360 if ($az2 < 0); $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az1, $min_m, \$min_lat1, \$min_lon1, \$az ); $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az2, $min_m, \$min_lat2, \$min_lon2, \$az ); $finding = 1; $nxt_max_m = $max_m; # start with configured value $xcnt = 0; #################################################################### while ($finding) { $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az1, $nxt_max_m, \$max_lat1, \$max_lon1, \$az ); $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az2, $nxt_max_m, \$max_lat2, \$max_lon2, \$az ); prt("BBOX: $min_lat1,$min_lon1 $max_lat1,$max_lon1 $min_lat2,$min_lon2 $max_lat2,$max_lon2\n") if (VERB9()); $bbox = latlon_2_bbox($min_lat1,$min_lon1,$max_lat1,$max_lon1,$min_lat2,$min_lon2,$max_lat2,$max_lon2); prt("BBOX: $bbox\n") if (VERB5()); $cnt = 0; $wpts_fnd = 0; if (find_wpts($bbox,\@wpts,$flag)) { $finding = 0; $wpts_fnd = scalar @wpts; prt("Got $wpts_fnd waypoints...\n") if (VERB9()); foreach $ra (@wpts) { show_navaid($ra) if (VERB9()); $typ = ${$ra}[0]; $nlat = ${$ra}[1]; $nlon = ${$ra}[2]; $nalt = ${$ra}[3]; $nfrq = ${$ra}[4]; $nrng = ${$ra}[5]; $nfrq2 = ${$ra}[6]; $nid = ${$ra}[7]; $name = ${$ra}[8]; $dist1 = ${$ra}[9]; $az11 = ${$ra}[10]; $dist2 = ${$ra}[11]; $az21 = ${$ra}[12]; if ($cnt == 0) { $nxtwpt = $ra; } else { # if (($typ == 3)||($typ == 12)||($typ == 13)) { # my $navVOR = '3'; if (($typ == 3)||($typ == 12)) { # my $navVOR = '3'; $typ2 = ${$nxtwpt}[0]; # if (($typ2 == 3)||($typ2 == 12)||($typ2 == 13)) { # my $navVOR = '3'; if (($typ2 == 3)||($typ2 == 12)) { # my $navVOR = '3'; # must choose - closest, OR better nearest desired bearing, $nxt_az $nlat2 = ${$nxtwpt}[1]; $nlon2 = ${$nxtwpt}[2]; $res = fg_geo_inverse_wgs_84 ($nxt_lat,$nxt_lon,$nlat,$nlon,\$az11,\$az12,\$dist1); $res = fg_geo_inverse_wgs_84 ($nxt_lat,$nxt_lon,$nlat2,$nlon2,\$az21,\$az22,\$dist1); # if $az11 closer to $nxt_az than current choice $az21 if (abs($nxt_az - $az11) < abs($nxt_az - $az21)) { prt("Changed next wpt due bearing ".int($az11 + 0.5)." closer to desired ".int($nxt_az)."\n") if (VERB2()); $nxtwpt = $ra; } } else { $nxtwpt = $ra; } } } $cnt++; } } else { $xcnt++; $nxt_max_m += nm_2_meter(10); if ($nxt_max_m > nm_2_meter($max_max_dist)) { $nxt_max_m -= nm_2_meter(10); prt("OOPS: NO waypoints with extended max to ".int(meter_2_nm($nxt_max_m))." nm.\n") if (VERB5()); $cnt = 0; last; } prt("UGH: Got NO waypoints... extended max to ".int(meter_2_nm($nxt_max_m))." nm.\n") if (VERB5()); } } ######################################################################### if ($cnt == 0) { my $nxt_spread = $deg_spread + 2; my $spread_find = 1; prt("\nIncreasing spread to $nxt_spread, to try some more...\n") if (VERB5()); while ($spread_find) { $az1 = $nxt_az + $nxt_spread; $az1 -= 360 if ($az1 >= 360); $az2 = $nxt_az - $nxt_spread; $az2 += 360 if ($az2 < 0); $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az1, $min_m, \$min_lat1, \$min_lon1, \$az ); $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az2, $min_m, \$min_lat2, \$min_lon2, \$az ); $finding = 1; $nxt_max_m = $max_m; # start with configured value $xcnt = 0; #################################################################### while ($finding) { $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az1, $nxt_max_m, \$max_lat1, \$max_lon1, \$az ); $res = fg_geo_direct_wgs_84( $nxt_lat, $nxt_lon, $az2, $nxt_max_m, \$max_lat2, \$max_lon2, \$az ); prt("BBOX: $min_lat1,$min_lon1 $max_lat1,$max_lon1 $min_lat2,$min_lon2 $max_lat2,$max_lon2\n") if (VERB9()); $bbox = latlon_2_bbox($min_lat1,$min_lon1,$max_lat1,$max_lon1,$min_lat2,$min_lon2,$max_lat2,$max_lon2); prt("BBOX: $bbox\n") if (VERB5()); $cnt = 0; $wpts_fnd = 0; if (find_wpts($bbox,\@wpts,$flag)) { $finding = 0; $wpts_fnd = scalar @wpts; prt("Got $wpts_fnd waypoints...\n") if (VERB9()); foreach $ra (@wpts) { show_navaid($ra) if (VERB9()); $typ = ${$ra}[0]; $nlat = ${$ra}[1]; $nlon = ${$ra}[2]; $nalt = ${$ra}[3]; $nfrq = ${$ra}[4]; $nrng = ${$ra}[5]; $nfrq2 = ${$ra}[6]; $nid = ${$ra}[7]; $name = ${$ra}[8]; $dist1 = ${$ra}[9]; $az11 = ${$ra}[10]; $dist2 = ${$ra}[11]; $az21 = ${$ra}[12]; if ($cnt == 0) { $nxtwpt = $ra; } else { # if (($typ == 3)||($typ == 12)||($typ == 13)) { # my $navVOR = '3'; if (($typ == 3)||($typ == 12)) { # my $navVOR = '3'; $typ2 = ${$nxtwpt}[0]; # if (($typ2 == 3)||($typ2 == 12)||($typ2 == 13)) { # my $navVOR = '3'; if (($typ2 == 3)||($typ2 == 12)) { # my $navVOR = '3'; # must choose - closest, OR better nearest desired bearing, $nxt_az $nlat2 = ${$nxtwpt}[1]; $nlon2 = ${$nxtwpt}[2]; $res = fg_geo_inverse_wgs_84 ($nxt_lat,$nxt_lon,$nlat,$nlon,\$az11,\$az12,\$dist1); $res = fg_geo_inverse_wgs_84 ($nxt_lat,$nxt_lon,$nlat2,$nlon2,\$az21,\$az22,\$dist1); # if $az11 closer to $nxt_az than current choice $az21 if (abs($nxt_az - $az11) < abs($nxt_az - $az21)) { prt("Changed next wpt due bearing ".int($az11 + 0.5)." closer to desired ".int($nxt_az)."\n") if (VERB2()); $nxtwpt = $ra; } } else { $nxtwpt = $ra; } } } $cnt++; } } else { $xcnt++; $nxt_max_m += nm_2_meter(10); if ($nxt_max_m > nm_2_meter($max_max_dist)) { $nxt_max_m -= nm_2_meter(10); prt("BAH: NO waypoints, spread $nxt_spread, extended to ".int(meter_2_nm($nxt_max_m))." nm.\n") if (VERB5()); last; } prt("UGH: NO waypoints, nxt spread $nxt_spread. Extended max to ".int(meter_2_nm($nxt_max_m))." nm.\n") if (VERB5()); } } ######################################################################### if ($cnt > 0) { $spread_find = 0; } else { $nxt_spread += 2; if ($nxt_spread > $max_deg_spread) { prt("ZUTE: Reached max deg spread $max_deg_spread with no waypoint found!\n") if (VERB5()); last; } else { prt("\nIncreased spread to $nxt_spread!\n") if (VERB5()); } } } } $apts_fnd = 0; if (find_apts($bbox,\@apts)) { $apts_fnd = scalar @apts; if (VERB2()) { prt("Got $apts_fnd airports...\n"); foreach $ra (@apts) { show_airport($ra); } } } else { # prt("UGH: Got NO airports...\n"); } if ($cnt > 0) { $ra = $nxtwpt; $typ = ${$ra}[0]; $nlat = ${$ra}[1]; $nlon = ${$ra}[2]; $nalt = ${$ra}[3]; $nfrq = ${$ra}[4]; $nrng = ${$ra}[5]; $nfrq2 = ${$ra}[6]; $nid = ${$ra}[7]; $name = ${$ra}[8]; $dist1 = ${$ra}[9]; $az11 = ${$ra}[10]; $dist2 = ${$ra}[11]; $az21 = ${$ra}[12]; $tmpxg .= "anno $nlon $nlat $name\n"; $tmpxg .= bbox_2_xg($bbox); $res = fg_geo_inverse_wgs_84 ($nxt_lat,$nxt_lon,$nlat,$nlon,\$az11,\$az12,\$dist1); $total_dist += $dist1; $nxt_lat = $nlat; $nxt_lon = $nlon; $wpt_cnt++; push(@track,[$nlat,$nlon,$nid,$nalt]); set_extended_bbox($nlat,$nlon); # for display ########################################################################### $az12 = int($az1 + 0.5); $dist2 = int( ($dist1 / 1000) + 0.5 )." km (".int(meter_2_nm($dist1))."nm)"; # 1234567890123456 # 1667 km (1000nm) $dist2 .= ' ' while (length($dist2) < 16); if (($typ == 3)||($typ == 12)||($typ == 13)) { # my $navVOR = '3'; $nfrq /= 100; $nfrq .= "." if (!($nfrq =~ /\./)); $nfrq .= '0' while (length($nfrq) < 6); } else { $nfrq = ' '.$nfrq while (length($nfrq) < 6); } $nlon2 = sprintf("%12.6f",$nlon); $nlat2 = sprintf("%12.6f",$nlat); $acnt = sprintf("%2d",$wpt_cnt); $nid .= ' ' while (length($nid) < 3); $typ = get_nav_type($typ); prt("$acnt wpt $typ $nid $nfrq on $az12, dist $dist2 ($nlat2,$nlon2) $name (w=$wpts_fnd/a=$apts_fnd/x=$xcnt)\n"); ########################################################################### $res = fg_geo_inverse_wgs_84 ($nxt_lat,$nxt_lon,$end_lat,$end_lon,\$az11,\$az12,\$dist1); $dist_nm = meter_2_nm($dist1); $nxt_az = $az11; if ($dist_nm < $max_dist) { # too short - just a direct flight $ra = $g_aptlist[$end_off]; $alt = ${$ra}[4]; prt("Final bearing ".int($bgn_az+0.5)." degrees, distance ".int($dist_nm + 0.5)." nm\n"); prt("END: $end_icao ($end_lat,$end_lon), total dist ".int(meter_2_nm($total_dist))." nm\n"); push(@track,[$end_lat,$end_lon,$end_icao,$alt]); $home = 1; show_airport_all($ra); } } else { prt("FAILED\n"); $home = 2; } } if (($home == 1) && length($tmpxg) && length($out_xg)) { $ra = $g_aptlist[$bgn_off]; $tmpxg .= get_runways_xg($ra); $ra = $g_aptlist[$end_off]; $tmpxg .= get_runways_xg($ra); $tmpxg .= "color $track_color\n"; $cnt = scalar @track; for (my $i = 0; $i < $cnt; $i++) { $ra = $track[$i]; $nlat = ${$ra}[0]; $nlon = ${$ra}[1]; $tmpxg .= "$nlon $nlat\n"; if ($i == 0) { $ra = $g_aptlist[$bgn_off]; $icao = ${$ra}[0]; $tmpxg .= "anno $nlon $nlat BGN $icao\n"; } elsif (($i + 1) == $cnt) { $ra = $g_aptlist[$end_off]; $icao = ${$ra}[0]; $tmpxg .= "anno $nlon $nlat END $icao\n"; } } $tmpxg .= "NEXT\n"; $typ = "# flight plan from $bgn_icao to $end_icao, generate by $pgmname on ".lu_get_YYYYMMDD_hhmmss_UTC(time())." UTC\n"; $typ .= "# bounding box: bbox=$g_min_lon,$g_min_lat,$g_max_lon,$g_max_lat (min_lon,min_lat,max_lon,max_lat)\n"; write2file($typ.$tmpxg,$out_xg); prt("Bounding boxes written to $out_xg\n"); } if (($home == 1) && length($out_xml)) { my $xml = "\n"; $xml .= "\n"; $xml .= " 2\n"; $ra = $g_aptlist[$bgn_off]; $icao = ${$ra}[0]; $xml .= " \n"; $xml .= " $icao\n"; # 21 $xml .= " \n"; $xml .= " \n"; $ra = $g_aptlist[$end_off]; $xml .= " ".${$ra}[0]."\n"; $xml .= " \n"; $xml .= " \n"; $xml .= " \n"; $xml .= " basic\n"; $xml .= " true\n"; $ra = $track[0]; $nlat = ${$ra}[0]; $nlon = ${$ra}[1]; # $xml .= " 21\n"; $xml .= " $nlon\n"; $xml .= " $nlat\n"; $xml .= " $icao\n"; $xml .= " \n"; $cnt = scalar @track - 1; for (my $i = 1; $i < $cnt; $i++) { $ra = $track[$i]; $nlat = ${$ra}[0]; $nlon = ${$ra}[1]; $id = ${$ra}[2]; $alt = ${$ra}[3]; $alt = (int(($alt + 500) / 1000) * 1000) + $stdalt; $xml .= " navaid\n"; #if (($i + 1) != $cnt) { $xml .= " at\n"; $xml .= " $alt\n"; #} $xml .= " $id\n"; $xml .= " $nlon\n"; $xml .= " $nlat\n"; $xml .= " \n"; } $xml .= " \n"; $xml .= "\n"; write2file($xml,$out_xml); prt("XML gpx written to $out_xml\n"); } } ######################################### ### MAIN ### parse_args(@ARGV); if ($debug_on) { #set_defs(); } process_inputs(); load_all_navaids(); get_flight_plan(); pgm_exit(0,""); ######################################## sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have a following argument!\n") if (!@av); } sub parse_args { my (@av) = @_; my ($arg,$sarg,$cnt); my $verb = VERB2(); $cnt = 0; while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i)||($sarg eq '?')) { give_help(); pgm_exit(0,"Help exit(0)"); } elsif ($sarg =~ /^a/) { need_arg(@av); shift @av; $sarg = $av[0]; $g_aptdat = $sarg; prt("Set apt.dat.gz file to [$g_aptdat].\n") if ($verb); } elsif ($sarg =~ /^n/) { need_arg(@av); shift @av; $sarg = $av[0]; $g_navdat = $sarg; prt("Set nav.dat.gz file to [$g_navdat].\n") if ($verb); } elsif ($sarg =~ /^v/) { if ($sarg =~ /^v.*(\d+)$/) { $verbosity = $1; } else { while ($sarg =~ /^v/) { $verbosity++; $sarg = substr($sarg,1); } } $verb = VERB2(); prt("Verbosity = $verbosity\n") if ($verb); } elsif ($sarg =~ /^l/) { if ($sarg =~ /^ll/) { $load_log = 2; } else { $load_log = 1; } prt("Set to load log at end. ($load_log)\n") if ($verb); } elsif ($sarg =~ /^o/) { need_arg(@av); shift @av; $sarg = $av[0]; $out_file = $sarg; prt("Set out file to [$out_file].\n") if ($verb); } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { if ($cnt == 0) { $bgn_icao = $arg; prt("Set begin ICAO to [$bgn_icao]\n") if ($verb); } elsif ($cnt == 1) { $end_icao = $arg; prt("Set end ICAO to [$end_icao]\n") if ($verb); } else { pgm_exit(1,"Already have begin $bgn_icao, and end $end_icao!\nWhat is this [$arg]?\n"); } $cnt++; } shift @av; } if ($debug_on) { prtw("WARNING: DEBUG is ON!\n"); if (length($bgn_icao) == 0) { $bgn_icao = $def_bgn; prt("Set DEFAULT begin to [$bgn_icao]\n"); } if (length($end_icao) == 0) { $end_icao = $def_end; prt("Set DEFAULT end to [$end_icao]\n"); } } if (! -f $g_aptdat) { pgm_exit(1,"ERROR: Can NOT stat apt dat file $g_aptdat!\n"); } if (! -f $g_navdat) { pgm_exit(1,"ERROR: Can NOT stat nav dat file $g_navdat!\n"); } if (length($bgn_icao) == 0) { pgm_exit(1,"ERROR: No begin icao found in command!\n"); } if (length($end_icao) == 0) { pgm_exit(1,"ERROR: No end icao found in command!\n"); } } sub give_help { prt("$pgmname: version $VERS\n"); prt("Usage: $pgmname [options] in-file\n"); prt("Options:\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); prt(" --verb[n] (-v) = Bump [or set] verbosity. (def=$verbosity)\n"); prt(" --load (-l) = Load LOG at end. ($outfile)\n"); prt(" --air (-a) = Set apt.dat.gz file (def=$g_aptdat) ". ((-f $g_aptdat) ? "ok" : "NOT FOUND")."\n"); prt(" --nav (-a) = Set nav.dat.gz file (def=$g_navdat) ". ((-f $g_navdat) ? "ok" : "NOT FOUND")."\n"); prt(" --out (-o) = Write output to this file.\n"); } # eof - template.pl