Generated: Sun Aug 21 11:11:14 2011 from math_trig.pl 2011/02/23 12.7 KB.
#!/usr/bin/perl -w # NAME: math_trig.pl # AIM: use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; use Math::Trig; my $perl_dir = 'C:\GTools\perl'; unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl'! Check location and \@INC content.\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"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $perl_dir."\\temp.$pgmname.txt"; open_log($outfile); # user variables my $load_log = 0; my $in_file = ''; # 935 YSDU Dubbo -32.217486500,148.577270000 # 05/23 (53.61) 5600 ft. (s=Asphalt) -32.218265,148.576145 # 05: -32.2136987804606,148.583432501246 23: -32.2228307960945,148.568856770273 # 11/29 (119.17) 3494 ft. (s=Asphalt) -32.216708,148.578395 # 11: -32.2190483614171,148.583327271364 29: -32.2143674452924,148.573462981327 # rt:2 [ ATIS: 114.4 (AWIS) Unicom: 134 (CTAF)] fg=e140s40/e148s33 # 1807 YSDU Dubbo (-32.2174865,148.57727) (3) # Type Latitude Logitude Alt. Freq. Range Frequency2 ID Name # VOR -32.21952800, 148.57770800, 935, 11440, 50, 11.0, DU, DUBBO VOR-DME (0.23Km on 169.7, ap1) (SGDist: 230 m, <1km on 169.6) # VDME -32.21968100, 148.57766100, 935, 11440, 50, 0.0, DU, DUBBO VOR-DME DME (0.25Km on 171.4, ap1) (SGDist: 246 m, <1km on 171.3) # NDB -32.21753100, 148.55909400, 0, 251, 70, 0.0, DU, DUBBO NDB (1.71Km on 269.8, ap1) (SGDist: 1.7 km on 269.8) # from : http://www.airservicesaustralia.com/publications/pending/dap/SDUDG01-115.pdf # AD ELEV 935 feet - Altitudes below are MEAN SEA LEVEL (MSL) my $elev_YSDU = 935; # sector A - 007 - 281 in SE to NW my @distancesA = qw( 7.8 7 6 5 4 3 2.4 2.1 2 1.5 ); my @altitudesA = qw( 3700 3440 3120 2800 2480 2160 1960 1880 1850 1700 ); # sector B - 096 - 163 in NW to SE my @distancesB = qw( 9.1 8 7 6 5 4 3.6 3.4 3 2.7 ); my @altitudesB = qw( 3700 3350 3030 2710 2390 2080 1960 1880 1760 1650 ); # sector C - 217 - 219 in NE to SW - in on rwy 23 my @distancesC = qw( 9.1 8 7 6 5 4 3.6 3.4 3 2.7 ); my @altitudesC = qw( 3700 3350 3030 2710 2390 2080 1960 1880 1760 1650); my $debug_on = 0; my $def_file = 'def_file'; ### SIMGEAR constants my $SGD_PI = 3.1415926535; my $SGD_DEGREES_TO_RADIANS = $SGD_PI / 180.0; my $SGD_RADIANS_TO_DEGREES = 180.0 / $SGD_PI; # /** Feet to Meters */ my $SG_FEET_TO_METER = 0.3048; # /** Meters to Feet */ my $SG_METER_TO_FEET = 3.28083989501312335958; #/** Meters to Nautical Miles. 1 nm = 6076.11549 feet */ my $SG_METER_TO_NM = 0.0005399568034557235; #/** Nautical Miles to Meters */ my $SG_NM_TO_METER = 1852.0000; #/** Meters to Statute Miles. */ my $SG_METER_TO_SM = 0.0006213699494949496; #/** Statute Miles to Meters. */ my $SG_SM_TO_METER = 1609.3412196; ### DATA my $a_gil_lat = -31.697287500; my $a_gil_lon = 148.636942500; my $a_dub_lat = -32.2174865; my $a_dub_lon = 148.57727; # RUNWAY ARRARY OFFSETS my $RW_HDG = 0; my $RW_LEN = 1; my $RW_TT1 = 2; my $RW_TT2 = 3; my $RW_CLAT = 4; my $RW_CLON = 5; my $RW_DONE = 6; my $RW_LLAT = 7; my $RW_LLON = 8; my $RW_RLAT = 9; my $RW_RLON = 10; # Hdg Len Title RTit Ctr Lat Ctr Lon # 0 1 2 3 4 5 my @gil_rwys = ( [162.0, 4204, '15', '33', -31.696928, 148.636404, 0, 0, 0, 0, 0] ); #my @gil_navs = ( ["", 0 ] ); my @gil_navs = ( [ ] ); #my @gil_rwys = ( [162.0, 4204], [93.0, 1902] ); my @dub_rwys = ( [53.61, 5600, '05', '23', -32.218265, 148.576145, 0, 0, 0, 0, 0] ); my @dub_navs = ( ["VOR", 114.4], ["NDB", 251] ); my $OL_LAT = 0; my $OL_LON = 1; my $OL_NAV = 2; my $OL_RWY = 3; my %apt_locations = ( # ICAO Center LAT, LON NAVAIDS RUNWAYS 'YGIL' => [$a_gil_lat, $a_gil_lon, \@gil_navs, \@gil_rwys ], 'YSDU' => [$a_dub_lat, $a_dub_lon, \@dub_navs, \@dub_rwys ] ); sub get_locations() { return \%apt_locations; } ### program variables my @warnings = (); my $cwd = cwd(); my $os = $^O; 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" ); } } 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 set_decimal1_stg($) { my $r = shift; ${$r} = int((${$r} + 0.05) * 10) / 10; ${$r} = "0.0" if (${$r} == 0); ${$r} .= ".0" if !(${$r} =~ /\./); } sub set_int_stg($) { my $r = shift; ${$r} = int(${$r} + 0.5); } sub get_dist_stg_nm($) { my ($dist) = @_; my $nm = $dist * $SG_METER_TO_NM; set_decimal1_stg(\$nm); $nm .= "nm"; return $nm; } sub set_runway_ends($$$) { my ($rrwys,$i,$key) = @_; # set ENDS of runway my $rhdg = ${$rrwys}[$i][$RW_HDG]; my $rlen = ${$rrwys}[$i][$RW_LEN]; my $clat = ${$rrwys}[$i][$RW_CLAT]; my $clon = ${$rrwys}[$i][$RW_CLON]; my $rty1 = ${$rrwys}[$i][$RW_TT1]; my $rty2 = ${$rrwys}[$i][$RW_TT2]; my $rwlen2 = ($rlen * $SG_FEET_TO_METER) / 2; my ($elat1,$elon1,$eaz1,$elat2,$elon2,$eaz2); my $hdgr = $rhdg + 180; $hdgr -= 360 if ($hdgr >= 360); fg_geo_direct_wgs_84( $clat, $clon, $rhdg, $rwlen2, \$elat1, \$elon1, \$eaz1 ); fg_geo_direct_wgs_84( $clat, $clon, $hdgr, $rwlen2, \$elat2, \$elon2, \$eaz2 ); ${$rrwys}[$i][$RW_DONE] = 1; ${$rrwys}[$i][$RW_LLAT] = $elat1; ${$rrwys}[$i][$RW_LLON] = $elon1; ${$rrwys}[$i][$RW_RLAT] = $elat2; ${$rrwys}[$i][$RW_RLON] = $elon2; my ($az1,$az2,$dist); fg_geo_inverse_wgs_84 ($elat1,$elon1,$elat2,$elon2,\$az1,\$az2,\$dist); $dist = $dist * $SG_METER_TO_FEET; set_int_stg(\$az1); set_int_stg(\$az2); set_int_stg(\$dist); # init: YSDU: 23: -32.2136987804606,148.583432501246 05: -32.2228307960945,148.568856770273 234 5600 54 vs 53.61 5600 # init: YGIL: 33: -31.7024233216057,148.638492502638 15: -31.6914326394609,148.634315743548 342 4204 162 vs 162 4204 #prt("init: $key: $rty2: $elat1,$elon1 $az1 $rty1: $elat2,$elon2 $az1 $dist $az2 vs $rhdg $rlen\n"); prt("init: $key: $rty2:$az1: $elat1,$elon1 $rty1:$az2: $elat2,$elon2\n"); } sub init_runway_array() { my $rl = get_locations(); my ($key,$i,$cnt,$rrwys); foreach $key (keys %{$rl}) { $rrwys = ${$rl}{$key}[$OL_RWY]; $cnt = scalar @{$rrwys}; for ($i = 0; $i < $cnt; $i++) { set_runway_ends($rrwys,$i,$key); } } } sub get_dist_nm_for_alt_ft($) { my $alt_ft = shift; my $tan3 = tan( 3 * $SGD_DEGREES_TO_RADIANS ); my $alt_m = $alt_ft * $SG_FEET_TO_METER; my $dist_m = $alt_m / $tan3; my $dist_nm = $dist_m * $SG_METER_TO_NM; return $dist_nm; } sub show_calcs() { my ($alt_ft,$alt_m,$dist_m,$dist_nm,$tmp1,$tmp2); my $tan3 = tan( 3 * $SGD_DEGREES_TO_RADIANS ); $alt_ft = 0; # start from the deck prt("Computed distances (nm), at 3 degrees, for 0 to 2500 feet.\n"); while ($alt_ft <= 2500) { $alt_m = $alt_ft * $SG_FEET_TO_METER; $dist_m = $alt_m / $tan3; $dist_nm = $dist_m * $SG_METER_TO_NM; $tmp2 = get_dist_nm_for_alt_ft($alt_ft); set_decimal1_stg(\$dist_nm); set_decimal1_stg(\$tmp2); $tmp1 = $alt_ft; set_int_stg(\$tmp1); set_int_stg(\$alt_m); $tmp1 = " $tmp1" while (length($tmp1) < 4); prt("Dist $dist_nm nm, alt $tmp1 feet ($alt_m m) ($tmp2)\n"); $alt_ft += 250; } prt("Computed altitude (ft), at 3 degrees, for distances 1 - 9 nm.\n"); $dist_nm = 1; while ($dist_nm < 10) { $dist_m = $dist_nm * $SG_NM_TO_METER; $alt_m = $dist_m * $tan3; $alt_ft = $alt_m * $SG_METER_TO_FEET; $tmp1 = $dist_nm; set_int_stg(\$alt_ft); $alt_ft = " $alt_ft" while (length($alt_ft) < 4); set_int_stg(\$alt_m); prt("Dist $dist_nm nm, alt $alt_ft feet ($alt_m m)\n"); $dist_nm += 1; } } sub show_tan3() { my $tan3 = tan( 3 * $SGD_DEGREES_TO_RADIANS ); my $angle = atan($tan3) * $SGD_RADIANS_TO_DEGREES; set_int_stg(\$angle); prt("tan ( $angle ) = $tan3\n"); } # atan() is the complementary function of tan(), # which means that a == tan(atan(a)) for every value of a # that is within range... sub do_calcs($$$$) { my ($rd,$ra,$elev,$sect) = @_; my ($dist_nm, $alt_ft,$angle,$tdist_nm); my $max = scalar @{$rd}; my ($i,$dist_m,$alt_m,$ang_rad,$ratio,$ang_rad2); my $tan3 = tan( 3 * $SGD_DEGREES_TO_RADIANS ); prt("Calulations for $sect...\n"); my $l_elev = ${$ra}[-1]; for ($i = 0; $i < $max; $i++) { $dist_nm = ${$rd}[$i]; # WOW, look at this strangeness!!! $alt_ft = ${$ra}[$i] - $l_elev + $elev; # ========= ??????????? ========== $dist_m = $dist_nm * $SG_NM_TO_METER; $alt_m = $alt_ft * $SG_METER_TO_FEET; $ratio = ($alt_m / $dist_m); $ang_rad2 = atan($ratio); # OR $ang_rad = atan2($alt_m,$dist_m); $angle = $ang_rad * $SGD_RADIANS_TO_DEGREES; # *********** ??????????? ************* $angle /= 10; # WHY THIS??? # *********** ??????????? ************* $tdist_nm = get_dist_nm_for_alt_ft($alt_ft); set_decimal1_stg(\$angle); set_int_stg(\$dist_m); set_int_stg(\$alt_m); $dist_nm .= ".0" if !($dist_nm =~ /\./); #prt( "Dist $dist_nm nm ($dist_m), alt $alt_ft ($alt_m), angle $angle deg ($ratio, $ang_rad)\n"); $alt_ft = " $alt_ft" while (length($alt_ft) < 4); set_decimal1_stg(\$tdist_nm); prt( "Dist $dist_nm nm, alt $alt_ft ($alt_m), angle $angle deg ($tdist_nm - $ratio $ang_rad2)\n"); } } sub get_feet_per_min($$$$) { my ($aspd_kt,$dist_km,$agl_ft,$dbg) = @_; my $mps = $aspd_kt * $SG_NM_TO_METER / 3600; # convert speed to meters/second my $time = ($dist_km * 1000) / $mps; my $rate_mps = ( $agl_ft * $SG_FEET_TO_METER ) / $time; my $rate_fpm = ($rate_mps * $SG_METER_TO_FEET) * 60; if ($dbg) { my ($tmp1,$tmp2,$tmp3,$tmp4); $tmp1 = $mps; $tmp2 = $time; $tmp3 = $rate_fpm; $tmp4 = $dist_km; set_decimal1_stg(\$tmp1); set_decimal1_stg(\$tmp2); set_decimal1_stg(\$tmp3); set_decimal1_stg(\$tmp4); prt("An spd ${aspd_kt}Kt=${tmp1}mps, dist=${dist_km}KM. time=${tmp2}secs. rate ${tmp3}fpm\n"); } return $rate_fpm; } sub do_calc2() { my $aspd = 100; # air speed - knots my $dist = 10; # distance to a/p - KM my $agl = 1500; # current AGL - feet # so must decend x feet, in the time taken to cover the distance KM while ($dist <= 20) { get_feet_per_min($aspd,$dist,$agl,1); $dist += 2; } } ######################################### ### MAIN ### parse_args(@ARGV); show_tan3(); init_runway_array(); #do_calc2(); #show_calcs(); #do_calcs(\@distancesC,\@altitudesC,$elev_YSDU,"Section C"); #do_calcs(\@distancesB,\@altitudesB,$elev_YSDU,"Section B"); #do_calcs(\@distancesA,\@altitudesA,$elev_YSDU,"Section A"); pgm_exit(0,""); ######################################## sub give_help { prt("$pgmname: version 0.0.1 2010-09-11\n"); prt("Usage: $pgmname [options] in-file\n"); prt("Options:\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); } sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have following argument!\n") if (!@av); } sub parse_args { my (@av) = @_; my ($arg,$sarg); 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)"); } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { $in_file = $arg; prt("Set input to [$in_file]\n"); } shift @av; } } # eof - template.pl