#!/usr/bin/perl -w # NAME: test-findap.pl # AIM: Just a TEST module use strict; use warnings; use POSIX qw(ceil floor); 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"; open_log($outfile); # user variables my $VERS = "0.0.2 2014-01-13"; my $load_log = 0; my $in_file = ''; my $verbosity = 1; my $out_file = ''; my $FGROOT = 'X:/fgdata'; my $APTFILE = "$FGROOT/Airports/apt.dat.gz"; # le fichier contenant les aéroports my $KM2FEET = 3280.84; my $done_all = 0; my @all_airports = (); # ### DEBUG ### my $debug_on = 0; my $def_file = 'def_file'; ### 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 round($) { my $i = shift; my $m = (shift or 1); $i /= $m; $i = $i - &floor($i) >= 0.5 ? &ceil($i) : &floor($i); $i *= $m; return $i; } 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"); } } } # Airport Line. eg '1 5355 1 0 KABQ Albuquerque Intl Sunport' # 0 1 - this as an airport header line. 16 is a seaplane/floatplane base, 17 a heliport. # 1 5355 - Airport elevation (in feet above MSL). # 2 1 - Airport has a control tower (1=yes, 0=no). # 3 0 - Display X-Plane’s default airport buildings (1=yes, 0=no). # 4 KABQ - Identifying code for the airport (the ICAO code, if one exists). # 5+Albuquerque Intl Sunport - Airport name. sub load_airports() { my ($ver,$line,$type,$autre_bout); my $t1 = [gettimeofday]; if ( -e $APTFILE ) { open (APT, "gzip -d -c $APTFILE|") or die "je ne peux pas ouvrir $APTFILE\n" ; while () { if (/^(\d+)\s+Version\s+/) { $ver = $1; last; } } } else { prt("fichier $APTFILE introuvable\n"); prt("veuillez vérifier \$FGROOT\n"); prt("ou utilisez l'option --fg-root=répertoire\n"); prt("ou encore modifiez le script ver ligne 80\n"); exit 1; } if ($ver) { prt("Loading file $APTFILE, version $ver... moment...\n") if (VERB1()); } else { close APT; prt("Failed to find version in $APTFILE!\n"); exit 1; } my $aptcnt = 0; my $rwycnt = 0; my $comcnt = 0; while ($line = ) { chomp $line; next if ($line =~ /^\s*$/); $line = trim_all($line); my @header = split(/\s+/, $line); $type = $header[0]; last if ($type == 99); if ($type == 1) { # 0 1 2 3 4 5+ # # elev_ft twr bld icao name push(@all_airports, \@header); $aptcnt++; } elsif ($type == 10) { if ($header[3] ne 'xxx') { # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 # 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 $header[3] =~ /(..)(.)/; $autre_bout = ($1 > 18)? $1 - 18 : $1 + 18; $autre_bout = '0'.$autre_bout if ($autre_bout < 10); $autre_bout .= 'L' if ($2 eq 'R'); $autre_bout .= 'R' if ($2 eq 'L'); $autre_bout .= 'C' if ($2 eq 'C'); if ($2 eq 'x') { $header[3] = $1.' '; $autre_bout .= ' '; } $header[3] = $header[3].'/'.$autre_bout; push(@all_airports,\@header); $rwycnt++; } } elsif ($type == 100) { # See version 1000 specs # 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 my $rwy = $header[8]; $autre_bout = $header[17]; $rwy = '0'.$rwy if (length($rwy) < 2); $autre_bout = '0'.$autre_bout if (length($autre_bout) < 2); my $rwynm = $rwy.'/'.$autre_bout; my $rlat1 = $header[9]; # $of_lat1 my $rlon1 = $header[10]; # $of_lon1 my $rlat2 = $header[18]; # $of_lat2 my $rlon2 = $header[19]; # $of_lon2 my $rlat = ($rlat1 + $rlat2) / 2; my $rlon = ($rlon1 + $rlon2) / 2; my ($dist,$az1,$az2,$res,$s); #if ($use_sg_math) { $res = fg_geo_inverse_wgs_84($rlat1, $rlon1, $rlat2, $rlon2, \$az1, \$az2, \$s); $dist = int(($s / 1000) * $KM2FEET ); # runway length, in feet #} else { # $dist = distance_( [$rlat1, $rlon1, $rlat2, $rlon2] ); # $dist = int( $dist * $KM2FEET ); # runway length, in feet # $az1 = llll2dir_( [$rlat1, $rlon1, $rlat2, $rlon2] ); #} $az1 = round($az1); my @a = (); #push(@a,[10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0]); @a = (10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0); push(@all_airports, \@a); prt("10 $rlat $rlon $rwynm $az1 $dist\n") if (VERB9()); $rwycnt++; ### pgm_exit(1,"TEMP") if ($cnt > 10); } elsif (($type >= 50)&&($type <= 59)) { # on garde aussi les fréquences COM... push(@all_airports,\@header); $comcnt++; } } $done_all = scalar @all_airports; $type = $aptcnt + $rwycnt + $comcnt; my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("Loaded $aptcnt airports, $rwycnt runways, $comcnt coms. total $done_all ($type)...in $elap...\n") if (VERB1()); $done_all = 1; } my %airport_icao = (); sub get_apt_pos($) { my $ara = shift; my $max = scalar @{$ara}; my ($i,$typ,$ra); my $lat = 0; my $lon = 0; my $cnt = 0; for ($i = 0; $i < $max; $i++) { $ra = ${$ara}[$i]; $typ = ${$ra}[0]; if ($typ == 10) { $lat += ${$ra}[1]; $lon += ${$ra}[2]; $cnt++; } } if ($cnt > 0) { $lat /= $cnt; $lon /= $cnt; } return ($lat,$lon); } sub find_leg_ap($$$$) { my ($leg,$pos,$rap,$fudge) = @_; my ($lat1,$lon1,$lat2,$lon2,$lat,$lon); my ($i,$max,$ra,$typ,$icao,$ind,$fnd); $lat1 = ${$leg}[0]; $lon1 = ${$leg}[1]; $lat2 = ${$leg}[2]; $lon2 = ${$leg}[3]; if ($lat1 > $lat2) { $lat = $lat1; $lat1 = $lat2; $lat2 = $lat; } if ($lon1 > $lon2) { $lon = $lon1; $lon1 = $lon2; $lon2 = $lon; } $lat1 -= $fudge; $lat1 += 180 if ($lat1 < -180); $lat1 -= 180 if ($lat1 > 180); $lat2 += $fudge; $lat2 -= 180 if ($lat2 > 180); $lat2 += 180 if ($lat2 < -180); $lon1 -= $fudge; $lon1 += 360 if ($lon1 < -180); $lon1 -= 360 if ($lon1 > 180); $lon2 += $fudge; $lon2 += 360 if ($lon2 < -180); $lon2 -= 360 if ($lon2 > 180); #$lat = ($lat1 + $lat2) / 2; #$lon = ($lon1 + $lon2) / 2; $max = scalar @all_airports; # load ALL airports my @apts = (); for ($i = 0; $ i < $max; $i++) { $ra = $all_airports[$i]; $typ = ${$ra}[0]; if ($typ == 1) { # 0 1 2 3 4 5+ # # elev_ft twr bld icao name my @apt = (); $fnd = 0; $ind = $i; $icao = ${$ra}[4]; # set icao next if (defined $airport_icao{$icao}); push(@apt,$ra); $i++; for (; $i < $max; $i++) { $ra = $all_airports[$i]; $typ = ${$ra}[0]; if ($typ == 1) { $i--; last; } push(@apt,$ra); if ($typ == 10) { # 0 1 2 3 4 5 #push(@a,[10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0]); $lat = ${$ra}[1]; $lon = ${$ra}[2]; if (($lat >= $lat1)&& ($lat <= $lat2)&& ($lon >= $lon1)&& ($lon <= $lon2)) { $fnd++; } } } if ($fnd > 0) { $typ = scalar @apt; prt("Adding ref to $typ apt components ($fnd)\n"); push(@apts,\@apt); } } } $max = scalar @apts; prt("Found $max airports in box $lat1,$lon1,$lat2,$lon2, fudge=$fudge "); if ($max > 0) { $ind = 0; if ($max > 1) { # TODO: Select the ONE closest the TRACK, or ON some other criteria # maybe closest to this point $lat = ${$pos}[0]; $lon = ${$pos}[1]; my ($az1,$az2,$s,$dist); for ($i = 0; $i < $max; $i++) { $ra = $apts[$i]; my ($alat,$alon) = get_apt_pos($ra); my $res = fg_geo_inverse_wgs_84($lat, $lon, $alat, $alon, \$az1, \$az2, \$s); if ($i == 0) { $dist = $s; $ind = $i; } elsif ($s < $dist) { $dist = $s; $ind = $i; } } } # push(@{$rap},$apts[0]); ${$rap} = $apts[$ind]; prt($ind); } prt("\n"); return $max; } sub test_findap() { load_airports(); ###$load_log = 1; # leg: 51.37083300,006.39500000,50.70111100,005.54916700 pos: 50.932615943539,5.83791943554026 s 34 nm on 219 my $leg = [51.370833,6.395,50.701111,5.549167]; my $pos = [50.932615943539,5.83791943554026]; my $fudge = -0.5; my $az1 = 0; my ($ap); while (!find_leg_ap($leg,$pos,\$ap,$fudge)) { $fudge += 0.1; } my $max = scalar @{$ap}; my ($i,$ra,$ra2); for ($i = 0; $i < $max; $i++) { $ra = ${$ap}[$i]; prt(join(" ",@{$ra})."\n"); ##$ra2 = ${$ra}[0]; ##prt(join(" ",@{$ra2})."\n"); } } ######################################### ### MAIN ### ##parse_args(@ARGV); ##process_in_file($in_file); test_findap(); 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); my $verb = VERB2(); 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 =~ /^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 { $in_file = $arg; prt("Set input to [$in_file]\n") if ($verb); } shift @av; } if ($debug_on) { prtw("WARNING: DEBUG is ON!\n"); if (length($in_file) == 0) { $in_file = $def_file; prt("Set DEFAULT input to [$in_file]\n"); } } if (length($in_file) == 0) { pgm_exit(1,"ERROR: No input files found in command!\n"); } if (! -f $in_file) { pgm_exit(1,"ERROR: Unable to find in file [$in_file]! Check name, location...\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(" --out (-o) = Write output to this file.\n"); } # eof - template.pl