#!/usr/bin/perl -w # NAME: cookedcsv.pl # AIM: For the 'playback' fLight paths 3D display, read a 'cooked' CSV, and calculate the bounding box # 18/07/2020 - Review in Dell03 # 30/06/2016 - Initial cut use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Math::Trig; 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' Check paths in \@INC...\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.6 2020-07-18"; ###my $VERS = "0.0.5 2016-06-30"; my $load_log = 0; my $in_file = ''; my $verbosity = 0; my $out_file = ''; my $curr_zoom = 12; my $url_base = "http://a.tile.openstreetmap.org"; my $xg_out = $temp_dir.$PATH_SEP."tempslip.xg"; my $smudge_facter = 20; # percentage to INCREASE BBOX by my $add_theo_xg = 0; my $min_ias = 10; # ### DEBUG ### my $debug_on = 1; my $def_file = 'D:\FG\next\playbacks\LFPO-LFPG-cooked.csv'; ###my $def_file = 'D:\FG\d-and-c\tracks\VNLK-02-cooked.csv'; ###my $def_file = 'D:\FG\d-and-c\tracks\6-27-2016-1-cooked.csv'; my $UL_lat = 27.761329874505222; my $UL_lon = 86.66015625; my $LR_lat = 27.683528083787767; my $LR_lon = 86.748046875; my $t_ctr_lat = 27.722428979146493; my $t_ctr_lon = 86.7041015625; sub get_theo_xg() { my $xg = "# Theo lon lat UL $UL_lon $UL_lat LR $LR_lon $LR_lat\n"; $xg .= "color red\n"; $xg .= "$UL_lon $UL_lat\n"; $xg .= "$LR_lon $LR_lat\n"; $xg .= "NEXT\n"; $xg .= "color green\n"; $xg .= "$t_ctr_lon $t_ctr_lat\n"; $xg .= "NEXT\n"; $xg .= "anno $t_ctr_lon $t_ctr_lat Tile Ctr\n"; return $xg; } ### 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 getTileNumber($$$) { my ($lat,$lon,$zoom) = @_; my $z2 = 2 ** $zoom; my $xtile = int( ($lon+180)/360 * $z2 ) ; my $ytile = int( (1 - log(tan(deg2rad($lat)) + sec(deg2rad($lat)))/pi)/2 * $z2 ) ; return ($xtile, $ytile); } sub getLonLat { my ($xtile, $ytile, $zoom) = @_; my $n = 2 ** $zoom; my $lon_deg = $xtile / $n * 360.0 - 180.0; my $lat_deg = rad2deg(atan(sinh(pi * (1 - 2 * $ytile / $n)))); return ($lon_deg, $lat_deg); } ########################################################## sub get_double_stg($) { my $d = shift; my $cd = sprintf("%4.10f",$d); return $cd; } sub get_double($) { my $d = shift; return get_double_stg($d); } ########################################################## sub get_minmax_ref() { my @a = (200,200,-200,-200); return \@a; } sub set_minmax_ref($$$) { my ($rmm,$lat,$lon) = @_; ${$rmm}[0] = $lon if ($lon < ${$rmm}[0]); ${$rmm}[1] = $lat if ($lat < ${$rmm}[1]); ${$rmm}[2] = $lon if ($lon > ${$rmm}[2]); ${$rmm}[3] = $lat if ($lat > ${$rmm}[3]); } sub expand_minmax_ref($$) { my ($rmm,$factor) = @_; return if ($factor <= 0); my $min_lon = ${$rmm}[0]; my $min_lat = ${$rmm}[1]; my $max_lon = ${$rmm}[2]; my $max_lat = ${$rmm}[3]; my $lon_dif = $max_lon - $min_lon; my $lat_dif = $max_lat - $min_lat; # do we have positive difference return if ( !(($lon_dif > 0)&&($lat_dif > 0)) ); # calculate the smudge factors - in degrees my $lon_sm = (($factor / 100) * $lon_dif) / 2; my $lat_sm = (($factor / 100) * $lat_dif) / 2; # apply the smudge factors $min_lon -= $lon_sm; $min_lat -= $lat_sm; $max_lon += $lon_sm; $max_lat += $lat_sm; # update the reference set_minmax_ref($rmm,$min_lat,$min_lon); set_minmax_ref($rmm,$max_lat,$max_lon); } sub get_minmax_ref_xg($$) { my ($rmm,$color) = @_; my $min_lon = ${$rmm}[0]; my $min_lat = ${$rmm}[1]; my $max_lon = ${$rmm}[2]; my $max_lat = ${$rmm}[3]; my $xg = "# BBOX: $min_lon,$min_lat,$max_lon,$max_lat\n"; $xg .= "color $color\n"; $xg .= "$min_lon $min_lat\n"; $xg .= "$min_lon $max_lat\n"; $xg .= "$max_lon $max_lat\n"; $xg .= "$max_lon $min_lat\n"; $xg .= "$min_lon $min_lat\n"; $xg .= "NEXT\n"; return $xg; } ########################################################################### # assumed CSV input, like # lon,lat,alt,hdg,ias,roll,pitch,slip # lon, lat, alt,hdg,ias,roll,pitch,slip # 2.3768278670,48.7177639931,287,18,0,-0.019473,4.617867,0.000000 # 2.3768278696,48.7177639904,287,18,3,-0.007387,4.627360,-71.801193 # ... 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,@arr,$len); my ($lon,$lat,$alt,$hdg,$ias,$roll,$pitch,$slip); my ($spanx,$spany); my $min_lon = 200; my $max_lon = -200; my $min_lat = 200; my $max_lat = -200; my $z = $curr_zoom; my $rmm = get_minmax_ref(); my $rmmt = get_minmax_ref(); $lnn = 0; my $xg = "color yellow\n"; my $skipped_ias = 0; my $points_added = 0; foreach $line (@lines) { chomp $line; $lnn++; @arr = split(",",$line); $len = scalar @arr; if ($lnn == 1) { prt("$lnn: $line, items $len\n"); next; } if ($len < 8) { prt("$lnn: BAD length, got $len, expect 8\n"); next; } $lon = $arr[0]; $lat = $arr[1]; $alt = $arr[2]; $hdg = $arr[3]; $ias = $arr[4]; set_minmax_ref($rmm,$lat,$lon); $min_lon = $lon if ($lon < $min_lon); $max_lon = $lon if ($lon > $max_lon); $min_lat = $lat if ($lat < $min_lat); $max_lat = $lat if ($lat > $max_lat); if ($min_ias && ($ias >= $min_ias)) { $xg .= "$lon $lat ; $alt $hdg $ias\n"; $points_added++; } else { $skipped_ias++; } } $xg .= "NEXT\n"; prt("Processed $lncnt lines, added $points_added route pts, skipped $skipped_ias due ias\n"); $spanx = $max_lon - $min_lon; $spany = $max_lat - $min_lat; prt("BBOX: $min_lon,$min_lat,$max_lon,$max_lat\n"); $xg .= "# BBOX: $min_lon,$min_lat,$max_lon,$max_lat\n"; $lon = ($min_lon + $max_lon) / 2; $lat = ($min_lat + $max_lat) / 2; $xg .= "color gray\n"; $xg .= "$min_lon $min_lat\n"; $xg .= "$min_lon $max_lat\n"; $xg .= "$max_lon $max_lat\n"; $xg .= "$max_lon $min_lat\n"; $xg .= "$min_lon $min_lat\n"; $xg .= "NEXT\n"; $xg .= "# Expand the boundaries by $smudge_facter% in all directions...\n"; expand_minmax_ref($rmm,$smudge_facter); $xg .= get_minmax_ref_xg($rmm,'white'); prt("Center: lon/lat $lon,$lat, span x,y $spanx,$spany\n"); my ($x,$y) = getTileNumber($lat,$lon,$z); my $dir = "/$z/$x/$y.png"; prt("PNG: $url_base$dir\n"); $xg .= "# PNG: $url_base$dir\n"; my ($x1,$y1) = getTileNumber($lat,$lon,10); my $dir2 = "/10/$x1/$y1.png"; prt("PNG: $url_base$dir2\n"); #$xg .= "# PNG: $url_base$dir\n"; my ($tl_lon, $tl_lat) = getLonLat($x+0,$y+0,$z); my ($bl_lon, $bl_lat) = getLonLat($x+0,$y+1,$z); my ($tr_lon, $tr_lat) = getLonLat($x+1,$y+0,$z); my ($br_lon, $br_lat) = getLonLat($x+1,$y+1,$z); my $ctr_lat = ($tl_lat + $br_lat) / 2; my $ctr_lon = ($tl_lon + $br_lon) / 2; my ($cx, $cy) = getTileNumber($ctr_lat,$ctr_lon,$z); set_minmax_ref($rmmt,$tl_lat,$tl_lon); set_minmax_ref($rmmt,$bl_lat,$bl_lon); set_minmax_ref($rmmt,$tr_lat,$tr_lon); set_minmax_ref($rmmt,$br_lat,$br_lon); prt("Center: lat,lon ".get_double($ctr_lat).",".get_double($ctr_lon)); prt(" (".get_double(($bl_lat + $tr_lat) / 2).",".get_double(($bl_lon+$tr_lon) / 2)); prt(" /z/cx/cy.png /$z/$cx/$cy.png\n"); prt("\n"); # x y z prt("TL ".get_double($tl_lat).",".get_double($tl_lon)." y+0,x+0 ".($x+0).",".($y+0)."\n"); prt("BL ".get_double($bl_lat).",".get_double($bl_lon)." y+1,x+0 ".($x+0).",".($y+1)."\n"); prt("TR ".get_double($tr_lat).",".get_double($tr_lon)." y+0,x+1 ".($x+1).",".($y+0)."\n"); prt("BR ".get_double($br_lat).",".get_double($br_lon)." y+1,x+1 ".($x+1).",".($y+1)."\n"); prt("\n"); # $xg .= "color blue\n"; # $xg .= "$bl_lon $bl_lat\n"; # $xg .= "$tl_lon $tl_lat\n"; # $xg .= "$tr_lon $tr_lat\n"; # $xg .= "$br_lon $br_lat\n"; # $xg .= "$bl_lon $bl_lat\n"; # $xg .= "NEXT\n"; $xg .= get_minmax_ref_xg($rmmt,'blue'); $xg .= get_theo_xg() if ($add_theo_xg); rename_2_old_bak($xg_out); write2file($xg,$xg_out); prt("Written xg to $xg_out\n"); } ######################################### ### MAIN ### parse_args(@ARGV); process_in_file($in_file); 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); } elsif ($sarg =~ /^s/) { need_arg(@av); shift @av; $sarg = $av[0]; $min_ias = $sarg; if ($min_ias =~ /^\d+$/) { prt("Set min. IAS to [$min_ias].\n") if ($verb); } else { pgm_exit(1,"ERROR: Invalid argument '$arg $sarg'! Only integer allowed\n"); } } 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"); $load_log = 1; #$min_ias = 10; } } 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"); prt(" --speed (-s) = Only records that have this IAS. 0 to disable. (def=$min_ias)\n"); } # eof - cookedcsv.pl