Generated: Sun Aug 21 11:11:29 2011 from solve-ok.pl 2011/07/21 51.4 KB.
#!/usr/bin/perl -w # NAME: solve.pl # AIM: Given a position, decide the track to take to best arrive at a 'circuit' # Quite specialized! use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; use IO::Socket; use Term::ReadKey; use Time::HiRes qw( usleep gettimeofday tv_interval ); 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); ### constants my $SGD_PI = 3.1415926535; my $SGD_DEGREES_TO_RADIANS = $SGD_PI / 180.0; my $SGD_RADIANS_TO_DEGREES = 180.0 / $SGD_PI; my $DEF_GS = 3; my $ATAN3 = atan( $DEF_GS * $SGD_DEGREES_TO_RADIANS ); # /** Feet to Meters */ my $SG_FEET_TO_METER = 0.3048; # /** Meters to Feet */ my $SG_METER_TO_FEET = 3.28083989501312335958; my $SG_NM_TO_METER = 1852; my $SG_METER_TO_NM = 0.0005399568034557235; # user variables my $load_log = 1; my $in_file = ''; my $bad_latlon = 200; my $in_lat = $bad_latlon; my $in_lon = $bad_latlon; my $graf_file = "tempgraf.gif"; my $graf_bat = $perl_dir."\\tempgraf.bat"; my $debug_on = 1; my $def_latlon = "-31.6,148.6"; my $stand_glide_degs = 3; # degrees my $stand_patt_alt = 1000; # feet my $stand_cross_nm = 2.1; # nm, but this will depend on the aircraft ### program variables my @warnings = (); my $cwd = cwd(); my $os = $^O; my $a_gil_lat = -31.697287500; my $a_gil_lon = 148.636942500; my $a_dub_lat = -32.2174865; my $a_dub_lon = 148.57727; # rough Gil circuit my $tl_lat = -31.684063; my $tl_lon = 148.614120; my $bl_lat = -31.723495; my $bl_lon = 148.633003; my $br_lat = -31.716778; my $br_lon = 148.666992; my $tr_lat = -31.672960; my $tr_lon = 148.649139; # RUNWAY ARRAY OFFSETS my $RW_LEN = 0; my $RW_HDG = 1; my $RW_REV = 2; my $RW_TT1 = 3; my $RW_TT2 = 4; my $RW_CLAT = 5; my $RW_CLON = 6; my $RW_LLAT = 7; my $RW_LLON = 8; my $RW_RLAT = 9; my $RW_RLON = 10; my $RW_DONE = 11; # Len Hdg Rev Title RTit Ctr Lat Ctr Lon # 0 1 2 3 4 5 6 7 8 9 10 11 my @gil_patt = (); my @gil_rwys = ( [4204, 162.0, 0, '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_patt = ( [ ] ); my @dub_rwys = ( [5600, 53.61, 0, '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 $OL_PAT = 4; my %apt_locations = ( # ICAO Center LAT, LON NAVAIDS RUNWAYS 'YGIL' => [$a_gil_lat, $a_gil_lon, \@gil_navs, \@gil_rwys, \@gil_patt ], 'YSDU' => [$a_dub_lat, $a_dub_lon, \@dub_navs, \@dub_rwys, \@dub_patt ] ); sub get_locations() { return \%apt_locations; } # DEBUG my $dbg_01 = 0; my $dbg_02 = 0; 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 in_world_range($$) { my ($lat,$lon) = @_; if (($lat < -90) || ($lat > 90) || ($lon < -180) || ($lon > 180) ) { return 0; } return 1; } # ============================================================ # # SimGear Services, rendered in perl # ============================================================ # # dot(const SGVec3<T>& v1, const SGVec3<T>& v2) # { return v1(0)*v2(0) + v1(1)*v2(1) + v1(2)*v2(2); } # Given 2 Vectors3, return the dot product sub scalar_dot_product($$) { my ($rv1,$rv2) = @_; return ${$rv1}[0] * ${$rv2}[0] + ${$rv1}[1] * ${$rv2}[1] + ${$rv1}[2] * ${$rv2}[2]; } # In dimension 2, the dot product of vectors [a,b] and [c,d] is ac + bd sub scalar_dot_product2($$$$) { my ($v1x,$v1y,$v2x,$v2y) = @_; return ($v1x * $v2x) + ($v1y * $v2y); } # The euclidean norm of the vector, that is what most people call length # norm(const SGVec3<T>& v) # { return sqrt(dot(v, v)); } # Given a Vector3, return length sub norm_vector_length($) { my ($rv) = @_; return sqrt(scalar_dot_product($rv, $rv)); } sub norm_vector_length2($$) { my ($vx,$vy) = @_; return sqrt(scalar_dot_product2($vx, $vy, $vx, $vy)); } sub process_in_file($) { my ($inf) = @_; if (! open INF, "<$inf") { pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); } my @lines = <INF>; 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"); } } } sub set_int_stg($) { my $r = shift; ${$r} = int(${$r} + 0.5); } sub set_dist_stg($) { my $r = shift; set_int_stg($r); my $r5 = sprintf("%5d",${$r}); ${$r} = $r5; } sub set_hdg_stg($) { my $r = shift; set_int_stg($r); my $r3 = sprintf("%3d",${$r}); ${$r} = $r3; } sub set_lat_stg($) { my ($rl) = @_; ${$rl} = sprintf("%2.7f",${$rl}); } sub set_lon_stg($) { my ($rl) = @_; ${$rl} = sprintf("%3.7f",${$rl}); } 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 get_dist_stg_nm($) { my ($dist) = @_; my $nm = $dist * $SG_METER_TO_NM; set_decimal1_stg(\$nm); $nm .= "nm"; return $nm; } # ============================================ sub show_distance_heading($$$$) { my ($lat1,$lon1,$lat2,$lon2) = @_; my ($az1,$az2,$dist); fg_geo_inverse_wgs_84 ($lat1,$lon1,$lat2,$lon2,\$az1,\$az2,\$dist); $dist = get_dist_stg_nm($dist); set_hdg_stg(\$az1); prt("Is $dist, on heading $az1\n"); } sub show_rw_patt($$) { my ($key,$rpatts) = @_; my $cnt = scalar @{$rpatts}; prt("Display of $cnt patterns/circuits for $key...\n"); my ($i,$lat1,$lon1,$lat2,$lon2,$j); for ($i = 0; $i < $cnt; $i++) { for ($j = 0; $j < 8; $j += 2) { $lat1 = ${$rpatts}[$i][$j+0]; $lon1 = ${$rpatts}[$i][$j+1]; if ($j == 6) { $lat2 = ${$rpatts}[$i][0]; $lon2 = ${$rpatts}[$i][1]; } else { $lat2 = ${$rpatts}[$i][$j+2]; $lon2 = ${$rpatts}[$i][$j+3]; } prt("$i:$j: $lat1,$lon1 $lat2,$lon2\n"); show_distance_heading($lat1,$lon1,$lat2,$lon2); } } } sub set_runway_ends_and_patt($$$$) { my ($rrwys,$i,$key,$rpatts) = @_; # set ENDS of runway my $rlen = ${$rrwys}[$i][$RW_LEN]; my $rhdg = ${$rrwys}[$i][$RW_HDG]; 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); ${$rrwys}[$i][$RW_REV] = $hdgr; 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_LLAT] = $elat1; ${$rrwys}[$i][$RW_LLON] = $elon1; ${$rrwys}[$i][$RW_RLAT] = $elat2; ${$rrwys}[$i][$RW_RLON] = $elon2; ${$rrwys}[$i][$RW_DONE] = 1; 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"); # We have the RUNWAY ends - now extend out to first turn to crosswind leg, and turn to final # but by how MUCH - ok decide from runway end, out to where it is a 3 degree glide from 1000 feet $dist = ($stand_patt_alt * $SG_FEET_TO_METER) / tan($stand_glide_degs * $SGD_DEGREES_TO_RADIANS); my ($plat11,$plon11,$plat12,$plon12,$plat13,$plon13,$paz1); my ($plat21,$plon21,$plat22,$plon22,$plat23,$plon23,$paz2); my ($hdg1L,$hdg1R,$crossd); fg_geo_direct_wgs_84( $clat, $clon, $rhdg, $rwlen2+$dist, \$plat11, \$plon11, \$paz1 ); fg_geo_direct_wgs_84( $clat, $clon, $hdgr, $rwlen2+$dist, \$plat21, \$plon21, \$paz2 ); $hdg1L = normalised_hdg($rhdg - 90); $hdg1R = normalised_hdg($rhdg + 90); $crossd = $stand_cross_nm * $SG_NM_TO_METER; # ON $rhdg to $elat1, $elon1 to ... turn point, go LEFT and to get NEXT points, this end fg_geo_direct_wgs_84( $plat11, $plon11, $hdg1L, $crossd, \$plat12, \$plon12, \$paz1 ); fg_geo_direct_wgs_84( $plat21, $plon21, $hdg1L, $crossd, \$plat13, \$plon13, \$paz1 ); # from the turn point, go LEFT and RIGHT to get NEXT points, this other end fg_geo_direct_wgs_84( $plat21, $plon21, $hdg1R, $crossd, \$plat22, \$plon22, \$paz2 ); fg_geo_direct_wgs_84( $plat11, $plon11, $hdg1R, $crossd, \$plat23, \$plon23, \$paz2 ); if ($dbg_01) { # now we have 4 points, either side of the runway prt("On $rhdg, at $plat11,$plon11 turn $hdg1L to $plat12,$plon12\n"); show_distance_heading($plat11,$plon11,$plat12,$plon12); prt("On $hdg1L at $plat12,$plon12, turn $hdgr to $plat13,$plon13\n"); show_distance_heading($plat12,$plon12,$plat13,$plon13); prt("On $hdgr at $plat13,$plon13 turn $hdg1R to $plat21,$plon21\n"); show_distance_heading($plat13,$plon13,$plat21,$plon21); prt("On $hdg1R at $plat21,$plon21 turn $rhdg to $elat1,$elon1\n"); show_distance_heading($plat21,$plon21,$elat1,$elon2); prt("\n"); prt("On $hdgr at $plat21,$plon21 turn $hdg1R to $plat22,$plon22\n"); show_distance_heading($plat21,$plon21,$plat22,$plon22); prt("On $hdg1R at $plat22,$plon22 turn $rhdg to $plat23,$plon23\n"); show_distance_heading($plat22,$plon22,$plat23,$plon23); prt("On $rhdg at $plat23,$plon23 turn $hdg1L to $plat11,$plon11\n"); show_distance_heading($plat23,$plon23,$plat11,$plon11); prt("On $hdg1L at $plat11,$plon11 turn $hdgr to $elat2,$elon2\n"); show_distance_heading($plat11,$plon11,$elat2,$elon2); prt("\n"); } @{$rpatts} = (); push(@{$rpatts}, [$plat11,$plon11,$plat12,$plon12,$plat13,$plon13,$plat21,$plon21]); push(@{$rpatts}, [$plat21,$plon21,$plat22,$plon22,$plat23,$plon23,$plat11,$plon11]); } sub init_runway_array() { my $rl = get_locations(); my ($key,$i,$cnt,$rrwys,$rpatts); foreach $key (keys %{$rl}) { $rrwys = ${$rl}{$key}[$OL_RWY]; $rpatts = ${$rl}{$key}[$OL_PAT]; $cnt = scalar @{$rrwys}; for ($i = 0; $i < $cnt; $i++) { set_runway_ends_and_patt($rrwys,$i,$key,$rpatts); } } if ($dbg_02) { foreach $key (keys %{$rl}) { $rpatts = ${$rl}{$key}[$OL_PAT]; show_rw_patt($key,$rpatts); } } # pgm_exit(1,"Temp exit"); } sub get_runways_and_pattern($$) { my ($rh,$key) = @_; my $rl = get_locations(); my ($rrwys,$rpatts); if (defined ${$rl}{$key}) { $rrwys = ${$rl}{$key}[$OL_RWY]; $rpatts = ${$rl}{$key}[$OL_PAT]; ${$rh}{'runways'} = $rrwys; ${$rh}{'pattern'} = $rpatts; ${$rh}{'airport'} = $key; } else { pgm_exit(1,"ERROR: Key [$key] NOT in locations!\n"); } } # ============================================ sub set_circuit_values($$) { my ($rh,$show) = @_; my ($az1,$az2,$dist); if ($show) { #prt("Set, show circuit...\nTL ".${$rh}{'tl_lat'}.",".${$rh}{'tl_lon'}."\nBL ". # ${$rh}{'bl_lat'}.",".${$rh}{'bl_lon'}."\nBR ". # ${$rh}{'br_lat'}.",".${$rh}{'br_lon'}."\nTR ". # ${$rh}{'tr_lat'}.",".${$rh}{'tr_lon'}."\n"); my ($tllat,$tllon,$bllat,$bllon,$brlat,$brlon,$trlat,$trlon); $tllat = ${$rh}{'tl_lat'}; $tllon = ${$rh}{'tl_lon'}; $bllat = ${$rh}{'bl_lat'}; $bllon = ${$rh}{'bl_lon'}; $brlat = ${$rh}{'br_lat'}; $brlon = ${$rh}{'br_lon'}; $trlat = ${$rh}{'tr_lat'}; $trlon = ${$rh}{'tr_lon'}; set_lat_stg(\$tllat); set_lat_stg(\$bllat); set_lat_stg(\$brlat); set_lat_stg(\$trlat); set_lon_stg(\$tllon); set_lon_stg(\$bllon); set_lon_stg(\$brlon); set_lon_stg(\$trlon); prt("Set, show circuit...\nTL $tllat,$tllon\nBL ". "$bllat,$bllon\nBR ". "$brlat,$brlon\nTR ". "$trlat,$trlon\n"); } # anti-clockwise around circuit fg_geo_inverse_wgs_84 (${$rh}{'tl_lat'},${$rh}{'tl_lon'},${$rh}{'bl_lat'},${$rh}{'bl_lon'},\$az1,\$az2,\$dist); ${$rh}{'l1_az1'} = $az1; ${$rh}{'l1_az2'} = $az2; ${$rh}{'l1_dist'} = $dist; if ($show) { set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("l1 $dist m, on $az1 (tl2bl)\n"); } fg_geo_inverse_wgs_84 (${$rh}{'bl_lat'},${$rh}{'bl_lon'},${$rh}{'br_lat'},${$rh}{'br_lon'},\$az1,\$az2,\$dist); ${$rh}{'l2_az1'} = $az1; ${$rh}{'l2_az2'} = $az2; ${$rh}{'l2_dist'} = $dist; if ($show) { set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("l2 $dist m, on $az1 (bl2br)\n"); } fg_geo_inverse_wgs_84 (${$rh}{'br_lat'},${$rh}{'br_lon'},${$rh}{'tr_lat'},${$rh}{'tr_lon'},\$az1,\$az2,\$dist); ${$rh}{'l3_az1'} = $az1; ${$rh}{'l3_az2'} = $az2; ${$rh}{'l3_dist'} = $dist; if ($show) { set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("l3 $dist m, on $az1 (br2tr)\n"); } fg_geo_inverse_wgs_84 (${$rh}{'tr_lat'},${$rh}{'tr_lon'},${$rh}{'tl_lat'},${$rh}{'tl_lon'},\$az1,\$az2,\$dist); ${$rh}{'l4_az1'} = $az1; ${$rh}{'l4_az2'} = $az2; ${$rh}{'l4_dist'} = $dist; if ($show) { set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("l4 $dist m, on $az1 (tr2tl)\n"); } } sub set_most_values_plus($$$$$$) { my ($rh,$show,$u_lat,$u_lon,$t_lat,$t_lon) = @_; if (!defined ${$rh}{'user_points'}) { ${$rh}{'user_points'} = []; } my $ru = ${$rh}{'user_points'}; push(@{$ru}, [$u_lat,$u_lon,$t_lat,$t_lon]); } sub set_min_max($$$$$$) { my ($rmaxlat,$rminlat,$rmaxlon,$rminlon,$lat,$lon) = @_; ${$rmaxlat} = $lat if ($lat > ${$rmaxlat}); ${$rminlat} = $lat if ($lat < ${$rminlat}); ${$rmaxlon} = $lon if ($lon > ${$rmaxlon}); ${$rminlon} = $lon if ($lon < ${$rminlon}); } sub add_img_line($$$$$) { my ($rh,$lat1,$lon1,$lat2,$lon2) = @_; my $rmsg = ${$rh}{'rmsg'}; my ($w_ind1,$h_ind1,$w_ind2,$h_ind2); my ($maxlat,$minlat,$maxlon,$minlon); my ($w_dpp,$h_dpp); my ($sqwid,$sqhgt); $maxlat = ${$rh}{'max_lat'}; $minlat = ${$rh}{'min_lat'}; $maxlon = ${$rh}{'max_lon'}; $minlon = ${$rh}{'min_lon'}; $w_dpp = ${$rh}{'w_dpp'}; $h_dpp = ${$rh}{'h_dpp'}; $sqwid = ${$rh}{'sq_wid_adj'}; $sqhgt = ${$rh}{'sq_hgt_adj'}; $w_ind1 = int((($lon1 - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind1 = int((($lat1 - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind1 = $sqhgt - $h_ind1; $h_ind1 += 1 if ($h_ind1 == 0); $w_ind1 += 1 if ($w_ind1 == 0); $h_ind1 -= 1 if ($h_ind1 == $sqhgt); $w_ind1 -= 1 if ($w_ind1 == $sqwid); # ${$rmsg} .= "-draw \"circle ".($w_ind1-1).",$h_ind1 ".($w_ind1+1).",$h_ind1\" "; $w_ind2 = int((($lon2 - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind2 = int((($lat2 - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind2 = $sqhgt - $h_ind2; #$w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 += 1 if ($h_ind2 == 0); $w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 -= 1 if ($h_ind2 == $sqhgt); $w_ind2 -= 1 if ($w_ind2 == $sqwid); # ${$rmsg} .= "-draw \"circle ".($w_ind2-1).",$h_ind2 ".($w_ind2+1).",$h_ind2\" "; ${$rmsg} .= "-draw \"line $w_ind1,$h_ind1 $w_ind2,$h_ind2\" "; } sub paint_user_points($$) { my ($rh,$show) = @_; my ($tllat,$tllon,$bllat,$bllon,$brlat,$brlon,$trlat,$trlon); $tllat = ${$rh}{'tl_lat'}; $tllon = ${$rh}{'tl_lon'}; $bllat = ${$rh}{'bl_lat'}; $bllon = ${$rh}{'bl_lon'}; $brlat = ${$rh}{'br_lat'}; $brlon = ${$rh}{'br_lon'}; $trlat = ${$rh}{'tr_lat'}; $trlon = ${$rh}{'tr_lon'}; my ($minlat,$maxlat,$minlon,$maxlon); my ($latdegs,$londegs,$sqwid,$sqhgt); $minlat = $bad_latlon; $maxlat = -$bad_latlon; $minlon = $bad_latlon; $maxlon = -$bad_latlon; my ($u_lat,$u_lon,$t_lat,$t_lon,$i,$cnt,$ru); # TEST SET OF 4, PLUS USRE'S POSITION $maxlat = $tllat if ($tllat > $maxlat); $maxlat = $bllat if ($bllat > $maxlat); $maxlat = $brlat if ($brlat > $maxlat); $maxlat = $trlat if ($trlat > $maxlat); $minlat = $tllat if ($tllat < $minlat); $minlat = $bllat if ($bllat < $minlat); $minlat = $brlat if ($brlat < $minlat); $minlat = $trlat if ($trlat < $minlat); $maxlon = $tllon if ($tllon > $maxlon); $maxlon = $bllon if ($bllon > $maxlon); $maxlon = $brlon if ($brlon > $maxlon); $maxlon = $trlon if ($trlon > $maxlon); $minlon = $tllon if ($tllon < $minlon); $minlon = $bllon if ($bllon < $minlon); $minlon = $brlon if ($brlon < $minlon); $minlon = $trlon if ($trlon < $minlon); # expand by User points if (defined ${$rh}{'user_points'}) { $ru = ${$rh}{'user_points'}; $cnt = scalar @{$ru}; for ($i = 0; $i < $cnt; $i++) { $u_lat = ${$ru}[$i][0]; $u_lon = ${$ru}[$i][1]; $t_lat = ${$ru}[$i][2]; $t_lon = ${$ru}[$i][3]; $maxlat = $u_lat if ($u_lat > $maxlat); $minlat = $u_lat if ($u_lat < $minlat); $maxlon = $u_lon if ($u_lon > $maxlon); $minlon = $u_lon if ($u_lon < $minlon); } } my $key = ''; my $rcnt = 0; my $pcnt = 0; my ($rrwys,$rpatts); my ($elat1,$elon1,$elat2,$elon2); my ($plat11,$plon11,$plat12,$plon12,$plat13,$plon13,$plat21,$plon21); #my ($plat21,$plon21,$plat22,$plon22,$plat23,$plon23,$plat11,$plon11); if ((defined ${$rh}{'runways'})&&(defined ${$rh}{'pattern'})&&(defined ${$rh}{'airport'})) { $rrwys = ${$rh}{'runways'}; $rpatts = ${$rh}{'pattern'}; $key = ${$rh}{'airport'}; $rcnt = scalar @{$rrwys}; $pcnt = scalar @{$rpatts}; prt("Adding $rcnt runways, and $pcnt patterns...\n"); for ($i = 0; $i < $rcnt; $i++) { $elat1 = ${$rrwys}[$i][$RW_LLAT]; $elon1 = ${$rrwys}[$i][$RW_LLON]; $elat2 = ${$rrwys}[$i][$RW_RLAT]; $elon2 = ${$rrwys}[$i][$RW_RLON]; set_min_max(\$maxlat,\$minlat,\$maxlon,\$minlon,$elat1,$elon1); set_min_max(\$maxlat,\$minlat,\$maxlon,\$minlon,$elat2,$elon2); } for ($i = 0; $i < $pcnt; $i++) { # 0 1 2 3 4 5 6 7 # push(@{$rpatts}, [$plat11,$plon11,$plat12,$plon12,$plat13,$plon13,$plat21,$plon21]); # push(@{$rpatts}, [$plat21,$plon21,$plat22,$plon22,$plat23,$plon23,$plat11,$plon11]); $plat11 = ${$rpatts}[$i][0]; $plon11 = ${$rpatts}[$i][1]; $plat12 = ${$rpatts}[$i][2]; $plon12 = ${$rpatts}[$i][3]; $plat13 = ${$rpatts}[$i][4]; $plon13 = ${$rpatts}[$i][5]; $plat21 = ${$rpatts}[$i][6]; $plon21 = ${$rpatts}[$i][7]; set_min_max(\$maxlat,\$minlat,\$maxlon,\$minlon,$plat11,$plon11); set_min_max(\$maxlat,\$minlat,\$maxlon,\$minlon,$plat12,$plon12); set_min_max(\$maxlat,\$minlat,\$maxlon,\$minlon,$plat13,$plon13); set_min_max(\$maxlat,\$minlat,\$maxlon,\$minlon,$plat21,$plon21); } } ${$rh}{'max_lat'} = $maxlat; ${$rh}{'min_lat'} = $minlat; ${$rh}{'max_lon'} = $maxlon; ${$rh}{'min_lon'} = $minlon; my $lon_factor = 2; $latdegs = $maxlat - $minlat; $londegs = ($maxlon - $minlon) * $lon_factor; ${$rh}{'lon_degs'} = $londegs; ${$rh}{'lat_degs'} = $latdegs; $sqhgt = int(($latdegs * 10000) + 0.5); $sqwid = int(($londegs * 10000) + 0.5); ${$rh}{'sq_wid'} = $sqwid; ${$rh}{'sq_hgt'} = $sqhgt; # scale the image DOWN/up my $targ_wid = 400; my $ratio = $sqwid / $sqhgt; #if (($sqwid > $targ_wid) || ($sqhgt > $targ_wid)) { if ($ratio > 1) { # width > height $sqwid = $targ_wid; # set target width $sqhgt = int($targ_wid / $ratio); # and calculate NEW height } else { # height > width = set target height, adjust width accordingly $sqwid = int($targ_wid * $ratio); # calculate width $sqhgt = $targ_wid; # and set target width } #} ${$rh}{'sq_wid_adj'} = $sqwid; ${$rh}{'sq_hgt_adj'} = $sqhgt; my ($w_dpp,$h_dpp,$w_ind1,$h_ind1,$w_ind2,$h_ind2,$w_ind3,$h_ind3,$w_ind4,$h_ind4,$msg); my ($h_indu,$w_indu,$h_indt,$w_indt); $w_dpp = ($sqwid / $londegs) * $lon_factor; $h_dpp = $sqhgt / $latdegs; ${$rh}{'w_dpp'} = $w_dpp; ${$rh}{'h_dpp'} = $h_dpp; ${$rh}{'rmsg'} = \$msg; # Imagmagick colors - http://www.imagemagick.org/script/color.php $msg = "convert -size ${sqwid}x${sqhgt} xc:wheat +antialias -fill white "; # -stroke Gold -draw "path 'M 20,70 A 1,1 0 0,1 80,50'" \ # -stroke DodgerBlue -draw "line 30,10 50,80" \ # -stroke Red -draw "circle 80,60 82,60" \ # test.gif if (length($key) && $rcnt) { if ($pcnt) { $msg .= "-stroke SlateGray "; for ($i = 0; $i < $pcnt; $i++) { # 0 1 2 3 4 5 6 7 # push(@{$rpatts}, [$plat11,$plon11,$plat12,$plon12,$plat13,$plon13,$plat21,$plon21]); # push(@{$rpatts}, [$plat21,$plon21,$plat22,$plon22,$plat23,$plon23,$plat11,$plon11]); $plat11 = ${$rpatts}[$i][0]; $plon11 = ${$rpatts}[$i][1]; $plat12 = ${$rpatts}[$i][2]; $plon12 = ${$rpatts}[$i][3]; $plat13 = ${$rpatts}[$i][4]; $plon13 = ${$rpatts}[$i][5]; $plat21 = ${$rpatts}[$i][6]; $plon21 = ${$rpatts}[$i][7]; if ($i == 1) { add_img_line($rh,$plat11,$plon11,$plat12,$plon12); add_img_line($rh,$plat12,$plon12,$plat13,$plon13); add_img_line($rh,$plat13,$plon13,$plat21,$plon21); add_img_line($rh,$plat21,$plon21,$plat11,$plon11); } } } # set color $msg .= "-stroke blue "; for ($i = 0; $i < $rcnt; $i++) { $elat1 = ${$rrwys}[$i][$RW_LLAT]; $elon1 = ${$rrwys}[$i][$RW_LLON]; $elat2 = ${$rrwys}[$i][$RW_RLAT]; $elon2 = ${$rrwys}[$i][$RW_RLON]; $w_ind1 = int((($elon1 - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind1 = int((($elat1 - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind1 = $sqhgt - $h_ind1; $h_ind1 += 1 if ($h_ind1 == 0); $w_ind1 += 1 if ($w_ind1 == 0); $h_ind1 -= 1 if ($h_ind1 == $sqhgt); $w_ind1 -= 1 if ($w_ind1 == $sqwid); $msg .= "-draw \"circle ".($w_ind1-1).",$h_ind1 ".($w_ind1+1).",$h_ind1\" "; $w_ind2 = int((($elon2 - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind2 = int((($elat2 - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind2 = $sqhgt - $h_ind2; #$w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 += 1 if ($h_ind2 == 0); $w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 -= 1 if ($h_ind2 == $sqhgt); $w_ind2 -= 1 if ($w_ind2 == $sqwid); $msg .= "-draw \"circle ".($w_ind2-1).",$h_ind2 ".($w_ind2+1).",$h_ind2\" "; $msg .= "-draw \"line $w_ind1,$h_ind1 $w_ind2,$h_ind2\" "; } } # set color $msg .= "-stroke black "; # tllat,$tllon on square $w_ind1 = int((($tllon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind1 = int((($tllat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind1 = $sqhgt - $h_ind1; $h_ind1 += 1 if ($h_ind1 == 0); $w_ind1 += 1 if ($w_ind1 == 0); $h_ind1 -= 1 if ($h_ind1 == $sqhgt); $w_ind1 -= 1 if ($w_ind1 == $sqwid); $msg .= "-draw \"circle ".($w_ind1-1).",$h_ind1 ".($w_ind1+1).",$h_ind1\" "; # bllat,$bllon on square $w_ind2 = int((($bllon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind2 = int((($bllat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind2 = $sqhgt - $h_ind2; #$w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 += 1 if ($h_ind2 == 0); $w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 -= 1 if ($h_ind2 == $sqhgt); $w_ind2 -= 1 if ($w_ind2 == $sqwid); $msg .= "-draw \"circle ".($w_ind2-1).",$h_ind2 ".($w_ind2+1).",$h_ind2\" "; # brlat,$brlon on square $w_ind3 = int((($brlon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind3 = int((($brlat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind3 = $sqhgt - $h_ind3; #$w_ind3 += 1 if ($w_ind3 == 0); $h_ind3 += 1 if ($h_ind3 == 0); $w_ind3 += 1 if ($w_ind3 == 0); $h_ind3 -= 1 if ($h_ind3 == $sqhgt); $w_ind3 -= 1 if ($w_ind3 == $sqwid); $msg .= "-draw \"circle ".($w_ind3-1).",$h_ind3 ".($w_ind3+1).",$h_ind3\" "; # trlat,$trlon on square $w_ind4 = int((($trlon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind4 = int((($trlat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind4 = $sqhgt - $h_ind4; #$w_ind4 += 1 if ($w_ind4 == 0); $h_ind4 += 1 if ($h_ind4 == 0); $w_ind4 += 1 if ($w_ind4 == 0); $h_ind4 -= 1 if ($h_ind4 == $sqhgt); $w_ind4 -= 1 if ($w_ind4 == $sqwid); $msg .= "-draw \"circle ".($w_ind4-1).",$h_ind4 ".($w_ind4+1).",$h_ind4\" "; $msg .= "-draw \"line $w_ind1,$h_ind1 $w_ind2,$h_ind2\" "; $msg .= "-draw \"line $w_ind2,$h_ind2 $w_ind3,$h_ind3\" "; $msg .= "-draw \"line $w_ind3,$h_ind3 $w_ind4,$h_ind4\" "; $msg .= "-draw \"line $w_ind4,$h_ind4 $w_ind1,$h_ind1\" "; if (defined ${$rh}{'user_points'}) { $ru = ${$rh}{'user_points'}; $cnt = scalar @{$ru}; # u_lat,$u_lon on square for ($i = 0; $i < $cnt; $i++) { $u_lat = ${$ru}[$i][0]; $u_lon = ${$ru}[$i][1]; $t_lat = ${$ru}[$i][2]; $t_lon = ${$ru}[$i][3]; $w_indu = int((($u_lon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_indu = int((($u_lat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_indu = $sqhgt - $h_indu; $h_indu += 1 if ($h_indu == 0); $w_indu += 1 if ($w_indu == 0); $h_indu -= 1 if ($h_indu == $sqhgt); $w_indu -= 1 if ($w_indu == $sqwid); $msg .= "-stroke blue "; $msg .= "-draw \"circle ".($w_indu-1).",$h_indu ".($w_indu+1).",$h_indu\" "; # t_lat,$t_lon on square $w_indt = int((($t_lon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_indt = int((($t_lat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_indt = $sqhgt - $h_indt; $h_indt += 1 if ($h_indt == 0); $w_indt += 1 if ($w_indt == 0); $h_indt -= 1 if ($h_indt == $sqhgt); $w_indt -= 1 if ($w_indt == $sqwid); $msg .= "-draw \"circle ".($w_indu-1).",$h_indu ".($w_indu+1).",$h_indu\" "; $msg .= "-stroke red -draw \"line $w_indu,$h_indu $w_indt,$h_indt\" "; } } $msg .= "$graf_file\n"; $msg .= "imdisplay $graf_file\n"; write2file($msg,$graf_bat); prt("Written $graf_bat\n"); if ($show) { set_lat_stg(\$maxlat); set_lat_stg(\$minlat); set_lon_stg(\$maxlon); set_lon_stg(\$minlon); prt("Square wid=$londegs hgt=$latdegs ${sqwid}X${sqhgt}\n"); prt("TL $maxlat,$minlon\n"); prt("BL $minlat,$minlon\n"); prt("BR $minlat,$maxlon\n"); prt("TR $maxlat,$maxlon\n"); } } sub set_most_values_plus2($$$$$$) { my ($rh,$show,$u_lat,$u_lon,$t_lat,$t_lon) = @_; my ($tllat,$tllon,$bllat,$bllon,$brlat,$brlon,$trlat,$trlon); $tllat = ${$rh}{'tl_lat'}; $tllon = ${$rh}{'tl_lon'}; $bllat = ${$rh}{'bl_lat'}; $bllon = ${$rh}{'bl_lon'}; $brlat = ${$rh}{'br_lat'}; $brlon = ${$rh}{'br_lon'}; $trlat = ${$rh}{'tr_lat'}; $trlon = ${$rh}{'tr_lon'}; my ($minlat,$maxlat,$minlon,$maxlon); my ($latdegs,$londegs,$sqwid,$sqhgt); $minlat = $bad_latlon; $maxlat = -$bad_latlon; $minlon = $bad_latlon; $maxlon = -$bad_latlon; # TEST SET OF 4, PLUS USRE'S POSITION $maxlat = $tllat if ($tllat > $maxlat); $maxlat = $bllat if ($bllat > $maxlat); $maxlat = $brlat if ($brlat > $maxlat); $maxlat = $trlat if ($trlat > $maxlat); $maxlat = $u_lat if ($u_lat > $maxlat); $minlat = $tllat if ($tllat < $minlat); $minlat = $bllat if ($bllat < $minlat); $minlat = $brlat if ($brlat < $minlat); $minlat = $trlat if ($trlat < $minlat); $minlat = $u_lat if ($u_lat < $minlat); $maxlon = $tllon if ($tllon > $maxlon); $maxlon = $bllon if ($bllon > $maxlon); $maxlon = $brlon if ($brlon > $maxlon); $maxlon = $trlon if ($trlon > $maxlon); $maxlon = $u_lon if ($u_lon > $maxlon); $minlon = $tllon if ($tllon < $minlon); $minlon = $bllon if ($bllon < $minlon); $minlon = $brlon if ($brlon < $minlon); $minlon = $trlon if ($trlon < $minlon); $minlon = $u_lon if ($u_lon < $minlon); ${$rh}{'max_lat'} = $maxlat; ${$rh}{'min_lat'} = $minlat; ${$rh}{'max_lon'} = $maxlon; ${$rh}{'min_lon'} = $minlon; $latdegs = $maxlat - $minlat; $londegs = $maxlon - $minlon; ${$rh}{'lon_degs'} = $londegs; ${$rh}{'lat_degs'} = $latdegs; $sqwid = int(($latdegs * 10000) + 0.5); $sqhgt = int(($londegs * 10000) + 0.5); ${$rh}{'sq_wid'} = $sqwid; ${$rh}{'sq_hgt'} = $sqhgt; # scale the image DOWN/up my $targ_wid = 400; my $ratio = $sqwid / $sqhgt; #if (($sqwid > $targ_wid) || ($sqhgt > $targ_wid)) { if ($ratio > 1) { # width > height $sqwid = $targ_wid; # set target width $sqhgt = int($targ_wid / $ratio); # and calculate NEW height } else { # height > width = set target height, adjust width accordingly $sqwid = int($targ_wid * $ratio); # calculate width $sqhgt = $targ_wid; # and set target width } #} my ($w_dpp,$h_dpp,$w_ind1,$h_ind1,$w_ind2,$h_ind2,$w_ind3,$h_ind3,$w_ind4,$h_ind4,$msg); my ($h_indu,$w_indu,$h_indt,$w_indt); $w_dpp = $sqwid / $londegs; $h_dpp = $sqhgt / $latdegs; $msg = "convert -size ${sqwid}x${sqhgt} xc:wheat +antialias -fill white "; # -stroke Gold -draw "path 'M 20,70 A 1,1 0 0,1 80,50'" \ # -stroke DodgerBlue -draw "line 30,10 50,80" \ # -stroke Red -draw "circle 80,60 82,60" \ # sparse_source.gif # tllat,$tllon on square $w_ind1 = int((($tllon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind1 = int((($tllat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind1 = $sqhgt - $h_ind1; $h_ind1 += 1 if ($h_ind1 == 0); $w_ind1 += 1 if ($w_ind1 == 0); $h_ind1 -= 1 if ($h_ind1 == $sqhgt); $w_ind1 -= 1 if ($w_ind1 == $sqwid); $msg .= "-stroke black -draw \"circle ".($w_ind1-1).",$h_ind1 ".($w_ind1+1).",$h_ind1\" "; # bllat,$bllon on square $w_ind2 = int((($bllon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind2 = int((($bllat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind2 = $sqhgt - $h_ind2; #$w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 += 1 if ($h_ind2 == 0); $w_ind2 += 1 if ($w_ind2 == 0); $h_ind2 -= 1 if ($h_ind2 == $sqhgt); $w_ind2 -= 1 if ($w_ind2 == $sqwid); $msg .= "-draw \"circle ".($w_ind2-1).",$h_ind2 ".($w_ind2+1).",$h_ind2\" "; # brlat,$brlon on square $w_ind3 = int((($brlon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind3 = int((($brlat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind3 = $sqhgt - $h_ind3; #$w_ind3 += 1 if ($w_ind3 == 0); $h_ind3 += 1 if ($h_ind3 == 0); $w_ind3 += 1 if ($w_ind3 == 0); $h_ind3 -= 1 if ($h_ind3 == $sqhgt); $w_ind3 -= 1 if ($w_ind3 == $sqwid); $msg .= "-draw \"circle ".($w_ind3-1).",$h_ind3 ".($w_ind3+1).",$h_ind3\" "; # trlat,$trlon on square $w_ind4 = int((($trlon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_ind4 = int((($trlat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_ind4 = $sqhgt - $h_ind4; #$w_ind4 += 1 if ($w_ind4 == 0); $h_ind4 += 1 if ($h_ind4 == 0); $w_ind4 += 1 if ($w_ind4 == 0); $h_ind4 -= 1 if ($h_ind4 == $sqhgt); $w_ind4 -= 1 if ($w_ind4 == $sqwid); $msg .= "-draw \"circle ".($w_ind4-1).",$h_ind4 ".($w_ind4+1).",$h_ind4\" "; # u_lat,$u_lon on square $w_indu = int((($u_lon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_indu = int((($u_lat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_indu = $sqhgt - $h_indu; $h_indu += 1 if ($h_indu == 0); $w_indu += 1 if ($w_indu == 0); $h_indu -= 1 if ($h_indu == $sqhgt); $w_indu -= 1 if ($w_indu == $sqwid); $msg .= "-draw \"circle ".($w_indu-1).",$h_indu ".($w_indu+1).",$h_indu\" "; # t_lat,$t_lon on square $w_indt = int((($t_lon - $minlon) * $w_dpp) + 0.5); # get degrees/pixels from left edge $h_indt = int((($t_lat - $minlat) * $h_dpp) + 0.5); # get degrees/pixels from bottom edge $h_indt = $sqhgt - $h_indt; $h_indt += 1 if ($h_indt == 0); $w_indt += 1 if ($w_indt == 0); $h_indt -= 1 if ($h_indt == $sqhgt); $w_indt -= 1 if ($w_indt == $sqwid); $msg .= "-draw \"circle ".($w_indu-1).",$h_indu ".($w_indu+1).",$h_indu\" "; $msg .= "-draw \"line $w_ind1,$h_ind1 $w_ind2,$h_ind2\" "; $msg .= "-draw \"line $w_ind2,$h_ind2 $w_ind3,$h_ind3\" "; $msg .= "-draw \"line $w_ind3,$h_ind3 $w_ind4,$h_ind4\" "; $msg .= "-draw \"line $w_ind4,$h_ind4 $w_ind1,$h_ind1\" "; $msg .= "-stroke red -draw \"line $w_indu,$h_indu $w_indt,$h_indt\" "; $msg .= "$graf_file\n"; $msg .= "imdisplay $graf_file\n"; write2file($msg,$graf_bat); prt("Writtem $graf_bat\n"); if ($show) { set_lat_stg(\$maxlat); set_lat_stg(\$minlat); set_lon_stg(\$maxlon); set_lon_stg(\$minlon); prt("Square wid=$londegs hgt=$latdegs ${sqwid}X${sqhgt}\n"); prt("TL $maxlat,$minlon\n"); prt("BL $minlat,$minlon\n"); prt("BR $minlat,$maxlon\n"); prt("TR $maxlat,$maxlon\n"); } } sub get_circuit_hash() { my %h = (); $h{'tl_lat'} = $tl_lat; $h{'tl_lon'} = $tl_lon; $h{'bl_lat'} = $bl_lat; $h{'bl_lon'} = $bl_lon; $h{'br_lat'} = $br_lat; $h{'br_lon'} = $br_lon; $h{'tr_lat'} = $tr_lat; $h{'tr_lon'} = $tr_lon; set_circuit_values(\%h,1); #set_most_values(\%h,1); return \%h; } sub normalised_hdg($) { my $hdg = shift; $hdg += 360 if ($hdg < 0); $hdg -= 360 if ($hdg >= 360); return $hdg; } sub get_mid_tl2bl($$) { my ($rlat,$rlon) = @_; my ($az1,$az2,$dist); fg_geo_inverse_wgs_84 ($tl_lat,$tl_lon,$bl_lat,$bl_lon,\$az1,\$az2,\$dist); my $dist2 = $dist / 2; # get the center of this line my ($clat,$clon); #fg_geo_direct_wgs_84( $tl_lat, $tl_lon, $az1, $dist2, $rlat, $rlon, \$az2 ); fg_geo_direct_wgs_84( $tl_lat, $tl_lon, $az1, $dist2, \$clat, \$clon, \$az2 ); $az2 = normalised_hdg($az1 + 90); # turn 90 degrees, and get a point fg_geo_direct_wgs_84( $clat, $clon, $az2, $dist2, $rlat, $rlon, \$az1 ); } sub get_mid_bl2br($$) { my ($rlat,$rlon) = @_; my ($az1,$az2,$dist); fg_geo_inverse_wgs_84 ($bl_lat,$bl_lon,$br_lat,$br_lon,\$az1,\$az2,\$dist); my $dist2 = $dist / 2; fg_geo_direct_wgs_84( $bl_lat, $bl_lon, $az1, $dist2, $rlat, $rlon, \$az2 ); } sub get_mid_bl2br2($$) { my ($rlat,$rlon) = @_; my ($az1,$az2,$dist); fg_geo_inverse_wgs_84 ($bl_lat,$bl_lon,$br_lat,$br_lon,\$az1,\$az2,\$dist); my $dist2 = $dist / 2; my ($clat,$clon); fg_geo_direct_wgs_84( $bl_lat, $bl_lon, $az1, $dist2, \$clat, \$clon, \$az2 ); $az2 = normalised_hdg($az1 + 90); # turn 90 degrees, and get a point fg_geo_direct_wgs_84( $clat, $clon, $az2, $dist2, $rlat, $rlon, \$az1 ); } sub set_distances_bearings($$$$) { my ($rh,$lat,$lon,$msg) = @_; ${$rh}{'usr_lat'} = $lat; ${$rh}{'usr_lon'} = $lon; ${$rh}{'usr_msg'} = $msg; my ($tlat,$tlon); my ($az1,$az2,$dist); $msg = ''; $tlat = ${$rh}{'tl_lat'}; # = -31.684063; $tlon = ${$rh}{'tl_lon'}; # = 148.614120; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'tl_az1'} = $az1; ${$rh}{'tl_az2'} = $az2; ${$rh}{'tl_dist'} = $dist; set_dist_stg(\$dist); $msg .= "TL $dist "; $tlat = ${$rh}{'bl_lat'}; # = -31.723495; $tlon = ${$rh}{'bl_lon'}; # = 148.633003; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'bl_az1'} = $az1; ${$rh}{'bl_az2'} = $az2; ${$rh}{'bl_dist'} = $dist; set_dist_stg(\$dist); $msg .= "BL $dist "; $tlat = ${$rh}{'br_lat'}; # = -31.716778; $tlon = ${$rh}{'br_lon'}; # = 148.666992; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'br_az1'} = $az1; # from 'test' to BR point ${$rh}{'br_az2'} = $az2; ${$rh}{'br_dist'} = $dist; set_dist_stg(\$dist); $msg .= "BR $dist "; $tlat = ${$rh}{'tr_lat'}; # = -31.672960; $tlon = ${$rh}{'tr_lon'}; # = 148.649139; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'tr_az1'} = $az1; ${$rh}{'tr_az2'} = $az2; ${$rh}{'tr_dist'} = $dist; set_dist_stg(\$dist); $msg .= "TR $dist "; prt("Distances: $msg\n"); } sub dist_less_or_equal5($$) { my ($dist,$min_dist) = @_; return 1 if ($dist <= $min_dist); my $d5 = $dist * 0.95; return 2 if ($d5 < $min_dist); return 0; } sub process_lat_lon($$$$) { my ($rh,$lat,$lon,$msg) = @_; prt("\nSolving lat=$lat, lon=$lon $msg\n"); # get distances, and headings... my ($tlat,$tlon,$az1,$az2,$dist,$res); set_distances_bearings($rh,$lat,$lon,$msg); # 1: get closest point, on circuit # 1 Mile = 1609.344 Meters. my $min_dist = 12000 * 1700; my $hdto = 'unsolved'; my $targ_lon = $bad_latlon; my $targ_lat = $bad_latlon; my $targ_dist = 1000000000; my ($hdg); $tlat = ${$rh}{'tl_lat'}; # = -31.684063; $tlon = ${$rh}{'tl_lon'}; # = 148.614120; $az1 = ${$rh}{'tl_az1'}; $az2 = ${$rh}{'tl_az2'}; $dist = ${$rh}{'tl_dist'}; $res = 0; #if ($dist < $min_dist) { $min_dist = $dist; $hdto = "to top left ($res)"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; #} $tlat = ${$rh}{'bl_lat'}; # = -31.684063; $tlon = ${$rh}{'bl_lon'}; # = 148.614120; $az1 = ${$rh}{'bl_az1'}; $az2 = ${$rh}{'bl_az2'}; $dist = ${$rh}{'bl_dist'}; #if ($dist <= $min_dist) { $res = dist_less_or_equal5($dist,$min_dist); if ($res) { $min_dist = $dist; $hdto = "to bottom left ($res)"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } $tlat = ${$rh}{'br_lat'}; # = -31.684063; $tlon = ${$rh}{'br_lon'}; # = 148.614120; $az1 = ${$rh}{'br_az1'}; $az2 = ${$rh}{'br_az2'}; $dist = ${$rh}{'br_dist'}; #if ($dist < $min_dist) { $res = dist_less_or_equal5($dist,$min_dist); if ($res) { $min_dist = $dist; $hdto = "to bottom right ($res)"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } $tlat = ${$rh}{'tr_lat'}; # = -31.684063; $tlon = ${$rh}{'tr_lon'}; # = 148.614120; $az1 = ${$rh}{'tr_az1'}; $az2 = ${$rh}{'tr_az2'}; $dist = ${$rh}{'tr_dist'}; #if ($dist <= $min_dist) { $res = dist_less_or_equal5($dist,$min_dist); if ($res) { $min_dist = $dist; $hdto = "to top right ($res)"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } $tlat = ${$rh}{'tl_lat'}; # = -31.684063; $tlon = ${$rh}{'tl_lon'}; # = 148.614120; $az1 = ${$rh}{'tl_az1'}; $az2 = ${$rh}{'tl_az2'}; $dist = ${$rh}{'tl_dist'}; $res = dist_less_or_equal5($dist,$min_dist); if ($res) { $min_dist = $dist; $hdto = "to top left ($res)"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } set_most_values_plus($rh,1,$lat,$lon,$targ_lat,$targ_lon); # for display set_hdg_stg(\$hdg); set_dist_stg(\$targ_dist); set_lat_stg(\$targ_lat); set_lon_stg(\$targ_lon); prt("\nHeading: $hdto, hdg=$hdg, to $targ_lat,$targ_lon, at $targ_dist m.\n"); } sub process_lat_lon2($$$$) { my ($rh,$lat,$lon,$msg) = @_; prt("\nSolving lat=$lat, lon=$lon $msg\n"); # get distances, and headings... my ($tlat,$tlon); my ($az1,$az2,$dist,$diff); my ($mindif,$hdto,$hdg); my ($targ_lat,$targ_lon,$targ_dist); my ($mindif2,$hdto2,$hdg2); my ($targ_lat2,$targ_lon2,$targ_dist2); my $max_diff = 3; prt("Show distance, azmuth to circuit...\n"); $mindif = 400; $hdto = 'unsolved'; $targ_lon = $bad_latlon; $targ_lat = $bad_latlon; $targ_dist = 1000000000; $mindif2 = 400; $hdto2 = 'unsolved'; $targ_lon2 = $bad_latlon; $targ_lat2 = $bad_latlon; $targ_dist2 = 1000000000; $tlat = ${$rh}{'tl_lat'}; # = -31.684063; $tlon = ${$rh}{'tl_lon'}; # = 148.614120; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'tl_az1'} = $az1; ${$rh}{'tl_az2'} = $az2; ${$rh}{'tl_dist'} = $dist; set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("tl $dist m, on $az1 "); # check if from test pos to this point is close to the same track - +/- a degree or so # from TL to BL ${$rh}{'l1_az1'} = $az1; $az2 = ${$rh}{'l1_az1'}; $diff = abs(${$rh}{'tl_az1'} - ${$rh}{'l1_az1'}); ${$rh}{'tl2bl'} = $diff; if ($diff < $mindif) { $mindif = $diff; $hdto = "to top left"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } set_hdg_stg(\$az2); set_hdg_stg(\$diff); prt("to join $az2 (tl2bl) diff=$diff "); # diff of test -> TL and TR -> TL $diff = abs(${$rh}{'tl_az1'} - ${$rh}{'l4_az1'}); if (($diff < $max_diff)&&($diff < $mindif2)) { $mindif2 = $diff; $hdto2 = "to bottom left"; $hdg2 = $az1; $targ_lat2 = $tlat; $targ_lon2 = $tlon; $targ_dist2 = $dist; } set_hdg_stg(\$diff); prt("test->TL and TR->TL $diff"); prt("\n"); $tlat = ${$rh}{'bl_lat'}; # = -31.723495; $tlon = ${$rh}{'bl_lon'}; # = 148.633003; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'bl_az1'} = $az1; ${$rh}{'bl_az2'} = $az2; ${$rh}{'bl_dist'} = $dist; set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("bl $dist m, on $az1 "); $az2 = ${$rh}{'l2_az1'}; $diff = abs(${$rh}{'bl_az1'} - ${$rh}{'l2_az1'}); ${$rh}{'bl2br'} = $diff; if ($diff < $mindif) { $mindif = $diff; $hdto = "to bottom left"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } set_hdg_stg(\$az2); set_hdg_stg(\$diff); prt("to join $az2 (bl2br) diff=$diff "); # diff of test -> BL and TL -> BL $diff = abs(${$rh}{'bl_az1'} - ${$rh}{'l1_az1'}); if (($diff < $max_diff)&&($diff < $mindif2)) { $mindif2 = $diff; $hdto2 = "to bottom right"; $hdg2 = $az1; $targ_lat2 = $tlat; $targ_lon2 = $tlon; $targ_dist2 = $dist; } set_hdg_stg(\$diff); prt("test->BL and TL->BL $diff"); prt("\n"); $tlat = ${$rh}{'br_lat'}; # = -31.716778; $tlon = ${$rh}{'br_lon'}; # = 148.666992; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'br_az1'} = $az1; # from 'test' to BR point ${$rh}{'br_az2'} = $az2; ${$rh}{'br_dist'} = $dist; set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("br $dist m, on $az1 "); $az2 = ${$rh}{'l3_az1'}; $diff = abs(${$rh}{'br_az1'} - ${$rh}{'l3_az1'}); ${$rh}{'br2tr'} = $diff; if ($diff < $mindif) { $mindif = $diff; $hdto = "to bottom right"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } set_hdg_stg(\$diff); set_hdg_stg(\$az2); prt("to join $az2 (br2tr) diff=$diff "); # diff of test -> BR and BL -> BR $diff = abs(${$rh}{'br_az1'} - ${$rh}{'l2_az1'}); if (($diff < $max_diff)&&($diff < $mindif2)) { $mindif2 = $diff; $hdto2 = "to top right"; $hdg2 = $az1; $targ_lat2 = $tlat; $targ_lon2 = $tlon; $targ_dist2 = $dist; } set_hdg_stg(\$diff); prt("test->BR and BL->BR $diff"); prt("\n"); $tlat = ${$rh}{'tr_lat'}; # = -31.672960; $tlon = ${$rh}{'tr_lon'}; # = 148.649139; fg_geo_inverse_wgs_84 ($lat,$lon,$tlat,$tlon,\$az1,\$az2,\$dist); ${$rh}{'tr_az1'} = $az1; ${$rh}{'tr_az2'} = $az2; ${$rh}{'tr_dist'} = $dist; set_dist_stg(\$dist); set_hdg_stg(\$az1); prt("tr $dist m, on $az1 "); $az2 = ${$rh}{'l4_az1'}; $diff = abs(${$rh}{'tr_az1'} - ${$rh}{'l4_az1'}); ${$rh}{'tr2tl'} = $diff; if ($diff < $mindif) { $mindif = $diff; $hdto = "to top right"; $hdg = $az1; $targ_lat = $tlat; $targ_lon = $tlon; $targ_dist = $dist; } set_hdg_stg(\$diff); set_hdg_stg(\$az2); prt("to join $az2 (tr2tl) diff=$diff "); # diff of test -> TR and BR -> TR $diff = abs(${$rh}{'tr_az1'} - ${$rh}{'l3_az1'}); if (($diff < $max_diff)&&($diff < $mindif2)) { $mindif2 = $diff; $hdto2 = "to top left"; $hdg2 = $az1; $targ_lat2 = $tlat; $targ_lon2 = $tlon; $targ_dist2 = $dist; } set_hdg_stg(\$diff); prt("test->TR and BR->TR $diff"); prt("\n"); if ($hdto2 eq 'unsolved') { set_most_values_plus($rh,1,$lat,$lon,$targ_lat,$targ_lon); set_hdg_stg(\$mindif); prt("\nHeading: $hdto, hdg=$hdg, min diff $mindif, to $targ_lat,$targ_lon, at $targ_dist m.\n"); } else { set_most_values_plus($rh,1,$lat,$lon,$targ_lat2,$targ_lon2); set_hdg_stg(\$mindif2); prt("\nHeading: $hdto2, hdg2=$hdg, min diff $mindif2, to $targ_lat2,$targ_lon2, at $targ_dist2 m.\n"); } } ######################################### ### MAIN ### parse_args(@ARGV); my $ref_hash = get_circuit_hash(); init_runway_array(); get_runways_and_pattern($ref_hash,'YGIL'); process_lat_lon($ref_hash,$in_lat,$in_lon,"User input."); get_mid_tl2bl(\$in_lat,\$in_lon); process_lat_lon($ref_hash,$in_lat,$in_lon,"Mid tl2bl point."); #get_mid_bl2br(\$in_lat,\$in_lon); get_mid_bl2br2(\$in_lat,\$in_lon); process_lat_lon($ref_hash,$in_lat,$in_lon,"Mid bl2br point."); paint_user_points($ref_hash,1); pgm_exit(0,""); ######################################## sub give_help { prt("$pgmname: version 0.0.1 2010-09-11\n"); prt("Usage: $pgmname [options] lat,lon\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,@arr,$lat,$lon); 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 { @arr = split(",",$arg); if (scalar @arr == 2) { $lat = $arr[0]; $lon = $arr[1]; } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } shift @av; } if ((($in_lat == $bad_latlon)||($in_lon == $bad_latlon)) && $debug_on) { @arr = split(",",$def_latlon); if (scalar @arr == 2) { $lat = $arr[0]; $lon = $arr[1]; if (in_world_range($lat,$lon)) { $in_lat = $lat; $in_lon = $lon; prt("Set lat=$in_lat, lon=$in_lon\n"); } else { pgm_exit(1,"ERROR: lat=$lat, lon=$lon OUT OF WORLD RANGE!\n"); } } else { pgm_exit(1,"ERROR: Default is invlalid\n"); } } if (($in_lat == $bad_latlon)||($in_lon == $bad_latlon)) { pgm_exit(1,"ERROR: No lat,lon found in command!\n"); } } # eof - solve.pl