summaryrefslogtreecommitdiffstats
path: root/perl
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2017-08-10 20:33:14 -0400
committerSolomon Peachy <pizza@shaftnet.org>2017-08-10 20:33:14 -0400
commit8a331e00256cac4d78830c2bfce6b2713723e4c8 (patch)
tree15f431b156589158a991a998462352ca8edd9310 /perl
downloadgpligc-8a331e00256cac4d78830c2bfce6b2713723e4c8.tar.gz
gpligc-8a331e00256cac4d78830c2bfce6b2713723e4c8.tar.bz2
gpligc-8a331e00256cac4d78830c2bfce6b2713723e4c8.zip
initial commit -- gpligc 1.10.1
Diffstat (limited to 'perl')
-rwxr-xr-xperl/GPLIGC.pl6488
-rw-r--r--perl/GPLIGCfunctions.pm940
-rw-r--r--perl/Makefile.am16
-rw-r--r--perl/Makefile.in567
-rwxr-xr-xperl/gpsp2igc.pl144
-rwxr-xr-xperl/gpsp2igcfile.pl181
-rwxr-xr-xperl/loopviewer.pl39
7 files changed, 8375 insertions, 0 deletions
diff --git a/perl/GPLIGC.pl b/perl/GPLIGC.pl
new file mode 100755
index 0000000..111aaab
--- /dev/null
+++ b/perl/GPLIGC.pl
@@ -0,0 +1,6488 @@
+#!/usr/bin/perl -w
+
+# version and copyleft
+my $version='1.10.1';
+my $copyright_years="2000-2016";
+my $copyright="(c) $copyright_years by Hannes Krueger";
+
+# new version welcome message
+my $new_version_message=<<ENDE;
+News for version $version
+
+- some bugs fixed
+
+for details see ChangeLog and read the Manual
+
+If you're using GPLIGC/ogie on a regular basis,
+please consider to subscribe to the gpligc-announce
+mailinglist (see menu 'about')
+
+* to get rid of this message, choose 'save configuration'
+ from menu 'options' *
+ENDE
+
+# set default configuration settings (configuration-hash...)
+# needs some order ? alphabetic/functional groups?
+my %config = ();
+$config{'new_version_message_shown'}="0.1";
+$config{'photos'}=1; #use photos?
+$config{'photo_path'}="none";
+$config{'picture_viewer'} = "internal"; #internal, or ext app
+$config{'mm_player'} = "mplayer"; #multimedia
+$config{'skip_check'} = 1; #show gaps in track?
+$config{'skip_limit_minutes'} = 1.0; #actually, these are minutes now! 0.1 = 6sec
+$config{'skip_del_first_after'}=1; #first fix after skip will be deleted!
+$config{'terminal'}="xterm -hold -e";
+$config{'garmin_download'}="sudo gpspoint -dt -p /dev/ttyUSB2";
+$config{'gpsbabel_tdownload'}="sudo gpsbabel -t -i garmin -f /dev/ttyUSB2 -o igc -F ";
+$config{'geotag_force_overwrite'}= 0;
+$config{'mm_mountpoint'}="/mnt/sdC";
+$config{'mm_download_dirs'}="Aufnahmen Fotos Videoclips";
+$config{'browser'} = "/usr/bin/firefox";
+$config{'gnuplot_win_exec'} = "wgnuplot.exe";
+$config{'gnuplot_major_version'} = 4;
+$config{'gnuplot_4_terminal'} = 0;
+$config{'gnuplot_terminal_app'} = "xterm -e";
+$config{'gnuplot_3d_rotx'} = 30; # values for gnuplot 3d-view
+$config{'gnuplot_3d_rotz'} = 330;
+$config{'te_vario_fallback'} = 1; # calculate TE vario from groundspeed?
+$config{'te_warning'}=0; # set to 0 to avoid TE from groundspeed warning
+$config{'wind_analysis'} = 1; # wind analysis with f7 stat
+$config{'optimizer_cycles_mmc'} = 20;
+$config{'optimizer_cycles_sa'} = 5;
+$config{'optimizer_method'}="mmc";
+$config{'optimizer_mmc'}=" -m 1000 -mmc 25000 -devisor 3 -refine 2 ";
+$config{'optimizer_sa'}= " -sima -m 1000 -sacycles 500 -saexp -sapara 15.0 -saparb 0.03 -devisor 3 -refine 2 ";
+$config{'optimizer_verbose'} = 0;
+$config{'optimizer_debug'} = 0;
+$config{'maps'} = "1";
+$config{'map_type'}= "osm";
+$config{'map_gms_v'}=130; # as of 12/2013 v132 seems to be the lowest number
+$map_gms_v_min=10000;
+$map_gms_v_max=$config{'map_gms_v'};
+$config{'maps_zoomlevel'}= 8;
+$config{'map_max_scalesize'}=750;
+$config{'map_max_tiles'}=30;
+
+# set path for slippery map tiles cache
+if ($^O eq "MSWin32") {
+ if (defined $ENV{'GPLIGCHOME'}) {
+ $config{'map_path'} = $ENV{'GPLIGCHOME'}."/map/";
+ } else {
+ $config{'map_path'} = "C:/GPLIGC/map/";
+ }
+} else {
+ $config{'map_path'} = "$ENV{'HOME'}/.gpligc/map/";
+}
+
+$config{'vertical_speed_unit_name'} = "m/s"; # to add more units edit the options-menu
+$config{'vertical_speed_unit_factor'} = 1.0;
+$config{'speed_unit_name'} ="km/h";
+$config{'speed_unit_factor'} = 1.0;
+$config{'altitude_unit_name'} ="m";
+$config{'altitude_unit_factor'} = 1.0;
+$config{'distance_unit_name'} ="km";
+$config{'distance_unit_factor'} = 1.0;
+$config{'waypoint_linewidth'} = 3.0;
+$config{'cylinder_linewidth'} = 3.0;
+$config{'task_linewidth'} = 3.0;
+$config{'marker_linewidth'} = 3.0;
+$config{'fvw_grid'}='yes';
+$config{'fvw_baro_grid'}='yes';
+$config{'fvw_baro_fraction'}=3;
+$config{'open_additional_info'} = 0; # open the additional info window automatically, if no gpi file exists
+$config{'integrate_over'} = 10; # how many data-points are averaged for integration of...
+$config{'vario_histo_intervall'} = 0.5;
+$config{'speed_histo_intervall'} = 5;
+$config{'baro_histo_intervall'} = 50;
+$config{'baro_grid_small'} = 500;
+$config{'baro_grid_large'} = 1000;
+$config{'draw_task'}=0;
+$config{'draw_wpcyl'}=0;
+$config{'draw_accuracy'}=1;
+$config{'viewclick_res'}=1;
+$config{'timezone'} = "0"; # timzone offset from UTC to camera-time (and localtime?)
+$config{'libdir'} = "zzLIBDIRzz"; # LIBDIR PATH will be changed by the installation
+$config{'datadir'} = "zzDATADIRzz"; # DATADIR PATH will be changed by the installation
+$config{'gnuplot_draw_style'}="with lines";
+$config{'gnuplot_grid_state'}='set grid';
+$config{'gnuplot_terminal'}="x11";
+$config{'zylinder_radius'}=0.5; # now in km (09/2015)
+$config{'zylinder_wp_type'}="both";
+$config{'starting_line'}=10; # starting line length
+$config{'zylinder_names'}=1;
+$config{'zoom_sidelength'}="10"; # in km
+$config{'ENL_noise_limit'}=500;
+$config{'coordinate_print_format'}="igch"; # igch, zanh, deg
+$config{'DEBUG'} = 0;
+$config{'window_height'}=500; #this is initial height/width of frame_canvas
+$config{'window_width'}=900;
+
+my $text=<<ENDE;
+GPLIGC Version $version Copyright (c) $copyright_years by
+Hannes Krueger <Hannes.Krueger\@gmail.com> and Jan MW Krueger
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ENDE
+
+### Global variables
+$altmode = 'baro';
+$filestat='closed';
+$file='No file opened';
+#$sigusr2flag=0;
+$optimized_for = "none";
+$zoom = 0;
+$cut_track = 0;
+$hide_mm = 0; # if 1 hide pictures and mm
+$delta_photo_time = 0; # offset between GPS time and camera clock
+$savname = 'no'; # not set
+$zl = 0;
+$tiles = 0;
+$map_reload = 0;
+
+# flag for Tk::JPEG module
+my $have_jpeg = 0;
+
+# flag for Image:ExifTool
+my $have_EXIF = 0;
+
+# flag for Imager
+my $have_imager = 0;
+my $have_png = 0;
+
+$gpi{'qnh'} = 1013.25; # just to avoid an error if the pressure plot is issued without igc file
+
+# all temp-files to be cleaned later
+# these are the data files used for Gnuplot
+@clearlist=qw(zyl.dat speed.dat press.dat plot.bat vario.dat gpsvario.dat deltah.dat
+ baro.dat gpsalt.dat 3d.dat lonproj.dat latproj.dat befehl.dat
+ km.dat lonlat.dat enl.dat ias.dat iashisto.dat shisto.dat vhisto.dat
+ vhistogps.dat plot.gpl plot.bat barohisto.dat gpshisto.dat wind.dat sat.dat tmp.png);
+
+# ===16=== is this all needed... socket connection!!!
+# this is used for Communication with openGLIGCexplorer
+# use IPC::SysV qw(IPC_RMID IPC_CREAT S_IRWXU ftok);
+# use SysVIPC on non-windows platforms only
+# BEGIN {} is executed at compile time...
+# OLD CODE...
+BEGIN {
+ if ($^O ne "MSWin32") {
+# require IPC::SysV;
+# import IPC::SysV qw(IPC_RMID IPC_CREAT S_IRWXU ftok);
+ } else {
+ require Win32;
+ import Win32 qw(GetOSName);
+ }
+}
+
+# Tk-Module is needed!
+use Tk;
+
+# here we load the config (.gpligcrc) for the first time!
+# later, we need to load it another time, because all defaults will be set
+# while building the menus in FlightView()
+load_config(1);
+
+# check for Tk::JPEG module
+# since Tk804.026 jpeg should be available
+my $test_jpeg = eval{ require Tk::JPEG; };
+if (defined $test_jpeg && $test_jpeg == 1) {
+ $have_jpeg = 1;
+ print "Tk::JPEG module found ;-) !\n" if ($config{'DEBUG'});
+} else {
+ print "Perl module: Tk::JPEG not available :,-( !\n";# if ($config{'DEBUG'});
+}
+
+my $test_png = eval{require Tk::PNG;};
+if (defined $test_png && $test_png == 1) {
+ $have_png = 1;
+ print "PNG module found ;-) !\n" if ($config{'DEBUG'});
+} else {
+ print "Perl module: Tk::PNG not available :,-( !\n";# if ($config{'DEBUG'});
+}
+
+my $test_imager = eval{require Imager;};
+if (defined $test_imager && $test_imager == 1) {
+ $have_imager = 1;
+ print "Imager module found ;-) !\n" if ($config{'DEBUG'});
+} else {
+ print "Perl module: Imager not available :,-( !\n";# if ($config{'DEBUG'});
+}
+
+# check for the Image::ExifTool module.
+my $test_EXIF = eval{ require Image::ExifTool; };
+if (defined $test_EXIF && $test_EXIF == 1) {
+ $have_EXIF = 1;
+ print "Image::ExifTool module found ;-) !\n" if ($config{'DEBUG'});
+} else {
+ print "Perl module: Image::ExifTool not available :,-( !\n";# if ($config{'DEBUG'});
+}
+
+# check environment vars on win
+if ($^O eq "MSWin32") {
+ if (defined $ENV{'GPLIGCHOME'}) {
+ $config{'libdir'} = $ENV{'GPLIGCHOME'}."/";
+ $config{'datadir'} = $ENV{'GPLIGCHOME'}."/";
+ } else {
+ $config{'libdir'} = ".";
+ $config{'datadir'} = ".";
+ print "GPLIGCHOME is not defined !!!\n";
+ }
+
+ # workaround for old buggy win32 tk module < 800.23 ?
+ if (!defined $ENV{'HOME'}) {
+ $ENV{'HOME'} = "C:\\";
+ }
+} else { # Unix-case: allow overriding libdir by GPLIGCHOME
+ if (defined $ENV{'GPLIGCHOME'}) {
+ print "GPLIGCHOME is defined: $ENV{'GPLIGCHOME'}\n";
+ print "previous content of $config{'libdir'}="."$config{'libdir'} will be overridden.\n";
+ $config{'libdir'} = $ENV{'GPLIGCHOME'}."/";
+ $config{'datadir'} = $ENV{'GPLIGCHOME'}."/";
+ }
+}
+
+# add libdir to infotext
+$text .= "Library path: $config{'libdir'}\n";
+$text .= "Data path: $config{'datadir'}\n";
+
+use File::Spec;
+my $curdir = File::Spec->curdir;
+
+use File::Basename;
+my $scriptpath = File::Basename::dirname($0)."/";
+
+if ($config{'DEBUG'}) {
+ print "$scriptpath $0\n";
+ print "libdir: $config{'libdir'} \n";
+ print "datadir: $config{'datadir'} \n";
+ print "curdir: $curdir \n";
+ print "scriptpath: $scriptpath \n";
+}
+
+# define $config{'working_directory'} the starting path for open,save,etc.
+if ($^O eq "MSWin32") {
+ if (defined $ENV{'GPLIGCHOME'}) {
+ $config{'working_directory'} = $ENV{'GPLIGCHOME'};
+ } else {
+ $config{'working_directory'} = "C:\\";
+ }
+} else {
+ if (defined $ENV{'HOME'}) {
+ $config{'working_directory'} = $ENV{'HOME'};
+ } else {
+ $config{'working_directory'} = "/";
+ }
+}
+
+unshift (@INC, $curdir, $scriptpath, $config{'libdir'});
+
+# path seperator
+my $ps;
+if ($^O eq "MSWin32") { $ps =";";} else {$ps=":";}
+
+$ENV{'PATH'} = "$ENV{'PATH'}$ps$curdir$ps$config{'libdir'}$ps$scriptpath";
+
+#catch some signals for controlled shutdown.
+$SIG{'INT'} = \&gpligcexit;
+$SIG{'QUIT'} = \&gpligcexit;
+$SIG{'TERM'} = \&gpligcexit;
+
+require GPLIGCfunctions;
+
+if ($^O eq "MSWin32") {
+ my ($osname, $edition) = Win32::GetOSName();
+ $text .= "Windows version: $osname - $edition\n";
+}
+
+$text .= "Platform: ".$^O." Perl: ".$]." Tk: ".$Tk::VERSION."\n";
+
+# additional modules version info ######################
+if ($have_imager) {
+ $text .= "Imager: ".$Imager::VERSION." ";
+} else {
+ $text .= "Imager: not inst. ";
+}
+
+if ($have_EXIF) {
+ $text .= "Image::ExifTool: ".$Image::ExifTool::VERSION." ";
+} else {
+ $text .= "Image::ExifTool: not inst. ";
+}
+
+if ($have_jpeg) {
+ $text .= "Tk::JPEG: ".$Tk::JPEG::VERSION." ";
+} else {
+ $text .= "Tk::JPEG: not inst. ";
+}
+
+if ($have_png) {
+ $text .= "Tk::PNG: ".$Tk::PNG::VERSION."\n";
+} else {
+ $text .= "Tk::PNG: not inst.\n";
+}
+########################################################
+
+# /B Option for windows (DOS) command "start" to start the new DOS-window minimized
+# not available on all systems
+my $start_parameter;
+
+if ($^O eq "MSWin32") {
+ $start_parameter = "/b";
+ my ($osname, $edition) = Win32::GetOSName();
+
+ # if $osname contains one of the list-entries, delete the /B option
+ my @noB_OSlist = qw(Win95 Win98 WinME); #these OS's dont know the /B option for start-command
+ foreach (@noB_OSlist) {
+ if ($osname =~ /$_/i) {
+ $start_parameter = "";
+ }
+ }
+}
+
+# CREATE TMP-DIR
+# Make a temporary directory, only if it does not exist already
+# (|| will only get evaluated if it does _not_ exist yet.)
+if ($^O ne "MSWin32") {
+ $pfadftmp="/tmp/GPLIGC-$$/";
+ -d $pfadftmp || mkdir $pfadftmp;
+} else {
+ $pfadftmp = $ENV{'TMP'}."\\GPLIGC-$$\\";
+ -d $pfadftmp || mkdir $pfadftmp;
+}
+
+# ================ CREATE MAIN WINDOW ========================
+
+FlightView();
+
+# load configuration if available
+# second time. after defaults were set in FlightView
+load_config();
+
+print "config loaded 2nd time\n" if ($config{'DEBUG'});
+
+$map_gms_v_min=10000;
+$map_gms_v_max=$config{'map_gms_v'};
+
+if ($config{'maps'} && !($have_imager && $have_png)) {
+ Errorbox("The config{'maps'} is set, but imager and/or png modules are not available. I'll disable maps\n");
+ $config{'maps'}=0;
+}
+
+$zl = $config{'maps_zoomlevel'};
+
+# a timezone in config should be copied to gpi, before loading any files
+$gpi{'timezone'}=$config{'timezone'};
+
+# show new version welcome message
+if ($config{'new_version_message_shown'} ne $version) {
+ Errorbox($new_version_message);
+ $config{'new_version_message_shown'} = $version;
+}
+
+if (!-d $config{'working_directory'}) {
+ Errorbox("Working directory $config{'working_directory'} doesnt exits! Will be changed to $curdir\n");
+ $config{'working_directory'} = $curdir;
+}
+
+if ($config{'skip_limit_minutes'} <= 0.017) {
+ Errorbox("skip_limit_minutes is smaller than 0.017! That doesnt make sense! See manual. I'll set it to 0.1 now!");
+ $config{'skip_limit_minutes'}=0.1;
+}
+
+# final check of configuration
+check_config();
+
+# check for a file on commandline and load it
+# OR load "splash" image/text
+if($#ARGV == 0 ){
+ $file = $ARGV[0];
+ oeffnen($file);
+ updateFVW('i');
+} else {
+ FVWsetInfo();
+}
+
+
+### Main Event Loop
+MainLoop;
+
+###
+### Subroutines follow
+###
+###############################################################################
+
+sub updateCyl {
+ if (Exists($FlightView)) {
+ if ($wpcyl_state == 1) {wpcyldraw(0); wpcyldraw(1);}
+ }
+}
+
+sub updateZoom {
+ if ($zoom == 1) { zoom(); zoom(); }
+}
+
+# update flight view window
+sub updateFVW {
+
+ #if (Exists($FlightView)) {
+ my $initflag='u'; # update or initial //mapplot braucht das flag irgendwie beim erstem mal 'i'
+ if ($#_ != -1) { ## no parameters?
+ $initflag='i' if (shift eq 'i') ;
+ if (@introtext) {$canvas->delete(@introtext);}
+ }
+
+ # task and cylinder have to be erased first! (fix for bug #6)
+ if ($task_state == 1) {taskdraw(0);}
+ if ($wpcyl_state == 1) {wpcyldraw(0);}
+
+ mapplot($dxp, $dyp, $minlat, $minlon, $initflag);
+ trackplot($dxp, $dyp, $minlat, $minlon);
+ marksdraw();
+ baroplot();
+
+ if ($wpcyl_state == 1) {wpcyldraw(1);}
+ if ($task_state == 1) {taskdraw(1);}
+
+ FVWausg();
+}
+
+sub updateCoor {
+ FVWausg();
+ if (Exists($WPPlotWindow)) {WPPlotUpdate();}
+}
+
+sub oeffnen { ### open a File
+
+ my $backup=$file;
+ $file=shift; ### Filename wird vom Fileselektor uebernommen (file=global)
+
+ if ($file eq '') {$file=$backup; return;} ### Kein Filename -> zurueck
+
+ my $length=length($file);
+ my $test=substr($file, $length-3 ,3); ### Fileendung in $test
+
+ # check for igc-file (only file-ending...)
+ if ($test ne 'igc' && $test ne 'IGC') {
+ Errorbox("The file does not have igc or IGC ending. Trying to open anyway.");
+ }
+
+ if (! -r $file) {
+ Errorbox("Can't open $file");$file='No file opened'; return;
+ }
+
+ #if (Exists($initpic)) {$initpic->destroy;}
+ #reset alt-mode
+ $altmode = "baro";
+ $liftsexist=0;
+
+ #reset some variables (this was at prog-start in 1.6)
+ $xmin='';
+ $xmax='';
+ $ymin='';
+ $ymax='';
+ $zmin='0';
+ $zmax='';
+ $AKTWP=1;
+
+ $freeWP=1;
+ $offset=0; #elevation offset, used as openGLIGCexplorer option... after using elevation calibration of FVW!
+ $nr = 0 ;
+
+ # reset additional info in gpi-data
+ $gpi{'month'}="00";
+ $gpi{'day'}="00";
+ $gpi{'year'}="2009";
+ $gpi{'timezone'}=$config{'timezone'};
+ $gpi{'qnh'}=1013.25; # (this is also set in the beginning)
+ $gpi{'altitude_calibration_ref_press'}=0;
+ $gpi{'altitude_calibration_type'}="none";
+ $gpi{'altitude_calibration_point'}=0;
+ $gpi{'altitude_calibration_point_alt'}=0;
+ $gpi{'pilot'}="";
+ $gpi{'copilot'}="";
+ $gpi{'glider'}="";
+ $gpi{'callsign'}="";
+ $gpi{'airfield'}="";
+
+ $gpi{'logger'}="";
+ $gpi{'remarks'}="";
+ $gpi{'remarks2'}="";
+ $gpi{'remarks3'}="";
+
+ open(FILE,"<$file") || return; ### wie fehlermeldung und return?????
+
+ ($gpi{'year'}, $gpi{'month'}, $gpi{'day'}) = GPLIGCfunctions::guessdatefromfilename($file);
+
+ ### Einsaugen der IGC-Datei von File
+ @file=<FILE>; ###global! file fuer alle!!!
+ close (FILE);
+ $filestat='open'; ### Status : File geoeffnet
+
+ # reset some variables
+ $AKTWP=1;
+
+ ###alle array werden definiert!
+ @DECLON=();
+ @DECLAT=();
+ @DECTIME=();
+ @BARO=();
+ $BARO_max=-20000;
+ $BARO_min=100000;
+ @GPSALT=();
+ $GPSALT_max=-20000;
+ $GPSALT_min=100000;
+ @TIME=();
+ @LAT=();
+ @LON=();
+ @FIX=();
+ my @FIXb=();
+ @HEADER=();
+ @TASK=();
+ @ENL=(); #noise level
+ @IAS=(); #indicated airspeed
+ @SIU=(); # satellites in used
+ @FXA=(); # hor/vertical accuracy
+ @VXA=();
+ @RPM=();
+ $IAS_max=-10000;
+ $IAS_min=100000;
+ @ASPEED=();
+
+ # $ASPEED_max=-10000;
+ # $ASPEED_min=100000;
+ @compVARIO=();
+ @nonIVARIO=();
+ $nonIVARIO_max=-100;
+ $nonIVARIO_min=100;
+ @nonIVARIOGPS=();
+ $nonIVARIOGPS_max=-100;
+ $nonIVARIOGPS_min=100;
+ @IVARIO=();
+ @IVARIOGPS=();
+ @nonISPEED=();
+ $nonISPEED_max=-200000;
+ $nonISPEED_min=2000000;
+ @TASK_info=();
+ @WPIGCLAT=0;
+ @WPIGCLON=0;
+ @WPNAME=();
+ @WPLAT=();
+ @WPLON=();
+ @WPRADFAC=(); # WP radius factor (for cylinder/barrel)
+
+ # I-extensions to the B-record
+ $IASEXISTS = "no";
+ $IASLENGTH = 0;
+ $ENLEXISTS = "no";
+ $ENLLENGTH = 0;
+ $SIUEXISTS = "no";
+ $SIULENGTH = 0;
+ $FXAEXISTS = "no";
+ $FXALENGTH = 0;
+ $VXAEXISTS = "no";
+ $VXALENGTH = 0;
+ $RPMEXISTS = "no";
+ $RPMLENGTH = 0;
+
+ $TASKEXISTS = "no";
+
+ ## Trigonometric distances from some reference point
+ ## Skewed because we are on the surface of a sphere, but our
+ ## flown distances are a lot << than that very sphere we are on...
+
+ @KMY = ();
+ @KMX = ();
+
+ $busy=$FlightView->Busy;
+
+ ### Schleife ueber alle Zeilen und Selektierung der Eintraege nach A H C B
+ foreach my $zeile (@file) {
+
+ if ($zeile=~/^A(.+)\S?/) {$FDR=$1;}
+ if ($zeile=~/^H(.+)\S?/) {push(@HEADER , $1."\n");}
+
+ if ($zeile=~/^C(.+)\S?/) {
+ $TASKEXISTS="yes";
+ push(@TASK , $1."\n");
+ }
+
+ if ($zeile=~/^B(.+)\S?/) {push(@FIXb , $1."\n");}
+
+ # check for I_extensions to the Brecords (more here to be added SIU, FXA etc)
+ if ($zeile=~/^I(.+)\S?/) {
+ $izeile=$1;
+
+ if ($izeile =~/(\d{2})(\d{2})ENL/) {
+ $ENLSTART = $1 - 2;
+ $ENLLENGTH = $2 -$1 +1;
+
+ #$ENLEND = $2;
+ $ENLEXISTS = "yes";
+ }
+ if ($izeile =~/(\d{2})(\d{2})RPM/) {
+ $RPMSTART = $1 - 2;
+ $RPMLENGTH = $2 -$1 +1;
+
+ #$ENLEND = $2;
+ $RPMEXISTS = "yes";
+ }
+ if ($izeile =~/(\d{2})(\d{2})IAS/) {
+ $IASSTART = $1 - 2;
+ $IASLENGTH = $2 - $1 +1;
+ $IASEXISTS = "yes";
+ }
+ if ($izeile =~/(\d{2})(\d{2})SIU/) {
+ $SIUSTART = $1 - 2;
+ $SIULENGTH = $2 - $1 +1;
+ $SIUEXISTS = "yes";
+ }
+ if ($izeile =~/(\d{2})(\d{2})FXA/) {
+ $FXASTART = $1 - 2;
+ $FXALENGTH = $2 - $1 +1;
+ $FXAEXISTS = "yes";
+ }
+ if ($izeile =~/(\d{2})(\d{2})VXA/) {
+ $VXASTART = $1 - 2;
+ $VXALENGTH = $2 - $1 +1;
+ $VXAEXISTS = "yes";
+ }
+ }
+ }
+
+ # grep all "safe" position fixes (if 24th character is V == unsafe)
+ @FIX = grep { (substr($_,23,1) ne 'V'); } @FIXb;
+
+ # emergency Fallback, if no "A's" available
+ if ($#FIX == -1) {
+ Errorbox("No valid (A) position fixes found. Trying to use position fixes marked as invalid (V)");
+ @FIX = @FIXb;
+ }
+
+ # no fixes avaiilable? no safe ones and no unsafe ones... sorry, nothing to do
+ if ($#FIX == -1) {
+ Errorbox("No position fixes found - invalid igc-file!");
+ gpligcexit (1);
+ }
+
+ my $alterr=0;
+ ### read @BARO @GPSALT @TIME @LAT @LON from fixes-lines
+ for (my $z=0; $z<= $#FIX; $z++) {
+ my $skip=0;
+ if ($config{'skip_check'} && $config{'skip_del_first_after'} && !$z<1) {
+ if (GPLIGCfunctions::time2dec(substr($FIX[$z],0,6))-GPLIGCfunctions::time2dec(substr($FIX[$z-1],0,6)) > $config{'skip_limit_minutes'}/60 ) {$skip =1;}
+ }
+
+ if (! $skip) {
+ my $alt = substr($FIX[$z], 24,5);
+ my $gpsa = substr($FIX[$z], 29,5);
+ if ($alt > 20000) {$alt = 0; $alterr=1;}
+ if ($gpsa >20000) {$gpsa = 0; $alterr=1;}
+ push(@BARO, $alt);
+ push(@GPSALT, $gpsa);
+ push(@TIME, substr($FIX[$z], 0,6));
+ push(@LAT, substr($FIX[$z], 6, 8));
+ push(@LON, substr($FIX[$z], 14, 9));
+
+ if ($ENLEXISTS eq "yes") {
+ push(@ENL, substr($FIX[$z], $ENLSTART, $ENLLENGTH));
+ } else {
+ push(@ENL, "0");
+ }
+ if ($RPMEXISTS eq "yes") {
+ push(@RPM, substr($FIX[$z], $RPMSTART, $RPMLENGTH));
+ } else {
+ push(@RPM, "0");
+ }
+
+ if ($IASEXISTS eq "yes") {
+ push(@IAS, substr($FIX[$z], $IASSTART, $IASLENGTH));
+ } else {
+ push(@IAS, "0");
+ }
+
+ if ($SIUEXISTS eq "yes") {
+ push(@SIU, substr($FIX[$z], $SIUSTART, $SIULENGTH));
+ } else {
+ push(@SIU, "0");
+ }
+
+ if ($FXAEXISTS eq "yes") {
+ push(@FXA, substr($FIX[$z], $FXASTART, $FXALENGTH));
+ } else {
+ push(@FXA, "0");
+ }
+ if ($VXAEXISTS eq "yes") {
+ push(@VXA, substr($FIX[$z], $VXASTART, $VXALENGTH));
+ } else {
+ push(@VXA, "0");
+ }
+
+ }
+ }
+
+ if ($alterr) {
+ Errorbox("Very weird altitudes found! (>20.000m) They are set to 0. Check your igc-file.");
+ }
+
+ # convert time to decimal
+ foreach (@TIME) {
+ $tmptime=GPLIGCfunctions::time2dec($_);
+ push(@DECTIME, $tmptime);
+ }
+
+ # convert coordinates to decimal degrees
+ foreach (@LAT) {
+ push(@DECLAT, GPLIGCfunctions::igc2dec($_));
+ }
+
+ foreach (@LON) {
+ push(@DECLON, GPLIGCfunctions::igc2dec($_));
+ }
+
+ # Find reference point (center between max and min lat/lon)
+ my ($maxlat, $minlat)=GPLIGCfunctions::MaxKoor(\@DECLAT);
+ my ($maxlon, $minlon)=GPLIGCfunctions::MaxKoor(\@DECLON);
+ $centrex = ($minlon + $maxlon)/2;
+ $centrey = ($minlat + $maxlat)/2;
+
+
+ print "OEFFNEN: init maxlat minlat maxlon minlon: $maxlat $minlat $maxlon $minlon\n" if ($config{'DEBUG'});
+
+ # KMY and KMX are km distances in X ynd Y from refernece point
+
+ for ($i=0; $i<=$#DECLAT; $i++){
+ my $dist=GPLIGCfunctions::dist($centrey,$DECLON[$i],$DECLAT[$i],$DECLON[$i]);
+ if($centrey>$DECLAT[$i]){
+ $dist = -$dist;
+ }
+
+ #print "$i $dist\n";
+ push(@KMY, $dist);
+ }
+
+ for ($i=0; $i<=$#DECLON; $i++){
+ my $dist=GPLIGCfunctions::dist($DECLAT[$i],$centrex,$DECLAT[$i],$DECLON[$i]);
+ if($centrex>$DECLON[$i]){
+ $dist = -$dist;
+ }
+ push(@KMX, $dist);
+ }
+
+# average speed, vario, gpsvario (averaged by $config{'integrate_over'} position fixes)
+ for ($i=0; $i<=$#DECLAT; $i++){
+ if ($i >= $config{'integrate_over'}) {
+ my $dist=GPLIGCfunctions::dist($DECLAT[$i-$config{'integrate_over'}],$DECLON[$i-$config{'integrate_over'}],$DECLAT[$i],$DECLON[$i]);
+ push(@ASPEED, ($dist/($DECTIME[$i]-$DECTIME[$i-$config{'integrate_over'}])));
+ push(@IVARIO, (($BARO[$i]-$BARO[$i-$config{'integrate_over'}])/(($DECTIME[$i]-$DECTIME[$i-$config{'integrate_over'}])*3600)) );
+ push(@IVARIOGPS, (($GPSALT[$i]-$GPSALT[$i-$config{'integrate_over'}])/(($DECTIME[$i]-$DECTIME[$i-$config{'integrate_over'}])*3600)) );
+
+ } else {
+ push(@ASPEED, 0);
+ push(@IVARIO, 0);
+ push(@IVARIOGPS, 0);
+ }
+ }
+
+ # non averaged speed, vario. gpsvario TE vario(compVARIO)
+ for ($i=0; $i<=$#DECLAT; $i++) {
+ if ($i >= 1) {# && $i <$#DECLAT) {
+ my $dist=GPLIGCfunctions::dist($DECLAT[$i-1],$DECLON[$i-1],$DECLAT[$i],$DECLON[$i]);
+
+ my $delta_time=$DECTIME[$i]-$DECTIME[$i-1];
+
+ #my $delta_time_next=$DECTIME[$i+1]-$DECTIME[$i];
+ # WORKAROUND to avoid div by zero, if we have two identic B-records
+ if ($delta_time == 0) {$delta_time=0.00000001;Errorbox("Identical B records! check IGC file at ".GPLIGCfunctions::dec2time($DECTIME[$i])) }
+
+ #if ($delta_time_next == 0) {$delta_time_next=0.00000001;}
+
+ # check for time reversals!
+ # exception is 24:00->0:00 with a small window
+ # might be problematic for large interval files... :-(
+
+ my $trc=0; #time reversal count
+ my $firsttrcat=999; #first trc
+ my $nn; #n-1
+ if ($DECTIME[$i] < $DECTIME[$i-1] && !( $DECTIME[$i]<=0.2
+ && $DECTIME[$i]>=0
+ && $DECTIME[$i-1]<=24
+ && $DECTIME[$i-1]>=23.8 )) {
+
+ # ??? why this? $DECTIME[$i] = $DECTIME[$i-1] + 0.000014; # a half a second!
+ print " $DECTIME[$i] $DECTIME[$i-1] \n" if ($config{'DEBUG'});
+
+ if ($firsttrcat == 999) {
+ $firsttrcat = $DECTIME[$i];
+ $nn = $DECTIME[$i-1];
+ }
+ $trc++;
+ }
+ if ($trc > 0) {
+ Errorbox("$trc time reversal(s) found. between ".GPLIGCfunctions::dec2time($nn)."-".GPLIGCfunctions::dec2time($firsttrcat)."! Check your IGC file!");
+ }
+
+ # filter abnormal values....
+ #my $nonispeed = (($dist/$delta_time)+($distn/$delta_time_next))/2.0;
+ my $nonispeed = ($dist/$delta_time);
+ if ($nonispeed < 1200) {
+ push(@nonISPEED, $nonispeed);
+ } else {
+ push(@nonISPEED, 0);
+ }
+
+# my $nonivario = ((($BARO[$i]-$BARO[$i-1])/($delta_time*3600)) + (($BARO[$i+1]-$BARO[$i])/($delta_time_next*3600)))/2.0 ;
+ my $nonivario = ($BARO[$i]-$BARO[$i-1])/($delta_time*3600);
+ if (abs($nonivario) < 60) {
+ push(@nonIVARIO,$nonivario);
+ } else {
+ push(@nonIVARIO,0);
+ }
+
+ if ($IASEXISTS eq "yes") {
+ my $compvario = ( ($BARO[$i]-$BARO[$i-1]) -
+ ( ( (($IAS[$i-1]/3.6)**2) - ($IAS[$i]/3.6)**2) / 19.62) ) / ($delta_time*3600);
+ push(@compVARIO,$compvario);
+
+ } elsif ($config{'te_vario_fallback'}) { # ist das hier die richtige speed?
+ my $compvario = ( ($BARO[$i]-$BARO[$i-1]) -
+ ( ( (($nonISPEED[$i-1]/3.6)**2) - ($nonISPEED[$i]/3.6)**2) / 19.62) ) / ($delta_time*3600);
+ push(@compVARIO,$compvario);
+ }
+ else {push(@compVARIO,0);}
+
+#my $gpsvario = ((($GPSALT[$i]-$GPSALT[$i-1])/($delta_time*3600))+ (($GPSALT[$i+1]-$GPSALT[$i])/($delta_time_next*3600)))/2.0 ;
+ my $gpsvario = ($GPSALT[$i]-$GPSALT[$i-1])/($delta_time*3600);
+ if (abs($gpsvario) < 60) {
+ push(@nonIVARIOGPS,$gpsvario);
+ } else {
+ push(@nonIVARIOGPS,0);
+ }
+
+ } else { # this can be only calculated from the second data record. for the first record they will be set to zero
+ push(@nonISPEED, 0);
+ push(@nonIVARIO, 0);
+ push(@nonIVARIOGPS, 0);
+ if ($IASEXISTS eq "yes" || $config{'te_vario_fallback'} == 1) {
+ push(@compVARIO,0);
+ }
+ }
+ }
+
+ # warning
+ if ($IASEXISTS ne "yes" && $config{'te_vario_fallback'} == 1 && $config{'te_warning'})
+ {Errorbox("total energy compensation was calculated from gps groundspeed!\nTo turn off this warning set te_warning = 0.\nAlso see te_vario_fallback");}
+
+ # Maximum/minimum height:
+ ($maxbaro, $minbaro)=GPLIGCfunctions::MaxKoor(\@BARO);
+ ($maxgpsalt, $mingpsalt)=GPLIGCfunctions::MaxKoor(\@GPSALT);
+
+ # write tmp-files
+ tmpfileout();
+
+ sub tmpfileout {
+
+ open (BARO,">${pfadftmp}baro.dat");
+ open (GPSALT,">${pfadftmp}gpsalt.dat");
+ open (PRESS,">${pfadftmp}press.dat");
+ open (SPACE,">${pfadftmp}3d.dat");
+ open (LATPROJ,">${pfadftmp}latproj.dat");
+ open (LONPROJ,">${pfadftmp}lonproj.dat");
+ open (DELTAH,">${pfadftmp}deltah.dat");
+ open (VARIO,">${pfadftmp}vario.dat");
+ open (GPSVARIO,">${pfadftmp}gpsvario.dat");
+ open (SPEED,">${pfadftmp}speed.dat");
+ open (LONLAT,">${pfadftmp}lonlat.dat");
+ open (KM,">${pfadftmp}km.dat");
+ open (ENL, ">${pfadftmp}enl.dat");
+ open (IAS, ">${pfadftmp}ias.dat");
+ open (SAT, ">${pfadftmp}sat.dat");
+
+ # ----------------- LOOP over all data-records (fixes) --------------------
+
+ # writing tmp-files
+ for (my $i=0; $i<=$#DECTIME; $i++) { # DECTIME nicht FIX!
+
+ # processing of decimal time.....
+ # check if we pass the 24:00
+ if ($i > 0) { # not in first cycle
+
+ # if time goes backwards 24:00 -> 0:00
+ if ($DECTIME[$i] < $DECTIME[$i-1]) {
+
+ print "2400 -> 0000 detected, altering DECTIME...\n" if ($config{'DEBUG'});
+ print " $#DECTIME, dect,,,,, $#FIX fix...\n" if ($config{'DEBUG'});
+
+ # alter all time-points after this one... + 24
+ for (my $z=$i; $z<=$#DECTIME; $z++) {
+ $DECTIME[$z] = $DECTIME[$z] + 24;
+ }
+ }
+ }
+
+ print KM $KMX[$i]," ",$KMY[$i]," ",$BARO[$i],"\n";
+ print LONLAT $i," ",$LON[$i]," ",$LAT[$i],"\n";
+ print BARO $DECTIME[$i]," ",$BARO[$i],"\n";
+ print PRESS $DECTIME[$i]," ",GPLIGCfunctions::pressure($BARO[$i],$gpi{'qnh'}),"\n";
+ if ($VXAEXISTS eq "no") {
+ print GPSALT $DECTIME[$i]," ",$GPSALT[$i],"\n";
+ } else {
+ print GPSALT $DECTIME[$i]," ",$GPSALT[$i]," ", $VXA[$i],"\n";
+ }
+ print ENL $DECTIME[$i], " ", $ENL[$i], " ", $RPM[$i], "\n";
+ print IAS $DECTIME[$i], " ", $IAS[$i],"\n";
+ print SPACE $DECLON[$i]," ",$DECLAT[$i]," ",$BARO[$i]," ",$GPSALT[$i],"\n";
+ print LATPROJ $DECLAT[$i]," ",$BARO[$i]," ",$GPSALT[$i],"\n";
+ print LONPROJ $DECLON[$i]," ",$BARO[$i]," ",$GPSALT[$i],"\n";
+ print DELTAH $DECTIME[$i]," ",$BARO[$i]-$GPSALT[$i],"\n";
+
+ # averaged vario, speed, gps-vario
+ print VARIO $DECTIME[$i]," ",$IVARIO[$i],"\n";
+ print GPSVARIO $DECTIME[$i]," ",$IVARIOGPS[$i],"\n";
+ print SPEED $DECTIME[$i]," ",$ASPEED[$i],"\n";
+
+ print SAT $DECTIME[$i]," ",$SIU[$i]," ",$FXA[$i]," ", $VXA[$i],"\n";
+
+ # getting extrema of some values;
+
+ $BARO_max = $BARO[$i] if ($BARO[$i] > $BARO_max);
+ $BARO_min = $BARO[$i] if ($BARO[$i] < $BARO_min);
+ $GPSALT_max = $GPSALT[$i] if ($GPSALT[$i] > $GPSALT_max);
+ $GPSALT_min = $GPSALT[$i] if ($GPSALT[$i] < $GPSALT_min);
+
+ $nonISPEED_max = $nonISPEED[$i] if ($nonISPEED[$i] > $nonISPEED_max);
+ $nonISPEED_min = $nonISPEED[$i] if ($nonISPEED[$i] < $nonISPEED_min);
+
+ $IAS_max = $IAS[$i] if ($IAS[$i] > $IAS_max);
+ $IAS_min = $IAS[$i] if ($IAS[$i] < $IAS_min);
+
+ $nonIVARIO_max = $nonIVARIO[$i] if ($nonIVARIO[$i] > $nonIVARIO_max);
+ $nonIVARIO_min = $nonIVARIO[$i] if ($nonIVARIO[$i] < $nonIVARIO_min);
+
+ $nonIVARIOGPS_max = $nonIVARIOGPS[$i] if ($nonIVARIOGPS[$i] > $nonIVARIOGPS_max);
+ $nonIVARIOGPS_min = $nonIVARIOGPS[$i] if ($nonIVARIOGPS[$i] < $nonIVARIOGPS_min);
+
+ }
+
+ #rounding vario-extrema
+ $nonIVARIO_max = sprintf("%.4f",$nonIVARIO_max);
+ $nonIVARIO_min = sprintf("%.4f",$nonIVARIO_min);
+ $nonIVARIOGPS_max = sprintf("%.4f",$nonIVARIOGPS_max);
+ $nonIVARIOGPS_min = sprintf("%.4f",$nonIVARIOGPS_min);
+
+ # closing files
+ close (BARO);
+ close (GPSALT);
+ close (SPACE);
+ close (LATPROJ);
+ close (LONPROJ);
+ close (DELTAH);
+ close (VARIO);
+ close (SPEED);
+ close (LONLAT);
+ close (ENL);
+ close (IAS);
+ close (KM);
+ close (SAT);
+
+ }
+
+ if ($config{'DEBUG'}) {
+
+ print "Debugging in Oeffnen: max and min values\n";
+ print "baro $BARO_max \n";#= $BARO[$i] if ($BARO[$i] > $BARO_max);
+ print " $BARO_min \n";#= $BARO[$i] if ($BARO[$i] < $BARO_min);
+ print "gps $GPSALT_max \n";#= $GPSALT[$i] if ($GPSALT[$i] > $GPSALT_max);
+ print " $GPSALT_min \n";#= $GPSALT[$i] if ($GPSALT[$i] < $GPSALT_min);
+ print "nISp $nonISPEED_max \n";#= $nonISPEED[$i] if ($nonISPEED[$i] > $nonISPEED_max);
+ print " $nonISPEED_min \n";#= $nonISPEED[$i] if ($nonISPEED[$i] < $nonISPEED_min);
+ print "IAS $IAS_max \n";#= $IAS[$i] if ($IAS[$i] > $IAS_max);
+ print " $IAS_min \n";#= $IAS[$i] if ($IAS[$i] < $IAS_min);
+ print "nIV $nonIVARIO_max \n";#= $nonIVARIO[$i] if ($nonIVARIO[$i] > $nonIVARIO_max);
+ print " $nonIVARIO_min \n";#= $nonIVARIO[$i] if ($nonIVARIO[$i] < $nonIVARIO_min);
+ print "nIVgps $nonIVARIOGPS_max \n";#= $nonIVARIOGPS[$i] if ($nonIVARIOGPS[$i] > $nonIVARIOGPS_max);
+ print " $nonIVARIOGPS_min \n";#= $nonIVARIOGPS[$i] if ($nonIVARIOGPS[$i] < $nonIVARIOGPS_min);
+
+ }
+
+ # Generating HISTOGRAMS
+
+ # we need the decimal flighttime!
+ my $starttimeindex=GPLIGCfunctions::takeoff_detect(\@nonISPEED, 's');
+ my $landtimeindex=GPLIGCfunctions::takeoff_detect(\@nonISPEED, 'l');
+ my $decflighttime=$DECTIME[$landtimeindex]-$DECTIME[$starttimeindex];
+
+ # histogram intervals for vario
+ my $histo_intervall_vario = $config{'vario_histo_intervall'};#0.2;
+
+ # histogram intervals and limits for speed
+ my $histo_intervall = $config{'speed_histo_intervall'};#2.5;
+
+ ### GROUND SPEED HISTOGRAM
+ # initialize arrays for speed histogram
+ my @speedBEREICH=();
+ my @speedHISTO=();
+ my $i = 0;
+ for (my $bereich=$nonISPEED_min; $bereich <= $nonISPEED_max; $bereich+=$histo_intervall) {
+ push(@speedHISTO,0);
+ push(@speedBEREICH,$bereich);
+ }
+
+ # summarize the intervals
+ for (my $z=$starttimeindex ; $z < $landtimeindex; $z++) {
+ my $index = int(($nonISPEED[$z] - $nonISPEED_min ) / $histo_intervall);
+
+ #print "$index \n";
+ if ($index >= 0 && $index < (($nonISPEED_max-$nonISPEED_min)/$histo_intervall)) {
+
+ #print "if $index\n";
+ $speedHISTO[$index]+= $DECTIME[$z+1]-$DECTIME[$z];
+ }
+ }
+
+ #output
+ open (SHISTO,">${pfadftmp}shisto.dat");
+
+ #output in % of flighttime!
+ for (my $z=0; $z < $#speedHISTO; $z++) {
+
+ #print "$z $#speedHISTO \n";
+ print SHISTO $speedBEREICH[$z]+($histo_intervall/2)." ".(($speedHISTO[$z]/$decflighttime)*100)."\n";
+ }
+ close (SHISTO);
+
+ ### AIRSPEED HISTOGRAM
+ # initialize arrays
+ @speedBEREICH=();
+ @speedHISTO=();
+ $i = 0;
+
+ # initialize the histo-arrays
+ for (my $bereich=$IAS_min; $bereich <= $IAS_max; $bereich+=$histo_intervall) {
+ push(@speedHISTO,0);
+ push(@speedBEREICH,$bereich);
+ }
+
+ # summieren der intervalle
+ for (my $z=$starttimeindex ; $z < $landtimeindex; $z++) {
+ my $index = int(($IAS[$z] - $IAS_min ) / $histo_intervall);
+
+ #print "$index \n";
+ if ($index >= 0 && $index < (($IAS_max-$IAS_min)/$histo_intervall)) {
+
+ #print "if $index\n";
+ $speedHISTO[$index]+= $DECTIME[$z+1]-$DECTIME[$z];
+ }
+ }
+
+ #output
+ open (ASHISTO,">${pfadftmp}iashisto.dat");
+
+ #output in % of flighttime!
+ for (my $z=0; $z < $#speedHISTO; $z++) {
+
+ #print "$z $#speedHISTO \n";
+ print ASHISTO $speedBEREICH[$z]+($histo_intervall/2)." ".(($speedHISTO[$z]/$decflighttime)*100)."\n";
+ }
+ close (ASHISTO);
+
+ ### VARIO HISTO BARO
+
+ my @varioBEREICH=();
+ my @varioHISTO=();
+ $i = 0;
+
+ # initialize the histo-arrays
+ for (my $bereich=$nonIVARIO_min; $bereich <= $nonIVARIO_max; $bereich+=$histo_intervall_vario) {
+ push(@varioHISTO,0);
+ push(@varioBEREICH,$bereich);
+ }
+
+
+ # summieren der intervalle
+ for (my $z=$starttimeindex ; $z < $landtimeindex; $z++) {
+ my $index = int(($nonIVARIO[$z] - $nonIVARIO_min ) / $histo_intervall_vario);
+
+ #print "$index \n";
+ if ($index >= 0 && $index < (($nonIVARIO_max-$nonIVARIO_min)/$histo_intervall_vario)) {
+
+ #print "if $index\n";
+ $varioHISTO[$index]+= $DECTIME[$z+1]-$DECTIME[$z];
+ }
+ }
+
+
+ #output
+ open (VHISTO,">${pfadftmp}vhisto.dat");
+
+ #output in % of flighttime!
+ for (my $z=0; $z < $#varioHISTO; $z++) {
+ print VHISTO $varioBEREICH[$z]+($histo_intervall_vario/2)." ".(($varioHISTO[$z]/$decflighttime)*100)."\n";
+ }
+ close (VHISTO);
+
+ ### VARIO HISTO GPS
+
+ @varioBEREICH=();
+ @varioHISTO=();
+ $i = 0;
+
+ # initialize the histo-arrays
+ for (my $bereich=$nonIVARIOGPS_min; $bereich <= $nonIVARIOGPS_max; $bereich+=$histo_intervall_vario) {
+ push(@varioHISTO,0);
+ push(@varioBEREICH,$bereich);
+
+ #print "$bereich ..\n";
+ }
+
+ # summieren der intervalle
+
+ for (my $z=$starttimeindex ; $z < $landtimeindex; $z++) {
+ my $index = int((($nonIVARIOGPS[$z] - $nonIVARIOGPS_min ) / $histo_intervall_vario)+.5);
+
+ #print "$nonIVARIOGPS[$z] \n";
+
+ if ($index >= 0 && $index < (($nonIVARIOGPS_max-$nonIVARIOGPS_min)/$histo_intervall_vario)) {
+
+ #print "if $index\n";
+ $varioHISTO[$index]+= $DECTIME[$z+1]-$DECTIME[$z];
+ }
+ }
+
+ #output
+ open (VHISTOGPS,">${pfadftmp}vhistogps.dat");
+
+ #output in % of flighttime!
+ for (my $z=0; $z < $#varioHISTO; $z++) {
+ print VHISTOGPS $varioBEREICH[$z]+($histo_intervall_vario/2)." ".(($varioHISTO[$z]/$decflighttime)*100)."\n";
+ }
+ close (VHISTOGPS);
+
+ ### BARO HISTO
+
+ @baroBEREICH=();
+ @baroHISTO=();
+ $i = 0;
+
+ # initialize the histo-arrays
+ for (my $bereich=$BARO_min; $bereich <= $BARO_max; $bereich+=$config{'baro_histo_intervall'}) {
+ push(@baroHISTO,0);
+ push(@baroBEREICH,$bereich);
+ }
+
+ # summieren der intervalle
+ for (my $z=$starttimeindex ; $z < $landtimeindex; $z++) {
+ my $index = int(($BARO[$z] - $BARO_min ) / $config{'baro_histo_intervall'});
+
+ #print "$index \n";
+ if ($index >= 0 && $index < (($BARO_max-$BARO_min)/$config{'baro_histo_intervall'})) {
+
+ #print "if $index\n";
+ $baroHISTO[$index]+= $DECTIME[$z+1]-$DECTIME[$z];
+ }
+ }
+
+
+ #output
+ open (BAROHISTO,">${pfadftmp}barohisto.dat");
+
+ #output in % of flighttime!
+ for (my $z=0; $z < $#baroHISTO; $z++) {
+ print BAROHISTO $baroBEREICH[$z]+($config{'baro_histo_intervall'}/2)." ".(($baroHISTO[$z]/$decflighttime)*100)."\n";
+ }
+ close (BAROHISTO);
+
+ ### GPS HISTO
+
+ @baroBEREICH=();
+ @baroHISTO=();
+ $i = 0;
+
+ # initialize the histo-arrays
+ for (my $bereich=$GPSALT_min; $bereich <= $GPSALT_max; $bereich+=$config{'baro_histo_intervall'}) {
+ push(@baroHISTO,0);
+ push(@baroBEREICH,$bereich);
+ }
+
+ # summieren der intervalle
+ for (my $z=$starttimeindex ; $z < $landtimeindex; $z++) {
+ my $index = int(($GPSALT[$z] - $GPSALT_min ) / $config{'baro_histo_intervall'});
+
+ #print "$index \n";
+ if ($index >= 0 && $index < (($GPSALT_max-$GPSALT_min)/$config{'baro_histo_intervall'})) {
+
+ #print "if $index\n";
+ $baroHISTO[$index]+= $DECTIME[$z+1]-$DECTIME[$z];
+ }
+ }
+
+
+ #output
+ open (BAROHISTO,">${pfadftmp}gpshisto.dat");
+
+ #output in % of flighttime!
+ for (my $z=0; $z < $#baroHISTO; $z++) {
+ print BAROHISTO $baroBEREICH[$z]+($config{'baro_histo_intervall'}/2)." ".(($baroHISTO[$z]/$decflighttime)*100)."\n";
+ }
+ close (BAROHISTO);
+
+ ##################
+ # This is a work-around for files without pressure altitude...
+ # hell knows how that can happen, but I have seen such.
+ $dybaro = ($maxbaro - $minbaro);
+
+ if($dybaro == 0){ #some sick files only have GPS altitude...
+ Errorbox("Work-around enabled! NO PRESSURE ALTITUDE FOUND IN FILE! USING GPS ALTITUDE");
+ $minbaro = $mingpsalt;
+ $maxbaro = $maxgpsalt;
+ @BARO = @GPSALT;
+ @nonIVARIO = @nonIVARIOGPS;
+ @IVARIO = @IVARIOGPS;
+ $altmode = "gps";
+ }
+ #################
+
+ # evaluation of @TASK
+ my $z=0;
+ $MAXWP=0;
+
+ my $j=1;
+
+ # this is the new and better task scan-function
+ foreach (@TASK) {
+ if (substr($_,7,1) ne 'N' && substr($_,7,1) ne 'S') {
+
+ # $_ is a task-definition !
+
+ $TASK_ID=substr($_,18,4);
+ my $zwisch_date=GPLIGCfunctions::time2human(substr($_,0,6),'d');
+ my $zwisch_zeit=GPLIGCfunctions::time2human(substr($_,6,6),'t');
+ $TASK_TIME=$zwisch_date." ".$zwisch_zeit;
+ $TASK_DATE=GPLIGCfunctions::time2human(substr($_,12,6),'d');
+ $TASK_WPs=substr($_,22,2);
+
+ #$MAXWP=$MAXWP+($TASK_WPs+4); # + start, abflug, finish, landing
+
+ push(@TASK_info, "------------");
+ push(@TASK_info, "Task ID: $TASK_ID");
+
+ push(@TASK_info, "Task set time: $TASK_TIME");
+ push(@TASK_info, "Task date: $TASK_DATE");
+ push(@TASK_info, "#WPs : $TASK_WPs");
+
+ } else {
+
+ #only if different from last one (avoid the doubled entries)
+ if ( (substr($_,0,8) ne $WPIGCLAT[$j-1] && substr($_,8,9) ne $WPIGCLON[$j-1]) &&
+ !( substr($_,0,7) eq "0000000" && substr($_,8,8) eq "00000000" ) # ignore 0/0 coordinates (invalid WPs) Bug #4
+ ) {
+
+ $WPIGCLAT[$j]=substr($_,0,8);
+ $WPIGCLON[$j]=substr($_,8,9);
+ $WPNAME[$j]=substr($_,17);
+ $WPRADFAC[$j]=1.0;
+ chop($WPNAME[$j]); #cut CR
+ chop($WPNAME[$j]); #cut LF
+
+ my $formlat=GPLIGCfunctions::coorconvert(GPLIGCfunctions::igc2dec($WPIGCLAT[$j]),'lat','igch');
+ my $formlon=GPLIGCfunctions::coorconvert(GPLIGCfunctions::igc2dec($WPIGCLON[$j]),'lon','igch');
+
+ #push(@TASK_info, "$WPIGCLAT[$j] $WPIGCLON[$j] $WPNAME[$j]");
+ push(@TASK_info, "$formlat $formlon $WPNAME[$j]");
+ $j++;
+ $MAXWP++;
+ } else { # if doubled, put in TASK_info trotzdem
+ my $wpname=substr($_,17);
+ my $wplat=substr($_,0,8);
+ my $wplon=substr($_,8,9);
+
+ chop($wpname); #cut CR
+ chop($wpname); #cut LF
+ my $formlat=GPLIGCfunctions::coorconvert(GPLIGCfunctions::igc2dec($wplat),'lat','igch');
+ my $formlon=GPLIGCfunctions::coorconvert(GPLIGCfunctions::igc2dec($wplon),'lon','igch');
+ push(@TASK_info, "$formlat $formlon $wpname");
+ }
+ }
+ }
+
+ #if there is no task in the igc-file set some, to prevent errors
+ if ($TASKEXISTS eq "no" ) {
+ $MAXWP =1;
+
+ # canberra
+ $WPIGCLAT[1]="3515690S";
+ $WPIGCLON[1]="14908123E";
+ $WPNAME[1]="GPLIGC Headquarter";
+ $WPRADFAC[1]=1.0;
+ }
+
+ # convert all wp's to decimal format!
+ for ($i=1; $i<=$#WPIGCLAT; $i++){
+ $WPLAT[$i]=GPLIGCfunctions::igc2dec($WPIGCLAT[$i]);
+ $WPLON[$i]=GPLIGCfunctions::igc2dec($WPIGCLON[$i]);
+ }
+
+# set start and finish time (for task_speed) initially to takeoff and landing time
+# also the unpowered flight window
+#$task_start_time_index = GPLIGCfunctions::takeoff_detect(\@nonISPEED,'s');
+ $task_finish_time_index = GPLIGCfunctions::takeoff_detect(\@nonISPEED,'l');
+
+ $task_start_time_index = GPLIGCfunctions::releaseDetect(\@BARO,GPLIGCfunctions::takeoff_detect(\@nonISPEED,'s'));
+
+ ###test triangle
+ #GPLIGCfunctions::bestriangle(\@DECLAT, \@DECLON, 1, $#DECLAT, 'x', 100000);
+ #print "hannes routine..... is working\n";
+ #GPLIGCfunctions::bestrecurse(\@DECLAT, \@DECLON);
+ #print "ready \n";
+
+ foreach (@HEADER) {
+
+ # i have to chop off trailing garbage first
+ $_ =~ s/\s+$// ;
+ if (/^FPLT[\w\d\s]+:(.+)$/) {$gpi{'pilot'} = $1}
+ if (/^FGTY[\w\d\s]+:(.+)$/) {$gpi{'glider'} = $1}
+ if (/^FGID[\w\d\s]+:(.+)$/) {$gpi{'callsign'} = $1}
+ if ($gpi{'year'} == 0 && $gpi{'month'} == 0 && $gpi{'day'} == 0) {
+ if (/^FDTE(\d{6})/) {$gpi{'day'} = substr($1,0,2); $gpi{'month'}=substr($1,2,2); $gpi{'year'}=substr($1,4,2);
+ if ($gpi{'year'} > 90) {$gpi{'year'} +=1900} else {$gpi{'year'} +=2000}
+ }
+ }
+
+ }
+
+ $stat_start =0;
+ $stat_end= $#BARO;
+
+ # check for gpi file and load if present!
+ # if not
+
+ my $gpifile = substr($file, 0, -3)."gpi";
+
+ if (-r $gpifile) {load_gpi();}
+ elsif ($config{'open_additional_info'} == 1) {
+ gpiinput();
+ }
+
+ if ($gpi{'altitude_calibration_type'} eq "baro") {elevationcalibration("baro",$gpi{'altitude_calibration_point_alt'},$gpi{'altitude_calibration_point'},1);}
+ if ($gpi{'altitude_calibration_type'} eq "constant") {elevationcalibration("constant",$gpi{'altitude_calibration_point_alt'},$gpi{'altitude_calibration_point'},1);}
+ if ($gpi{'altitude_calibration_type'} eq "refpress") {qnhcalibration($gpi{'qnh'},$gpi{'altitude_calibration_ref_press'},1);}
+
+ unzoomed();
+
+ if ($config{'photos'}) {
+ print "Starting to process Photo-stuff.... .... \n" if ($config{'DEBUG'});
+ checkPhotos();
+ processPhotos();
+ print "..... processing Photo-stuff finished. \n" if ($config{'DEBUG'});
+ }
+
+ my($ofilename, $odirectories, $osuffix) = File::Basename::fileparse($file);
+ $FlightView->configure(-title=>"$ofilename");#.$osuffix"); #<-- osuffix empty
+ $busy=$FlightView->Unbusy;
+
+ print "sub oeffnen fertig\n" if ($config{'DEBUG'});
+}
+# oeffnen
+###############################################################################
+
+# Give out plots via gnuplot
+sub Ausgabe { ### Ausgabe der Plots mit Gnuplot
+ if ($filestat eq 'closed') {
+ $FlightView->bell;
+ return;
+ }
+
+ #check for gnuplot!
+ if ($^O ne "MSWin32") {
+ if (system("echo 'q' | gnuplot")) {
+ Errorbox("Can't execute gnuplot. Please check your gnuplot installation");
+ return;
+ }
+ }
+
+ my $mode = shift;
+
+ $bereich='['.$xmin.':'.$xmax.']['.$ymin.':'.$ymax.']['.$zmin.':'.$zmax.']';
+
+ # Linux/Unix Gnupot 3.x
+ if ( $^O ne "MSWin32" && $config{'gnuplot_major_version'} != 4 ) {
+ open (BPIPE, "| gnuplot -persist"); ###oeffnen von GNUPLOT write-Pipe
+ print "using old gnuplot 3.x \n" if ($config{'DEBUG'});
+
+ } else {
+ unlink ("${pfadftmp}plot.gpl");
+ open (BPIPE, ">${pfadftmp}plot.gpl"); # command file for gnuplot
+ print "using new gnuplot 4.x \n" if ($config{'DEBUG'} && $config{'gnuplot_major_version'} == 4);
+ print "using windows gnuplot: $config{'gnuplot_win_exec'} \n" if ($config{'DEBUG'} && $^O eq "MSWin32") ;
+ }
+
+ my $w32_persist;
+ my $linuxquiet = '';
+ if ($^O ne "MSWin32") {$linuxquiet =' 2>/dev/null >&2';}
+
+ if ( ($config{'gnuplot_terminal'} ne 'x11') && ($config{'gnuplot_terminal'} ne 'qt')){
+ if ($savname eq 'no'){$savname=save();}
+ if ($savname eq 'no'){close BPIPE;return;}
+ if ($savname ne 'no'){print BPIPE "set term $config{'gnuplot_terminal'}\n";
+ print BPIPE "set output "."\'".$savname."\'"."\n";}
+ $w32_persist = "";
+ } else {
+ print BPIPE "set term $config{'gnuplot_terminal'}\n";
+ $w32_persist = "-";
+ }
+
+ $busy=$FlightView->Busy;
+ $file=~ /(.+)\/(.+?)$/; #Filename nach letztem "/" in $2
+ my $title=$2; ### titel fuer plot
+
+ if (defined $title) {} else {$title="No Title";}
+
+ print BPIPE "set title \"$title\"\n"; ### wird gesetzt
+
+ if ($mode eq '3d') {
+ print BPIPE "set view ".(90-$config{'gnuplot_3d_rotx'}).",".(360-$config{'gnuplot_3d_rotz'})."\n";
+ print BPIPE "set ticslevel 0\n";
+ }
+
+ if ($config{'gnuplot_grid_state'} eq 'set grid') {
+ print BPIPE "set grid\n";
+ } ### grid on
+
+ #experimental
+ #print BPIPE "set mouse\n";
+
+ print BPIPE "set title \"$file\"\n";
+ print BPIPE $com1." $bereich ".$com2."\n";
+
+ print $com1." $bereich ".$com2."\n" if ($config{'DEBUG'});
+
+ close (BPIPE) if ($^O ne "MSWin32" && $config{'gnuplot_major_version'} == 3);
+
+ if ($^O eq "MSWin32") {
+ close (BPIPE);
+ open (BATCH, ">${pfadftmp}plot.bat");
+ print BATCH "\@ECHO off\n";
+ print BATCH "$config{'gnuplot_win_exec'} ${pfadftmp}plot.gpl $w32_persist\n";
+ close (BATCH);
+ system("start $start_parameter ${pfadftmp}plot.bat"); # windows trick ;-)
+ } elsif ($config{'gnuplot_major_version'} == 4) {
+
+ # here new start of gnuplot for unices
+ # if gnuplot==4
+ #print BPIPE "bind x \"quit\"\n";
+ print BPIPE "pause -1 \n" if (!$config{'gnuplot_4_terminal'});
+
+ #print BPIPE "exit \n";
+ close (BPIPE);
+ my $pidf = fork();
+ if ($pidf == 0) {
+ print "starting gnuplot 4 forked!\n" if ($config{'DEBUG'});
+ system( "gnuplot ${pfadftmp}plot.gpl $w32_persist $linuxquiet") if (!$config{'gnuplot_4_terminal'});
+ system( "$config{'gnuplot_terminal_app'} \'gnuplot ${pfadftmp}plot.gpl $w32_persist\'") if ($config{'gnuplot_4_terminal'});
+
+ #use POSIX ":sys_wait_h";
+ #waitpid($pidgp,NULL);
+ #close(GP);
+ wait();
+ CORE::exit();
+ }
+
+ }
+
+ $savname='no'; ##nach ausgabe savname auf 'no' damit next time ein neuer name abgefragt wird
+ $bereich=''; ### bereich loeschen!
+ $busy=$FlightView->Unbusy;
+}
+
+# Ausgabe
+###############################################################################
+
+# give out an error message
+sub Errorbox {
+ my $fm=$_[0];
+ my $Errorbox=$FlightView->messageBox(-message=>$fm, -type=>OK, -icon=>'error');
+ return ;
+}
+
+
+# Errorbox
+###############################################################################
+
+sub Photodirselect {
+
+ if (!$config{'photos'}) {return;}
+
+ my $initdir = $config{'working_directory'};
+
+ if ($config{'photo_path'} ne "none") {
+ $initdir = $config{'photo_path'};
+ }
+
+ my $types = [
+ ['JPEG photos', ['.jpg', '.JPG', '.JPEG', '.jpeg']],
+ ['Audio', ['.amr', '.mp3', '.AMR', '.MP3','.ogg','.OGG']],
+ ['Video', ['.3gp', '.3GP', '.avi', '.AVI']],
+ ['All Files', '*' , ],
+ ];
+
+ my $dir = $FlightView->getOpenFile(-initialdir=>$initdir,-title=>"Open photos",-filetypes=>$types);
+
+ if (defined $dir) {
+ $dir = GPLIGCfunctions::setpwd($dir);
+ if (-d $dir) {
+ $config{'photo_path'}= $dir;
+
+ checkPhotos(1); # 1 = flag, that we call from Photodirselect and photo_path should be used first!
+ processPhotos();
+
+ }
+ }
+
+ return;
+
+}
+
+# Fileselector for opening (called from main loop)
+sub Fileselekt {
+
+ my $types = [
+ ['IGC Files', ['.igc', '.IGC']],
+ ['All Files', '*' ]
+ ];
+
+ my $pwd_winsafe = $config{'working_directory'};
+
+ if ($^O eq "MSWin32") {
+ $pwd_winsafe =~ s#/#\\#g;
+ }
+
+ my $file = $FlightView->getOpenFile(-initialdir=>$pwd_winsafe,-title=>"Open IGC file",-filetypes=>$types);
+
+ if (defined $file) {
+ schliessen();
+ $config{'working_directory'}=GPLIGCfunctions::setpwd($file);
+ oeffnen($file);
+
+ updateFVW('i');
+
+ }
+ return;
+}
+
+# Fileselekt
+###############################################################################
+
+###Fileselector f.saving files
+sub save {
+ my $vorschlag = shift;
+ if (!defined $vorschlag) {$vorschlag="";}
+ my $sfile=$FlightView->getSaveFile(-initialfile=>$vorschlag,-initialdir=>$config{'working_directory'}, -title=>"Save output as");
+
+ if (defined $sfile) {
+ $config{'working_directory'}=GPLIGCfunctions::setpwd($sfile);
+
+# thats tested by getSaveFile already and asked for overwriting!
+#if (open (TEST,"<$sfile")) {close (TEST); Errorbox("File exists"); return ('no');}
+ if (open (TEST,">$sfile")) {
+ close (TEST);
+ unlink($sfile);
+ } else {
+ close (TEST); Errorbox("Cannot write"); return('no');
+ }
+ } else {
+ $sfile='no';
+ }
+
+ return ($sfile);
+}
+
+sub directory {
+ my $sfile=$FlightView->chooseDirectory(-initialdir=>$config{'working_directory'}, -title=>"Choose Directory");
+
+ if (defined $sfile && $file ne "") {
+ $config{'working_directory'}=$sfile;
+
+ return ($sfile);
+ } else {
+
+ return ("no");
+ }
+
+}
+
+###############################################################################
+
+###schliessen
+# used if new file is opened
+sub schliessen {
+
+ # clear temp files
+ foreach (@clearlist) {
+ unlink($pfadftmp.$_);
+ }
+
+ #$calcstat='no';
+ if ($filestat eq 'closed'){return;}
+ $filestat='closed';
+ $file='No file opened';
+
+ #close additional windows
+ if (Exists($FF)) {$FF->destroy;}
+ if (Exists($FI)) {$FI->destroy;}
+ if (Exists($MF)) {$MF->destroy;}
+ if (Exists($WPPlotWindow)) {$WPPlotWindow->destroy;}
+ if (Exists($thermal_statistik)) {$thermal_statistik->destroy;}
+ if (Exists($glide_statistik)) {$glide_statistik->destroy;}
+
+ #check for input-windows?!
+
+ # clear drawing
+ if (@trackplot) {$canvas -> delete (@trackplot); undef @trackplot;}
+ if (@mapplot) {$canvas -> delete (@mapplot); undef @mapplot;}
+ if (@wpcyl_lines) {$canvas -> delete (@wpcyl_lines); undef @wpcyl_lines;}
+ if (@acc_lines) {$canvas -> delete (@acc_lines); undef @acc_lines;}
+ if (@task_lines) {$canvas -> delete (@task_lines); undef @task_lines;}
+ if (@baroplot) {$barocanvas -> delete (@baroplot); undef @baroplot;}
+ if (@baroplot_task) {$barocanvas -> delete (@baroplot_task); undef @baroplot_task;}
+ if (@marks_lines) {$canvas -> delete (@marks_lines); undef @marks_lines;}
+}
+
+###############################################################################
+
+### subroutine ende. alle erzeugten *.dat werden geloescht
+sub gpligcexit {
+
+ # remove temporary files
+ foreach (@clearlist) {
+ unlink($pfadftmp.$_);
+ }
+
+ #system ("rm -r $pfadftmp");
+ rmdir $pfadftmp;
+
+ # remove the shared memory segment
+ # if ($^O ne "MSWin32") {
+ # if (defined $shm_id) {
+ # shmctl($shm_id, IPC_RMID, 0) || print "Error removing shared mem\n";
+ # }
+ # }
+
+ #print "ENDE!!!!!!!!!! GUT ALLES GUT! \n";
+
+ exit;
+
+}
+
+###############################################################################
+
+sub FVWsetInfo {
+ @introtext=();
+ push(@introtext, $canvas->createText(5,5, -anchor=>"nw", -text=>$text, -fill=>"black"));
+ $canvas->update();
+}
+
+### subroutine info
+sub info {
+
+ # jpg if Tk::JPEG availabel, otherwise gif
+ my $pictype;
+ my $picname = "logos";
+ if ($have_jpeg) {
+ $pictype = "jpg";
+ print "Tk::JPEG available. Trying to use jpeg-logo!\n" if ($config{'DEBUG'});
+ } else {
+ $pictype = "gif";
+ print "Tk::JPEG not available. Trying to use gif-logo!\n" if ($config{'DEBUG'});
+ }
+
+ if (Exists($infoFenster)) {$infoFenster->destroy;}
+
+ $infoFenster=$FlightView->Toplevel();
+ $infoFenster->configure(-title=>"Information");
+
+ setexit($infoFenster);
+ my $pic=$infoFenster->Photo();
+
+ # Look in install-directory AND in ./ for appropriate files...
+ if(-f "$config{'datadir'}/$picname.$pictype"){
+ $pic->configure(-file=>"$config{'datadir'}/$picname.$pictype");
+ } elsif (-f "./$picname.$pictype"){
+ $pic->configure(-file=>"./$picname.$pictype");
+ } elsif(-f "${scriptpath}$picname.$pictype") {
+ $pic->configure(-file=>"${scriptpath}$picname.$pictype");
+ } else {
+
+ print "Could not find \'$picname.$pictype\' in $config{'datadir'}/ and ./ and $scriptpath Fix this, please. Exiting now...\n";
+ gpligcexit(1);
+ }
+
+ my $picbut=$infoFenster->Label(-image=>$pic);
+ $picbut->pack();
+
+ my $mess=$infoFenster->Message(-width=>"80c",-text=>$text);
+ $mess->pack();
+ my $exb=$infoFenster->Button(-text=>"Exit",-command=>sub{$infoFenster->destroy();});
+ $exb->pack();
+}
+
+sub help {
+
+ # jpg if Tk::JPEG availabel, otherwise gif
+ if (Exists($helpFenster)) {$helpFenster->destroy;}
+
+ $helpFenster=$FlightView->Toplevel();
+ $helpFenster->configure(-title=>"Help / Keys");
+
+ setexit($helpFenster);
+
+ my $labeltext= <<ENDE;
+Move cursor:
+ <<(F1) <(F2) (F3)> (F4)>>
+
+Measuring/select tool:
+ (F5)=Set first point, (F6)=Set second point, (F7)=Measure
+ (F11)=zoom to selection, (F12)=reset selection
+
+Statistics:
+ (F8)=Thermal statistics, (F9)=Glide statistics
+
+Set task markers:
+ (s)start, (f)inish
+
+Tasks:
+ (t)=on/off, add (w)aypoint, insert waypoint (b)efore / (a)fter actual WP, re(p)lace WP
+
+Waypoints:
+ (c)ylinder on/off, set (r)ange
+
+Output:
+ (o)utput to postscript, (i)=baro, (F10)=save point to .lif file
+
+Altitude:
+ (e)levation calibration, Q(n)H calibration
+
+Drawing:
+ (g)rid on/off, (y) resize/redraw, (z)oom on/off,
+ (M)aps on/off, (#)=re-download maps, (+)/(-) change map zoom level
+ (F11)=zoom to selected
+
+ENDE
+
+ if ($config{'photos'}) {
+ $labeltext .= "Photos / Multimedia:\n (v)iew next photo/mm, e(x)act photo/mm time calibration\n (h)ide photos/mm, (m)edia list, geotag pict(u)res\n\n";
+ }
+
+ $labeltext .= "(ESC) Exit";
+
+ my $mess=$helpFenster->Message(-text=>$labeltext); #-width=>"80c",-text=>$labeltext);
+ $mess->pack();
+ my $exb=$helpFenster->Button(-text=>"Exit",-command=>sub{$helpFenster->destroy();});
+ $exb->pack();
+}
+
+###############################################################################
+
+sub OpenGLexplorer {
+ if ($filestat eq 'closed') {$FlightView->bell; return;}
+
+ # we may have more that one...
+ # if ($^O ne "MSWin32") {
+ # if (defined $oGLePID) {return}
+ # }
+
+ if (system("ogie --check")) {Errorbox("Can't execute \"ogie\". Check installation");
+ return;}
+
+ # We start the explorer with --parent-pid $$, it will send a SIGUSR1 on exit
+ # On receiving SIGUSR1 we will waitpid for it (we dont need a zombie...)
+ # but not on windows
+
+ my $DEBUGOGIE = "";
+ $DEBUGOGIE = "--debug" if ($config{'DEBUG'});
+
+ my $lifts="";
+ $liftfile = substr($file, 0, -3)."lif";
+ if (-r $liftfile) {$lifts= "--lifts \"$liftfile\"";}
+
+ # so far lifts or photos
+ else {
+ if ($config{'photos'} && !$hide_mm && $#PHOTO_FILES > 0) {
+
+ $pfile = substr($file, 0, -3)."photocoord";
+ open (PF, ">$pfile");
+
+ for (my $z=0; $z<=$#PHOTO_FILES;$z++) {
+ my ($picname, $p, $suf) = File::Basename::fileparse($PHOTO_FILES[$z]);
+ print PF "$DECLAT[$PHOTO_FILES_INDICES[$z]] $DECLON[$PHOTO_FILES_INDICES[$z]] $BARO[$PHOTO_FILES_INDICES[$z]] 0 0 0 0 $picname \n";
+ }
+ close PF;
+
+ # ausgabe pseudo-liftsfile
+ $lifts = "--lifts-info-mode 7 --lifts \"$pfile\" ";
+ }
+ }
+
+ if ($^O ne "MSWin32") {
+
+ # this produced the warning
+
+ $oGLePID = open (OGLEX, "| ogie $DEBUGOGIE -i \"$file\" --parent-pid $$ --marker-pos $nr --marker --offset $offset --quiet $lifts ");
+
+# $oGLePID = open (OGLEX, "| ogie $DEBUGOGIE -i \"$file\" --marker-pos $nr --marker --offset $offset --quiet");
+ print "OGIE PID is : $oGLePID \n" if ($config{'DEBUG'});
+
+ #close (OGLEX);
+
+# -> Don't forget to waitpid somewhere.... (what formerly was don on receiving SIGUSR1, see below)
+
+ ### This was the old SysV IPC communication (shared memory)
+ ### not available on many platforms (win32)
+ ### SIGNAL handling "too" safe in perl for that reason
+ ### no signal processing in MainLoop, when idle.
+
+ $SIG{'USR1'} = sub {waitpid $oGLePID,0; close OGLEX; undef $oGLePID;
+
+ # shmctl($shm_id, IPC_RMID, 0) || print "Error removing shared mem\n";
+ # undef $shm_id;
+ };
+ #
+ ## what to do on receiving sigusr2, sigusr2 is send by openGLIGCexplorer, when marker is moved...
+#$SIG{'USR2'} = sub {$sigusr2flag=1; print "got sigusr2.. (GPLIGC)\n"; FVWausg();$FlightView->update;};
+#
+ ## After we startet the explorer we can initialize the SysV IPC shared Memory.....
+ ## 76 is a magic number
+ #$shm_key = ftok($file, 76);
+ #
+ ##print "SHM_key vom GPLIGC = $shm_key \n";
+#$shm_id = shmget($shm_key , 4, IPC_CREAT | S_IRWXU);
+#
+#if (!defined $shm_id) {
+# print "Error initializing the SysV IPC Shared Memory.... No communication with openGLIGCexplorer :-(\n";
+
+ #}
+
+ } else { # starting openGLIGCexplorer for windows
+
+ system("start $start_parameter ogie $DEBUGOGIE -i \"$file\" --marker-pos $nr --marker --offset $offset --quiet $lifts ");
+
+#print "start /B ogie -i $file --marker-pos $nr --marker --offset $offset --quiet";
+ }
+
+ ###
+ # -> Here goes the new sockets-code
+ # start a listening tcp server (non-blocking mode)
+ # with fileevent-> callback for recieving and updating
+
+ # we need a flag to decide if explorer is running
+ # and we need to send the explorer positions also.
+ # ............
+
+}
+
+########################################
+
+### FlightInfo
+sub FlightInfo {
+ if (Exists($FI)) {$FI->destroy;}
+
+ if ($filestat eq 'closed') {$FlightView->bell; return;}
+ $FI=$FlightView->Toplevel();
+ $FI->configure(-title=>"Flight information");
+
+ setexit($FI);
+
+ $FDR = "unknown" if !defined $FDR;
+ my $finfotext="Flight data recorder:\n$FDR\nHeader:\n";
+
+ foreach (@HEADER) {
+ $_=~/(.*?)(\s*)$/;
+ $finfotext.=$1."\n";
+ }
+
+ foreach (@TASK_info) {
+ $finfotext.=$_."\n";
+ }
+
+ my $label=$FI->Message(-width=>"80c",-textvariable=>\$finfotext);
+ $label->pack(-fill=>"x");
+
+ my $exb=$FI->Button(-text=>"Exit",-command=>sub{$FI->destroy();});
+ $exb->pack();
+}
+
+###############################################################################
+
+### Flight Statistics
+sub FlightStatistics {
+ if (Exists($FF)) {$FF->destroy;}
+
+ if ($filestat eq 'closed') {$FlightView->bell; return;}
+ $FF=$FlightView->Toplevel();
+ $FF->configure(-title=>"Flight Statistics");
+
+ $fstattext='';
+
+ setexit($FF);
+
+ FSupdate();
+
+ my $label=$FF->Message(-width=>"80c",-textvariable=>\$fstattext);
+ $label->pack();
+
+ my $exb=$FF->Button(-text=>"Exit",-command=>sub{$FF->destroy();});
+ $exb->pack();
+
+ print "Flight statistics:\n".$fstattext if ($config{'DEBUG'});
+}
+
+################################################################################
+
+sub FSupdate {
+ if (!Exists($FF)) {return;}
+
+ $fstattext='';
+
+ my $starttimeindex=GPLIGCfunctions::takeoff_detect(\@nonISPEED, 's');
+ my $landtimeindex=GPLIGCfunctions::takeoff_detect(\@nonISPEED, 'l');
+
+ my $stime=GPLIGCfunctions::time2human($TIME[$starttimeindex], 't');
+ my $ltime=GPLIGCfunctions::time2human($TIME[$landtimeindex], 't');
+
+ $fstattext.="Takeoff: $stime\nLanding: $ltime\n";
+
+ my $decflighttime=$DECTIME[$landtimeindex]-$DECTIME[$starttimeindex];
+
+ my $flighttime=GPLIGCfunctions::dec2time($decflighttime);
+ $fstattext.="Time of flight: $flighttime\n";
+
+ my ($maxalt,$maxpalt,$t100,$t125,$t125acc,$t140,$t180,$l100,$l125,$l125acc,$l140,$l180,$free) = GPLIGCfunctions::OxygenStatistics(\@BARO,\@DECTIME,$gpi{'qnh'});
+
+ $fstattext.="Maximum baro altitude: ".sprintf("%.0f",$maxalt*$config{'altitude_unit_factor'})." ".$config{'altitude_unit_name'}."\n";
+
+ $fstattext.="Maximum press altitude: ".sprintf("%.0f",$maxpalt*$config{'altitude_unit_factor'})." ".$config{'altitude_unit_name'}." (assuming QNH $gpi{'qnh'})\n";
+
+ $fstattext.="Maximum GPS altitude: ".sprintf("%.0f",$GPSALT_max*$config{'altitude_unit_factor'})." ".$config{'altitude_unit_name'}."\n-----\n";
+
+ $fstattext.="Oxygen debriefing, FAR 91.211 (constant open flow systems)\n";
+ $fstattext.="FL100 < alt < FL125: ".sprintf("%.0f",$t100*60)." min ".sprintf("%.1f",$l100)." l (".sprintf("%.1f",$l100/3)." l) \n";
+ $fstattext.="FL125 < alt < FL140: ".sprintf("%.0f",$t125*60)." min ".sprintf("%.1f",$l125)." l (".sprintf("%.1f",$l125/3)." l), FAA: ".sprintf("%.0f min %.1f l (%.1f l)\n",$t125acc*60, $l125acc,$l125acc/3);
+
+ $fstattext.="FL140 < alt < FL180: ".sprintf("%.0f",$t140*60)." min ".sprintf("%.1f",$l140)." l (".sprintf("%.1f",$l140/3)." l) \n";
+
+ $fstattext.="FL180 < alt < ORBIT: ".sprintf("%.0f",$t180*60)." min ".sprintf("%.1f",$l180)." l\n";
+
+ my $rec= $l100+$l125+$l140+$l180;
+ my $rec_oxy = $l100/3+$l125/3+$l140/3+$l180;
+ my $faa = $l125acc+$l140+$l180;
+ my $faa_oxy= $l125acc/3+$l140/3+$l180;
+
+ $fstattext .= sprintf("Oxygen totals:\nRecommended: %.1f l (%.1f l)\n",$rec,$rec_oxy);
+ $fstattext .= sprintf ("FAA: %.1f l (%.1f l)\n",$faa,$faa_oxy);
+
+ $fstattext.="-----\n"; #5
+
+ # sum all legs (plain task)
+ my $entf=0;
+ my @entf=();
+ $entf[0]=0;
+
+ for (my $zaehl=1 ; $zaehl<=$#WPLAT-1; $zaehl++) {
+ $entf[$zaehl]=GPLIGCfunctions::dist($WPLAT[$zaehl],$WPLON[$zaehl],$WPLAT[$zaehl+1],$WPLON[$zaehl+1]);
+ }
+
+ foreach (@entf) {
+ $entf+=$_;
+ }
+
+ #print "$task_start_time \n $task_finish_time \n";
+
+ my $taskstt=GPLIGCfunctions::time2human($TIME[$task_start_time_index],'t');
+ my $taskft=GPLIGCfunctions::time2human($TIME[$task_finish_time_index],'t');
+
+ $fstattext.="Begin of task/unpowered flight (s-marker): $taskstt \nEnd of task/unpowered flight (f-marker): $taskft\n";
+ $task_time=GPLIGCfunctions::dec2time($DECTIME[$task_finish_time_index]-$DECTIME[$task_start_time_index]);
+
+ $fstattext.="Task time (unpowered flight time): $task_time\n";
+
+ $dec_task_time=$DECTIME[$task_finish_time_index]-$DECTIME[$task_start_time_index];
+
+ if ($dec_task_time != 0) { $task_speed= $entf / $dec_task_time ;} else { $task_speed = "42";} #this is an egg :)
+
+ $fstattext.= "-----\n"; #5
+
+ # calculate partial distances
+ my @anteil=();
+ $anteil[0]=0;
+ my @anteil_ohne_null=();
+
+ #bestimmung der entfernungen und anteile zwischen allen wp
+ for (my $zaehl=1 ; $zaehl<=$#WPLAT-1; $zaehl++) {
+ $anteil[$zaehl] = ($entf[$zaehl]/$entf)*100 if $entf != 0;
+ if ($entf == 0) {$anteil[$zaehl] = 0;}
+ $anteil[$zaehl] = sprintf ("%5.2f",$anteil[$zaehl]);
+ my $p_entf=sprintf ("%6.2f",$entf[$zaehl]*$config{'distance_unit_factor'});
+ $fstattext.="$anteil[$zaehl] % $p_entf $config{'distance_unit_name'} $WPNAME[$zaehl] -> $WPNAME[$zaehl+1]\n";
+ }
+
+ my $print_entf=sprintf("%.4f", $entf*$config{'distance_unit_factor'});
+
+ $fstattext.="Taskdistance: $print_entf $config{'distance_unit_name'}\n";
+
+ my $task_speed_rounded = sprintf ("%.2f",$task_speed*$config{'speed_unit_factor'});
+ $fstattext.="Task speed: $task_speed_rounded $config{'speed_unit_name'}\n";
+
+ #BESTIMMUNG OB DREIECK UND FAI!!!
+
+ #How many legs has the task?
+ my $z = 0;
+
+ # z ist die anzahl der schenkel mit anteil > 0
+ foreach (@anteil) {
+ $z++ if $_ != 0;
+ }
+
+ # calculate task for triangular task
+ $entf = 0;
+ @entf=();
+ $entf[0]=0;
+
+ if ($#WPLAT >= 4 ) {
+ for (my $z=2; $z<4; $z++) {
+ $entf[$z-1]=GPLIGCfunctions::dist($WPLAT[$z],$WPLON[$z],$WPLAT[$z+1],$WPLON[$z+1]);
+ $entf+=$entf[$z-1];
+ }
+
+ $entf[3] = GPLIGCfunctions::dist($WPLAT[4],$WPLON[4],$WPLAT[2],$WPLON[2]);
+ $entf+=$entf[3];
+
+ # triangular task
+ if ( (($z == 4) && ($WPNAME[1] eq $WPNAME[5])) || (($z == 4) && (GPLIGCfunctions::dist($WPLAT[1],$WPLON[1],$WPLAT[5],$WPLON[5]) <= 0.2 * $entf) ) ) {
+
+ $fstattext.="\n-----\nTriangular task (start and finish on leg)\n";
+
+ my $print_close = (GPLIGCfunctions::dist($WPLAT[1],$WPLON[1],$WPLAT[5],$WPLON[5])/$entf)*100;
+ $print_close = sprintf("%.1f",$print_close);
+
+ my $print_close_dist = GPLIGCfunctions::dist($WPLAT[1],$WPLON[1],$WPLAT[5],$WPLON[5]) * $config{'distance_unit_factor'};
+ my $print_close_distr = sprintf("%.4f",$print_close_dist);
+ my $task_m_close = sprintf("%.4f", $entf - $print_close_dist);
+
+ $fstattext.="Closing distance (between start and finish): ".$print_close_distr." $config{'distance_unit_name'} ".$print_close."% of triangular task\n";
+
+ @anteil=();
+ $anteil[0]=0;
+
+ for (my $zaehl=2 ; $zaehl<4; $zaehl++) {
+ $anteil[$zaehl-1] = ($entf[$zaehl-1]/$entf)*100 if $entf != 0;
+ $anteil[$zaehl-1] = sprintf ("%5.2f",$anteil[$zaehl-1]);
+ my $p_entf =sprintf ("%6.2f",$entf[$zaehl-1]*$config{'distance_unit_factor'});
+
+ $fstattext.="$anteil[$zaehl-1] % $p_entf $config{'distance_unit_name'} $WPNAME[$zaehl] -> $WPNAME[$zaehl+1]\n";
+
+ }
+
+ $anteil[3] = ($entf[3]/$entf)*100 if $entf != 0;
+ $anteil[3] = sprintf ("%5.2f",$anteil[3]);
+ my $p_entf =sprintf ("%6.2f",$entf[3]*$config{'distance_unit_factor'});
+
+ $fstattext.="$anteil[3] % $p_entf $config{'distance_unit_name'} $WPNAME[4] -> $WPNAME[2]\n";
+
+ my $p2_entf=sprintf("%.4f", $entf * $config{'distance_unit_factor'});
+ $fstattext.="Triangular task distance: $p2_entf $config{'distance_unit_name'}\n";
+ if ($dec_task_time != 0) { $task_speed= $entf / $dec_task_time ;} else { $task_speed = "42";} #this is an egg :)
+ my $task_speed_rounded = sprintf ("%.2f",$task_speed * $config{'speed_unit_factor'});
+ $fstattext.="Triangular task speed: $task_speed_rounded $config{'speed_unit_name'}\n";
+ $fstattext.="Triangular task distance - closing: $task_m_close\n";
+ }
+ }
+
+ #check for FAI Task
+ #we need an array of the percentages, but without the ones which are zero
+ for (my $run=0; $run <=$#anteil; $run++) {
+ if ($anteil[$run] != 0) {push(@anteil_ohne_null,$anteil[$run]);}
+ }
+
+ #check if task is triangular...
+ my $TASKSHAPE = 'unknown';
+
+ # z==3: these can only be a predeclared task, (or defined by hand? :( )
+ if (($z == 3) && (($WPNAME[1] eq $WPNAME[4]) || (GPLIGCfunctions::dist($WPLAT[1],$WPLON[1],$WPLAT[4],$WPLON[4]) <= 1.0) ) ){$TASKSHAPE='triangular';}
+
+ # z==4 this should be an optimized task, we will assume the "softest" closing criteria (holc)
+ if (($z == 4) && (($WPNAME[1] eq $WPNAME[5]) || (GPLIGCfunctions::dist($WPLAT[1],$WPLON[1],$WPLAT[5],$WPLON[5]) <= 0.2 * $entf) ) ){$TASKSHAPE='triangular';}
+
+ if ($TASKSHAPE eq 'triangular') { #Task has 3 legs and closed FAI?
+ my ($max, $min) = GPLIGCfunctions::MaxKoor(\@anteil_ohne_null); # can be used to get maximum and minimum... :)
+ #print "$min $max\n";
+ $fstattext.="Triangular task ";
+
+ if ($entf < 500) { #kleiner 500
+ #print "kleiner 500\n";
+ if ($min >= 28) {$fstattext.= "with FAI record shape";}
+ }
+
+ if ($entf >= 500) {
+
+ #print "guter pilot, ueber 500! :) \n";
+ if ($min > 25 && $max <=45) {$fstattext.= "with FAI record shape";}
+ }
+
+ $fstattext.="\n";
+ }
+
+ $fstattext.="-----\nFlown task:\n";
+ my ($wpinxref, $wpnameref) = getWPreachedIndices();
+
+ for (my $idx=0; $idx < $#{$wpinxref}; $idx++) {
+
+ my $legdist = GPLIGCfunctions::dist($DECLAT[$wpinxref->[$idx]], $DECLON[$wpinxref->[$idx]],$DECLAT[$wpinxref->[$idx+1]], $DECLON[$wpinxref->[$idx+1]]);
+ my $dtime = $DECTIME[$wpinxref->[$idx+1]]-$DECTIME[$wpinxref->[$idx]];
+
+ my $legspeed;
+ if ($dtime !=0) { $legspeed=$legdist / $dtime;} else {$legspeed = 9999;}
+ my $legaltdiff = $BARO[$wpinxref->[$idx+1]]-$BARO[$wpinxref->[$idx]];
+ my $legtime = GPLIGCfunctions::time2human($TIME[$wpinxref->[$idx]],'t')."-".GPLIGCfunctions::time2human($TIME[$wpinxref->[$idx+1]],'t');
+ my $legglide;
+ if ($legaltdiff !=0 ){ $legglide = ($legdist * 1000) / -$legaltdiff;} else {$legglide= 9999;}
+ print "$legglide\n" if ($config{'DEBUG'});
+
+ $legdist *= $config{'distance_unit_factor'};
+ $legaltdiff *= $config{'altitude_unit_factor'};
+ $fstattext.= sprintf("%1.0f: %4.2f $config{'distance_unit_name'} %3.0f $config{'speed_unit_name'} $legaltdiff $config{'altitude_unit_name'} %.0f $legtime $wpnameref->[$idx] -> $wpnameref->[$idx+1]\n",$idx+1, $legdist,$legspeed, $legglide);
+
+ }
+
+}
+
+##############################################################################
+
+sub zylinder {
+ use Math::Trig;
+ my ($lat, $lon, $r, $h) = @_; ###r=durchmesser
+ my $gpx;
+
+ Ausschnitt($lat, $lon);
+
+ #if ($r eq "point") {$gpx=0.0008993216;} ### 100m for point-like marks
+ #if ($r eq "200m") {$gpx=0.0017986432;} ### /0.3km on great-circle on FAI-Spheroid
+ #if ($r eq "300m") {$gpx=0.002697964;} ### /0.3km on great-circle on FAI-Spheroid
+ #if ($r eq "400m") {$gpx=0.0035972864;} ### /0.3km on great-circle on FAI-Spheroid
+ #if ($r eq "500m") {$gpx=0.004496608;} ### /0.5km on great-circle on FAI-Spheroid
+ #if ($r eq "1km") {$gpx=0.0089932161;}
+ $gpx=0.0089932161 * $r;
+ #if ($r eq "FAI") {$gpx=0.026979648;} ### 3 km for FAI sector
+ #if ($r eq "off") {$gpx=0;}
+
+ my @dlat=();
+ my @dlon=();
+
+ for (my $a=0;$a<=6.283185307;$a=$a+0.0314) {
+ push(@dlat, cos($a)*$gpx);
+ push(@dlon, sin($a)*$gpx*(1/cos(deg2rad($lat))));
+ }
+
+ open (ZYLOUT,">${pfadftmp}zyl.dat");
+
+ for ($i=0; $i<=$#dlat; $i++) {
+ for ($j=0; $j<=$h; $j=$j+100) { ###make it a zylinder!
+ print ZYLOUT $lon+$dlon[$i]," ",$lat+$dlat[$i]," $j \n";
+ }
+ }
+
+ close ZYLOUT;
+}
+
+# end zylinder
+
+##############################################################################################################################################
+##############################################################################################################################################
+################################# FLIGHTVIEW #################################################################################################
+sub FlightView {
+
+ if ($config{'fvw_baro_fraction'} < 1.1 || $config{'fvw_baro_fraction'} > 10) {
+ print ("fvw_baro_fraction should be larger than 1.1 and smaller than 10\n");
+ gpligcexit();
+ }
+
+ $FlightView = MainWindow->new();
+ $FlightView->configure(-title=>"GPLIGC $version");
+
+ # this catches wm-exit-button, wm-exit...
+ $FlightView->protocol('WM_DELETE_WINDOW', =>\&gpligcexit);
+
+ $FlightView->wm("iconname", "GPLIGC");
+
+ #$Fenster->resizable(0, 0);
+
+ # CREATE AND pack menu bar
+ my $menuleiste=$FlightView->Frame(-relief=>'solid', -borderwidth=>1);
+ my $menu_file=$menuleiste->Menubutton(-text=>"File");#, -underline=>0);
+ $menu_file->command(-label=>"Open", -command=>sub{Fileselekt();});
+
+ $menu_file->command(-label=>"Reload", -command=>sub{
+ if ($filestat ne 'closed') { oeffnen($file);FVWausg();FSupdate();}
+ });
+
+ $menu_file->command(-label=>"Download track (gpsbabel)", -command=>sub{download_gpsbabel();});
+
+ if ($^O ne "MSWin32") {
+ $menu_file->command(-label=>"Download garmin (gpspoint)", -command=>sub{download_garmin();});
+ $menu_file->command(-label=>"Download media", -command=>sub{download_media();});
+ }
+
+ $menu_file->command(-label=>"Export kml", -command=>sub{kml_export();});
+ $menu_file->command(-label=>"Export gpx", -command=>sub{gpx_export();});
+
+ # this is not needed.
+ #$menu_file->command(-label=>"Close",-command=>sub{schliessen();});
+
+# if ($config{'photos'}) {
+ $menu_file->command(-label=>"Open photo/multimedia directory", -command=>sub{
+ if ($filestat ne 'closed') {
+ Photodirselect();}
+ });
+# }
+
+ $menu_file->separator();
+ $menu_file->command(-label=>"Exit",-command=>\&gpligcexit);
+ $menuleiste->pack(-side=>'top', -fill=>'x',-padx=>3);
+ $menu_file->pack(-side=>'left');
+
+ my $menu_about=$menuleiste->Menubutton(-text=>"About");
+ $menu_about->command(-label=>"Help",-command=>\&help);
+ $menu_about->command(-label=>"Info",-command=>\&info);
+ $menu_about->command(-label=>"GPLIGC home",-command=>sub{browseURL("http://gpligc.sf.net");});
+ $menu_about->command(-label=>"Subscribe mailinglist",-command=>sub{browseURL("https://lists.sourceforge.net/lists/listinfo/gpligc-announce");});
+ $menu_about->command(-label=>"Get support / report bugs",-command=>sub{browseURL("https://sourceforge.net/projects/gpligc/support");});
+
+#$menu_about->command(-label=>"donate money",-command=>sub{browseURL("https://sourceforge.net/donate/index.php?group_id=101635");});
+ $menu_about->pack(-side=>"right");
+
+ my $menu_options=$menuleiste->Menubutton(-text=>"Options");#,-underline=>0);
+
+ $menu_options->separator();
+
+ $mapmenu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Map settings", -menu=> $mapmenu);
+
+ $mapmenu->checkbutton(-label =>"Use maps", -variable=>\$config{'maps'},-command=>sub{if (Exists($FlightView)) {updateFVW('i');} });
+ $mapmenu->radiobutton(-label => "Open street map",-variable => \$config{'map_type'},-value => "osm",-command=>sub{if (Exists($FlightView)) {updateFVW();} });
+ $mapmenu->radiobutton(-label => "Open cycle map",-variable => \$config{'map_type'},-value => "osmC",-command=>sub{if (Exists($FlightView)) {updateFVW();} });
+ #$mapmenu->radiobutton(-label => "Open Sea map",-variable => \$config{'map_type'},-value => "oseam",-command=>sub{if (Exists($FlightView)) {updateFVW();} });
+ $mapmenu->radiobutton(-label => "Gmaps",-variable => \$config{'map_type'},-value => "gmm",-command=>sub{if (Exists($FlightView)) {updateFVW();} });
+ $mapmenu->radiobutton(-label => "Gmaps terrain",-variable => \$config{'map_type'},-value => "gmt",-command=>sub{if (Exists($FlightView)) {updateFVW();} });
+ $mapmenu->radiobutton(-label => "Gmaps satellite",-variable => \$config{'map_type'},-value => "gms",-command=>sub{if (Exists($FlightView)) {updateFVW();} });
+ $mapmenu->radiobutton(-label => "Gmaps hybrid",-variable => \$config{'map_type'},-value => "gmh",-command=>sub{if (Exists($FlightView)) {updateFVW();} });
+
+ #$menu_options->seperator();
+
+ $gpmenu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Gnuplot settings", -menu=> $gpmenu);
+
+ if ($^O ne "MSWin32") {
+ $gpmenu->radiobutton(-label=>"Gnuplot 4.x",-variable=>\$config{'gnuplot_major_version'},-value=>"4");
+ $gpmenu->radiobutton(-label=>"Gnuplot 3.x",-variable=>\$config{'gnuplot_major_version'},-value=>"3");
+ $gpmenu->radiobutton(-label=>"Open Gnuplot-shell",-variable=>\$config{'gnuplot_4_terminal'},-value=>"1");
+ $gpmenu->radiobutton(-label=>"No Gnuplot-shell",-variable=>\$config{'gnuplot_4_terminal'},-value=>"0");
+ $gpmenu->separator();
+ }
+
+ $gpmenu->radiobutton(-label=>"Grid on",-variable=>\$config{'gnuplot_grid_state'},-value=>"set grid");
+ $gpmenu->radiobutton(-label=>"Grid off",-variable=>\$config{'gnuplot_grid_state'},-value=>'');
+
+ $gpmenu->separator;
+
+ $drawmenu = $gpmenu->Menu();
+ $gpmenu->cascade(-label=>"Draw options", -menu=> $drawmenu);
+
+ $drawmenu->radiobutton(-label => "Lines",-variable => \$config{'gnuplot_draw_style'},-value => "with lines");
+ $drawmenu->radiobutton(-label => "Dots",-variable => \$config{'gnuplot_draw_style'},-value => "with dots");
+ $drawmenu->radiobutton(-label => "Linespoints",-variable => \$config{'gnuplot_draw_style'},-value => "with linespoints");
+
+ $termmenu = $gpmenu->Menu();
+ $gpmenu->cascade(-label=>"Gnuplot terminal", -menu=> $termmenu);
+
+ $termmenu->radiobutton(-label => "x11",-variable => \$config{'gnuplot_terminal'},-value => "x11");
+ $termmenu->radiobutton(-label => "qt",-variable => \$config{'gnuplot_terminal'},-value => "qt");
+ $termmenu->radiobutton(-label => "pngcairo",-variable => \$config{'gnuplot_terminal'},-value => "pngcairo");
+ $termmenu->radiobutton(-label => "epscairo",-variable => \$config{'gnuplot_terminal'},-value => "epscairo");
+ $termmenu->radiobutton(-label => "pdfcairo",-variable => \$config{'gnuplot_terminal'},-value => "pdfcairo");
+
+ $termmenu->radiobutton(-label => "png",-variable => \$config{'gnuplot_terminal'},-value => "png");
+ $termmenu->radiobutton(-label => "ps color",-variable => \$config{'gnuplot_terminal'},-value => "postscript color solid");
+ $termmenu->radiobutton(-label => "eps color",-variable => \$config{'gnuplot_terminal'},-value => "postscript eps color solid");
+ $termmenu->radiobutton(-label => "fig monochrome",-variable => \$config{'gnuplot_terminal'},-value => "fig monochrome");
+ $termmenu->radiobutton(-label => "fig color",-variable => \$config{'gnuplot_terminal'},-value => "fig color");
+
+ $optmenu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Optimizer method", -menu=> $optmenu);
+ $optmenu->radiobutton(-label => "Metropolis Montecarlo",-variable => \$config{'optimizer_method'},-value => "mmc");
+ $optmenu->radiobutton(-label => "Simulated Annealing",-variable => \$config{'optimizer_method'},-value => "sa");
+
+ $zylmenu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"WP Cylinder/Sector", -menu=> $zylmenu);
+
+ $zylmenu->radiobutton(-label => "FAI Sectors", -variable=>\$config{'zylinder_wp_type'}, -value=>"sec",-command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "Cylinders",-variable=>\$config{'zylinder_wp_type'},-value=>"cyl",-command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "FAI Sec and Cylinders", -variable=>\$config{'zylinder_wp_type'}, -value=>"both", -command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "None", -variable=>\$config{'zylinder_wp_type'}, -value=>"off", -command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "200m",-variable=>\$config{'zylinder_radius'},-value=>0.2,-command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "300m",-variable=>\$config{'zylinder_radius'},-value=>0.3,-command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "400m",-variable=>\$config{'zylinder_radius'},-value=>0.4,-command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "500m",-variable=>\$config{'zylinder_radius'},-value=>0.5,-command=>\&updateCyl);
+ $zylmenu->radiobutton(-label => "1km - DMSt start/finish", -variable=>\$config{'zylinder_radius'},-value=>1.0,-command=>\&updateCyl);
+ $zylmenu->checkbutton(-label => "Show names", -variable=>\$config{'zylinder_names'}, -command=>sub{updateCyl(); baroplot();});#_task();});
+
+ $zoommenu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"WP-Plot/Zoom sidelength", -menu=> $zoommenu);
+
+ #$menu_options->separator();
+ #$menu_options->command(-label=>'WP-Plot/Zoom sidelength');
+ $zoommenu->radiobutton(-label=>"1km",-variable=>\$config{'zoom_sidelength'},-value=>"1",-command=>\&updateZoom);
+ $zoommenu->radiobutton(-label=>"3km",-variable=>\$config{'zoom_sidelength'},-value=>"3",-command=>\&updateZoom);
+ $zoommenu->radiobutton(-label=>"5km",-variable=>\$config{'zoom_sidelength'},-value=>"5",-command=>\&updateZoom);
+ $zoommenu->radiobutton(-label=>"10km",-variable=>\$config{'zoom_sidelength'},-value=>"10",-command=>\&updateZoom);
+
+ $noiselevelmenu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Noise Level Limit", -menu=> $noiselevelmenu);
+
+ $noiselevelmenu->radiobutton(-label=>"50", -variable=>\$config{'ENL_noise_limit'},-value=>"50",-command=>\&updateFVW);
+ $noiselevelmenu->radiobutton(-label=>"100",-variable=>\$config{'ENL_noise_limit'},-value=>"100",-command=>\&updateFVW);
+ $noiselevelmenu->radiobutton(-label=>"250",-variable=>\$config{'ENL_noise_limit'},-value=>"250",-command=>\&updateFVW);
+ $noiselevelmenu->radiobutton(-label=>"500",-variable=>\$config{'ENL_noise_limit'},-value=>"500",-command=>\&updateFVW);
+ $noiselevelmenu->radiobutton(-label=>"750",-variable=>\$config{'ENL_noise_limit'},-value=>"750",-command=>\&updateFVW);
+
+ $datfile="3d.dat"; ###default
+
+ $coormenu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Coordinate format", -menu=> $coormenu);
+
+ #$menu_options->separator();
+ #$menu_options->command(-label=>'Coordinates in');
+ $coormenu->radiobutton(-label=>"mm.mmm", -variable=>\$config{'coordinate_print_format'},-value=>"igch",-command=>\&updateCoor);
+ $coormenu->radiobutton(-label=>"mm ss", -variable=>\$config{'coordinate_print_format'},-value=>"zanh",-command=>\&updateCoor);
+ $coormenu->radiobutton(-label=>"dd.ddddd", -variable=>\$config{'coordinate_print_format'},-value=>"deg",-command=>\&updateCoor);
+
+ # SPEED UNITS
+ $speed_menu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Speed units", -menu=> $speed_menu);
+ $speed_menu->radiobutton(-label=>"km/h", -variable=>\$config{'speed_unit_name'},-value=>"km/h",-command=>sub{
+ $config{'speed_unit_factor'}=1.0;
+ FVWausg();
+ FSupdate();
+ });
+ $speed_menu->radiobutton(-label=>"Knots", -variable=>\$config{'speed_unit_name'},-value=>"knots",-command=>sub{
+ $config{'speed_unit_factor'}=0.539956803;
+ FVWausg();
+ FSupdate();
+ });
+ $speed_menu->radiobutton(-label=>"Miles per hour", -variable=>\$config{'speed_unit_name'},-value=>"mph",-command=>sub{
+ $config{'speed_unit_factor'}=0.621504;
+ FVWausg();
+ FSupdate();
+ });
+
+ $speed_menu->radiobutton(-label=>"m/s", -variable=>\$config{'speed_unit_name'},-value=>"m/s",-command=>sub{
+ $config{'speed_unit_factor'}=0.277777777;
+ FVWausg();
+ FSupdate();
+ });
+
+ # VERTICAL SPEED UNITS
+ $vspeed_menu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Vertical speed units", -menu=> $vspeed_menu);
+ $vspeed_menu->radiobutton(-label=>"m/s", -variable=>\$config{'vertical_speed_unit_name'},-value=>"m/s",-command=>sub{
+ $config{'vertical_speed_unit_factor'}=1.0;
+ FVWausg();
+ });
+ $vspeed_menu->radiobutton(-label=>"Knots", -variable=>\$config{'vertical_speed_unit_name'},-value=>"knots",-command=>sub{
+ $config{'vertical_speed_unit_factor'}=1.943844492;
+ FVWausg();
+ });
+ $vspeed_menu->radiobutton(-label=>"ft/min", -variable=>\$config{'vertical_speed_unit_name'},-value=>"ft/min",-command=>sub{
+ $config{'vertical_speed_unit_factor'}=196.8;
+ FVWausg();
+ });
+ $vspeed_menu->radiobutton(-label=>"km/h", -variable=>\$config{'vertical_speed_unit_name'},-value=>"km/h",-command=>sub{
+ $config{'vertical_speed_unit_factor'}=3.6;
+ FVWausg();
+ });
+
+ # ALTITUDE UNITS
+ $alt_menu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Altitude units", -menu=> $alt_menu);
+ $alt_menu->radiobutton(-label=>"m", -variable=>\$config{'altitude_unit_name'},-value=>"m",-command=>sub{
+ $config{'altitude_unit_factor'}=1.0;
+ FVWausg();
+ baroplot();
+ });
+ $alt_menu->radiobutton(-label=>"ft", -variable=>\$config{'altitude_unit_name'},-value=>"ft",-command=>sub{
+ $config{'altitude_unit_factor'}=3.28;
+ FVWausg();
+ baroplot();
+ });
+
+ # DISTANCE UNITS
+ $dist_menu = $menu_options->cget(-menu)->Menu();
+ $menu_options->cascade(-label=>"Distance units", -menu=> $dist_menu);
+ $dist_menu->radiobutton(-label=>"km", -variable=>\$config{'distance_unit_name'},-value=>"km",-command=>sub{
+ $config{'distance_unit_factor'}=1.0;
+ FVWausg();
+ FSupdate();
+ });
+ $dist_menu->radiobutton(-label=>"Miles", -variable=>\$config{'distance_unit_name'},-value=>"miles",-command=>sub{
+ $config{'distance_unit_factor'}=0.621504;
+ FVWausg();
+ FSupdate();
+ });
+ $dist_menu->radiobutton(-label=>"Nautical Miles", -variable=>\$config{'distance_unit_name'},-value=>"NM",-command=>sub{
+ $config{'distance_unit_factor'}=0.539956803;
+ FVWausg();
+ FSupdate();
+ });
+
+ $menu_options->separator();
+ $menu_options->checkbutton(-label =>"Show accuracy", -variable=>\$config{'draw_accuracy'},-command=>sub{
+ if (Exists($FlightView)) {FVWausg();}
+
+ });
+
+ $menu_options->checkbutton(-label => "Photo locator", -variable=>\$config{'photos'},-command=>sub{
+
+ if ($config{'photos'}) {
+ checkPhotos();
+ processPhotos();
+ }
+
+ if (!$config{'photos'}) {
+ if (Exists($FlightView)) {
+ trackplot($dxp, $dyp, $minlat, $minlon);
+ }
+ }
+ });
+ $menu_options->checkbutton(-label => "Debugging output", -variable=>\$config{'DEBUG'});
+ $menu_options->command(-label=>"Save configuration", -command=>\&save_config);
+ $menu_options->command(-label=>"Reread configuration", -command=>\&load_config);
+
+ $menu_options->pack(-side=>"left");
+
+###########################################
+ # CREATE AND pack Plotting menus!
+ my $menu_plot2d=$menuleiste->Menubutton(-text=>"Plots-2D");#, -underline=>0);
+
+ $menu_plot2d->command(-label=>"Barogramm", -command=>sub{$com1="set ylabel \"Altitude [$config{'altitude_unit_name'}]\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}baro.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}) title \"Barogramm\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Altitude histogram (baro)", -command=>sub{$com1="set nokey\n set ylabel \"% of flighttime\" \n set xlabel \"Altitude (baro) [$config{'altitude_unit_name'}]\" \n plot";$com2="\'${pfadftmp}barohisto.dat\' using (\$1*$config{'altitude_unit_factor'}):(\$2) with boxes fs solid 1 "; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Baro / GPS",-command=>sub{$com1="set ylabel \"Altitude [$config{'altitude_unit_name'}]\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}baro.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}) title \"Barogramm\""." ".$config{'gnuplot_draw_style'}.", \'${pfadftmp}gpsalt.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}) title \"GPS Altitude\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Pressure",-command=>sub{$com1="set key top center\nset ylabel \"Pressure [hPa] (QNH $gpi{'qnh'})\" \n set xlabel \"time \" \n f(x)=696.86\ng(x)=631.87\nh(x)=595.29\ni(x)=506.06\nj(x)=376.07\nplot";$com2="\'${pfadftmp}press.dat\' using (\$1):(\$2) title \"Pressure plot\""." ".$config{'gnuplot_draw_style'}.",f(x) title \"FL100\", g(x) title \"FL125\", h(x) title \"FL140\", i(x) title \"FL180\", j(x) title \"FL250\""; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Variogramm (baro)",-command=>sub{$com1="set ylabel \"Vertical speed (baro) [$config{'vertical_speed_unit_name'}]\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}vario.dat\' using (\$1):(\$2*$config{'vertical_speed_unit_factor'})title \"Variogramm (baro)\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Vario histogram (baro)", -command=>sub{$com1="set nokey\n set ylabel \"% of flighttime\" \n set xlabel \"vertical speed (baro) [$config{'vertical_speed_unit_name'}]\" \n plot";$com2="\'${pfadftmp}vhisto.dat\' using (\$1*$config{'vertical_speed_unit_factor'}):(\$2) with boxes fs solid 1 "; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Speedogramm",-command=>sub{$com1="set ylabel \"(10 fixes mean) ground speed [$config{'speed_unit_name'}]\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}speed.dat\' using (\$1):(\$2*$config{'speed_unit_factor'}) title \"Speedogramm\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Indicated air speed",-command=>sub{$com1="set ylabel \"Indicated Airspeed [$config{'speed_unit_name'}]\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}ias.dat\' using (\$1):(\$2*$config{'speed_unit_factor'}) title \"Indicated Airspeed\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Engine noise level / RPM",-command=>sub{$com1="set ylabel \"Noise Level / RPM\" \n set xlabel \"time \" \n plot";
+ $com2="\'${pfadftmp}enl.dat\' title \"Engine noise level\" ".$config{'gnuplot_draw_style'}.", \'${pfadftmp}enl.dat\' using 1:3 title \"RPM\" ".$config{'gnuplot_draw_style'};
+ Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Satellites used",-command=>sub{$com1="set ylabel \"Satellites used\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}sat.dat\' title \"Satellites used\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Projection lat (gps)",-command=>sub{$com1="set xlabel \"Latitude []\" \n set ylabel \"Altitude (gps) [$config{'altitude_unit_name'}] \" \n plot";$com2="\'${pfadftmp}latproj.dat\' using (\$1):(\$3*$config{'altitude_unit_factor'}) title \"Flightpath\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Projection lon (gps)",-command=>sub{$com1="set xlabel \"Longitude []\" \n set ylabel \"Altitude (gps) [$config{'altitude_unit_name'}] \" \n plot";$com2="\'${pfadftmp}lonproj.dat\' using (\$1):(\$3*$config{'altitude_unit_factor'}) title \"Flightpath\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"GPS altitude",-command=>sub{
+ $com1="set ylabel \"Altitude [$config{'altitude_unit_name'}]\" \n set xlabel \"time \" \n plot";
+ $com2="\'${pfadftmp}gpsalt.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}) title \"GPS Altitude\" ".$config{'gnuplot_draw_style'};
+ $com2.=", \'${pfadftmp}gpsalt.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}):(\$3*$config{'altitude_unit_factor'}) title \"Accuracy\" with yerrorbars" if ($VXAEXISTS eq "yes" && $config{'draw_accuracy'});
+ Ausgabe("2d");
+ });
+
+ $menu_plot2d->command(-label=>"Altitude histogram (gps)", -command=>sub{$com1="set nokey\n set ylabel \"% of flighttime\" \n set xlabel \"Altitude (gps) [$config{'altitude_unit_name'}]\" \n plot";$com2="\'${pfadftmp}gpshisto.dat\' using (\$1*$config{'altitude_unit_factor'}):(\$2) with boxes fs solid 1 "; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Baro-GPS",-command=>sub{$com1="set ylabel \"Difference [$config{'altitude_unit_name'}]\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}deltah.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}) title \"Difference (Baro-GPS)\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Variogramm (gps)",-command=>sub{$com1="set ylabel \"Vertical speed (gps) [$config{'vertical_speed_unit_name'}]\" \n set xlabel \"time \" \n plot";$com2="\'${pfadftmp}gpsvario.dat\' using (\$1):(\$2*$config{'vertical_speed_unit_factor'})title \"Variogramm (gps)\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Vario histogram (gps)", -command=>sub{$com1="set nokey\n set ylabel \"% of flighttime\" \n set xlabel \"vertical speed (gps) [$config{'vertical_speed_unit_name'}]\" \n plot";$com2="\'${pfadftmp}vhistogps.dat\' using (\$1*$config{'vertical_speed_unit_factor'}):(\$2) with boxes fs solid 1 "; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Groundspeed histogram", -command=>sub{$com1="set nokey\n set ylabel \"% of flighttime\" \n set xlabel \"ground speed [$config{'speed_unit_name'}]\" \n plot";$com2="\'${pfadftmp}shisto.dat\' using (\$1*$config{'speed_unit_factor'}):(\$2) with boxes fs solid 1 "; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Indicated airspeed histogram", -command=>sub{$com1="set nokey\n set ylabel \"% of flighttime\" \n set xlabel \"Indicated Airspeed [$config{'speed_unit_name'}]\" \n plot";$com2="\'${pfadftmp}iashisto.dat\' using (\$1*$config{'speed_unit_factor'}):(\$2) with boxes fs solid 1 "; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Accuracy",-command=>sub{$com1="set ylabel \"Position Accuracy [$config{'altitude_unit_name'}]\" \n set xlabel \"time \" \n plot";
+ $com2="\'${pfadftmp}sat.dat\' using 1:(\$3*$config{'altitude_unit_factor'}) title \"Horizontal Accuracy\" $config{'gnuplot_draw_style'}, \'${pfadftmp}sat.dat\' using 1:(\$4*$config{'altitude_unit_factor'}) title \"Vertical Accuracy\" $config{'gnuplot_draw_style'} "; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Track plot",-command=>sub{$com1="set ylabel \"Latitude []\" \n set xlabel \"Longitude [] \" \n plot";$com2="\'$pfadftmp$datfile\' title \"Flightpath\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Projection lat (baro)",-command=>sub{$com1="set xlabel \"Latitude []\" \n set ylabel \"Altitude (baro) [$config{'altitude_unit_name'}] \" \n plot";$com2="\'${pfadftmp}latproj.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}) title \"Flightpath\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ $menu_plot2d->command(-label=>"Projection lon (baro)",-command=>sub{$com1="set xlabel \"Longitude []\" \n set ylabel \"Altitude (baro) [$config{'altitude_unit_name'}] \" \n plot";$com2="\'${pfadftmp}lonproj.dat\' using (\$1):(\$2*$config{'altitude_unit_factor'}) title \"Flightpath\" ".$config{'gnuplot_draw_style'}; Ausgabe("2d");});
+
+ #$menuleiste->pack(-side=>'top', -fill=>'x',-padx=>3);
+ $menu_plot2d->pack(-side=>'left');
+
+###########################################
+ # CREATE AND pack Plotting menus!
+ my $menu_plot3d=$menuleiste->Menubutton(-text=>"Plots-3D");#, -underline=>0);
+
+ $menu_plot3d->command(-label=>"3D View (baro)",-command=>sub{$com1="set ylabel \"Latitude []\" \n set xlabel \"Longitude []\" \n set zlabel \"Altitude (baro)[$config{'altitude_unit_name'}]\" \n splot";$com2="\'$pfadftmp$datfile\' using (\$1):(\$2):(\$3*$config{'altitude_unit_factor'}) title \"Flightpath\" ".$config{'gnuplot_draw_style'}; Ausgabe("3d");});
+ $menu_plot3d->command(-label=>"3D View (gps)",-command=>sub{$com1="set ylabel \"Latitude []\" \n set xlabel \"Longitude []\" \n set zlabel \"Altitude (gps)[$config{'altitude_unit_name'}]\" \n splot";$com2="\'$pfadftmp$datfile\' using (\$1):(\$2):(\$4*$config{'altitude_unit_factor'}) title \"Flightpath\" ".$config{'gnuplot_draw_style'}; Ausgabe("3d");});
+ $menu_plot3d->command(-label=>"3D View + groundtrack (baro)",-command=>sub{$com1="set ylabel \"Latitude []\" \n set xlabel \"Longitude []\" \n set zlabel \"Altitude (baro)[$config{'altitude_unit_name'}]\" \n splot";$com2="\'$pfadftmp$datfile\' using (\$1):(\$2):(\$3*$config{'altitude_unit_factor'}) title \"Flightpath\""." ".$config{'gnuplot_draw_style'}.", \'$pfadftmp$datfile\' using (\$1):(\$2):(\$3*0) title \"Groundtrack\" ".$config{'gnuplot_draw_style'}; Ausgabe("3d");});
+ $menu_plot3d->command(-label=>"3D View + groundtrack (gps)",-command=>sub{$com1="set ylabel \"Latitude []\" \n set xlabel \"Longitude []\" \n set zlabel \"Altitude (gps)[$config{'altitude_unit_name'}]\" \n splot";$com2="\'$pfadftmp$datfile\' using (\$1):(\$2):(\$4*$config{'altitude_unit_factor'}) title \"Flightpath\""." ".$config{'gnuplot_draw_style'}.", \'$pfadftmp$datfile\' using (\$1):(\$2):(\$4*0) title \"Groundtrack\" ".$config{'gnuplot_draw_style'}; Ausgabe("3d");});
+
+ $menu_plot3d->command(-label=>"Clear ranges",-command=>sub{$xmin='';$xmax='';$ymin='';$ymax='';$zmin='0';$zmax='';});
+
+ #$menuleiste->pack(-side=>'top', -fill=>'x',-padx=>3);
+ $menu_plot3d->pack(-side=>'left');
+
+ my $menu_stuff=$menuleiste->Menubutton(-text=>"Tools");#, -underline=>0);
+### frame fuer restl funktionen
+ $menu_stuff->command(-label=>"Flight info (igc)",-command=>\&FlightInfo);
+
+ $menu_stuff->command(-label=>"Flight info (additional)",-command=>\&gpiinput);
+
+ $menu_stuff->command(-label=>"Flight statistics",-command=>\&FlightStatistics);
+
+ $menu_stuff->command(-label=>"Task editor",-command=>\&WpPlot);
+
+# lol!
+#$menu_stuff->command(-label=>"Flight view window (fvw)", -command=>\&FlightView);
+ $menu_stuff->command(-label=>"OGIE - 3d", -command=>\&OpenGLexplorer); #sub{system("ogie ${pfadftmp}km.dat");});
+
+ #Experimental Logger Window, for Windows-version...
+ if ($^O eq "MSWin32") {
+ $menu_stuff->command(-label=>"Read logger", -command=>\&ReadLogger);
+ }
+
+ $menu_stuff->pack(-side=>'left');
+
+ $zoom = 0;
+
+ $fvwtext="\n\n\n\n"; # five lines
+
+ my $top_text = $FlightView->Label(-textvariable=>\$fvwtext)->pack(-side=>"top");
+
+
+ # looks better with solid 1 relief
+ $canvas_frame = $FlightView->Frame(-borderwidth=>0); #-width=>$config{'window_width'},-borderwidth=>0);
+
+
+ $trackheight = int (( (1-(1/$config{'fvw_baro_fraction'}))*$config{'window_height'} )+0.5)-2;
+
+ # for some UNKNOWN reason the canvas is gonna be two pixels wider than requested !!!!!!!!!!!!!!!!!!
+ $canvas=$canvas_frame->Canvas(-height=>$trackheight, -width=>$config{'window_width'}-2, -background=>"white",-borderwidth=>0,
+ -scrollregion=>[0,0,$config{'window_width'}-2,$trackheight]);
+
+ $canvas->CanvasBind('<1>' => \&viewclick);
+ $canvas->CanvasBind('<B3-Motion>' => \&zoomdrag);
+ $canvas->CanvasBind('<3>' => \&zoompress);
+ $canvas->CanvasBind('<B3-ButtonRelease>' => \&zoomrelease);
+ $canvas->pack(-expand=>"yes",-fill=>"both");
+
+ # Here we add a slim strip for the barograph canvas...
+ $baroheight = int ( ($config{'window_height'}/ $config{'fvw_baro_fraction'})+0.5 )-2;
+ $barocanvas = $canvas_frame->Canvas(-height=>$baroheight, -width=>$config{'window_width'}-2, -background=>"grey90",-borderwidth=>0,
+ -scrollregion=>[0,0,$config{'window_width'}-2,$baroheight]);
+
+ $barocanvas->pack(-expand=>"yes",-fill=>"both");
+ $barocanvas->CanvasBind('<B1-Motion>' => \&baroclick);
+ $barocanvas->CanvasBind('<1>' => \&baroclick);
+
+ $canvas_frame->pack(-expand=>"yes",-fill=>"both");
+
+ # box to determine fine pixel borders
+ @debugboxlist=();
+ if ($config{'DEBUG'}){
+ push(@debugboxlist, $canvas->createLine(0,$trackheight-1,$config{'window_width'}-3,$trackheight-1 ,-fill=>"red"));
+ push(@debugboxlist, $canvas->createLine($config{'window_width'}-3,0,$config{'window_width'}-3, $trackheight, -fill=>"red"));
+ push(@debugboxlist, $canvas->createLine(0,0,0,$trackheight,-fill=>"red"));
+ push(@debugboxlist, $canvas->createLine(0,0,$config{'window_width'}-3,0, -fill=>"red"));
+ }
+
+ if ($config{'DEBUG'}){
+ push(@debugboxlist, $barocanvas->createLine(0,$baroheight-1,$config{'window_width'}-3,$baroheight-1 ,-fill=>"green"));
+ push(@debugboxlist, $barocanvas->createLine($config{'window_width'}-3,0,$config{'window_width'}-3, $baroheight-1, -fill=>"green"));
+ push(@debugboxlist, $barocanvas->createLine(0,0,0,$baroheight-1,-fill=>"green"));
+ push(@debugboxlist, $barocanvas->createLine(0,0,$config{'window_width'}-3,0, -fill=>"green"));
+ }
+
+ $nr=0;
+
+ unzoomed();
+ mapplot($dxp, $dyp, $minlat, $minlon,"i");
+
+ trackplot($dxp, $dyp, $minlat, $minlon);
+ baroplot();
+
+ #$fvwtextobj=$canvas->createText(0,0,text=>" ");
+ $horizontal=$canvas->createLine(0,0,0,0);
+ $vertical=$canvas->createLine(0,0,0,0);
+ $barovertical = $barocanvas->createLine(0,0,0,0);
+
+ FVWausg();
+ marksdraw();
+
+ $FlightView->bind("<Key-F3>", sub {if ($filestat eq 'closed') { return; } $nr++ ; FVWausg();});
+ $FlightView->bind("<Key-F4>", sub {if ($filestat eq 'closed') { return; } $nr=$nr+5 ; FVWausg();});
+ $FlightView->bind("<Key-F1>", sub {if ($filestat eq 'closed') { return; } $nr=$nr-5 ; FVWausg();});
+ $FlightView->bind("<Key-F2>", sub {if ($filestat eq 'closed') { return; } $nr-- ; FVWausg();});
+ $FlightView->bind("<Key-F5>", sub {
+ if ($filestat eq 'closed') { return; }
+ $stat_start=$nr;$FlightView->bell; baroplot();
+ if ($cut_track == 1) {trackplot($dxp, $dyp, $minlat, $minlon);FVWausg();}
+ marksdraw();
+
+ });
+
+ # reset F5/F6 not documented
+ $FlightView->bind("<Key-F12>", sub {
+ if ($filestat eq 'closed') { return; }
+ $stat_start=0;$stat_end=$#BARO; $FlightView->bell;
+ marksdraw();
+ $cut_track=0;trackplot($dxp, $dyp, $minlat, $minlon);baroplot();FVWausg();
+ });
+ $FlightView->bind("<Key-F6>", sub {
+ if ($filestat eq 'closed') { return; }
+ $stat_end=$nr;$FlightView->bell; baroplot();
+ if ($cut_track == 1) {trackplot($dxp, $dyp, $minlat, $minlon);FVWausg();}
+ marksdraw();
+ });
+ $FlightView->bind("<Key-F7>", sub {if ($filestat eq 'closed') { return; }statistik($stat_start, $stat_end);});
+ $FlightView->bind("<Key-F8>", sub {if ($filestat eq 'closed') { return; }thermik_statistik();});
+ $FlightView->bind("<Key-F9>", sub {if ($filestat eq 'closed') { return; }glide_statistik();});
+
+ $FlightView->bind("<Key-F10>", sub {
+ if ($filestat eq 'closed') { return; }
+ $FlightView->bell;
+ my $lifts = substr($file, 0, -3)."lif";
+ $liftsexist =1;
+ open (LIFTS, ">>$lifts");
+
+ # vielleicht noch das datum!
+ my ($name, $p, $suf) = File::Basename::fileparse($file);
+ printf LIFTS ("%.4f %.4f %.0f %.2f %.2f %.3f %02d-%02d-%04d $name\n",$DECLAT[$nr],$DECLON[$nr],$BARO[$nr],$IVARIO[$nr],$nonIVARIO[$nr],$DECTIME[$nr],$gpi{'day'},$gpi{'month'},$gpi{'year'});
+ close LIFTS;
+
+ });
+
+ $FlightView->bind("<Key-F11>", sub {
+ if ($filestat eq 'closed') { return; }
+ if ($cut_track == 0) {$cut_track=1;trackplot($dxp, $dyp, $minlat, $minlon);baroplot();FVWausg();return;}
+ if ($cut_track == 1) {$cut_track=0;trackplot($dxp, $dyp, $minlat, $minlon);baroplot();FVWausg();}
+ });
+
+ $FlightView->bind("<Key-s>", sub {
+ if ($filestat eq 'closed') { return; }
+ if ($nr < $task_finish_time_index) {
+ $task_start_time_index = $nr; $FlightView->bell;
+ FSupdate();
+ baroplot();
+
+ #baroplot_task(); in baroplot already
+ marksdraw();
+
+ #if ($task_state ==1) {taskdraw(1);}
+ #if task changed since optimization loose ability to olc-file output
+ undef $olcFirstWPindex;
+ $optimized_for = "none";
+ }
+ });
+
+ $FlightView->bind("<Key-f>", sub {
+ if ($filestat eq 'closed') { return; }
+ if ($nr > $task_start_time_index) {
+ $task_finish_time_index = $nr; $FlightView->bell;
+ FSupdate();
+ baroplot();
+
+ #baroplot_task();
+ marksdraw();
+
+ #if ($task_state ==1) {taskdraw(1);}
+ #if task changed since optimization loose ability to olc-file output
+ undef $olcFirstWPindex;
+ $optimized_for = "none";
+ }
+ });
+
+ $FlightView->bind("<Key-e>",sub {if ($filestat eq 'closed') { return; } calibrationinput();});
+ $FlightView->bind("<Key-n>",sub {if ($filestat eq 'closed') { return; } qnhcalibrationinput();});
+ $FlightView->bind("<Key-x>",sub {if ($filestat eq 'closed') { return; } phototimecalibration();});
+ $FlightView->bind("<Key-u>",sub {if ($filestat eq 'closed') { return; } geotag_photos();});
+ $FlightView->bind("<Key-m>",sub {
+ if ($filestat eq 'closed') { return; }
+
+ # sub medialist
+ my $list;
+ if ($#PHOTO_FILES < 1 ) {Errorbox("List is empty"); return;}
+ if (Exists($mmlist)) {$mmlist->destroy;}
+
+ $mmlist=$FlightView->Toplevel();
+ $mmlist->configure(-title=>"Media List");
+ setexit($mmlist);
+
+ $mm_list_box = $mmlist->ScrlListbox(-label=>"Media List", -selectmode=>"single",-height=>"0",-width=>"0")->pack(-side=>"left");
+ $mm_list_box->bind("<Double-Button-1>" => \&mm_click);
+
+ for (my $z=0; $z<=$#PHOTO_FILES;$z++) {
+ $list = GPLIGCfunctions::dec2time($PHOTO_FILES_TIMES[$z])." $PHOTO_FILES[$z]";
+ $mm_list_box->insert("end", $list);
+ };
+ sub mm_click {
+ my $sel=$mm_list_box->curselection();
+
+ if (defined @$sel[0]) {
+ FVWausg($PHOTO_FILES_INDICES[@$sel[0]]);
+ }
+
+ }
+ });
+
+ $FlightView->bind("<Key-r>", sub{
+ if ($filestat eq 'closed') { return; }
+ Ausschnitt($DECLAT[$nr], $DECLON[$nr]); $FlightView->bell;
+ });
+
+ $FlightView->bind("<Key-t>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($task_state == 0) {taskdraw(1);$task_state=1;return;}
+ if ($task_state == 1) {taskdraw(0);$task_state=0;}
+ });
+
+ $FlightView->bind("<Key-w>", sub{
+ if ($filestat eq 'closed') { return; }
+ $FlightView->bell;
+ push(@WPNAME, "WP$freeWP");
+ $freeWP++;
+ $MAXWP++;
+ push(@WPLAT, $DECLAT[$nr]);
+ push(@WPLON, $DECLON[$nr]);
+ push(@WPRADFAC, 1.0);
+
+ WPPlotUpdate();
+ baroplot(); #_task();
+ FSupdate();
+ TaskUpdate();
+
+ #if task changed since optimization loose ability to olc-file output
+ undef $olcFirstWPindex;
+ $optimized_for = "none";
+ });
+
+ $FlightView->bind("<Key-a>", sub{
+ if ($filestat eq 'closed') { return; }
+ $FlightView->bell;
+ print "Bef: aktwp: $AKTWP + 1, maxwp $MAXWP, nowplat: $#WPLAT \n" if ($config{'DEBUG'});
+
+ my $add = 1;
+ if ($AKTWP == 1 && $MAXWP == 0) {$add = 0;}
+
+ splice(@WPNAME, $AKTWP+$add , 0 , "WP$freeWP");
+ splice(@WPLAT, $AKTWP+$add , 0 , $DECLAT[$nr]);
+ splice(@WPLON, $AKTWP+$add , 0 , $DECLON[$nr]);
+ splice(@WPRADFAC, $AKTWP+$add , 0 , 1.0);
+ $freeWP++;
+ $MAXWP++;
+
+ print "Aft: aktwp: $AKTWP + 1, maxwp $MAXWP, nowplat: $#WPLAT \n" if ($config{'DEBUG'});
+
+ WPPlotUpdate();
+ baroplot();#_task();
+ FSupdate();
+ TaskUpdate();
+ FVWausg();
+
+ #if task changed since optimization loose ability to olc-file output
+ undef $olcFirstWPindex;
+ $optimized_for = "none";
+ });
+
+ $FlightView->bind("<Key-b>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($AKTWP == 1 && $MAXWP == 0) {return;} #no other WPs yet
+ $FlightView->bell;
+ splice(@WPNAME, $AKTWP , 0 , "WP$freeWP");
+ splice(@WPLAT, $AKTWP , 0 , $DECLAT[$nr]);
+ splice(@WPLON, $AKTWP , 0 , $DECLON[$nr]);
+ splice(@WPRADFAC, $AKTWP , 0 , 1.0);
+ $freeWP++;
+ $MAXWP++;
+
+ $AKTWP++;
+ WPPlotUpdate();
+ baroplot();#_task();
+ FSupdate();
+
+ FVWausg();
+ TaskUpdate();
+
+ #if task changed since optimization loose ability to olc-file output
+ undef $olcFirstWPindex;
+ $optimized_for = "none";
+ });
+
+ $FlightView->bind("<Key-p>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($AKTWP == 1 && $MAXWP == 0) {return;} #no other WPs yet
+ $FlightView->bell;
+ splice(@WPNAME, $AKTWP , 1 , "WP$freeWP");
+ splice(@WPLAT, $AKTWP , 1 , $DECLAT[$nr]);
+ splice(@WPLON, $AKTWP , 1 , $DECLON[$nr]);
+ splice(@WPRADFAC, $AKTWP , 1 , 1.0);
+ $freeWP++;
+
+ WPPlotUpdate();
+ baroplot();#_task();
+ FSupdate();
+ FVWausg();
+ TaskUpdate();
+
+ #if task changed since optimization loose ability to olc-file output
+ # replace should be allowed, in case modification is needed...
+ #undef $olcFirstWPindex;
+ });
+
+ $FlightView->bind("<Key-g>", sub{
+ if ($filestat eq 'closed') { return; }
+
+ if ($config{'fvw_grid'} eq 'yes' && $config{'fvw_baro_grid'} eq 'yes') {
+ $config{'fvw_grid'} = 'no' ; $config{'fvw_baro_grid'} = 'no';
+ updateFVW(); return;
+ }
+
+ if ($config{'fvw_grid'} eq 'no' && $config{'fvw_baro_grid'} eq 'no') {
+ $config{'fvw_grid'} = 'yes' ; $config{'fvw_baro_grid'} = 'no';
+ updateFVW(); return;
+ }
+
+ if ($config{'fvw_grid'} eq 'yes' && $config{'fvw_baro_grid'} eq 'no') {
+ $config{'fvw_grid'} = 'no' ; $config{'fvw_baro_grid'} = 'yes';
+ updateFVW(); return;
+ }
+
+ if ($config{'fvw_grid'} eq 'no' && $config{'fvw_baro_grid'} eq 'yes') {
+ $config{'fvw_grid'} = 'yes' ; $config{'fvw_baro_grid'} = 'yes';
+ updateFVW(); return;
+ }
+ });
+
+ $FlightView->bind("<Key-o>", sub{
+ if ($filestat eq 'closed') { return; }
+ $savename = save();
+ if ($savename eq "no") {return;}
+ MessageFenster("Postscript Output", "$savename wird ausgegeben");
+ $canvas->postscript(-file=>$savename, -colormode=>"color");
+ });
+
+ $FlightView->bind("<Key-i>", sub{
+ if ($filestat eq 'closed') { return; }
+ $savename = save();
+ if ($savename eq "no") {return;}
+ MessageFenster("Postscript Output", "$savename wird ausgegeben");
+ $barocanvas->postscript(-file=>$savename, -colormode=>"color");
+ });
+
+ $FlightView->bind("<Key-h>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($hide_mm == 0) {$hide_mm =1;} else {$hide_mm=0;}
+ updateFVW();
+ });
+
+ $FlightView->bind('<Key-y>',sub{ if ($filestat eq 'closed') { return; } FVWresize();});
+ $FlightView->bind("<Key-z>", sub{ if ($filestat eq 'closed') { return; } zoom();});
+ $FlightView->bind("<Key-v>", sub{
+ if ($filestat eq 'closed') { return; }
+ # view next photo
+ my $min = 100000;
+ my $min_idx = -77;
+ for (my $z=0; $z<=$#PHOTO_FILES_INDICES; $z++){
+ if ( abs($nr-$PHOTO_FILES_INDICES[$z]) < $min ) {
+ $min = abs($nr-$PHOTO_FILES_INDICES[$z]);
+ $min_idx = $z;
+ }
+ }
+
+ if ($min_idx != -77) {
+ $lastphoto_idx = $min_idx;
+ print "The last photo: $lastphoto_idx $PHOTO_FILES[$lastphoto_idx] \n$PHOTO_FILES_TIMES[$lastphoto_idx] $PHOTO_FILES_INDICES[$lastphoto_idx]\n" if ($config{'DEBUG'});
+ showMM($PHOTO_FILES[$min_idx]);
+ }
+ });
+
+ # Turn on the following by default...
+ $task_state=$config{'draw_task'};
+ $wpcyl_state=$config{'draw_wpcyl'};
+
+ taskdraw($task_state);
+ wpcyldraw($wpcyl_state);
+
+ $FlightView->bind("<Key-c>",sub {
+ if ($filestat eq 'closed') { return; }
+ # hier kommt die wendepunktzeichenroutine rein!
+ if ($wpcyl_state == 0) {wpcyldraw(1);$wpcyl_state=1;return;}
+ if ($wpcyl_state == 1) {wpcyldraw(0);$wpcyl_state=0;}
+ });
+
+ $FlightView->bind("<plus>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($config{'maps'}) {
+ if ($zl < 18) {
+ $zl++;
+ updateFVW(); #FVWausg();
+ }
+ }
+ } );
+
+ $FlightView->bind("<Key-M>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($config{'maps'}) {$config{'maps'}=0;}else{$config{'maps'}=1;}
+
+ updateFVW();
+ #mapplot($dxp, $dyp, $minlat, $minlon,"z");
+ #trackplot($dxp, $dyp, $minlat, $minlon);
+ #marksdraw();
+ #baroplot();
+ #FVWausg();
+
+ } );
+
+ $FlightView->bind("<minus>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($config{'maps'}) {
+ if ($zl > 0) {
+ $zl--;
+ updateFVW(); #FVWausg();
+ }
+ }
+ } );
+
+ # hash-key "#" trigger re-download
+ $FlightView->bind("<numbersign>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($config{'maps'}) {
+ $map_reload = 1;
+ updateFVW(); #FVWausg();
+
+ }
+ } );
+
+ # undocumented! increase gmaps version number and reload maps
+ $FlightView->bind("<Control-numbersign>", sub{
+ if ($filestat eq 'closed') { return; }
+ if ($config{'maps'}) {
+ $map_reload = 1;
+ $config{'map_gms_v'}++;
+ updateFVW(); #FVWausg();
+
+ }
+ } );
+
+ $FlightView->bind("<Key-H>", sub{
+ print "$config{'fvw_grid'}=fvw_grid $config{'fvw_baro_grid'}=fvw_baro_grid\n";
+
+ print @baroplot ." bp\n";
+ print @baroplot_task ." bpt\n";
+ print @trackplot ." tp\n";
+ print @mapplot ." mp\n";
+ print @task_lines ." tl\n";
+ print @acc_lines ." accl\n";
+ print @marks_lines ." ml\n";
+ print @wpcyl_lines ." wpcl\n";
+
+ # ZZZZ
+ #this is purely for debugging one memory leak
+ # VERY STRANGE
+ # symptoms:
+ # repeatedly pressing H leaks some memory
+ # ONLY if fvw_grid is "no" ???? WTF
+ # fvw_grid isnt used at ALL in baroplot()
+ #
+
+ baroplot();
+
+ } );
+
+ $FlightView->bind("<Escape>", sub{$FlightView->destroy; gpligcexit();} );
+}
+
+sub mapplot {
+ if ($filestat eq 'closed') { return; }
+
+ print "mapplot ---------\n" if ($config{'DEBUG'});
+
+ if ($config{'maps'} && !($have_imager && $have_png)) {
+ $config{'maps'}=0;
+ Errorbox("You cant use maps without PNG and Imager modules!");
+ return;
+ }
+
+ if (!($have_imager && $have_png)) {return;}
+
+ # maps are off? then delete them (if present) and return
+ if (!$config{'maps'}) {
+ if (@mapplot) { $canvas->delete(@mapplot); @mapplot=();}
+ return;
+ }
+
+ # check or load needed modules
+ require Tk::PNG;
+ use File::Path;
+ require Imager;
+ use MIME::Base64;# qw(decode_base64);
+ require LWP::Simple;
+
+ if ($config{'DEBUG'}) {
+ print "mapplot: zoomlevel=$zl\n";
+ }
+
+ # maxima,minima: do nothing:
+ # ZZZ this should be selective for different map-types!
+ if ($zl > 18) {$zl=18; return;}
+ if ($zl < 0 ) {$zl=0; return;}
+ if ($config{'DEBUG'}) {print "FIXME! mapplot, zoomlevel-checks (min/max)\n";}
+
+ # remember number of map tiles
+ my $number_of_tiles_old=$tiles;
+
+ $FlightView->Busy;
+
+ # set up path
+ my $osmpath=$config{'map_path'}."/".$config{'map_type'};
+
+ # for hybrid layer we need two passes.
+ if ($config{'map_type'} eq "gmh") {$osmpath=$config{'map_path'}."/gms";}
+ my $addlayer = 0; #additional layer. this will be set to 1 in second pass
+
+ # get resolution and minima from func call
+ my ($dxp, $dyp, $minlat, $minlon, $calledfrom) =@_;
+
+ # calc maxima
+ my $maxlat = $minlat + $dyp * ($trackheight-1);
+ my $maxlon = $minlon + $dxp * ($config{'window_width'}-1);
+
+ # jump address for reload at changed zl (if zl has to be changed because of limits)
+ mapreload:
+
+ # calc upper left and lower right tile at this zl
+ my ($x1,$y1) = GPLIGCfunctions::getTileNumber($maxlat,$minlon,$zl);
+ my ($x2,$y2) = GPLIGCfunctions::getTileNumber($minlat,$maxlon,$zl);
+
+ $tiles = ($x2-$x1+1)*($y2-$y1+1);
+
+ if ($tiles > $config{'map_max_tiles'}) {
+ $zl-- if ($zl >0);
+ if ($calledfrom eq "u") {
+ $tiles=$number_of_tiles_old;
+ return;
+ }
+ goto mapreload;
+ }
+
+ print "mapplot: needed tiles: $x1,$y1 => $x2,$y2\n" if ($config{'DEBUG'});
+ my $xt=$x1;
+ my $yt=$y1;
+
+ # check for maximum scaling before entering the loop! prevents uneccessary reloading of the map
+ my ($tlatmin,$tlonmin,$tlatmax,$tlonmax) =GPLIGCfunctions::Project( $xt,$yt,$zl);
+
+ # calculate resizing of tile (they ship as 256x256)
+ my $xsize = ($tlonmax-$tlonmin)/$dxp; #print "xsise $xsize\n";
+ my $ysize = ($tlatmax-$tlatmin)/$dyp; #print "ysize $ysize\n";
+
+ if ($config{'DEBUG'}) {print "mapplot scalesize $xsize\n";}
+
+ if ($xsize > $config{'map_max_scalesize'}) {
+ $zl++;
+ if ($zl > 18) {$zl = 18;};
+ if ($calledfrom eq "u") {
+ $tiles=$number_of_tiles_old;
+ return;
+ }
+
+ if ($zl == 18 && $xsize > $config{'map_max_scalesize'} ) {
+ print "mapplot: accepting large scaling. Very small track?\n" if ($config{'DEBUG'});
+
+ } else {
+ goto mapreload;
+ }
+ }
+
+ if (@mapplot) {$canvas -> delete (@mapplot); @mapplot=();} # delete old maps
+
+ # we'll jump here for the second pass (hybrid layer)
+ maplayer:
+
+ # loop to load and display map tiles in range
+ while ($xt<=$x2 && $yt<=$y2) {
+
+ # get boundaries for actual map tile
+ my ($tlatmin,$tlonmin,$tlatmax,$tlonmax) =GPLIGCfunctions::Project( $xt,$yt,$zl);
+
+ # calculate resizing of tile (they ship as 256x256)
+ my $xsize = ($tlonmax-$tlonmin)/$dxp; #print "xsise $xsize\n";
+ my $ysize = ($tlatmax-$tlatmin)/$dyp; #print "ysize $ysize\n";
+
+ # check if tile exists
+ if (!-e "$osmpath/$zl/$xt/$yt.png" || $map_reload == 1){
+
+ $canvas -> delete (@textplot);
+ @textplot=();
+ my $dlplottext="DOWNLOADING MAP TILE ($config{'map_type'} $zl $xt $yt";
+
+ if ($config{'map_type'} eq "gms" || $config{'map_type'} eq "gmh") {
+ $dlplottext .= " v=$config{'map_gms_v'}";
+ }
+
+ $dlplottext .= ")";
+ push (@textplot, $canvas->createText(20,20, -anchor=>"w", -text=>$dlplottext, -fill=>"red"));
+ $canvas->update;
+
+ my $dladdr;
+ $dladdr = "http://tile.openstreetmap.org/$zl/$xt/$yt.png" if ($config{'map_type'} eq "osm");
+ $dladdr = "http://a.tile.opencyclemap.org/cycle/$zl/$xt/$yt.png" if ($config{'map_type'} eq "osmC");
+
+ # seems not to work, yet?
+ $dladdr = "http://t1.openseamap.org/seamark/$zl/$xt/$yt.png" if ($config{'map_type'} eq "oseam");
+
+ $rand = int(rand(4));
+ $dladdr = "http://mt$rand.google.com/vt/lyrs=t,r&hl=en&x=$xt&y=$yt&z=$zl" if ($config{'map_type'} eq "gmt");
+ $dladdr = "http://mt$rand.google.com/vt/lyrs=m&hl=en&x=$xt&y=$yt&z=$zl" if ($config{'map_type'} eq "gmm" );
+
+ $retry_gms_counter=-1;
+ retry_gms:
+ $retry_gms_counter++;
+
+ if ($retry_gms_counter >= 50) {
+ Errorbox("cannot download map tile. (20x404). giving up. Maps disabled");
+ $config{'maps'}=0;
+ $canvas -> delete (@textplot);
+ goto load_map_tiles;
+ }
+
+ # for sat and hybrid load sat layer
+ $dladdr = "http://khm$rand.google.com/kh/v=".($config{'map_gms_v'}+$retry_gms_counter)."&hl=en&x=$xt&y=$yt&z=$zl" if ($config{'map_type'} eq "gms" || $config{'map_type'} eq "gmh" );
+
+ $dladdr = "http://mt$rand.google.com/vt/lyrs=h&hl=en&x=$xt&y=$yt&z=$zl" if ($addlayer == 1);
+
+ if (!-d "$osmpath/$zl/$xt") {File::Path::mkpath "$osmpath/$zl/$xt";}
+ $resp = LWP::Simple::getstore($dladdr, "$osmpath/$zl/$xt/$yt.png");
+ print "$resp DOWNLOAD: \"$dladdr\" ==> $osmpath/$zl/$xt/$yt.png\n" if ($config{'DEBUG'});
+
+ if ($resp != 200) {print "$resp error: $dladdr\n" if ($config{'DEBUG'}); }
+ else {
+ #if success, record min/max
+ if (($config{'map_gms_v'}+$retry_gms_counter) < $map_gms_v_min) {$map_gms_v_min = $config{'map_gms_v'}+$retry_gms_counter;}
+ if (($config{'map_gms_v'}+$retry_gms_counter) > $map_gms_v_max) {$map_gms_v_max = $config{'map_gms_v'}+$retry_gms_counter;}
+
+ }
+
+ if ($resp == 404 && $addlayer == 0 && ($config{'map_type'} eq "gms" || $config{'map_type'} eq "gmh")) {
+ print "$resp error: $dladdr - SAT v=".($config{'map_gms_v'}+$retry_gms_counter).". Retrying newer version \n" if ($config{'DEBUG'});
+ goto retry_gms;
+ }
+
+ if ($retry_gms_counter > 0) {$config{'map_gms_v'} += $retry_gms_counter; print "Map Version updated\n" if ($config{'DEBUG'}); }
+
+ # not needed evt for later use by ogie?! solange er kein png versteht
+ # system ("convert $osmpath/$zl/$xt/$yt.png $osmpath/$zl/$xt/$yt.jpg");
+ }
+
+ # load image and resize
+ # check for zero size before!
+ load_map_tiles:
+ if (-s "$osmpath/$zl/$xt/$yt.png") {
+
+ $canvas -> delete (@textplot);
+ @textplot=();
+ push (@textplot, $canvas->createText(20,20, -anchor=>"w", -text=>"LOADING MAP TILE ($config{'map_type'} $zl $xt $yt)", -fill=>"black"));
+ $canvas->update;
+
+ my $img = Imager->new;
+ $img->read(file => "$osmpath/$zl/$xt/$yt.png");
+ my $newimg = $img->scale(xpixels=>$xsize+.5, ypixels=>$ysize+.5);
+
+ #my $zzz;
+ #$newimg->write(data => \$zzz, type=>"png"); #OLD Method, mem-leak!
+ $newimg->write(file => "${pfadftmp}tmp.png" , type=>"png"); # now, via tmp file
+
+ # this creates a horrible memory leak. see:
+ # https://rt.cpan.org/Public/Bug/Display.html?id=29640
+ # http://www.perlmonks.org/?node_id=986015
+ #my $nmt= $FlightView->Photo(-data => encode_base64($zzz));
+ my $nmt= $FlightView->Photo(-file => "${pfadftmp}tmp.png");
+
+ # new code, does NOT work
+ #if (!defined $nmt) {
+ # $nmt = $FlightView->Photo();
+ #}
+ #$nmt->configure(-data => encode_base64($zzz));
+
+ # calculate shift
+ my $cx = ($tlonmin - $minlon)/$dxp ;
+ my $cy = ($tlatmax - $maxlat)/$dyp;
+
+
+ # load into canvas
+ push(@mapplot, $canvas->createImage($cx,-$cy, -anchor=>"nw", -image => $nmt));
+
+ #$nmt->delete;
+
+
+ } else {
+
+ # file has 0 bytes:
+ print "ERROR $osmpath/$zl/$xt/$yt.png has size 0! probably failed download. I'll delete this.\n" if ($config{'DEBUG'});
+ unlink ("$osmpath/$zl/$xt/$yt.png");
+
+ }
+ $canvas -> delete (@textplot);
+ @textplot=();
+
+ # next tiles!
+ $xt++;
+ if ($xt>$x2) {$xt=$x1;$yt++;}
+ }
+
+ # add second layer for gm hybrid
+ if ($addlayer == 0 && $config{'map_type'} eq "gmh") {
+ $addlayer=1;
+ $osmpath=$config{'map_path'}."/gmh";
+ $xt=$x1;
+ $yt=$y1;
+ goto maplayer;
+ }
+
+#######################################
+ # draw boxes for debugging:
+ # if ($config{'DEBUG'}) {
+ # $xt=$x1;
+ # $yt=$y1;
+ # while ($xt<=$x2 && $yt<=$y2) {
+
+# get boundaries for actual map tile
+# my ($tlatmin,$tlonmin,$tlatmax,$tlonmax) =GPLIGCfunctions::Project( $xt,$yt,$zl);
+#print "Tile $xt,$yt: latmin:$tlatmin, lonmin:$tlonmin, latmax:$tlatmax, lonmax:$tlonmax\n";
+
+ # calculate resizing of tile (they ship as 256x256)
+ # my $xsize = ($tlonmax-$tlonmin)/$dxp; #print "xsise $xsize\n";
+ # my $ysize = ($tlatmax-$tlatmin)/$dyp; #print "ysize $ysize\n";
+
+ # my $cx = ($tlonmin - $minlon)/$dxp ;
+ # my $cy = ($tlatmax - $maxlat)/$dyp;
+
+# push(@mapplot, $canvas->createLine($cx,-$cy, $cx+$xsize+.5, -$cy , -fill=>"black"));
+# push(@mapplot, $canvas->createLine($cx,-$cy, $cx, -$cy+$ysize+0.5, -fill=>"black"));
+# push(@mapplot, $canvas->createLine($cx+$xsize+.5,-$cy+$ysize+0.5, $cx+$xsize+.5, -$cy, -fill=>"black"));
+# push(@mapplot, $canvas->createLine($cx+$xsize+.5,-$cy+$ysize+0.5, $cx, -$cy+$ysize+.5, -fill=>"black"));
+
+ # $xt++;
+ # if ($xt>$x2) {$xt=$x1;$yt++;}
+ # }
+ # }
+#######################################
+
+ if ($config{'DEBUG'}) {
+ print "gm-v min: $map_gms_v_min max: $map_gms_v_max\n";
+ }
+
+ $FlightView->Unbusy;
+ $canvas -> delete (@textplot);
+ @textplot=();
+ $map_reload = 0;
+}
+
+########### FlightView end #########################
+
+sub trackplot {
+ if ($filestat eq 'closed') {
+ return;
+ }
+
+ print "trackplot ---------\n" if ($config{'DEBUG'});
+
+ $FlightView->Busy;
+ my ($dxp, $dyp, $minlat, $minlon) =@_;
+
+ print "TRACKPLOT (dxp dyp minlat minlon): $dxp $dyp $minlat $minlon\n" if ($config{'DEBUG'});
+
+ if (@trackplot) {$canvas -> delete (@trackplot);}
+ @trackplot =();
+
+ # gridlines to be added here
+ if ($config{'fvw_grid'} eq 'yes') {
+
+ my $gridstep= 1/6;
+
+ #first lat grid line at....
+ my $firstlatgrid = int($minlat) + int(($minlat - int($minlat)) / $gridstep)* $gridstep;
+
+ for (my $latgrid = $firstlatgrid; $trackheight > (($latgrid-$minlat)/$dyp); $latgrid += $gridstep) {
+
+ #print "$latgrid ...\n";
+ #print " ".abs($latgrid-int($latgrid))." \n";
+
+ my $y = int ($trackheight - (($latgrid-$minlat)/$dyp));
+
+ #bei ganzen graden....
+ if (abs($latgrid-int($latgrid)) < 0.01 || abs($latgrid-int($latgrid)) > 0.99 ) {
+ push (@trackplot, $canvas->createLine(0, $y, $config{'window_width'}-2, $y,-fill=>'gray70'));
+ my $text = int ($latgrid + 0.5)."";
+ push (@trackplot, $canvas->createText(0,$y, -anchor=>"w", -text=>$text, -fill=>"gray30"));
+ } else {
+ push (@trackplot, $canvas->createLine(0, $y, $config{'window_width'}-2, $y,-fill=>'gray90'));
+ }
+ }
+
+ #first lon grid line at....
+ my $firstlongrid = int($minlon) + int(($minlon - int($minlon)) / $gridstep)* $gridstep;
+
+ for (my $longrid = $firstlongrid; $config{'window_width'}-2 > (($longrid-$minlon)/$dxp); $longrid += $gridstep) {
+
+ #print "$latgrid ...\n";
+
+ my $x = int (($longrid-$minlon)/$dxp);
+
+ if (abs($longrid-int($longrid)) < 0.01 || abs($longrid-int($longrid)) > 0.99 ) {
+
+ push (@trackplot, $canvas->createLine($x, 0, $x, $trackheight,-fill=>"gray80"));
+ my $text =int ($longrid + 0.5)."";
+ push (@trackplot, $canvas->createText($x, 0, -anchor=>"n", -text=>$text, -fill=>"black"));
+
+ } else {
+ push (@trackplot, $canvas->createLine($x, 0, $x, $trackheight,-fill=>"gray90"));
+ }
+ }
+ }
+
+ # TRACKPLOT
+ # This plots the Track
+
+ my $pstart = 1;
+ my $pend=$#LAT;
+ if ($cut_track == 1 && !($stat_start == 0 && $stat_end == $#BARO) && $stat_start < $stat_end) {
+ $pstart=$stat_start+1; $pend=$stat_end;
+ }
+
+ for (my $zaehler=$pstart; $zaehler<=$pend ;$zaehler++) {
+ my $x1= int(($DECLON[$zaehler-1]-$minlon)/$dxp);
+ my $x2= int(($DECLON[$zaehler]-$minlon)/$dxp);
+ my $y1= int($trackheight-(($DECLAT[$zaehler-1]-$minlat)/$dyp));
+ my $y2= int($trackheight-(($DECLAT[$zaehler]-$minlat)/$dyp));
+
+ if ($ENL[$zaehler] < $config{'ENL_noise_limit'}) {
+ if ($nonIVARIO[$zaehler] <= 0) {push (@trackplot, $canvas->createLine( $x1, $y1, $x2, $y2,-fill=>"blue"));}
+ if ($nonIVARIO[$zaehler] > 0) {push (@trackplot, $canvas->createLine( $x1, $y1, $x2, $y2,-fill=>"red"));}
+
+ # display skips in different color
+ if ($config{'skip_check'}) {
+ if ($DECTIME[$zaehler] - $DECTIME[$zaehler-1] > ($config{'skip_limit_minutes'}/60)) {
+ push (@trackplot, $canvas->createLine( $x1, $y1, $x2, $y2,-fill=>"black",-width=>2,-arrow=>"both"));
+ print "skip detected at >>".($zaehler-1)." - $zaehler \n" if ($config{'DEBUG'});
+ }
+
+ }
+
+ # This is powered flight!!!!
+ } else {
+ push (@trackplot, $canvas->createLine( $x1, $y1, $x2, $y2,-fill=>"green"));
+ }
+
+ if ($config{'photos'} && !$hide_mm) {
+ for (my $g = 0; $g <= $#PHOTO_FILES; $g++) {
+ if ($PHOTO_FILES_INDICES[$g] == $zaehler-1) {
+ my ($name, $p, $suf) = File::Basename::fileparse($PHOTO_FILES[$g]);
+
+ #print "$name <<<<<<<<<<\n";
+
+ push(@trackplot, $canvas->createText($x1, $y1, -anchor=>"w", -text=>$name,-fill=>"gray10"));
+ }
+ }
+ }
+ }
+ $FlightView->Unbusy;
+}
+
+sub wpcyldraw {
+ my $on_off= shift;
+
+ print "wpcyldraw (on/off = $on_off) ---------\n" if ($config{'DEBUG'});
+
+ if ($on_off == 1) {
+ if ($MAXWP >= 1) {
+ @wpcyl_lines=();
+ for (my $zaehl=1; $zaehl<=$#WPLAT; $zaehl++){
+
+ # draw cylinders
+ if ($config{'zylinder_wp_type'} eq "cyl" || $config{'zylinder_wp_type'} eq "both") {
+ my ($cylref_lat, $cylref_lon) = GPLIGCfunctions::zylinder2( $WPLAT[$zaehl], $WPLON[$zaehl], $config{'zylinder_radius'}*($WPRADFAC[$zaehl]+0.000000000001), 0, 359.99999);
+
+ # adding a very small value in the last line seems to circumvent some bug in perl?
+ # without it the result of zyl_rad * wprfac comes as integer wtf????
+
+# if ($config{'DEBUG'}) {
+# my $GGG1= $WPRADFAC[$zaehl] * $config{'zylinder_radius'};
+# my $GGG2= ($WPRADFAC[$zaehl]+0.000000000001)* $config{'zylinder_radius'};
+
+# if (abs($GGG1-$GGG2) > 0.1) {
+# print "IS THIS A BUG in Perl ???:\n";
+# print 'This is the value of the hash/key >>> $config{\'zylinder_radius\'} :>>'.$config{'zylinder_radius'}."<<\n";
+# print 'This is the value of the array/index >>> $WPRADFAC[$zaehl] :>>'.$WPRADFAC[$zaehl]."<<\n";
+# print 'The product $WPRADFAC[$zaehl] * $config{\'zylinder_radius\'} = '.$GGG1."\n";
+# print 'The product ($WPRADFAC[$zaehl]+0.000000000001) * $config{\'zylinder_radius\'} = '.$GGG2."\n";
+# print "\n*******************\n $GGG1 = $GGG2 \n*******************\n\n";
+# }
+# }
+
+ for (my $xzaehl=0; $xzaehl<=$#$cylref_lat-1; $xzaehl++) {
+
+ my $x1= int( ( ($WPLON[$zaehl]+${$cylref_lon}[$xzaehl]) -$minlon) /$dxp);
+ my $x2= int( ( ($WPLON[$zaehl]+${$cylref_lon}[$xzaehl+1]) -$minlon) /$dxp);
+ my $y1= int($trackheight-( ( ($WPLAT[$zaehl]+${$cylref_lat}[$xzaehl]) -$minlat )/$dyp));
+ my $y2= int($trackheight-( ( ($WPLAT[$zaehl]+${$cylref_lat}[$xzaehl+1]) -$minlat )/$dyp));
+ push(@wpcyl_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-width=>$config{'cylinder_linewidth'},-fill=>"dark violet"));
+ }
+ }
+
+ if ($config{'zylinder_names'} == 1) {
+
+ my $y = int($trackheight-(($WPLAT[$zaehl]-$minlat) / $dyp )+ 0.5) ;
+ my $x = int((($WPLON[$zaehl]-$minlon) / $dxp )+ 0.5) ;
+
+ push(@wpcyl_lines, $canvas->createText($x,$y,-anchor=>"n",-text=>$WPNAME[$zaehl],-fill=>"gray10"));
+
+ }
+
+ if ($config{'zylinder_wp_type'} eq "sec" || $config{'zylinder_wp_type'} eq "both") {
+ if ($MAXWP > 1) {
+ my $secdir = 0;
+
+ # in this cases it is the first or last wp!
+ if ($zaehl == 1) { $secdir = GPLIGCfunctions::gegenkurs(GPLIGCfunctions::kurs( $WPLAT[$zaehl], $WPLON[$zaehl], $WPLAT[$zaehl+1], $WPLON[$zaehl+1])); }
+ if ($zaehl == $#WPLAT) { $secdir = GPLIGCfunctions::gegenkurs(GPLIGCfunctions::kurs( $WPLAT[$zaehl], $WPLON[$zaehl], $WPLAT[$zaehl-1], $WPLON[$zaehl-1])); }
+
+ #a "normal wp"
+ if ($zaehl != 1 && $zaehl != $#WPLAT ) { $secdir = GPLIGCfunctions::sectordirection(
+ GPLIGCfunctions::kurs( $WPLAT[$zaehl], $WPLON[$zaehl], $WPLAT[$zaehl+1], $WPLON[$zaehl+1]),
+ GPLIGCfunctions::kurs( $WPLAT[$zaehl], $WPLON[$zaehl], $WPLAT[$zaehl-1], $WPLON[$zaehl-1])); }
+
+ $sec2up = $secdir +90; if ($sec2up < 0) { $sec2up = $sec2up + 360 ;} if ($sec2up > 360) { $sec2up = $sec2up - 360 ;}
+ $sec2down = $secdir -90; if ($sec2down < 0) { $sec2down = $sec2down + 360 ;} if ($sec2down > 360) { $sec2down = $sec2down - 360 ;}
+ $sec1up = $secdir +45; if ($sec1up < 0) { $sec1up = $sec1up + 360 ;} if ($sec1up > 360) { $sec1up = $sec1up - 360 ;}
+ $sec1down = $secdir -45; if ($sec1down < 0) { $sec1down = $sec1down + 360 ;} if ($sec1down > 360) { $sec1down = $sec1down - 360 ;}
+
+ ($cylref_lat, $cylref_lon) = GPLIGCfunctions::zylinder2($WPLAT[$zaehl], $WPLON[$zaehl], '3.0' , $sec2down, 180); # FAI = 3.0 km sector
+
+ for (my $xzaehl=0; $xzaehl<=$#$cylref_lat-1; $xzaehl++) {
+
+ my $x1= int( ( ($WPLON[$zaehl]+${$cylref_lon}[$xzaehl]) -$minlon) /$dxp);
+ my $x2= int( ( ($WPLON[$zaehl]+${$cylref_lon}[$xzaehl+1]) -$minlon) /$dxp);
+ my $y1= int($trackheight-( ( ($WPLAT[$zaehl]+${$cylref_lat}[$xzaehl]) -$minlat )/$dyp));
+ my $y2= int($trackheight-( ( ($WPLAT[$zaehl]+${$cylref_lat}[$xzaehl+1]) -$minlat )/$dyp));
+
+ if ($zaehl == 1) {
+ push(@wpcyl_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-width=>$config{'waypoint_linewidth'} ,-fill=>"dark red"));
+ } else {
+ push(@wpcyl_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-width=>$config{'waypoint_linewidth'} ,-fill=>"dark green"));
+ }
+ }
+
+ my $whatline=0; # used to make sec2up/down for first wp 10km (starting-line)
+ foreach ($sec2up, $sec2down, $sec1up, $sec1down) {
+
+ #print "teil: $_ \n";
+
+ my $x1= int( ( ($WPLON[$zaehl]) -$minlon) /$dxp);
+ my $y1= int($trackheight-( ( ($WPLAT[$zaehl]) -$minlat )/$dyp));
+
+ my $base_line = 3;
+ if ($zaehl == 1 && ($whatline == 0 || $whatline==1)) {$base_line=$config{'starting_line'}/2.0;}
+ $whatline++;
+ my ($lat, $lon) = GPLIGCfunctions::go($WPLAT[$zaehl],$WPLON[$zaehl], $_, $base_line);
+
+ #print " $lat $lon \n";
+
+ my $x2= int( ( ($lon) -$minlon) /$dxp);
+ my $y2= int($trackheight-( ( ($lat) -$minlat )/$dyp));
+
+ if ($zaehl == 1) {
+ push(@wpcyl_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-width=>$config{'waypoint_linewidth'},-fill=>"dark red"));
+ } else {
+ push(@wpcyl_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-width=>$config{'waypoint_linewidth'},-fill=>"dark green"));
+ }
+
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ if ($on_off == 0){
+ $canvas->delete(@wpcyl_lines);
+ @wpcyl_lines=();
+ }
+}
+
+sub taskdraw {
+ my $on_off = shift;
+
+ print "taskdraw (on/off = $on_off) ---------\n" if ($config{'DEBUG'});
+
+ if ($on_off == 1) {
+
+ # delete task-lines and replot
+ $canvas->delete(@task_lines);
+ @task_lines=();
+ for (my $zaehl=1 ; $zaehl<=$#WPLAT-1; $zaehl++) {
+ my $x1= int(($WPLON[$zaehl]-$minlon)/$dxp);
+ my $x2= int(($WPLON[$zaehl+1]-$minlon)/$dxp);
+ my $y1= int($trackheight-(($WPLAT[$zaehl]-$minlat)/$dyp));
+ my $y2= int($trackheight-(($WPLAT[$zaehl+1]-$minlat)/$dyp));
+ push(@task_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-width=>$config{'task_linewidth'},-fill=>"dark violet"));
+ }
+ }
+
+ if ($on_off == 0) {
+ $canvas->delete(@task_lines);
+ @task_lines=();
+ }
+}
+
+
+sub baroplot {
+ if ($filestat eq 'closed') {
+ return;
+ }
+
+ print "baroplot ---------\n" if ($config{'DEBUG'});
+
+ # erase all plotted stuff from previous and clean array!
+ if (@baroplot){$barocanvas -> delete (@baroplot);}
+ @baroplot = (0,1); undef @baroplot;
+ @baroplot = ();
+
+ if (@baroplot_task){$barocanvas -> delete (@baroplot_task);}
+ @baroplot_task=();
+
+ $FlightView->Busy;
+
+ # JMWK 2.9.2001 heavily edited by kruegerh october 2002
+
+ my $baronumber = $#BARO;
+ my $bstart = 0;
+ my $bend = $#BARO-1;
+ my $bcut = 0;
+ my $bmaxbaro = $maxbaro;
+ my $bminbaro = $minbaro;
+
+ if ($cut_track == 1 && !($stat_start == 0 && $stat_end == $#BARO) && $stat_end > $stat_start) {
+ $baronumber = $stat_end - $stat_start;
+ $bstart=$stat_start; $bend=$stat_end;
+ $bcut=1;
+ $bminbaro = 99999;
+ $bmaxbaro = -99999;
+ for (my $x=$stat_start; $x <= $stat_end; $x++) {
+ $bminbaro = $BARO[$x] if ($bminbaro > $BARO[$x]);
+ $bmaxbaro = $BARO[$x] if ($bmaxbaro < $BARO[$x]);
+ }
+ }
+
+ $dxbaro = $baronumber/($config{'window_width'}-3);
+ $dybaro = (($bmaxbaro * $config{'altitude_unit_factor'}) - ($bminbaro*$config{'altitude_unit_factor'}))/($baroheight-1);
+
+ # dev by zero workaround (for files all altitudes are 0)
+ if ($dybaro == 0) {
+ $dybaro = 0.1 ;
+ Errorbox("No altitude information found...");
+ }
+
+
+ # plot area of unpowered flight (white background)
+ my $x1 = int ( ($task_start_time_index-$bstart) / $dxbaro);
+ my $y1 = int (($baroheight-1)-((($bmaxbaro*$config{'altitude_unit_factor'})-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro));
+
+
+ my $x2 = int ( ($task_finish_time_index-$bstart) / $dxbaro);
+ my $y2 = int (($baroheight-1)-((($bmaxbaro*$config{'altitude_unit_factor'})-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro));
+
+ push (@baroplot, $barocanvas->createRectangle($x1,$y1,$x2,$baroheight,-fill=>"white",-outline=>"white"));
+
+ # plot selected statistics zone (red background)
+ # this needs to be done before "start" and "finish" text
+ if ( !($stat_start == 0 && $stat_end == $#BARO) && $bcut != 1) {
+ my $rx1 = int ($stat_start / $dxbaro);
+ my $ry1 = int ($baroheight-((($bmaxbaro*$config{'altitude_unit_factor'})-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro));
+ my $rx2 = int ($stat_end / $dxbaro);
+ my $ry2 = int ($baroheight);
+ push (@baroplot, $barocanvas->createRectangle($rx1,$ry1,$rx2,$ry2,-fill=>"#FFEEEE",-outline=>"#FFEEEE"));
+ }
+
+ push (@baroplot_task, $barocanvas->createText($x1, $y1,-anchor=>"n",-text=>"start" , -fill=>"black"));
+ push (@baroplot_task, $barocanvas->createText($x2, $y2,-anchor=>"n",-text=>"finish" , -fill=>"black"));
+
+ if ($config{'fvw_baro_grid'} eq 'yes') {
+
+ # horizontal lines (500, 1000m) in barogram
+ for (my $z = int($minbaro*$config{'altitude_unit_factor'}) ; $z <= ($maxbaro*$config{'altitude_unit_factor'}); $z++) {
+
+ if ( ($z % $config{'baro_grid_small'}) == 0 ) {
+
+ my $x1 = int ( 1 / $dxbaro );
+ my $x2 = int ( $#BARO / $dxbaro );
+ my $y = int ($baroheight- (($z-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro));
+
+ if ( ($z % $config{'baro_grid_large'}) == 0) {
+
+ push (@baroplot, $barocanvas->createLine($x1, $y, $x2, $y, -fill=>"gray80"));
+ push (@baroplot, $barocanvas->createText($x1, $y,-anchor=>"w",-text=>$z , -fill=>"black"));
+
+ } else {
+
+ push (@baroplot, $barocanvas->createLine($x1, $y, $x2, $y, -fill=>"gray90"));
+ }
+ }
+ }
+
+ # vertical lines every hour
+ for (my $zaehler = 2; $zaehler <$#DECTIME; $zaehler++) {
+
+ if ( int($DECTIME[$zaehler]) != int($DECTIME[$zaehler+1]) ) {
+
+ my $zeit = int($DECTIME[$zaehler+1]);
+ while ($zeit >= 24) {$zeit-=24;}
+ my $x = int ( ($zaehler-$bstart) / $dxbaro);
+ my $y1 = int ($baroheight);
+ my $y2 = int ($baroheight-((($bmaxbaro*$config{'altitude_unit_factor'})-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro));
+
+ push (@baroplot, $barocanvas->createLine($x, $y1, $x, $y2, -fill=>"gray80"));
+ push (@baroplot, $barocanvas->createText($x, $y1,-anchor=>"s",-text=>$zeit , -fill=>"gray30"));
+ }
+ }
+ }
+
+ baroplot_task();
+
+ #barogram-plotting
+ for (my $zaehler=$bstart; $zaehler<$bend ;$zaehler++) {
+ my $x1= int((($zaehler-$bstart)/$dxbaro)+.5);
+ my $x2= int(((($zaehler-$bstart)+1)/$dxbaro)+.5);
+ my $y1= int((($baroheight-1)-((($BARO[$zaehler]*$config{'altitude_unit_factor'})-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro))+.5);
+ my $y2= int((($baroheight-1)-((($BARO[$zaehler+1]*$config{'altitude_unit_factor'})-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro))+.5);
+
+ if ($ENL[$zaehler] < $config{'ENL_noise_limit'}) {
+ if ($nonIVARIO[$zaehler] <= 0) {push (@baroplot, $barocanvas->createLine( $x1, $y1, $x2, $y2,-fill=>"blue"));}
+ if ($nonIVARIO[$zaehler] > 0) {push (@baroplot, $barocanvas->createLine( $x1, $y1, $x2, $y2,-fill=>"red"));}
+
+ # display skips in different color
+ if ($config{'skip_check'}) {
+ if ($DECTIME[$zaehler] - $DECTIME[$zaehler-1] > ($config{'skip_limit_minutes'}/60)) {
+
+ my $y1 = int ($baroheight);
+ my $y2 = int ($baroheight-((($bmaxbaro*$config{'altitude_unit_factor'})-($bminbaro*$config{'altitude_unit_factor'}))/$dybaro));
+ push (@baroplot, $barocanvas->createLine( $x1, $y1, $x1, $y2,-fill=>"black",-width=>2,-arrow=>"both"));
+
+#print "skip detected at >>".($zaehler-1)." - $zaehler \n" if ($config{'DEBUG'});
+ }
+
+ }
+
+ } else {
+ push (@baroplot, $barocanvas->createLine( $x1, $y1, $x2, $y2,-fill=>"green"));
+ }
+ }
+
+ $FlightView->Unbusy;
+}
+
+
+# will be called from baroplot only
+sub baroplot_task {
+ if (!Exists($FlightView)) {return;}
+# if (@baroplot_task){$barocanvas -> delete (@baroplot_task);}
+# @baroplot_task =();
+
+ print "baroplot_task ---------\n" if ($config{'DEBUG'});
+
+ my ($wpindicesref, $wpnamesref) = getWPreachedIndices();
+
+ # DISPLAY lines in barogram, where wp were reached
+ my $counter = 0;
+ my $add = 0;
+
+ if ($cut_track == 1 && !($stat_start == 0 && $stat_end == $#BARO) && $stat_end > $stat_start) {
+ $add = $stat_start;
+ }
+
+ foreach (@{$wpindicesref}) {
+
+ my $x = int ( ($_-$add) / $dxbaro);
+ my $y1 = int ($baroheight);
+ my $y2 = int ($baroheight-((($maxbaro*$config{'altitude_unit_factor'})-($minbaro*$config{'altitude_unit_factor'}))/$dybaro)) ;
+
+ #print "NEU\n $_\nx=$x\ny1=$y1\ny2=$y2\n";
+
+ push (@baroplot_task, $barocanvas->createLine($x, $y1, $x, $y2, -fill=>"black"));
+
+ if ($config{'zylinder_names'} ==1 ) {
+ push (@baroplot_task, $barocanvas->createText($x, $y2,-anchor=>"n",-text=>$wpnamesref->[$counter++] , -fill=>"gray30"));
+ }
+
+ }
+
+}
+
+# draw marks (start/end of unpowered flight, F5/F6)
+sub marksdraw {
+
+ if ($filestat eq 'closed') {
+ return;
+ }
+
+ print "marksdraw ---------\n" if ($config{'DEBUG'});
+
+ if (@marks_lines) {$canvas->delete(@marks_lines);}
+
+ @marks_lines=();
+ foreach my $z ($task_start_time_index, $task_finish_time_index) {
+ my ($cylref_lat, $cylref_lon) = GPLIGCfunctions::zylinder2($DECLAT[$z], $DECLON[$z], '0.1', 0, 359.99999); # point = 0.1
+ for (my $xzaehl=0; $xzaehl<=$#$cylref_lat-1; $xzaehl++) {
+ my $x1= int( ( ($DECLON[$z]+${$cylref_lon}[$xzaehl]) -$minlon) /$dxp);
+ my $x2= int( ( ($DECLON[$z]+${$cylref_lon}[$xzaehl+1]) -$minlon) /$dxp);
+ my $y1= int($trackheight-( ( ($DECLAT[$z]+${$cylref_lat}[$xzaehl]) -$minlat )/$dyp));
+ my $y2= int($trackheight-( ( ($DECLAT[$z]+${$cylref_lat}[$xzaehl+1]) -$minlat )/$dyp));
+ push(@marks_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-fill=>"black",-width=>$config{'marker_linewidth'}));
+ }
+ }
+
+ foreach my $z ($stat_start, $stat_end) {
+
+ if ($z != 0 && $z != 999999) {
+ my ($cylref_lat, $cylref_lon) = GPLIGCfunctions::zylinder2($DECLAT[$z], $DECLON[$z], '0.1', 0, 359.99999);
+ for (my $xzaehl=0; $xzaehl<=$#$cylref_lat-1; $xzaehl++) {
+ my $x1= int( ( ($DECLON[$z]+${$cylref_lon}[$xzaehl]) -$minlon) /$dxp);
+ my $x2= int( ( ($DECLON[$z]+${$cylref_lon}[$xzaehl+1]) -$minlon) /$dxp);
+ my $y1= int($trackheight-( ( ($DECLAT[$z]+${$cylref_lat}[$xzaehl]) -$minlat )/$dyp));
+ my $y2= int($trackheight-( ( ($DECLAT[$z]+${$cylref_lat}[$xzaehl+1]) -$minlat )/$dyp));
+ push(@marks_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-fill=>"green",-width=>$config{'marker_linewidth'}));
+ }
+ }
+ }
+}
+
+sub baroclick {
+ if ($filestat eq 'closed') { return; }
+
+ my $e = $barocanvas->XEvent;
+ my ($barocanv_x, $barocanv_y) = ($e->x, $e->y);
+
+ # (This is how a 'reverse' lookup should usually be done...)
+ $nr = int($barocanv_x * $dxbaro);
+
+ # zoomed baro view
+ if ($cut_track == 1 && !($stat_start == 0 && $stat_end == $#BARO) && $stat_end > $stat_start) {
+ $nr += $stat_start;
+ }
+
+ # Disable the calbacks until we're finisched. (fixes bug #6)
+ $barocanvas->CanvasBind('<B1-Motion>' , "");
+ $barocanvas->CanvasBind('<1>' , "");
+ FVWausg();
+ $barocanvas->CanvasBind('<B1-Motion>' => \&baroclick);
+ $barocanvas->CanvasBind('<1>' => \&baroclick);
+}
+
+sub zoom {
+ print "zoom()\n" if ($config{'DEBUG'});
+ if ($zoom == 1 || $zoom == 2) {
+ unzoomed ();
+ $zoom=0;
+ if ($task_state == 1) {taskdraw(0);}
+ if ($wpcyl_state == 1) {wpcyldraw(0);}
+ mapplot($dxp, $dyp, $minlat, $minlon,"z");
+ trackplot($dxp, $dyp, $minlat, $minlon);
+ if ($task_state == 1) {taskdraw(1);}
+ if ($wpcyl_state == 1) {wpcyldraw(1);}
+ marksdraw();
+ FVWausg();
+ $zoom = 0;
+ return;
+ }
+
+ if ($zoom == 0) {
+ $zoom=1;
+ ($maxlon, $minlon, $maxlat, $minlat)=GPLIGCfunctions::Ausschnitt2($trackheight, $config{'window_width'}-2, $DECLAT[$nr], $DECLON[$nr], $config{'zoom_sidelength'});
+
+ $delta_lat = $maxlat-$minlat;
+ if ($delta_lat == 0) {$delta_lat = 0.5;}
+ $delta_lon = $maxlon-$minlon;
+ if ($delta_lon == 0) {$delta_lon = 0.5;}
+ $dyp=($delta_lat)/($trackheight-1);
+ $dxp=($delta_lon)/($config{'window_width'}-1);
+
+ if ($task_state == 1) {taskdraw(0);}
+ if ($wpcyl_state == 1) {wpcyldraw(0);}
+ mapplot($dxp, $dyp, $minlat, $minlon,"z");
+ trackplot($dxp, $dyp, $minlat, $minlon);
+ if ($task_state == 1) {taskdraw(1);}
+ if ($wpcyl_state == 1) {wpcyldraw(1);}
+ marksdraw();
+ FVWausg();
+ $zoom=1;
+ }
+}
+
+sub unzoomed {
+ if ($filestat eq 'closed') {
+ return;
+ }
+
+ print "\nunzoomed()\n" if ($config{'DEBUG'});
+
+ ($maxlat, $minlat)=GPLIGCfunctions::MaxKoor(\@DECLAT);
+ ($maxlon, $minlon)=GPLIGCfunctions::MaxKoor(\@DECLON);
+
+ print "\nunzoomed $maxlat $minlat $maxlon $minlon \n" if ($config{'DEBUG'});
+
+ $max_kmdist_x = GPLIGCfunctions::dist($centrey,$minlon,$centrey,$maxlon);
+ $max_kmdist_y = GPLIGCfunctions::dist($minlat,$centrex,$maxlat,$centrex);
+
+ $fvw_side_ratio=$trackheight/($config{'window_width'});
+
+ if ($max_kmdist_x eq 0) { print STDERR "max_kmdist_x == 0, forced to 1\n"; $max_kmdist_x=1;}
+ if ($max_kmdist_y eq 0) { print STDERR "max_kmdist_y == 0, forced to 1\n"; $max_kmdist_y=1;}
+
+ $task_side_ratio=$max_kmdist_y/$max_kmdist_x;
+
+ # x (lon) is limiting
+ if ($task_side_ratio <= $fvw_side_ratio ) {
+
+ $delta_lon = $maxlon-$minlon;
+ if ($delta_lon == 0) {$delta_lon = 0.5;}
+
+ # -3 avoids plotting over the edge (rounding)
+ $dxp = ($delta_lon)/($config{'window_width'}-3); #degrees x per pixel (usually > $dyp)
+ $dyp = $dxp * (cos(deg2rad($centrey))); #degrees y per pixel
+
+ # what the heck subtract was good for?!
+ my $subtract = $dyp * ($trackheight - (($config{'window_width'}) * $task_side_ratio))/2;
+
+ $minlat = $minlat - $subtract;
+ $maxlat = $maxlat + $subtract;
+
+ } else { # y (lat) is limiting
+
+ $delta_lat = $maxlat-$minlat;
+ if ($delta_lat == 0) {$delta_lat = 0.5;}
+
+ $dyp = ($delta_lat)/($trackheight-1); #degrees y per pixel
+ $dxp = $dyp*(1/cos(deg2rad($centrey))); #degrees x per pixel (usually > $dyp)
+
+ my $subtract = $dxp * (($config{'window_width'}) - (($trackheight)/$task_side_ratio))/2;
+
+ $minlon = $minlon - $subtract;
+ $maxlon = $maxlon + $subtract;
+ }
+}
+# end unzoomed
+
+
+sub zoom2 {
+ print "zoom2()\n" if ($config{'DEBUG'});
+ #my $recenter = shift;
+ if (!defined shift) {
+ ($maxlon, $minlon, $maxlat, $minlat)=GPLIGCfunctions::Ausschnitt2($trackheight, $config{'window_width'}-2, $zoomclickcenterx, $zoomclickcentery, $kl2);
+ } else {
+ ($maxlon, $minlon, $maxlat, $minlat)=GPLIGCfunctions::Ausschnitt2($trackheight, $config{'window_width'}-2, $DECLAT[$nr], $DECLON[$nr], $kl2);
+ }
+
+ $delta_lat = $maxlat-$minlat;
+ if ($delta_lat == 0) {$delta_lat = 0.5;}
+ $delta_lon = $maxlon-$minlon;
+ if ($delta_lon == 0) {$delta_lon = 0.5;}
+ $dyp=($delta_lat)/($trackheight-1);
+ $dxp=($delta_lon)/($config{'window_width'}-3);
+
+ if ($task_state == 1) {taskdraw(0);}
+ if ($wpcyl_state == 1) {wpcyldraw(0);}
+
+ $zoom=2;
+ mapplot($dxp, $dyp, $minlat, $minlon,"z");
+ trackplot($dxp, $dyp, $minlat, $minlon);
+
+ if ($task_state == 1) {taskdraw(1);}
+ if ($wpcyl_state == 1) {wpcyldraw(1);}
+ marksdraw();
+
+ FVWausg();
+
+ $zoom=2;
+}
+
+
+sub viewclick {
+ if ($filestat eq 'closed') { return; }
+ my $e = $canvas->XEvent;
+ my ($canvas_x, $canvas_y) = ($e->x, $e->y);
+
+ #print "$canvas_x $canvas_y \n";
+
+ my $lat_click = ($trackheight - $canvas_y) * $dyp + $minlat;
+ my $lon_click = $canvas_x * $dxp + $minlon;
+
+ my $index_of_nearest=1;
+ my $minimum_distance=5000;
+
+ for (my $z=0; $z <= $#DECLAT; $z=$z+$config{'viewclick_res'}) { #increment of 3 is only for saving time (slow machines....)
+ my $actual_dist=GPLIGCfunctions::dist($lat_click, $lon_click, $DECLAT[$z], $DECLON[$z]);
+ if ($actual_dist < $minimum_distance) {
+ $minimum_distance = $actual_dist;
+ $index_of_nearest = $z;
+ }
+ }
+
+ $nr=$index_of_nearest;
+ FVWausg($index_of_nearest);
+}
+
+
+sub zoomdrag {
+ if ($filestat eq 'closed') { return; }
+ my $e = $canvas->XEvent;
+ my ($canvas_x, $canvas_y) = ($e->x, $e->y);
+ if (@zoomrubber) {$canvas -> delete (@zoomrubber);}
+ @zoomrubber=();
+ push(@zoomrubber, $canvas->createRectangle($zoompressedX, $zoompressedY, $canvas_x, $canvas_y, -outline=>"black"));
+
+ if ($config{'DEBUG'}) {print "$zoompressedX $zoompressedY $canvas_x $canvas_y\n";}
+}
+
+
+sub zoompress {
+ if ($filestat eq 'closed') { return; }
+ my $e = $canvas->XEvent;
+ my ($canvas_x, $canvas_y) = ($e->x, $e->y);
+ $zoompressedX = $canvas_x;
+ $zoompressedY = $canvas_y;
+}
+
+
+sub zoomrelease {
+ if ($filestat eq 'closed') { return; }
+ my $e = $canvas->XEvent;
+ my ($canvas_x, $canvas_y) = ($e->x, $e->y);
+ if (@zoomrubber){$canvas -> delete (@zoomrubber);}
+ if ( (($zoompressedX - $canvas_x) == 0) || (($zoompressedY - $canvas_y) == 0) ) {
+ return;
+ }
+
+ my $lat_rel = ($trackheight - $canvas_y) * $dyp + $minlat;
+ my $lon_rel = $canvas_x * $dxp + $minlon;
+
+ my $lat_click = ($trackheight - $zoompressedY) * $dyp + $minlat;
+ my $lon_click = $zoompressedX * $dxp + $minlon;
+
+ my $zoomareasideratio = abs($zoompressedY - $canvas_y) / abs($zoompressedX - $canvas_x);
+ my $canvassideratio = $canvas->Height / $canvas->Width;
+
+ if ($config{'DEBUG'}) {
+ print "Release: $lat_rel $lon_rel Click: $lat_click $lon_click\n";
+ print "zoomarea $zoomareasideratio: ";
+ print "landscape \n" if ($zoomareasideratio <= 1);
+ print "portrait\n" if ($zoomareasideratio > 1);
+ print "canvas $canvassideratio\n";
+ }
+
+ $zoomclickcenterx = ($lat_rel + $lat_click) / 2;
+ $zoomclickcentery = ($lon_rel + $lon_click) / 2;
+
+ $kl2 = GPLIGCfunctions::dist($zoomclickcenterx, $lon_click, $zoomclickcenterx, $lon_rel);
+
+ if ($zoomareasideratio <= $canvassideratio) {
+ print "Selection is more landscape than window\n" if ($config{'DEBUG'});
+ }
+
+ if ($zoomareasideratio > $canvassideratio) {
+ print "Selection is more portrait than window: $kl2\n" if ($config{'DEBUG'});
+ $kl2 *= $zoomareasideratio;
+ print "$kl2\n" if ($config{'DEBUG'});
+ $kl2 /= $canvassideratio;
+ print "$kl2\n" if ($config{'DEBUG'});
+
+ }
+
+ ## test, ob pointer in neuem ausschnitt liegt...
+ my $TEST = 'OUT';
+
+ my ($maxlonT, $minlonT, $maxlatT, $minlatT)=GPLIGCfunctions::Ausschnitt2($trackheight, $config{'window_width'}-2, $zoomclickcenterx, $zoomclickcentery, $kl2);
+
+ my $dypT=($maxlatT-$minlatT)/($trackheight-1);
+ my $dxpT=($maxlonT-$minlonT)/($config{'window_width'}-1);
+
+ my $xT= int(($DECLON[$nr]-$minlonT)/$dxpT);
+ my $yT= int($trackheight-(($DECLAT[$nr]-$minlatT)/$dypT));
+
+ if ($xT > 0 && $xT < $config{'window_width'}-1) {
+ if ($yT > 0 && $yT < $trackheight) {
+ $TEST = 'INSIDE';
+ }
+ }
+
+ ########
+ if ($TEST eq 'OUT') {
+ my $index_of_nearest=1;
+ my $minimum_distance=5000;
+
+ for (my $z=0; $z <= $#DECLAT; $z=$z+3) { #increment of 3 is only for saving time (slow machines....)
+
+ my $actual_dist=GPLIGCfunctions::dist($zoomclickcenterx, $zoomclickcentery, $DECLAT[$z], $DECLON[$z]);
+
+ if ($actual_dist < $minimum_distance) {
+ $minimum_distance = $actual_dist;
+ $index_of_nearest = $z;
+ }
+ }
+
+ $nr=$index_of_nearest;
+
+ #print "nummer $nr \n";
+ }
+
+ zoom2();
+}
+
+sub FVWresize {
+
+ if ($config{'DEBUG'}){
+ print "\n\nFVWresize()\n";
+ print "config{'window_height'}=$config{'window_height'} \n";
+ print "config{'window_width'}=$config{'window_width'} \n";
+ my $cfw=$canvas->width;
+ my $cfh=$canvas->height;
+ my $bch=$barocanvas->height;
+ my $cffh=$canvas_frame->height;
+ print "canvas w = $cfw \n";
+ print "canvas h = $cfh \n";
+ print "baroconvh = $bch \n";
+ print "canv_fra_h = $cffh \n";
+ }
+
+ if (($config{'window_width'} != $canvas_frame->width) || ($config{'window_height'} != $canvas_frame->height)) {
+
+ #print "resize $config{'window_width'} ->".$canvas->width."\n";
+
+ $config{'window_width'} = $canvas_frame->width;
+ $config{'window_height'} = $canvas_frame->height;
+
+ print "canvas_frame size is: $config{'window_width'} x $config{'window_height'} \n" if ($config{'DEBUG'});
+
+ $baroheight = int (( ($config{'window_height'}) / $config{'fvw_baro_fraction'})+0.5)-2;
+ $trackheight = int (( (1-(1/$config{'fvw_baro_fraction'}))*$config{'window_height'} )+0.5)-2;
+
+ # fix for rounding error!
+ if ( ($baroheight+$trackheight) - $canvas_frame->height == -3) {
+ $baroheight--;
+ }
+
+ #$trackheight = int (((2*$canvas_frame->height) / 3)+0.5)-2;
+
+ # canvas will be two pixel larger than requested!
+ # therefore we request smalle (-2)
+ $barocanvas->configure(-width=>$config{'window_width'}-2, -height=>$baroheight, -scrollregion=>[0,0,$config{'window_width'}-2,$baroheight]);
+ $canvas->configure(-width=>$config{'window_width'}-2, -height=>$trackheight, -scrollregion=>[0,0,$config{'window_width'}-2,$trackheight]);
+
+ if ($config{'DEBUG'}) {
+ print "baroheight=$baroheight, trackheight=$trackheight sum=".($baroheight+$trackheight)."\n";
+ }
+
+ #
+ if ($config{'DEBUG'}){
+ $canvas->delete(@debugboxlist);
+ @debugboxlist=();
+ push(@debugboxlist, $canvas->createLine(0,$trackheight-1,$config{'window_width'}-3,$trackheight-1 ,-fill=>"red"));
+ push(@debugboxlist, $canvas->createLine($config{'window_width'}-3,0,$config{'window_width'}-3, $trackheight, -fill=>"red"));
+ push(@debugboxlist, $canvas->createLine(0,0,0,$trackheight,-fill=>"red"));
+ push(@debugboxlist, $canvas->createLine(0,0,$config{'window_width'}-3,0, -fill=>"red"));
+
+ $barocanvas->delete(@debugboxlist);
+ push(@debugboxlist, $barocanvas->createLine(0,$baroheight-1,$config{'window_width'}-3,$baroheight-1 ,-fill=>"green"));
+ push(@debugboxlist, $barocanvas->createLine($config{'window_width'}-3,0,$config{'window_width'}-3, $baroheight-1, -fill=>"green"));
+ push(@debugboxlist, $barocanvas->createLine(0,0,0,$baroheight-1,-fill=>"green"));
+ push(@debugboxlist, $barocanvas->createLine(0,0,$config{'window_width'}-3,0, -fill=>"green"));
+ } else {
+ $barocanvas->delete(@debugboxlist);
+ $canvas->delete(@debugboxlist);
+ }
+
+ baroplot();
+
+ if ($zoom == 1) {
+ ($maxlon, $minlon, $maxlat, $minlat)=GPLIGCfunctions::Ausschnitt2($trackheight, $config{'window_width'}, $DECLAT[$nr], $DECLON[$nr], $config{'zoom_sidelength'});
+ }
+
+ if ($zoom == 2) {
+ ($maxlon, $minlon, $maxlat, $minlat)=GPLIGCfunctions::Ausschnitt2($trackheight, $config{'window_width'}, $DECLAT[$nr], $DECLON[$nr], $kl2);
+ }
+
+ if ($filestat eq 'closed') {return;}
+
+ $delta_lat = $maxlat-$minlat;
+ if ($delta_lat == 0) {$delta_lat = 0.5;}
+ $delta_lon = $maxlon-$minlon;
+ if ($delta_lon == 0) {$delta_lon = 0.5;}
+
+ $dyp=($delta_lat)/($trackheight-1);
+ $dxp=($delta_lon)/($config{'window_width'}-3);
+
+ if ($zoom ==0) {unzoomed();}
+
+ mapplot($dxp, $dyp, $minlat, $minlon,"z");
+ trackplot($dxp, $dyp, $minlat, $minlon);
+
+ if ($task_state == 1) {taskdraw(0);taskdraw(1);}
+ if ($wpcyl_state == 1) {wpcyldraw(0);wpcyldraw(1);}
+ marksdraw();
+
+ FVWausg();
+ } else {
+ print "nothing to resize\n" if ($config{'DEBUG'});
+ }
+}
+
+
+# this function plots the markerlines (crosshair and vertical line in baroview)
+# and updates info-text
+# wraps $nr if needed and changes shown area if marker outside
+sub FVWausg {
+ if ($filestat eq 'closed') {
+ return 0;
+ }
+ if (!Exists($FlightView)) {return;}
+
+# print "FVWausg ---------\n" if ($config{'DEBUG'});
+
+ #$SIG{'USR2'} = IGNORE;
+
+ # falls ein Wert uebergeben wird uebergeben wird...
+ # otherwise $nr is used as in global scope
+
+# print "FVWausg nr before $nr\n" if ($config{'DEBUG'});
+ if (@_ >= 1) {
+ $nr = shift;
+ }
+
+ # wrap, if outside of range
+ if ($nr > $#LAT-1){$nr=0;}
+ if ($nr < 0) {$nr=$#LAT-1;}
+
+ print "FVWausg($nr) ----------- \n" if ($config{'DEBUG'});
+
+ # OLD Code, maybe reactivated later
+# if ($^O ne "MSWin32") {
+# if (defined $oGLePID) {
+# if (kill 0, $oGLePID) {
+# if (defined $shm_id) {
+#
+# # if we havnt got sigusr2 from openGLIGCexplorer (FVWausg called from "inside-event")
+# if ($sigusr2flag == 0){
+#
+# #write data in SysV IPC shared memory
+# shmwrite($shm_id, pack("i", $nr) , 0, 4) || print "Error writing Shared Memory (SysV IPC)\n";
+#
+# #send USR1 to explorer (update signal)
+# system("kill -USR1 $oGLePID");
+# } else {
+#
+# #print "Got SIGUSR2 from somewere... need to read shmem block here...\n";
+# shmread($shm_id, $getfromshmem, 0, 4) || print "Error reading Shared Memory (SysV IPC)\n";
+# $nr = unpack("i", $getfromshmem);
+#
+# #print "GPLIGC: $nr gelesen von shmem\n";
+# $sigusr2flag=0;
+# }
+# }
+# }
+# }
+# }
+
+ # formatted strings for output
+ my $speed = sprintf("%.0f",$nonISPEED[$nr]*$config{'speed_unit_factor'});
+ my $aspeed = sprintf("%.0f",$IAS[$nr]*$config{'speed_unit_factor'});
+
+ # in GPS-mode IVARIO arrays are swapped with GPS arrays
+ my $vario = sprintf("%.2f", $nonIVARIO[$nr]*$config{'vertical_speed_unit_factor'});
+ my $intvario = sprintf("%.2f", $IVARIO[$nr]*$config{'vertical_speed_unit_factor'});
+ my $compvario = sprintf("%.2f", $compVARIO[$nr]*$config{'vertical_speed_unit_factor'});
+
+ my $htime=GPLIGCfunctions::time2human($TIME[$nr],'t');
+
+ if ($config{'DEBUG'}){
+ $htime .= " (index: $nr)";
+ }
+
+ my $dist_towp = 0;
+ my $bear_towp= 0;
+ my $wp_name="-";
+
+ if ($MAXWP >= 1) {
+ $dist_towp=sprintf("%.2f",GPLIGCfunctions::dist($DECLAT[$nr],$DECLON[$nr],$WPLAT[$AKTWP],$WPLON[$AKTWP])*$config{'distance_unit_factor'});
+ $bear_towp= int (GPLIGCfunctions::kurs($DECLAT[$nr], $DECLON[$nr], $WPLAT[$AKTWP], $WPLON[$AKTWP]) + 0.5);
+
+ if (length($bear_towp) == 2 ) { $bear_towp = "0".$bear_towp; }
+ if (length($bear_towp) == 1 ) { $bear_towp = "00".$bear_towp; }
+ $wp_name=$WPNAME[$AKTWP];
+ } else {
+ $dist_towp ="-"; $bear_towp="-";
+ }
+
+ my $heading = int(GPLIGCfunctions::kurs($DECLAT[$nr], $DECLON[$nr], $DECLAT[$nr+1], $DECLON[$nr+1]) + 0.5);
+ if (length($heading) == 2) {$heading="0".$heading;}
+ if (length($heading) == 1) {$heading="00".$heading;}
+
+ my $format_lat=GPLIGCfunctions::coorconvert($DECLAT[$nr],'lat',$config{'coordinate_print_format'});
+ my $format_lon=GPLIGCfunctions::coorconvert($DECLON[$nr],'lon',$config{'coordinate_print_format'});
+
+ # in GPS-Mode BARO is swapped with GPSALT
+ my $alt = sprintf("%.0f",$config{'altitude_unit_factor'}*$BARO[$nr]);
+ my $gpsalt = sprintf("%.0f",$config{'altitude_unit_factor'}*$GPSALT[$nr]);
+ $gpsalt = sprintf("%.0f(%.0f)",$config{'altitude_unit_factor'}*$GPSALT[$nr],$config{'altitude_unit_factor'}*$VXA[$nr]) if ($VXAEXISTS eq "yes" && $config{'draw_accuracy'});
+ my $press = sprintf("%.1f",GPLIGCfunctions::pressure($BARO[$nr],$gpi{'qnh'}));
+ my $opress = sprintf("%.1f",GPLIGCfunctions::pressure($BARO[$nr],$gpi{'qnh'})*0.20942);
+
+ my $altmode_txt = "Baro";
+ if ($altmode eq "gps") {$altmode_txt="GPS-Altitude";}
+
+ my $pressline="";
+
+ if ($gpi{'qnh'} != 0) {
+ $pressline=sprintf(" QNH (hPa): %.0f Pressure altitude: %.0f $config{'altitude_unit_name'}",$gpi{'qnh'},$config{'altitude_unit_factor'}*(GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($BARO[$nr],$gpi{'qnh'}),1013.25)));
+ }
+
+ $fvwtext = "Coordinates: $format_lat $format_lon Time (UTC): $htime No.: $nr $altmode_txt: $alt $config{'altitude_unit_name'} GPS: $gpsalt $config{'altitude_unit_name'}\nPressure $press hPa pO2 $opress hPa$pressline\n";
+ $fvwtext.= "Groundspeed: $speed $config{'speed_unit_name'} Airspeed: $aspeed $config{'speed_unit_name'} Heading: $heading";
+
+ if ($SIUEXISTS eq "yes") {
+ $fvwtext .= " Sats used: $SIU[$nr]";
+ }
+ if ($FXAEXISTS eq "yes") {
+ $fvwtext.=" Acc.Hor: ".(int($FXA[$nr]*$config{'altitude_unit_factor'}))." [$config{'altitude_unit_name'}]";
+ }
+ if ($VXAEXISTS eq "yes") {
+ $fvwtext.=" Acc.Vert: ".(int($VXA[$nr]*$config{'altitude_unit_factor'}))." [$config{'altitude_unit_name'}]";
+ }
+
+ $fvwtext.="\n";
+ $fvwtext.="Vario: $vario $config{'vertical_speed_unit_name'} int.Vario: $intvario $config{'vertical_speed_unit_name'} TEcompVario: $compvario $config{'vertical_speed_unit_name'}\n";
+ $fvwtext.="To $wp_name: $dist_towp $config{'distance_unit_name'} , $bear_towp";
+
+ if ($config{'maps'}) {
+ $fvwtext.=", Map zoomlevel/Tiles: $zl / $tiles";
+ }
+
+ if ($altmode eq "gps") { $fvwtext.="\nGPS-Altitude modus!";}
+
+ $canvas->delete($horizontal, $vertical);
+ $barocanvas->delete($barovertical);
+
+ if ($FXAEXISTS eq "yes" ) {
+ if (@acc_lines) {$canvas->delete(@acc_lines);}
+ @acc_lines = ();
+ }
+
+ my $x= int(($DECLON[$nr]-$minlon)/$dxp);
+ my $y= int($trackheight-(($DECLAT[$nr]-$minlat)/$dyp));
+ my $xbaro = int($nr/$dxbaro);
+
+ if ($cut_track == 1 && !($stat_start == 0 && $stat_end == $#BARO) && $stat_end > $stat_start) {
+ $xbaro = int(($nr-$stat_start)/$dxbaro);
+ }
+
+ #drawing lines (horizontal/vertical)
+ $horizontal=$canvas->createLine(0,$y,$config{'window_width'},$y,-fill=>"navy blue");
+ $vertical=$canvas->createLine($x,0,$x,$trackheight,-fill=>"navy blue");
+ $barovertical = $barocanvas->createLine($xbaro,0,$xbaro,$baroheight,-fill=>"navy blue");
+
+ #draw accuracy circle if wanted
+ if ($FXAEXISTS eq "yes" && $config{'draw_accuracy'}) {
+
+ my ($cylref_lat, $cylref_lon) = GPLIGCfunctions::zylinder2( $DECLAT[$nr], $DECLON[$nr], ($FXA[$nr]/1000), 0, 359.99999);
+
+ for (my $xzaehl=0; $xzaehl<=$#$cylref_lat-1; $xzaehl++) {
+
+ my $x1= int( ( ($DECLON[$nr]+${$cylref_lon}[$xzaehl]) -$minlon) /$dxp);
+ my $x2= int( ( ($DECLON[$nr]+${$cylref_lon}[$xzaehl+1]) -$minlon) /$dxp);
+ my $y1= int($trackheight-( ( ($DECLAT[$nr]+${$cylref_lat}[$xzaehl]) -$minlat )/$dyp));
+ my $y2= int($trackheight-( ( ($DECLAT[$nr]+${$cylref_lat}[$xzaehl+1]) -$minlat )/$dyp));
+ push(@acc_lines, $canvas->createLine( $x1, $y1, $x2, $y2,-width=>1,-fill=>"navy blue"));
+ }
+
+ }
+
+# if ($config{'DEBUG'}) {
+# if ($x > $config{'window_width'} || $x < 0) { print "X is outside range ($x)!\n";}
+# if ($y > $trackheight || $y <0) { print "Y is outside range ($y)!\n";}
+# }
+
+ if ($x > $config{'window_width'} || $x < 0) { if ($zoom==2) {zoom2(1);} else {$zoom=0; zoom(); } return; }
+ if ($y > $trackheight || $y <0) {if ($zoom==2) {zoom2(1);} else {$zoom=0; zoom(); } return; }
+
+
+#$SIG{'USR2'} = sub {$sigusr2flag=1; print "sigusr2 got... (FVW)\n"; FVWausg();$FlightView->update;};
+
+}
+
+#############################################################################
+
+sub WpPlot {
+
+ #WPPlotWindow already exists?
+ if (Exists($WPPlotWindow)) {$WPPlotWindow->destroy;}
+
+ if ($filestat eq 'closed') {$FlightView->bell; return;}
+ $WPPlotWindow=$FlightView->Toplevel();
+ $WPPlotWindow->configure(-title=>"Task Editor");
+
+ setexit($WPPlotWindow);
+
+ my $pltb2d=$WPPlotWindow->Button(-text=>"plot 2D",-command=>sub{
+
+ if ($MAXWP > 0) {
+ zylinder($WPLAT[$AKTWP],$WPLON[$AKTWP],$config{'zylinder_radius'}*($WPRADFAC[$AKTWP]+0.000000000001),"1000");
+ $com1="plot";
+ $com2="\'${pfadftmp}zyl.dat\' title \"Zylinder"."($config{'zylinder_radius'}*$WPRADFAC[$AKTWP]) $WPNAME[$AKTWP] "."\" with lines, \'${pfadftmp}3d.dat\' title \"Flightpath\" ".$config{'gnuplot_draw_style'};
+ Ausgabe("2d");
+ $xmin = $xmax = $ymin = $ymax = $zmax = ''; $zmin = 0;
+ }
+ });
+
+ $pltb2d->pack(-fill=>"x");
+
+ my $pltb3d=$WPPlotWindow->Button(-text=>"plot 3D",-command=>sub{
+
+ if ($MAXWP > 0 ) {
+ zylinder($WPLAT[$AKTWP],$WPLON[$AKTWP],$config{'zylinder_radius'}*($WPRADFAC[$AKTWP]+0.000000000001),"1000");
+ $com1="splot";
+ $com2="\'${pfadftmp}zyl.dat\' title \"Zylinder"."($config{'zylinder_radius'}*$WPRADFAC[$AKTWP]) $WPNAME[$AKTWP]"."\" with dots, \'${pfadftmp}3d.dat\' using (\$1):(\$2):(\$3*0) title \"Groundtrack\" ".$config{'gnuplot_draw_style'}.", \'${pfadftmp}3d.dat\' title \"Flightpath\" ".$config{'gnuplot_draw_style'};
+ Ausgabe("3d");
+ $xmin = $xmax = $ymin = $ymax = $zmax = ''; $zmin = 0;
+ }
+ });
+
+ $pltb3d->pack(-fill=>"x");
+
+ $myWPN=$WPNAME[$AKTWP];
+ $myWPRF=$WPRADFAC[$AKTWP]; # WP Radius Factor local var
+ $wppwlat=GPLIGCfunctions::coorconvert($WPLAT[$AKTWP],'lat',$config{'coordinate_print_format'});
+ $wppwlon=GPLIGCfunctions::coorconvert($WPLON[$AKTWP],'lon',$config{'coordinate_print_format'});
+
+ my $wpframe=$WPPlotWindow->Frame();
+ my $LB=$wpframe->Button(-text=>'<<',-command=>sub{
+ if ($MAXWP > 0) {
+ $WPRADFAC[$AKTWP]=$myWPRF;
+ $AKTWP--;
+ if ($AKTWP==0) {$AKTWP++;}
+ $myWPN=$WPNAME[$AKTWP];
+ $myWPRF=$WPRADFAC[$AKTWP];
+ $wppwlat=GPLIGCfunctions::coorconvert($WPLAT[$AKTWP],'lat',$config{'coordinate_print_format'});
+ $wppwlon=GPLIGCfunctions::coorconvert($WPLON[$AKTWP],'lon',$config{'coordinate_print_format'});
+ FVWausg();
+ TaskUpdate();
+ }
+ });
+
+ my $WPANZ=$wpframe->Label(-textvariable=>\$AKTWP);
+ my $RB=$wpframe->Button(-text=>'>>',-command=>sub{
+ if ($MAXWP > 0) {
+ $WPRADFAC[$AKTWP]=$myWPRF;
+ $AKTWP++;
+ if ($AKTWP>$MAXWP) {$AKTWP--;}
+ $myWPN=$WPNAME[$AKTWP];
+ $myWPRF=$WPRADFAC[$AKTWP];
+ $wppwlat=GPLIGCfunctions::coorconvert($WPLAT[$AKTWP],'lat',$config{'coordinate_print_format'});
+ $wppwlon=GPLIGCfunctions::coorconvert($WPLON[$AKTWP],'lon',$config{'coordinate_print_format'});
+ FVWausg();
+ TaskUpdate();
+ }
+ });
+
+ $LB->pack(-expand=>"yes",-side=>"left",-fill=>"x");
+ $WPANZ->pack(-side=>"left",-fill=>"x");
+
+ $RB->pack(-expand=>"yes",-side=>"left",-fill=>"x");
+
+ $wpframe->pack(-expand=>"yes",-fill=>"x");
+
+ my $wpndf=$WPPlotWindow->Label(-textvariable=>\$myWPN);
+
+ my $rfframe=$WPPlotWindow->Frame();
+
+ my $WPRFl=$rfframe->Label(-text=>"Radius factor");
+ my $WPRF=$rfframe->Entry(-textvariable=>\$myWPRF);
+ $wpndf->pack(-fill=>"x");
+
+ $WPRFl->pack(-expand=>"yes",-side=>"left",-fill=>"x");
+ $WPRF->pack(-expand=>"yes",-side=>"left",-fill=>"x");
+ $rfframe->pack(-fill=>"x");
+
+ my $coor_lat=$WPPlotWindow->Label(-textvariable=>\$wppwlat);
+ my $coor_lon=$WPPlotWindow->Label(-textvariable=>\$wppwlon);
+ $coor_lat->pack(-fill=>"x");
+ $coor_lon->pack(-fill=>"x");
+
+ my $savebut=$WPPlotWindow->Button(-text=>"Save Task (.tsk)",-command=>sub{
+ save_tsk();
+ })->pack(-fill=>"x");
+
+ my $delbut=$WPPlotWindow->Button(-text=>"Delete Waypoint",-command=>sub{
+ if ($MAXWP > 0) {
+ $MAXWP--;
+
+ #removes 1 element at $AKTWP!
+ splice @WPNAME, $AKTWP, 1;
+ splice @WPLAT, $AKTWP, 1;
+ splice @WPLON, $AKTWP, 1;
+
+ #if task changed since optimization loose ability to olc-file output
+ undef $olcFirstWPindex;
+ $optimized_for = "none";
+
+ if ($AKTWP > $MAXWP) {
+ $AKTWP--;
+ }
+
+ if ($AKTWP == 0) {
+ $AKTWP++;
+ $myWPN="All Waypoints deleted";
+ $wppwlat='-';
+ $wppwlon='-';
+ $freeWP = 1;
+ } else {
+ $myWPN=$WPNAME[$AKTWP];
+ $wppwlat=GPLIGCfunctions::coorconvert($WPLAT[$AKTWP],'lat',$config{'coordinate_print_format'});
+ $wppwlon=GPLIGCfunctions::coorconvert($WPLON[$AKTWP],'lon',$config{'coordinate_print_format'});
+ }
+
+ print "No of WPs (maxwp): $MAXWP // Actual WP (aktwp): $AKTWP // Size of array (\$#WPLAT): $#WPLAT \n" if ($config{'DEBUG'});
+
+ FVWausg();
+ FSupdate();
+ TaskUpdate();
+ baroplot();#_task();
+ }
+ })->pack(-fill=>"x");
+
+ my $last_first=$WPPlotWindow->Button(-text=>"Set last point same as first",-command=>sub{
+ if ($MAXWP == 0) {return;}
+ push @WPNAME, $WPNAME[1];
+ push @WPLAT, $WPLAT[1];
+ push @WPLON, $WPLON[1];
+ $MAXWP++;
+
+ #if task changed since optimization loose ability to olc-file output
+ undef $olcFirstWPindex;
+ $optimized_for = "none";
+
+ FSupdate();
+ TaskUpdate();
+
+ });
+
+ $last_first->pack(-fill=>"x");
+
+ #-----------------------------------
+
+ # THE REAL OPTIMIZATION
+ # using the cpp program optimizer....
+
+ my $optiV3=$WPPlotWindow->Button(-text=>"Optimize for OLC-Classic 10/2007", -command=>sub{ optimizer("olc-class"); })->pack(-fill=>"x");
+ my $optiV3a=$WPPlotWindow->Button(-text=>"Optimize for OLC-Fai 10/2007", -command=>sub{ optimizer("olc-fai"); })->pack(-fill=>"x");
+ my $optiV4=$WPPlotWindow->Button(-text=>"Optimize for DMSt 2006", -command=>sub{ optimizer("dmst"); })->pack(-fill=>"x");
+ my $optiV5=$WPPlotWindow->Button(-text=>"Optimize for OLC-Phg 3/2007", -command=>sub{ optimizer("olc-phg"); })->pack(-fill=>"x");
+
+ my $exb=$WPPlotWindow->Button(-text=>"Exit",-command=>sub{$WPPlotWindow->destroy();});
+ $exb->pack(-fill=>"x");
+
+}
+
+########################################
+
+# this function updates the variables for output in WpPlotWindow
+sub WPPlotUpdate {
+
+ #print "$myWPN $wppwlat $wppwlon\n";
+
+ $myWPN=$WPNAME[$AKTWP];
+ $myWPRF=$WPRADFAC[$AKTWP];
+ $wppwlat=GPLIGCfunctions::coorconvert($WPLAT[$AKTWP],'lat',$config{'coordinate_print_format'});
+ $wppwlon=GPLIGCfunctions::coorconvert($WPLON[$AKTWP],'lon',$config{'coordinate_print_format'});
+
+ #print "$myWPN $wppwlat $wppwlon\n";
+
+}
+
+#####################################################################################
+
+sub Ausschnitt {
+
+ use Math::Trig;
+
+ my ($lat, $lon) = @_;
+ my $halbkilometer=0.004496608;
+
+ $xmin=$lon-($config{'zoom_sidelength'}*$halbkilometer*(1/cos(deg2rad($lat))));
+ $xmax=$lon+($config{'zoom_sidelength'}*$halbkilometer*(1/cos(deg2rad($lat))));
+ $ymin=$lat-($config{'zoom_sidelength'}*$halbkilometer);
+ $ymax=$lat+($config{'zoom_sidelength'}*$halbkilometer);
+}
+
+################################################################################
+
+sub TaskUpdate {
+ if (Exists($FlightView)) {
+ if ($task_state == 1) { taskdraw(0); taskdraw(1);}
+ if ($wpcyl_state == 1) { wpcyldraw(0); wpcyldraw(1); }
+ }
+}
+
+###################### elevation calibration
+
+sub elevationcalibration {
+
+ my $caltype= shift;
+ my $elevation = shift;
+ my $nx = shift;
+ my $initflag = shift; # =1 for initial call (file opening) to avoid trackplot
+
+
+ if (!defined $elevation) { Errorbox("cancelled");
+ return;
+ }
+
+
+ if ($caltype eq "constant"){
+ my $delta = $BARO[$nx] - ($elevation/$config{'altitude_unit_factor'});
+ $offset -= int($delta+.5);
+
+ for (my $z=0; $z <= $#BARO; $z++) {
+ $BARO[$z] -= $delta;
+ }
+
+ $minbaro -= $delta;
+ $maxbaro -= $delta;
+
+ $gpi{'altitude_calibration_type'}=$caltype;
+ $gpi{'altitude_calibration_point'}=$nx;
+ $gpi{'altitude_calibration_point_alt'}=$elevation;
+ }
+
+ if ($caltype eq "baro") {
+
+ my $p0 = GPLIGCfunctions::referencepressure($BARO[$nx], GPLIGCfunctions::pressure($elevation,$gpi{'qnh'}) );
+
+ for (my $z=0; $z <= $#BARO; $z++) {
+ $BARO[$z] = GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($BARO[$z],$p0),$gpi{'qnh'});
+ }
+
+ $offset = -int(($minbaro - GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($minbaro,$p0),$gpi{'qnh'}))+.5);
+ $minbaro = GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($minbaro,$p0),$gpi{'qnh'});
+ $maxbaro = GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($maxbaro,$p0),$gpi{'qnh'});
+
+ $gpi{'altitude_calibration_type'}=$caltype;
+ $gpi{'altitude_calibration_point'}=$nx;
+ $gpi{'altitude_calibration_point_alt'}=$elevation;
+ }
+
+ if (Exists($FlightView)){
+ updateFVW() if (!$initflag);
+ }
+
+ tmpfileout();
+ FSupdate();
+}
+
+#################################
+
+sub calibrationinput {
+
+ if ($gpi{'altitude_calibration_type'} ne "none") { Errorbox("applying another calibration may result in weird effects!");}
+
+ my $input=$FlightView->Toplevel();
+ my $elevation=0;
+ my $caltype ="baro";
+ $input->configure(-title=>"Elevation input");
+
+ my $eleframe=$input->Frame()->pack();
+ my $radfr=$input->Frame()->pack;
+ my $bfr=$input->Frame()->pack();
+
+ $eleframe->Label(-text=> "Elevation at selected point ($config{'altitude_unit_name'})")->pack(-side=>"left");
+ $eleframe->Entry(-textvariable=>\$elevation)->pack(-side=>"right");
+
+ $radfr->Radiobutton(-text=>"constant shift",-variable=>\$caltype,-value=>"constant")->pack();
+ $radfr->Radiobutton(-text=>"barometric",-variable=>\$caltype,-value=>"baro")->pack();
+
+ $bfr->Button(-text=>"OK",-command=>sub{
+ $input->destroy();
+ elevationcalibration($caltype, $elevation, $nr, 0);
+ })->pack(-side=>"left");
+ $bfr->Button(-text=>"cancel",-command=>sub{
+ $input->destroy();
+ undef $elevation;
+ return; # back to nix
+ })->pack(-side=>"right");
+
+ $input -> waitWindow;
+}
+
+sub qnhcalibration {
+
+ if ($gpi{'altitude_calibration_type'} ne "none") { Errorbox("applying another calibration may result in weird effects!");}
+ #qnhcalibrationinput();
+ my $newqnh=shift;
+ my $newrefp=shift;
+ my $initflag = shift;
+
+ if ($newqnh < 800 || $newqnh >1200) { Errorbox("cancelled");
+ return;
+ }
+
+ $gpi{'qnh'}=$newqnh;
+
+ #my $pressdiff = 1013.25 - $gpi{'qnh'};
+
+ if ($newqnh != 0 && $newrefp != 0) {
+
+ for (my $z=0; $z <= $#BARO; $z++) {
+ $BARO[$z] = GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($BARO[$z],$newrefp),$newqnh);
+ }
+
+ $offset = -int(($minbaro - GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($minbaro,$newrefp),$newqnh))+.5);
+ $minbaro = GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($minbaro,$newrefp),$newqnh);
+ $maxbaro = GPLIGCfunctions::altitude(GPLIGCfunctions::pressure($maxbaro,$newrefp),$newqnh);
+
+ $gpi{'altitude_calibration_type'}="refpress";
+ $gpi{'altitude_calibration_ref_press'}=$newrefp;
+ }
+
+ tmpfileout();
+ if (Exists($FlightView)){
+ updateFVW() if (!$initflag);
+ }
+ FSupdate();
+
+ ##########################################
+
+}
+
+sub qnhcalibrationinput {
+ my $input=$FlightView->Toplevel();
+ my $newqnh=$gpi{'qnh'};
+ my $newrefp=0;
+
+ $input->configure(-title=>"Pressure calibration");
+
+ my $eleframe=$input->Frame()->pack();
+ my $elevf2=$input->Frame()->pack();
+ my $bfr=$input->Frame()->pack();
+
+ $eleframe->Label(-text=> "QNH (hPa)")->pack(-side=>"left");
+ $eleframe->Entry(-textvariable=>\$newqnh)->pack(-side=>"right");
+ $elevf2->Label(-text=> "Reference pressure of logged altitude (hPa)")->pack(-side=>"left");
+ $elevf2->Entry(-textvariable=>\$newrefp)->pack(-side=>"right");
+
+ $bfr->Button(-text=>"OK",-command=>sub{
+ $input->destroy();
+ qnhcalibration($newqnh,$newrefp,0);
+ return;
+ })->pack(-side=>"left");
+ $bfr->Button(-text=>"cancel",-command=>sub{
+ $input->destroy();
+ return;
+ })->pack(-side=>"right");
+
+ $input -> waitWindow;
+}
+
+########################################
+
+sub statistik {
+
+ my ($start, $end) = @_;
+
+ if ($start >= $end) {Errorbox("Endpoint (F6) is before Startpoint (F5) - swapping"); my $tmp = $start; $start = $end; $end = $tmp;}
+ if ($start == $end) {Errorbox("Start (F5) and end (F6) are the same!"); return;}
+
+ my $delta_h = $BARO[$end]-$BARO[$start];
+ my $delta_h_unit = $delta_h;
+
+ my $delta_t = $DECTIME[$end]-$DECTIME[$start];
+ my $delta_th = GPLIGCfunctions::dec2time($delta_t);
+ my $climb = ( ($delta_h/1000) / $delta_t) / 3.6;
+ my $time = GPLIGCfunctions::time2human($TIME[$start],'t')."-".GPLIGCfunctions::time2human($TIME[$end],'t');
+
+ $delta_h_unit *= $config{'altitude_unit_factor'};
+ $climb *= $config{'vertical_speed_unit_factor'};
+
+ my($ofilename, $odirectories, $osuffix) = File::Basename::fileparse($file);
+ my $message = "File: $ofilename\n";
+
+ $message .= sprintf("Time: $time\nTime: $delta_th\nAltitude difference: $delta_h_unit $config{'altitude_unit_name'} \nClimb rate: %.1f $config{'vertical_speed_unit_name'}", $climb );
+
+ my $distance = GPLIGCfunctions::dist($DECLAT[$start], $DECLON[$start], $DECLAT[$end], $DECLON[$end]);
+ my $speed = $distance / $delta_t;
+ my $glide;
+ if ($delta_h != 0) {$glide = ($distance*1000) / -$delta_h;} else {$glide = 9999;}
+
+ $distance *= $config{'distance_unit_factor'};
+ $speed *= $config{'speed_unit_factor'};
+
+ $message .= sprintf("\nDistance: %.1f $config{'distance_unit_name'} \nSpeed: %.0f $config{'speed_unit_name'}", $distance, $speed);
+ $message .= sprintf("\nGlide ratio: %.1f", $glide);
+
+ my $head = GPLIGCfunctions::kurs($DECLAT[$start], $DECLON[$start], $DECLAT[$end], $DECLON[$end]);
+
+ $message .= sprintf("\nCourse: %.0f",$head);
+
+ my $cum_dist =0;
+ my $cum_climb = 0;
+ my $cum_sink = 0;
+
+ my %wind;
+ my %windcount;
+ my @minval=(0);
+ my @maxval=(0);
+ my @mink=(0);
+ my @maxk=(0);
+
+ for (my $z=$start; $z<$end; $z++) {
+ $cum_dist += GPLIGCfunctions::dist($DECLAT[$z], $DECLON[$z], $DECLAT[$z+1], $DECLON[$z+1]);
+ $cum_climb += $BARO[$z+1]-$BARO[$z] if ($BARO[$z+1]-$BARO[$z] > 0);
+ $cum_sink += $BARO[$z+1]-$BARO[$z] if ($BARO[$z+1]-$BARO[$z] < 0);
+
+ my $diff = $IAS[$z] - (($nonISPEED[$z]+$nonISPEED[$z+1])/2) ;
+
+ my $kurs = GPLIGCfunctions::kurs($DECLAT[$z-1], $DECLON[$z-1], $DECLAT[$z+1], $DECLON[$z+1]);
+ my $roundk = int($kurs+0.5);
+
+ $wind{$roundk} += $diff;
+ $windcount{$roundk} ++;
+ }
+
+ foreach $key (keys %wind) {
+ if ($windcount{$key} > 1) {$wind{$key} = $wind{$key}/$windcount{$key}}
+ }
+
+ open (WIND,">${pfadftmp}wind.dat");
+ for (my $z=0;$z<=361;$z++) {
+ if (exists($wind{$z})) {print WIND "$z $wind{$z}\n";}
+ }
+ close(WIND);
+
+ if ($config{'wind_analysis'}) {
+ $com1="f(x)=a*sin((x/57.29578)+(-b/57.29578))+c \na=150\nb=45\nc=-100\n g(x) = c \n fit f(x) \'${pfadftmp}wind.dat\' via a,b,c \n set ylabel \"airspeed - groundspeed [$config{'speed_unit_name'}]\" \n set xlabel \"direction \" \n set xrange [0:360]\n";
+ $com1.= "set label 1 \"offset = %.1f km/h\",c at graph 0.02, graph 0.95 \n";
+ $com1.= "set label 2 \"amplitude = %.1f km/h\",a at graph 0.02, graph 0.90\n";
+ $com1.= "set label 3 \"direction = %.1f\",b+90 at graph 0.02, graph 0.85\n plot ";
+ $com2="\'${pfadftmp}wind.dat\' using (\$1):(\$2*$config{'speed_unit_factor'}) title \"windplot from last f5f6f7\" ".$config{'gnuplot_draw_style'}.",f(x), g(x) \n print \"Speed offset: \", c,\" km/h\"\n print \"Maxima \", b+90, \" grad\"\n print \"Speed \", a, \" km/h\"";
+ Ausgabe("2d");
+ }
+
+ $message .= sprintf("\nCumulated climb: %.0f $config{'altitude_unit_name'}", $cum_climb * $config{'altitude_unit_factor'});
+ $message .= sprintf("\nCumulated sink: %.0f $config{'altitude_unit_name'}", $cum_sink * $config{'altitude_unit_factor'});
+ $message .= sprintf("\nCumulated distance: %.1f $config{'distance_unit_name'}", $cum_dist * $config{'distance_unit_factor'});
+
+ my $speed_cum_dist = $cum_dist / $delta_t;
+
+ my $glideratio_cum = 77777; # just big for div/0
+ if ($delta_h != 0) {$glideratio_cum = ($cum_dist * 1000 ) / -$delta_h}
+ $message .= sprintf("\nSpeed : %.0f $config{'speed_unit_name'}", $speed_cum_dist * $config{'speed_unit_factor'});
+ $message .= sprintf("\nGlide ratio cumulated distance: %.1f", $glideratio_cum);
+
+ MessageFenster("Statistic", $message);
+}
+
+########################################
+
+sub thermik_statistik {
+
+ @thermal_start_time_index = ();
+ my @thermal_end_time_index = ();
+ my @circled=();
+ my @circled_abs =();
+
+ # default values for thermal search
+ my $circles = 2; #how many circles needed
+ my $steps = 3;
+ my $heading_delta = 15;
+
+ my $in_thermal = 'no';
+ my $in_counter = 0;
+ my $out_counter = 0;
+ my $circle_sum_abs = 0;
+ my $circle_sum = 0;
+ my $tmp_start_index = 0;
+
+ for (my $z= $task_start_time_index; $z < $task_finish_time_index; $z++) {
+
+ my $k_alt = GPLIGCfunctions::kurs($DECLAT[$z-1], $DECLON[$z-1], $DECLAT[$z], $DECLON[$z]);
+ my $k_new = GPLIGCfunctions::kurs($DECLAT[$z], $DECLON[$z], $DECLAT[$z+1], $DECLON[$z+1]);
+ my $k_delta = $k_alt-$k_new;
+
+ if (abs($k_delta) > 180) {
+
+ #print "***";
+ if ($k_delta < 0) {$k_delta += 360;} else {$k_delta -= 360;}
+ }
+
+ $circle_sum_abs += abs($k_delta);
+ $circle_sum += $k_delta;
+
+ if ($in_thermal eq 'no') {
+
+ #print "out\n";
+ if (abs($k_delta) < $heading_delta) { $in_counter=0; $circle_sum=0; $circle_sum_abs=0;}
+ if (abs($k_delta) > $heading_delta) { $in_counter++;}
+ if ($in_counter== $steps) {$in_thermal='yes'; $tmp_start_index = $z - $steps;}
+ }
+
+ if ($in_thermal eq 'yes') {
+
+ #print "in\n";
+ if (abs($k_delta) > $heading_delta) { $out_counter=0; }
+ if (abs($k_delta) < $heading_delta) { $out_counter++;}
+
+ if ($out_counter == $steps) {
+ $in_thermal = 'no';
+ $in_counter=0;
+
+ #print "summe ==== $circle_sum\n";
+
+ if (abs($circle_sum_abs) > ($circles*360)) {
+ push (@thermal_start_time_index, $tmp_start_index);
+ push (@thermal_end_time_index, $z - $steps);
+ push (@circled_abs, $circle_sum_abs);
+ push (@circled, $circle_sum);
+
+ #print "thermal !!!!!!!!!\n";
+ }
+
+ $circle_sum=0; $circle_sum_abs=0;
+ }
+ }
+
+ }
+
+ if (Exists($thermal_statistik)) {$thermal_statistik->destroy;}
+
+ $thermal_statistik=$FlightView->Toplevel();
+ $thermal_statistik->configure(-title=>"Thermals");
+ setexit($thermal_statistik);
+
+ $therm_list_box = $thermal_statistik->ScrlListbox(-label=>"Thermals", -selectmode=>"single",-height=>"0",-width=>"0")->pack(-side=>"left");
+ $therm_list_box->bind("<Double-Button-1>" => \&therm_click);
+
+ my $total_climb_alt = 0;
+ my $total_climb_t = 0;
+ my $thermal_stat_text = '';
+
+ my($ofilename, $odirectories, $osuffix) = File::Basename::fileparse($file);
+ $thermal_stat_text .= "File: $ofilename\n";
+
+ my $thermal_r = 0;
+ my $thermal_l = 0;
+ my $thermal_lr = 0;
+ my $best = 0;
+ my $worst = 10;
+
+ for (my $z=0; $z<= $#thermal_start_time_index; $z++) {
+
+ my $list_zeile='';
+ $list_zeile .= GPLIGCfunctions::time2human($TIME[$thermal_start_time_index[$z]],'t')."-".GPLIGCfunctions::time2human($TIME[$thermal_end_time_index[$z]],'t')." ";
+
+ $list_zeile .= GPLIGCfunctions::dec2time($DECTIME[$thermal_end_time_index[$z]] - $DECTIME[$thermal_start_time_index[$z]])." ";
+
+ my $circles = $circled[$z] / 360;
+ my $circles_abs = $circled_abs[$z] / 360;
+
+ $list_zeile .= sprintf (" %3.0f", $circles_abs);
+
+ if ( abs(abs($circles)-$circles_abs) < 1 ) {
+ if ($circles < 0) {$list_zeile .= "R "; $thermal_r++;}
+ if ($circles > 0) {$list_zeile .= "L "; $thermal_l++;}
+ } else {
+
+ $list_zeile .= "R/L";
+ $thermal_lr++;
+
+ #print "$circles $circles_abs\n";
+
+ }
+
+ my $delta_h = $BARO[$thermal_end_time_index[$z]] - $BARO[$thermal_start_time_index[$z]];
+
+ $total_climb_alt += $delta_h;
+ my $delta_t = $DECTIME[$thermal_end_time_index[$z]] - $DECTIME[$thermal_start_time_index[$z]];
+
+ $total_climb_t += $delta_t;
+ my $climb_rate = ( ($delta_h/1000) / $delta_t) / 3.6;
+
+ if ($climb_rate < $worst) {$worst = $climb_rate;}
+ if ($climb_rate > $best) {$best = $climb_rate;}
+
+ $list_zeile .= sprintf (" %4.0f $config{'altitude_unit_name'} %2.1f $config{'vertical_speed_unit_name'}", $delta_h*$config{'altitude_unit_factor'}, $climb_rate*$config{'vertical_speed_unit_factor'});
+
+ #print $list_zeile."\n";
+
+ $therm_list_box->insert("end", $list_zeile);
+ }
+
+ #statistics window:
+ my $statw_tot_alt = sprintf("%.0f",$total_climb_alt*$config{'altitude_unit_factor'});
+ $thermal_stat_text .= "Total height climbed in circles: $statw_tot_alt $config{'altitude_unit_name'}\n";
+ my $total_climb_rate = (($total_climb_alt/1000) / $total_climb_t) / 3.6;
+ $total_climb_rate *= $config{'vertical_speed_unit_factor'};
+ $thermal_stat_text .= sprintf ("Average climb rate: %.2f $config{'vertical_speed_unit_name'}\n", $total_climb_rate);
+
+ my $circling = $total_climb_t / ($DECTIME[$task_finish_time_index] - $DECTIME[$task_start_time_index]) *100;
+ $thermal_stat_text .= sprintf ("Circling: %.1f", $circling)."\%\n";
+
+ $thermal_stat_text .= sprintf("Best: %.2f $config{'vertical_speed_unit_name'}\nWorst: %.2f $config{'vertical_speed_unit_name'}\n", $best*$config{'vertical_speed_unit_factor'}, $worst*$config{'vertical_speed_unit_factor'});
+
+ my $left_perc = $thermal_l / ($thermal_l+$thermal_r+$thermal_lr) * 100;
+ my $right_perc = $thermal_r / ($thermal_l+$thermal_r+$thermal_lr) * 100;
+ my $leftright_perc = $thermal_lr / ($thermal_l+$thermal_r+$thermal_lr) * 100;
+ $thermal_stat_text .= "# of thermals: ".($thermal_l+$thermal_r+$thermal_lr)."\n";
+ $thermal_stat_text .= sprintf ("Thermals left: %.0f", $left_perc)."\% ($thermal_l)\n";
+ $thermal_stat_text .= sprintf ("Thermals right: %.0f", $right_perc)."\% ($thermal_r)\n";
+ $thermal_stat_text .= sprintf ("Thermals left and right: %.0f", $leftright_perc)."\% ($thermal_lr)\n";
+
+ if ( $thermal_l+$thermal_r+$thermal_lr > 0) {
+ MessageFenster("Thermal statistics", $thermal_stat_text);
+ } else {
+ if (Exists($thermal_statistik)) {$thermal_statistik->destroy;}
+ Errorbox ("No thermals found");
+ }
+
+ sub therm_click {
+
+ #my $sel=$therm_list_box->curselection();
+ #$nr = $thermal_start_time_index[@$sel[0]];
+ #FVWausg($thermal_start_time_index[@$sel[0]]);
+ my @sel=$therm_list_box->curselection();
+ if (defined $sel[0]) {
+ $nr = $thermal_start_time_index[$sel[0]];
+ FVWausg($thermal_start_time_index[$sel[0]]);
+ }
+ }
+
+}
+
+########################################
+
+sub glide_statistik {
+
+ @glide_start_time_index = ();
+ my @glide_end_time_index = ();
+ my @glide_head = ();
+ my @glide_speed = ();
+ my @glide_dist=();
+
+ # default values for glide search
+
+ my $steps = 5;
+ my $heading_delta = 10;
+ my $min_km = 3; #min km
+
+ my $in_thermal = 'yes';
+ my $in_counter = 0;
+ my $out_counter = 0;
+ my $tmp_start_index = 0;
+
+ for (my $z= $task_start_time_index; $z < $task_finish_time_index; $z++) {
+
+ #print "$z \n";
+
+ my $k_alt = GPLIGCfunctions::kurs($DECLAT[$z-1], $DECLON[$z-1], $DECLAT[$z], $DECLON[$z]);
+ my $k_new = GPLIGCfunctions::kurs($DECLAT[$z], $DECLON[$z], $DECLAT[$z+1], $DECLON[$z+1]);
+ my $k_delta = $k_alt-$k_new;
+
+ if (abs($k_delta) > 180) {
+
+ #print "***";
+ if ($k_delta < 0) {$k_delta += 360;} else {$k_delta -= 360;}
+ }
+
+ if ($in_thermal eq 'no') {
+
+ #print "out\n";
+ if (abs($k_delta) < $heading_delta) { $in_counter=0; }#$circle_sum=0; $circle_sum_abs=0;
+ if (abs($k_delta) > $heading_delta) { $in_counter++;}
+ if ($in_counter== $steps) {
+ $in_thermal='yes';
+ if (GPLIGCfunctions::dist($DECLAT[$z-$steps], $DECLON[$z-$steps], $DECLAT[$tmp_start_index], $DECLON[$tmp_start_index]) > $min_km) {
+ push (@glide_start_time_index, $tmp_start_index);
+ push (@glide_end_time_index, $z - $steps);
+ push (@glide_head, GPLIGCfunctions::kurs($DECLAT[$tmp_start_index], $DECLON[$tmp_start_index], $DECLAT[$z-$steps], $DECLON[$z-$steps]));
+ my $speed = GPLIGCfunctions::dist($DECLAT[$z-$steps], $DECLON[$z-$steps], $DECLAT[$tmp_start_index], $DECLON[$tmp_start_index]) /
+ ($DECTIME[$z-$steps]-$DECTIME[$tmp_start_index]);
+ push (@glide_speed, $speed);
+
+ push (@glide_dist, GPLIGCfunctions::dist($DECLAT[$z-$steps], $DECLON[$z-$steps], $DECLAT[$tmp_start_index], $DECLON[$tmp_start_index]));
+ }
+ }
+ }
+
+ if ($in_thermal eq 'yes') {
+
+ #print "in\n";
+ if (abs($k_delta) > $heading_delta) { $out_counter=0; }
+ if (abs($k_delta) < $heading_delta) { $out_counter++;}
+ if ($out_counter == $steps) {
+ $in_thermal = 'no';
+ $in_counter=0;
+ $tmp_start_index = $z - $steps;
+ }
+ }
+ }
+
+ # wenn gleitstrecke ohne kurve endet (direkte landung zB)
+ if ($in_thermal eq 'no') {
+ if (GPLIGCfunctions::dist($DECLAT[$task_finish_time_index], $DECLON[$task_finish_time_index], $DECLAT[$tmp_start_index], $DECLON[$tmp_start_index]) > $min_km) {
+ push (@glide_start_time_index, $tmp_start_index);
+ push (@glide_end_time_index, $task_finish_time_index);
+ push (@glide_head, GPLIGCfunctions::kurs($DECLAT[$tmp_start_index], $DECLON[$tmp_start_index], $DECLAT[$task_finish_time_index], $DECLON[$task_finish_time_index]));
+ my $speed = GPLIGCfunctions::dist($DECLAT[$task_finish_time_index], $DECLON[$task_finish_time_index], $DECLAT[$tmp_start_index], $DECLON[$tmp_start_index]) /
+ ($DECTIME[$task_finish_time_index]-$DECTIME[$tmp_start_index]);
+ push (@glide_speed, $speed);
+
+ push (@glide_dist, GPLIGCfunctions::dist($DECLAT[$task_finish_time_index], $DECLON[$task_finish_time_index], $DECLAT[$tmp_start_index], $DECLON[$tmp_start_index]));
+
+ #print "Glide found !!!!!!! @ $TIME[$tmp_start_index]\n";
+ }
+ }
+
+ if (Exists($glide_statistik)) {$glide_statistik->destroy;}
+ $glide_statistik=$FlightView->Toplevel();
+ $glide_statistik->configure(-title=>"Glide");
+ setexit($glide_statistik);
+
+ $glide_list_box = $glide_statistik->ScrlListbox(-label=>"Glide", -selectmode=>"single",-height=>"0",-width=>"0")->pack(-side=>"left");
+ $glide_list_box->bind("<Double-Button-1>" => \&glide_click);
+
+ my $total_glide_alt = 0;
+ my $total_glide_t = 0;
+ my $total_glide_dist = 0;
+ my $glide_stat_text = '';
+
+ my($ofilename, $odirectories, $osuffix) = File::Basename::fileparse($file);
+ $glide_stat_text .= "File: $ofilename\n";
+
+ for (my $z=0; $z<= $#glide_start_time_index; $z++) {
+ my $list_zeile='';
+ $list_zeile .= GPLIGCfunctions::time2human($TIME[$glide_start_time_index[$z]],'t')."-".GPLIGCfunctions::time2human($TIME[$glide_end_time_index[$z]],'t')." ";
+
+ my $delta_h = $BARO[$glide_end_time_index[$z]] - $BARO[$glide_start_time_index[$z]];
+ $total_glide_alt += $delta_h;
+ my $delta_t = $DECTIME[$glide_end_time_index[$z]] - $DECTIME[$glide_start_time_index[$z]];
+
+ $list_zeile .= GPLIGCfunctions::dec2time($delta_t)." ";
+
+ $total_glide_t += $delta_t;
+ my $climb_rate = ( ($delta_h/1000) / $delta_t) / 3.6;
+
+ $list_zeile .= sprintf (" %4.0f $config{'altitude_unit_name'} %.2f $config{'vertical_speed_unit_name'} ", $delta_h*$config{'altitude_unit_factor'}, $climb_rate*$config{'vertical_speed_unit_factor'});
+
+ #print $list_zeile."\n";
+ $total_glide_dist += $glide_dist[$z];
+
+ $list_zeile .= sprintf ("%.0f $config{'speed_unit_name'} %.1f $config{'distance_unit_name'} %.0f", $glide_speed[$z]*$config{'speed_unit_factor'}, $glide_dist[$z]*$config{'distance_unit_factor'}, $glide_head[$z]);
+
+ my $tempdev = ($delta_h / 1000);
+ $tempdev=0.00000001 if ($tempdev==0);
+ my $gleitzahl = -1 * $glide_dist[$z] / $tempdev;
+
+ $list_zeile .= sprintf(" %.0f", $gleitzahl);
+
+ $glide_list_box->insert("end", $list_zeile);
+
+ }
+
+ #statistics window:
+ if ($total_glide_t != 0) { # if this is 0, there are no glides at all
+ my $durchschn_glide_speed = $total_glide_dist / $total_glide_t;
+ my $p_tot_gl = sprintf("%.0f",$total_glide_alt*$config{'altitude_unit_factor'});
+
+ $glide_stat_text .= "Total glide height : $p_tot_gl $config{'altitude_unit_name'}\n";
+ $glide_stat_text .= sprintf("Total glide distance : %.2f $config{'distance_unit_name'}\n",$total_glide_dist*$config{'distance_unit_factor'});
+ $glide_stat_text .= sprintf("Average glide speed: %.0f $config{'speed_unit_name'}\n", $durchschn_glide_speed*$config{'speed_unit_factor'});
+
+ MessageFenster("Glide statistics", $glide_stat_text);
+ } else {
+ if (Exists($glide_statistik)) {$glide_statistik->destroy;}
+ Errorbox("No glides found");
+ }
+
+ sub glide_click {
+ my @sel=$glide_list_box->curselection();
+
+ #print "$sel --->".@$sel[0]."<-x- \n";
+ #foreach (@$sel) {
+ # print "<-- $_ --> \n";
+ # }
+ if (defined $sel[0]) {
+ $nr = $glide_start_time_index[$sel[0]];
+ FVWausg($glide_start_time_index[$sel[0]]);
+ }
+ }
+
+}
+
+#####################################
+
+sub MessageFenster {
+ my ($head, $message) = @_;
+
+ my $MF=$FlightView->Toplevel();
+ $MF->configure(-title=>$head);
+
+ setexit($MF);
+
+ my $label=$MF->Message(-width=>"60c",-textvariable=>\$message);
+ $label->pack();
+
+ my $exb=$MF->Button(-text=>"Exit",-command=>sub{$MF->destroy();});
+ $exb->pack();
+}
+
+##################################
+
+sub save_config {
+
+ print "\nGoing to write the configuration file...\n" if ($config{'DEBUG'});
+
+ if ($^O ne "MSWin32") {
+
+ # unix systems:
+ open (RC, ">$ENV{'HOME'}/.gpligcrc") || die "cannot write configfile";
+ } else {
+
+ # windows system, with environmentvariable GPLIGCHOME
+ if (defined $ENV{'GPLIGCHOME'}) {
+
+ # if writable
+ if ( (-f "$ENV{'GPLIGCHOME'}\\gpligc.ini" && -w "$ENV{'GPLIGCHOME'}\\gpligc.ini")
+ || (!-f "$ENV{'GPLIGCHOME'}\\gpligc.ini" && -w $ENV{'GPLIGCHOME'}) ) {
+
+ open (RC, ">$ENV{'GPLIGCHOME'}\\gpligc.ini") || die "cannot write $ENV{'GPLIGCHOME'}\\gpligc.ini";
+ } else {
+ Errorbox("Can't write configfile!");
+ return;
+ }
+ } else {
+ Errorbox( "GPLIGCHOME Environment variable is not defined. Cannot save config!");
+ return;
+ }
+ }
+
+ print "Writing configuration to file...\n" if ($config{'DEBUG'});
+
+ # write the configfile
+ my $count = 0;
+ foreach $key (sort(keys %config)) {
+
+ print "$key \"$config{$key}\" \n" if ($config{'DEBUG'});
+ print RC "$key \"$config{$key}\" \n";
+ $count++;
+ }
+
+ close RC;
+
+ print "$count parameters written....\n\n" if ($config{'DEBUG'});
+
+}
+
+sub save_gpi {
+ my $gpifile = substr($file, 0, -3)."gpi";
+ open(GP,">$gpifile") || die "$gpifile cannot be written";
+
+ print "Writing gpi to file...\n" if ($config{'DEBUG'});
+
+ my $count = 0;
+ foreach $key (sort(keys %gpi)) {
+ print "$key \"$gpi{$key}\" \n" if ($config{'DEBUG'});
+ print GP "$key \"$gpi{$key}\" \n";
+ $count++;
+ }
+
+ close GP;
+ print "$count parameters written....\n\n" if ($config{'DEBUG'});
+}
+
+sub save_tsk {
+ my $tskfile = substr($file, 0, -3)."tsk";
+ open(GP,">$tskfile") || die "$tskfile cannot be written";
+
+ print "Writing task to file \"$tskfile\"\n" if ($config{'DEBUG'});
+
+ for ($i=1; $i<=$#WPNAME; $i++){
+
+ print "\"$WPNAME[$i]\" $WPLAT[$i] $WPLON[$i] $WPRADFAC[$i]\n" if ($config{'DEBUG'});
+ print GP "\"$WPNAME[$i]\" $WPLAT[$i] $WPLON[$i] $WPRADFAC[$i]\n";
+
+ }
+ close GP;
+}
+
+
+########################################
+
+# get rid of old config file in 1.10!
+sub load_config {
+
+ my $configfile ;
+ my $no_tk = shift;
+
+ print "\nGoing to read the configuration file...\n" if ($config{'DEBUG'});
+
+ # determine name and path for configfile
+
+ # unix platforms
+ if ($^O ne "MSWin32") {
+ $configfile = "$ENV{'HOME'}/.gpligcrc";
+
+ # test old one
+ if (!-r $configfile) {
+ $configfile = "$ENV{'HOME'}/.GPLIGCrc";
+ if (!-r $configfile) {return;}
+ }
+
+ # and windows platforms
+ } else {
+
+ my $gpligchome;
+ if (defined $ENV{'GPLIGCHOME'}) { $gpligchome = $ENV{'GPLIGCHOME'}; }
+ else { $gpligchome = ".";}
+
+ $configfile = "$gpligchome\\GPLIGC.ini";
+
+ if (!-r $configfile) {
+ $configfile = "$gpligchome\\GPLIGCrc";
+ if (!-r $configfile) {return;}
+ }
+
+ }
+
+ # open the configfile and check size
+ open (RC, "<$configfile") || die "cannot read $configfile";
+ my @test = <RC>; close RC;
+
+ print "Size of $configfile is $#test lines \n" if ($config{'DEBUG'});
+
+ # Version 1.4 has 17 options....
+ # and since 1.5 we have more
+ if ($#test <= 17) {
+
+ # do not use "Errorbox" in windows active perl/Tk 800.024
+ my $warn = 1;
+ if ($^O eq "MSWin32") {
+ if ($Tk::VERSION eq "800.024") { $warn=0;}
+ }
+ if (defined $no_tk) {$warn=0;}
+
+# strangely this causes hanging main loop on some active perl implementations...?
+
+ if ($warn) {
+ Errorbox ("The configuration file ($configfile) is not in the right format for GPLIGC $version \nIt is probably from an older version.\nUse the \"save configuration\"-option to create a new one, or delete the old one.");
+ } else {
+ print "The configuration file ($configfile) is not in the right format for GPLIGC $version \nIt is probably from an older version.\nUse the \"save configuration\"-option to create a new one, or delete the old one.\n";
+ }
+
+ #return;
+ }
+
+ open (RC, "<$configfile") || die "cannot open $configfile";
+ my @in = ();
+ @in = <RC>;
+ close RC;
+
+ my $count = 0;
+ foreach (@in) {
+ if ($_ =~ /(\w+)\s+\"(.*?)\"/) { $count++;}
+
+ print "$1=\"$2\" \n" if ($config{'DEBUG'});
+ $config{$1} = $2;
+ }
+ print "$count parameters read.\n\n" if ($config{'DEBUG'});
+
+ # legacy code to deal with old config files.
+ $config{'zylinder_radius'} = 0.2 if ($config{'zylinder_radius'} eq "200m");
+ $config{'zylinder_radius'} = 0.3 if ($config{'zylinder_radius'} eq "300m");
+ $config{'zylinder_radius'} = 0.4 if ($config{'zylinder_radius'} eq "400m");
+ $config{'zylinder_radius'} = 0.5 if ($config{'zylinder_radius'} eq "500m");
+ $config{'zylinder_radius'} = 1.0 if ($config{'zylinder_radius'} eq "1km");
+
+
+}
+
+sub load_gpi {
+ my $gpifile = substr($file, 0, -3)."gpi";
+ if (-r $gpifile) {open(GP,"<$gpifile") || die "cannot read $gpifile";} else {Errorbox("$gpifile cannot be read"); return;}
+
+ my @in = ();
+ @in = <GP>;
+ close GP;
+
+ my $count = 0;
+ foreach (@in) {
+ if ($_ =~ /(\w+)\s+\"(.*?)\"/) { $count++;}
+
+ print "$1= >>$2<< \n" if ($config{'DEBUG'});
+ $gpi{$1} = $2;
+ }
+ print "$count parameters read.\n\n" if ($config{'DEBUG'});
+}
+
+########################################
+
+
+# this sets exit bindings q, esacpe for given widget
+sub setexit {
+
+ my $widget = shift;
+
+ $widget->bind("<Key-q>",sub {$widget->destroy();});
+ $widget->bind("<Escape>",sub {$widget->destroy();});
+
+}
+
+###########################################
+
+sub optimizer {
+
+ my $contest = shift;
+ my $optimizer_cmd;
+ my @scoring;
+
+ my $optimizer_cycles;
+ $optimizer_cycles = $config{'optimizer_cycles_sa'} if ($config{'optimizer_method'} eq "sa");
+ $optimizer_cycles = $config{'optimizer_cycles_mmc'} if ($config{'optimizer_method'} eq "mmc");
+
+ if ($contest eq "olc-class") { # this is olc-calssic rules 10/2007 see optimizer
+ #$optimizer_cmd = "-delta 1000 -w 7 -p 1 1 1 1 0.8 0.6";
+ $optimizer_cmd = "-olc-class -w 7 -p 1 1 1 1 0.8 0.6";
+ @scoring = (1, 1, 1, 1, 0.8, 0.6);
+
+ #print "$#scoring \n";
+ }
+
+ if ($contest eq "olc-fai") { # this is olc-calssic rules 10/2007 see optimizer
+ #$optimizer_cmd = "-delta 1000 -w 7 -p 1 1 1 1 0.8 0.6";
+ $optimizer_cmd = "-olc-fai -w 5 -p 1 1 1 1";
+ @scoring = (1, 1, 1, 1);
+
+ #print "$#scoring \n";
+ }
+
+ if ($contest eq "dmst") { # rules 2005 ?, see optimizer
+ $optimizer_cmd = "-dmst -w 5 -p 1 1 1 1";
+ @scoring = (1, 1, 1, 1);
+
+ #print "$#scoring \n";
+ }
+
+ if ($contest eq "olc-phg"){ # rules 3/2008 ? see optimizer
+ $optimizer_cmd = "-holc -w 5 -p 1.5 1.5 1.5 1.5";
+ @scoring = (1.5, 1.5, 1.5, 1.5);
+ }
+
+ if ($config{'optimizer_debug'}) {
+ $optimizer_cmd .= " -debug ";
+ }
+
+ if ($config{'optimizer_verbose'}) {
+ $optimizer_cmd .= " -v ";
+ }
+
+ #check if optimizer is in path:
+ if (system("optimizer")) {Errorbox("Can't execute the \"optimizer\". Check installation.");
+ return;
+ }
+
+ $optimizer_cmd .= " $config{'optimizer_mmc'} " if ($config{'optimizer_method'} eq "mmc");
+ $optimizer_cmd .= " $config{'optimizer_sa'} " if ($config{'optimizer_method'} eq "sa");
+
+ $busy = $FlightView->Busy;
+ $busy2 = $WPPlotWindow->Busy;
+
+ #$busy_fvw = $FlightView->Busy if (Exists($FlightView));
+
+ if ($contest eq "olc-phg"){
+ if ($BARO[$task_start_time_index] - $BARO[0] > 762.195) { # 2500ft
+ my $delta = ($BARO[$task_start_time_index]-$BARO[0])*$config{'altitude_unit_factor'};
+ Errorbox("WARNING: Altitude difference between take-off location and release point: "
+ . "$delta $config{'altitude_unit_name'}. This violates 4.5 in DHV Online contest Rules for 2005 (Rel. 1.5)".
+ " in the case you were towed by an UL. According to 4.5 winch launching seems to be OK.");
+ }
+ }
+
+ #progress bar!
+ require Tk::ProgressBar;
+ my $progresswindow = $FlightView->Toplevel();
+ $progresswindow->configure(-title=>"Optimization progress");
+ my $leer;
+
+ # using the -variable is a workaround for some small bug in ProgressBar
+ my $progress = $progresswindow -> ProgressBar(-width=>20, -length=>400, -blocks=>1,
+ -anchor=>'w',-from=>0,-to=>$optimizer_cycles,-variable=>\$leer, -colors=>[0, "blue"],- troughcolor=>"grey") ->pack;
+
+ my @optwpindex=();
+ my @Points=();
+ my @Dist=();
+ for (my $t=0; $t<=$optimizer_cycles; $t++) { ##########TO CHANGE NUMBER OF CYCLES######!!!
+ $optwpindex[$i]=GPLIGCfunctions::retArrayRef();
+ }
+
+ for (my $i=0 ; $i<=$optimizer_cycles; $i++){ #########################################!!!
+ my $seed = int (rand 1000000)+1;
+ my $optimizeout = `optimizer $optimizer_cmd -c 1 -f $task_start_time_index -l $task_finish_time_index -d $pfadftmp/3d.dat -s $seed`;
+
+ if ($config{'DEBUG'}) {
+ print "optimizer $optimizer_cmd -c 1 -f $task_start_time_index -l $task_finish_time_index -d $pfadftmp/3d.dat -s $seed\n";
+ print "$optimizeout";
+ }
+
+ if ($#scoring == 5) {
+ $optimizeout =~ /\s*(\d+)\s+(\d+\.?\d*)\s+(\d+\.?\d*)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
+ $MAXWP = $1;
+ $Points[$i] = $3;
+ $Dist[$i] = $2;
+ @{$optwpindex[$i]} = ($4, $5, $6, $7, $8, $9, $10);
+ }
+
+ if ($#scoring == 2) {
+ $optimizeout =~ /\s*(\d+)\s+(\d+\.?\d*)\s+(\d+\.?\d*)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
+ $MAXWP = $1;
+ $Points[$i] = $3;
+ $Dist[$i] = $2;
+
+ #print "$MAXWP \n";
+ @{$optwpindex[$i]} = ($4, $5, $6, $7);
+ }
+
+ if ($#scoring == 3) {
+
+ #print "$optimizeout \n";
+ $optimizeout =~ /\s*(\d+)\s+(\d+\.?\d*)\s+(\d+\.?\d*)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
+ $MAXWP = $1;
+ $Points[$i] = $3;
+ $Dist[$i] = $2;
+
+ #print "$MAXWP \n";
+ @{$optwpindex[$i]} = ($4, $5, $6, $7, $8);
+
+ #print "$2, $3, $4, $5, $6, $7, $8 \n";
+ }
+
+ $progress->value($i);
+ $progresswindow->update;
+
+ #print "cycle $i punkte $Points[$i] \n";
+
+ }
+
+ $progresswindow->destroy();
+
+ my $entf=0;
+ my $pkt=0;
+ my $punkteMax=0;
+ my $punkteMaxIndex;
+
+ for (my $j=0; $j<=$optimizer_cycles; $j++) {
+ $pkt=0;
+ $pkt = $Points[$j];
+
+ if ($pkt > $punkteMax) {
+ $punkteMax= $pkt;
+ $punkteMaxIndex=$j;
+ }
+ }
+
+ # put optimized task in task variables
+ @WPNAME=();
+ @WPLAT=();
+ @WPLON=();
+ for (my $i=1; $i<=$MAXWP; $i++) {
+ $WPNAME[$i]="WP".($i);
+ $WPLAT[$i]=$DECLAT[${$optwpindex[$punkteMaxIndex]}[$i-1]];
+ $WPLON[$i]=$DECLON[${$optwpindex[$punkteMaxIndex]}[$i-1]];
+ }
+
+ # needed for calculation of Abflugzeit und Wertundsendezeit
+ $olcLastWPindex=${$optwpindex[$punkteMaxIndex]}[6] if ($contest eq "olc-class");
+ $olcLastWPindex=${$optwpindex[$punkteMaxIndex]}[4] if ($contest eq "dmst");
+ $olcLastWPindex=${$optwpindex[$punkteMaxIndex]}[4] if ($contest eq "olc-phg");
+ $olcFirstWPindex=${$optwpindex[$punkteMaxIndex]}[0];
+
+ $optimized_for = $contest;
+
+ WPPlotUpdate();
+
+ $entf = sprintf ("%4.2f",$Dist[$punkteMaxIndex]);
+ $pkt = sprintf ("%4.2f",$Points[$punkteMaxIndex]);
+
+ my ($mess2) = olctaskinfo();
+ my $mess = "Optimization ($contest) result: $entf km $pkt points\n\n".$mess2;
+
+ MessageFenster ("Optimization Results", $mess);
+
+ $busy = $FlightView->Unbusy;
+ $busy2 = $WPPlotWindow->Unbusy;
+
+ #$busy_fvw = $FlightView->Unbusy if (Exists($FlightView));
+
+ FSupdate();
+ TaskUpdate();
+ baroplot();#_task();
+
+}
+
+######### END OPTIMIZER ##################################
+
+# this is experimental for windows version, only
+
+sub ReadLogger {
+
+ if (Exists($LoggerWindow)) {return;}
+
+ $LoggerWindow=$FlightView->Toplevel();
+ $LoggerWindow->configure(-title=>"Read Logger");
+
+ # testing...
+ $lcommand_options="-pANY"; #-d$config{'working_directory'}";
+ # -d$config{'working_directory'} ?gehts bei allen, -pANY bei allen?
+ # options-menu, add COM select?
+
+ my $cam2=$LoggerWindow->Button(-text=>"Camebridge 2",-command=>sub{
+ $lcommand="datacam2";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $cam=$LoggerWindow->Button(-text=>"Camebridge",-command=>sub{
+ $lcommand="data-cam";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $ewa=$LoggerWindow->Button(-text=>"Ewa",-command=>sub{
+ $lcommand="data-ewa";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $gcs=$LoggerWindow->Button(-text=>"Gcs",-command=>sub{
+ $lcommand="data-gcs";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $lxn=$LoggerWindow->Button(-text=>"LX",-command=>sub{
+ $lcommand="data-lxn";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $pes=$LoggerWindow->Button(-text=>"Peschges",-command=>sub{
+ $lcommand="data-pes";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $prt=$LoggerWindow->Button(-text=>"prt",-command=>sub{
+ $lcommand="data-prt";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $sch=$LoggerWindow->Button(-text=>"sch",-command=>sub{
+ $lcommand="data-sch";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $sdi=$LoggerWindow->Button(-text=>"SDI",-command=>sub{
+ $lcommand="data-sdi";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $zan=$LoggerWindow->Button(-text=>"Zander",-command=>sub{
+ $lcommand="data-zan";
+ exReader();
+ })->pack(-fill=>"x");
+
+ my $exb=$LoggerWindow->Button(-text=>"Exit",-command=>sub{$LoggerWindow->destroy();})->pack(-fill=>"x");
+
+ # execute the reader
+ sub exReader {
+ system("start $lcommand $lcommand_options");
+ }
+
+}
+
+sub getWPreachedIndices {
+ my @wpindex = ();
+ my @wpnames = ();
+
+ if ($MAXWP > 0) {
+ my $loopstart=1;
+ for (my $z=1; $z <= $MAXWP; $z++) {
+
+ my $limit = $config{'zylinder_radius'};
+
+ for (my $x=$loopstart; $x <= $#DECLAT; $x++) {
+ my $dist = GPLIGCfunctions::dist($DECLAT[$x], $DECLON[$x], $WPLAT[$z], $WPLON[$z]);
+ if ($dist <= $limit) {
+ push(@wpindex, $x);
+ push(@wpnames, $WPNAME[$z]);
+ $loopstart=$x;
+ print "reached WP: $WPNAME[$z], $x, $dist \n" if ($config{'DEBUG'});
+ last;
+ }
+ }
+
+ }
+ }
+
+ return (\@wpindex, \@wpnames);
+}
+
+# open given url in a browser
+sub browseURL {
+
+ print "browseURL called with following URL:\n" if ($config{'DEBUG'});
+
+ my $url = shift;
+
+ print ">>>$url<<<\n" if ($config{'DEBUG'});
+
+ # unix-case
+ if ($^O ne 'MSWin32') {
+
+ # browser is a user option
+ # $browser = "/usr/local/mozilla/mozilla"; # now in $config
+
+ print "This is NOT win32, config(browser) = >>$config{'browser'}<<\n" if ($config{'DEBUG'});
+
+ my $intbrows = "none";
+
+ if (-x $config{'browser'} && -f $config{'browser'}) {
+ $intbrows = $config{'browser'};
+ print "$config{'browser'} is OK\n" if ($config{'DEBUG'});
+
+ } else {
+
+ print "$config{'browser'} is NOT OK. We will try to find one of netscape, mozilla or firefox in std locations.\n" if ($config{'DEBUG'});
+
+ # try to find a browser
+ @browsbins = qw(
+ /usr/local/firefox/firefox
+ /usr/local/bin/firefox
+ /usr/bin/firefox
+ /opt/firefox/firefox
+ /usr/local/mozilla/mozilla
+ /usr/local/bin/mozilla
+ /usr/bin/mozilla
+ /opt/mozilla/mozilla
+ /usr/local/netscape/netscape
+ /usr/local/bin/netscape
+ /usr/bin/netscape
+ /opt/netscape/netscape
+ );
+
+ @binpaths = qw(/bin /usr/bin /usr/local/bin);
+ @binnames = qw(/firefox /mozilla /firebird /MozillaFirebird /netscape);
+
+ @installpaths = qw(/usr /usr/local /opt);
+
+ @bins2 = qw( /firefox/firefox
+ /mozilla/mozilla
+ /netscape/netscape
+ /firebird/firebird
+ /MozillaFirebird/MozillaFirebird
+ );
+
+ foreach my $b (@browsbins) {
+ if (-x $b && -f $b) {
+ $intbrows = $b;
+ print "$b is the browser!\n" if ($config{'DEBUG'});
+ }
+ }
+
+ foreach my $p1 (@binpaths) {
+ foreach my $p2 (@binnames) {
+ if (-x $p1.$p2 && -f $p1.$p2) {
+ $intbrows = $p1.$p2;
+ print "$p1$p2 is the browser!\n" if ($config{'DEBUG'});
+ }
+
+ }
+ }
+
+ foreach my $p1 (@installpaths) {
+ foreach my $p2 (@bins2) {
+ if (-x $p1.$p2 && -f $p1.$p2) {
+ $intbrows = $p1.$p2;
+ print "$p1$p2 is the browser!\n" if ($config{'DEBUG'});
+ }
+
+ }
+ }
+
+ }
+
+ if ($^O eq "darwin" && $intbrows eq "none") {
+
+ $intbrows = "open";
+
+ if ($config{'DEBUG'}) {
+ print "Operating system is darwin and we didnt find any special browser...! We will use the open command to start browser!\n";
+
+ }
+
+ }
+
+ if ($intbrows eq "none") {Errorbox("No browser available!"); return;}
+
+ # open URL on unix
+
+ # Mac OS X (darwin)
+ if ($^O eq "darwin" && $intbrows eq "open") {
+ my $ret = system ("$intbrows \"$url\" &");
+ print "$intbrows \"$url\" \n" if ($config{'DEBUG'});
+ print "return value of system .. open is >>>$ret<<<\n" if ($config{'DEBUG'});
+ } else {
+
+ print "$intbrows -remote \"openURL($url,new-window)\" \n" if ($config{'DEBUG'});
+
+ if (system("$intbrows -remote \"openURL($url,new-window)\"") != 0) {
+ print "couldn't start new browser window remotely\n" if ($config{'DEBUG'});
+ if (system("$intbrows \"$url\" &") != 0) {
+ print "opening of browser failed\n" if ($config{'DEBUG'});
+ Errorbox("Error while trying to start $intbrows");
+ }
+ } else {
+ print "opened a new $intbrows window!\n" if ($config{'DEBUG'});
+ }
+ }
+
+ } else {
+
+ # windows methods
+ system("rundll32 url.dll,FileProtocolHandler \"$url\"");
+ }
+
+}
+
+################################################################################
+
+sub checkPhotos {
+ my $flag_from_open_photos = shift;
+
+ ## this initializes photo functionality
+ ## reads photos via getPhotos
+ ## and gets times via GPLIGCfunctions::getJPEGtime
+
+ @PHOTO_tmp=();
+ @PHOTO_TIMES_tmp=();
+ $delta_photo_time = 0 ;
+
+ # Photo stuff
+ # initialization
+
+ if ($config{'photos'}) {
+
+ @PHOTO_tmp = getPhotos(File::Basename::dirname($file)) if (!$flag_from_open_photos);
+ print "$#PHOTO_tmp No. of Photos/Multimedia files\n" if ($config{'DEBUG'});
+
+ if ($#PHOTO_tmp < 0) {
+ if ($config{'photo_path'} ne "none") {
+ @PHOTO_tmp = getPhotos($config{'photo_path'});
+ } else {
+ @PHOTO_tmp = getPhotos(File::Basename::dirname($file));
+ }
+ }
+
+ # Process
+ if ($#PHOTO_tmp >= 0) {
+
+ my $time;
+ foreach (@PHOTO_tmp) {
+
+ $time=0;
+
+ if ($have_EXIF && (lc(substr($_,-3)) eq "jpg" || lc(substr($_,-4)) eq "jpeg") ) {
+ $time = GPLIGCfunctions::getJPEGtime($_);
+ }
+
+ #print "File >$_<\n";
+ if ($time == 0) {
+
+ #print "get from $_ \n";
+ $time = GPLIGCfunctions::getFiletime($_);
+ }
+
+ push (@PHOTO_TIMES_tmp, $time-$photo_timezone);
+
+ if ($config{'DEBUG'}){
+ print "$_ : $time - ($photo_timezone) \n";
+ }
+
+ }
+
+ }
+
+ }
+}
+
+################################################################################
+
+sub processPhotos {
+ @PHOTO_FILES=();
+ @PHOTO_FILES_INDICES=();
+ @PHOTO_FILES_TIMES=(); #
+
+ # photo analyzing II
+ # now we create array PHOTO_FILES an _INDICES and TIMES
+ if ($config{'photos'} && $#PHOTO_TIMES_tmp >= 0) {
+ for (my $z=0; $z<=$#PHOTO_tmp; $z++) {
+
+ print "." if ($config{'DEBUG'});
+
+ my $min = 0.0166666;
+ my $min_idx = 0;
+ my $ptime;
+ my $comptime;
+ for (my $x=0; $x<=$#DECTIME; $x++) {
+
+ #print "checking.... $x\n";
+
+ $ptime = $PHOTO_TIMES_tmp[$z]-$delta_photo_time;
+ $comptime = $DECTIME[$x];
+ while ($ptime < 0) {$ptime+=24;}
+ while ($ptime > 24) {$ptime-=24;}
+ while ($comptime < 0) {$comptime+=24;}
+ while ($comptime > 24) {$comptime-=24;}
+
+ if ( abs($comptime-$ptime) < $min ) {
+ $min = abs($comptime-$ptime);
+ $min_idx = $x;
+
+ }
+
+ }
+
+ if ($min < 0.016666) {
+ push (@PHOTO_FILES, $PHOTO_tmp[$z]);
+ push (@PHOTO_FILES_INDICES, $min_idx);
+ push (@PHOTO_FILES_TIMES, $ptime);
+ }
+
+ }
+
+ if ($config{'DEBUG'}){
+ print "These Photos/MM are close to track (in time):\n";
+ for (my $z=0; $z<=$#PHOTO_FILES; $z++) {
+ print "$PHOTO_FILES[$z] ---> $PHOTO_FILES_INDICES[$z] <-- $PHOTO_FILES_TIMES[$z]\n";
+ }
+ }
+
+ }
+
+}
+
+################################################################################
+
+sub getPhotos {
+
+ ## This reads jpeg filenames from given dir
+ ## and returns array
+
+ my $dir = shift;
+ my @jpegs = ();
+
+ # will be overridden by GPLIGC-timeshift file
+ $photo_timezone = $gpi{'timezone'};
+
+ print "trying to find photos/multimedia in $dir\n" if ($config{'DEBUG'});
+
+ opendir (PHOTODIR, $dir) || die "Can not read $dir";
+ my @content = sort readdir(PHOTODIR);
+ closedir (PHOTODIR);
+
+ foreach (@content) {
+
+ if ( lc(substr($_,-3)) eq "jpg" || lc(substr($_,-4)) eq "jpeg"
+ || lc(substr($_,-3)) eq "amr" || lc(substr($_,-3)) eq "ogg" || lc(substr($_,-3)) eq "mp3"
+ || lc(substr($_,-3)) eq "avi" || lc(substr($_,-3)) eq "3gp"
+ ) {
+
+ push (@jpegs, "$dir/$_");
+ print "$dir/$_<=== \n" if ($config{'DEBUG'});
+
+ }
+
+ }
+
+ if ($config{'DEBUG'}) {
+ print ($#jpegs+1);
+ print " pictures/mm (array+1) found!\n";
+ }
+
+ # this file overrides timezone from .GPLIGCrc or .gpi file
+ if (-r "$dir/.GPLIGC-timeshift") {
+ open (TS, "<$dir/.GPLIGC-timeshift") || die "Cant read $dir/.GPLIGC-timeshift";
+ chomp($delta_photo_time = <TS>);
+ chomp($photo_timezone = <TS>);
+ close TS;
+
+ print "read $dir/.GPLIGC-timeshift: $delta_photo_time \n" if ($config{'DEBUG'});
+ print "read $dir/.GPLIGC-timeshift (tz): $photo_timezone \n" if ($config{'DEBUG'});
+ }
+
+ return @jpegs;
+}
+
+################################################################################
+
+sub showMM {
+
+ my $file = shift;
+
+ print "Showing/Playing: $file \n" if ($config{'DEBUG'});
+
+ if ( lc(substr($file,-3)) eq "jpg" || lc(substr($file,-4)) eq "jpeg") {
+ if ($config{'picture_viewer'} eq "internal") {
+ viewPhoto($file);
+ } else {
+ system ( " $config{'picture_viewer'} $file 2>/dev/null >&2 &");
+ }
+ }
+
+ if (lc(substr($file,-3)) eq "avi" || lc(substr($file,-3)) eq "amr"
+ || lc(substr($file,-3)) eq "mp3" || lc(substr($file,-3)) eq "ogg"
+ || lc(substr($file,-3)) eq "3gp" || lc(substr($file,-3)) eq "wav"
+
+ ) {
+
+ system ( "$config{'mm_player'} $file 2>/dev/null >&2 &");
+
+ }
+
+}
+
+sub viewPhoto {
+
+ #this is our internal photo viewer
+
+ my $file = shift;
+
+ if ($config{'DEBUG'}) {
+ print "$file will be viewed...\n";
+ }
+
+ if (!$have_jpeg) {
+ Errorbox ("Sorry. No Tk::JPEG module avaiable");
+ return;
+ }
+
+ my $viewer=$FlightView->Toplevel();
+ $viewer->configure(-title=>"GPLIGC: $file");
+
+ my $canvas = $viewer->Canvas();
+ my $photo = $viewer->Photo();
+ $canvas->create('image', 0, 0, -image=>$photo, -anchor =>'nw');
+ my $yscroll = $viewer->Scrollbar(-command=>['yview',$canvas],-orient=>'vertical');
+ my $xscroll = $viewer->Scrollbar(-command=>['xview',$canvas],-orient=>'horizontal');
+
+ $canvas ->configure(-xscrollcommand=>['set', $xscroll], -yscrollcommand=>['set', $yscroll]);
+
+ $photo->configure(-file=>"$file");
+ $canvas->configure(-scrollregion=>[0,0,$photo->width,$photo->height],-width=>$photo->width,-height=>$photo->height);
+
+ $xscroll->pack(-side=>'bottom', -fill =>'x' );
+ $yscroll->pack(-side=>'right', -fill =>'y' );
+
+ $canvas->pack(-expand=>'yes', -fill=>'both',-anchor=>'s');
+
+ setexit($viewer);
+}
+
+sub geotag_photos {
+
+ if (!$config{'photos'}) {return;}
+ if (!have_EXIF) {Errorbox("Cannot do that without the Image::ExifTool module. Sorry!"); return;}
+ if ( $#PHOTO_FILES < 1 ) {Errorbox("No photos available to do that!");return;}
+
+ my $processed = 0;
+ my $err = 0;
+ my $rej_overwrite = 0;
+
+ my $resp=$FlightView->messageBox(-type=>'OkCancel', -default=>'Ok', -icon=>'question',
+ -message=>"This will geo-tag all jpeg's of the media list (".($#PHOTO_FILES+1)." files)");
+
+ if (lc($resp) eq 'cancel') {return;}
+
+ # check for jpeg...
+ # give list and option to cancel here!
+
+ $busy2 = $FlightView->Busy;
+
+ for (my $i = 0; $i<=$#PHOTO_FILES; $i++) {
+
+ if ($config{'DEBUG'}) {
+ print "Tag: $PHOTO_FILES[$i] $DECLAT[$PHOTO_FILES_INDICES[$i]] $DECLON[$PHOTO_FILES_INDICES[$i]] $BARO[$PHOTO_FILES_INDICES[$i]] \n";
+ }
+
+ # we should count files and intercept errors.
+ if ( lc(substr($PHOTO_FILES[$i],-3)) eq "jpg" || lc(substr($PHOTO_FILES[$i],-4)) eq "jpeg") {
+
+ my $ret = GPLIGCfunctions::geotag( $PHOTO_FILES[$i], $DECLAT[$PHOTO_FILES_INDICES[$i]], $DECLON[$PHOTO_FILES_INDICES[$i]], $BARO[$PHOTO_FILES_INDICES[$i]],
+ $DECTIME[$PHOTO_FILES_INDICES[$i]], $gpi{'timezone'}, $config{'geotag_force_overwrite'} );
+
+ if ( $ret == 1) { $processed += 1; }
+ if ( $ret == 2) { $rej_overwrite +=1; }
+ if ( $ret == 0) { $err +=1; }
+
+ } else {print "$PHOTO_FILES[$i] is not a jpeg\n" if ($config{'DEBUG'});}
+ }
+ $busy2 = $FlightView->Unbusy;
+ Errorbox("".($#PHOTO_FILES+1)." files. Processed: $processed Errors: $err Rejected to overwrite tags: $rej_overwrite");
+}
+
+###############################################################################
+
+sub phototimecalibration {
+
+ if (!defined $lastphoto_idx) {
+ Errorbox("Please view a photo first, subsequently you can enter the exact time for that photo.");
+ return;
+ }
+
+ my $input=$FlightView->Toplevel();
+
+ $input->configure(-title=>"Photo time calibration");
+
+ my $eleframe=$input->Frame()->pack();
+ my $buttonfr=$input->Frame()->pack();
+ my $extime = "$TIME[$nr]";
+ my ($name, $p, $suf) = File::Basename::fileparse($PHOTO_FILES[$lastphoto_idx]);
+
+ $eleframe->Label(-text=> "Exact time of last photo seen ($name) UTC (hh:mm:ss or hhmmss)")->pack(-side=>"left");
+ $eleframe->Entry(-textvariable=>\$extime)->pack(-side=>"right");
+
+ $buttonfr->Button(-text=>"OK",-command=>sub{
+ $input->destroy();
+ return;
+ })->pack(-side=>"left");
+ $buttonfr->Button(-text=>"cancel",-command=>sub{
+ $input->destroy();
+ undef $extime;
+ return;
+ })->pack(-side=>"right");
+
+ $input -> waitWindow;
+
+ ###### waiting?
+
+ if (!defined $extime) {
+ Errorbox ("No input given / cancelled");
+ return;
+ }
+
+ # check format
+ if (! ( $extime =~ /(\d{2}):(\d{2}):(\d{2})/ || $extime =~ /(\d{6})/ ) ) {
+ Errorbox ("Input not in required format");
+ return;
+ }
+
+ $extime =~s/://g; #strip ":" if existing
+ my $dectime = GPLIGCfunctions::time2dec($extime);
+ print "given: $extime $dectime\n" if ($config{'DEBUG'});
+ print "last photo: $PHOTO_FILES_TIMES[$lastphoto_idx] \n" if ($config{'DEBUG'});
+
+ $delta_photo_time = $PHOTO_FILES_TIMES[$lastphoto_idx] - $dectime;
+ print "Difference: $delta_photo_time to be applied to all photos!\n" if ($config{'DEBUG'});
+
+ for (my $x=0 ; $x <= $#PHOTO_FILES_TIMES; $x++) {
+ print "$PHOTO_FILES_TIMES[$x] -----> ".($PHOTO_FILES_TIMES[$x]-$delta_photo_time)."\n" if ($config{'DEBUG'});
+
+ # print "$PHOTO_TIMES[$x] \n " if ($config{'DEBUG'});
+ }
+
+ $p .= "/.GPLIGC-timeshift";
+
+ # if (!-w $p) {
+ # Errorbox ("Sorry couldn't write timeshiftfile: $p");
+ # } else {
+ open (TS, ">$p") || die "couldn't write timeshift-file: $p";
+ print TS $delta_photo_time."\n";
+ print TS $photo_timezone."\n";
+ close TS;
+
+ # }
+
+ processPhotos();
+
+}
+
+################################################# KML EXPORT
+sub kml_export {
+ if ($filestat eq 'closed') {$FlightView->bell; return;}
+ $kml_file = substr($file,0,-3)."kml";
+
+ print "kml file will be written to $kml_file\n" if ($config{'DEBUG'});
+ open (KML, ">$kml_file") || die "Cannot write $kml_file";
+
+ $kml_segment=1;
+ print KML "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://earth.google.com/kml/2.1\">\n<Document>\n";
+ print KML "\n <Placemark>\n <name>$kml_segment</name>\n <LineString>\n <altitudeMode>absolute</altitudeMode>\n <coordinates>\n";
+
+ for ($z=1; $z<=$#DECLAT; $z++) {
+ print KML " $DECLON[$z],$DECLAT[$z],$BARO[$z]\n";
+ }
+
+ print KML " </coordinates>\n </LineString>\n </Placemark>\n";
+ print KML "\n</Document>\n</kml>\n";
+ close KML;
+ MessageFenster("kml export","kml file was written to $kml_file");
+}
+
+########################################### GPX EXPORT
+sub gpx_export {
+ if ($filestat eq 'closed') {$FlightView->bell; return;}
+ my $gpx_file = substr($file,0,-3)."gpx";
+
+ print "gpx file will be written to $gpx_file\n" if ($config{'DEBUG'});
+ open (GPX, ">$gpx_file") || die "Cannot write $gpx_file";
+
+ print GPX "<?xml version=\"1.0\"?>\n<gpx version=\"1.0\" creator=\"GPLIGC $version\">\n";
+
+ print GPX "<time></time>\n";
+ print GPX "<trk>\n <name>$file</name>\n <trkseg>\n";
+
+ my $fakedate="1900-01-01";
+ my $ftime;
+ for ($z=1; $z<=$#DECLAT; $z++) {
+ print GPX " <trkpt lat=\"$DECLAT[$z]\" lon=\"$DECLON[$z]\">\n";
+ $ftime = GPLIGCfunctions::time2human($TIME[$z],'t');
+ print GPX " <ele>$BARO[$z]</ele>\n";
+ print GPX " <time>${fakedate}T${ftime}Z</time>\n";
+ print GPX " </trkpt>\n";
+ }
+
+ print GPX " </trkseg>\n</trk>\n</gpx>\n";
+
+ close GPX;
+ MessageFenster("gpx export","gpx file was written to $gpx_file");
+}
+##################################################
+sub download_media {
+ if ($^O eq "MSWin32") {Errorbox("not supported on windows!"); return;};
+ my $dir= directory();
+ if (-d $dir) {
+ my $com = "mount -v $config{'mm_mountpoint'} ";
+
+ foreach ( $config{'mm_download_dirs'} =~ /(\w+)/g ) {
+ $com .= " ; cp -av $config{'mm_mountpoint'}/$_/* $dir ";
+ }
+
+ $com .= " ; umount -v $config{'mm_mountpoint'} ";
+
+ print "Media DL command: $com \n" if ($config{'DEBUG'});
+
+ my $pid = fork();
+
+ if ($pid==0) {
+ system ("$config{'terminal'} \'$com\'");
+ wait();
+ CORE::exit();
+ }
+ } else {Errorbox("No direcotry chosen");}
+}
+
+#############################################################
+sub download_garmin {
+ if ($^O eq "MSWin32") {Errorbox("not supported on windows!"); return;};
+ my $file = save(GPLIGCfunctions::get_name_date()."-GAR-000-01.gpspoint");
+ my $path = File::Basename::dirname($file);
+
+ if ($file ne "no") {
+
+ my $com = " $config{'garmin_download'} >$file && cd $path && gpsp2igcfile.pl <$file && echo \"finished\"";
+ print "Garmin download command: $com \n" if ($config{'DEBUG'});
+
+ my $pid = fork();
+ if ($pid==0) {
+ system ("$config{'terminal'} \'$com\'");
+ wait();
+ CORE::exit();
+ }
+ }
+}
+
+sub download_gpsbabel {
+
+ # needs testing on windows
+ #if ($^O eq "MSWin32") {Errorbox("not supported on windows!"); return;};
+ #my $num=0;
+ #startover:
+
+ my $file = save(GPLIGCfunctions::get_name_date()."-XXX-000-01.igc");
+ my $path = File::Basename::dirname($file);
+
+ if (-e $file) {
+ Errorbox("File exists ($file)");
+ return; }
+
+ if ($file ne "no") {
+
+ my $com = " $config{'gpsbabel_tdownload'} $file && echo \"finished\"";
+
+ #print "$com \n";
+
+ if ($^O ne "MSWin32") {
+ my $pid = fork();
+ if ($pid==0) {
+ system ("$config{'terminal'} \'$com\'");
+ wait();
+ CORE::exit();
+ }
+ } else {
+
+ # windows code:
+ system ("start $com");
+
+ }
+ }
+}
+
+#####
+
+sub gpiinput {
+
+ if ($filestat eq 'closed') {$FlightView->bell; return;}
+ my $input=$FlightView->Toplevel();
+
+ $input->configure(-title=>"Additional flight information");
+
+ my %oldgpi = %gpi;
+
+ my $fr1=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr2=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr3=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr4=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr5=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+
+ #my $fr5b=$input->Frame()->pack;
+ my $fr6=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr7=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr8=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr9=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr10=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr11=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr12=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+ my $fr13=$input->Frame()->pack(-expand=>"yes",-fill=>"x");
+
+ my $bfr=$input->Frame()->pack();
+
+ $fr1->Label(-text=> "Date of flight")->pack(-side=>"left");
+ $fr1->Entry(-textvariable=>\$gpi{'year'})->pack(-expand=>"yes",-fill=>"x");
+ $fr1->Entry(-textvariable=>\$gpi{'month'})->pack(-expand=>"yes",-fill=>"x");
+ $fr1->Entry(-textvariable=>\$gpi{'day'})->pack(-expand=>"yes",-fill=>"x");
+
+ $fr2->Label(-text=> "Pilot",-width=>"8")->pack(-side=>"left",-anchor=>"w");
+ $fr2->Entry(-textvariable=>\$gpi{'pilot'})->pack(-expand=>"yes",-fill=>"x");
+
+ $fr3->Label(-text=> "Copilot",-width=>"8")->pack(-side=>"left");
+ $fr3->Entry(-textvariable=>\$gpi{'copilot'})->pack(-expand=>"yes",-fill=>"x");
+
+ $fr4->Label(-text=> "Glider",-width=>"8")->pack(-side=>"left");
+ $fr4->Entry(-textvariable=>\$gpi{'glider'})->pack(-expand=>"yes",-fill=>"x");
+
+ $fr5->Label(-text=> "Callsign",-width=>"8")->pack(-side=>"left");
+ $fr5->Entry(-textvariable=>\$gpi{'callsign'})->pack(-expand=>"yes",-fill=>"x");
+
+ #$fr5b->Label(-text=> "Glider mass [kg]")->pack(-side=>"left");
+ #$fr5b->Entry(-textvariable=>\$gpi{'glider_mass'})->pack();
+
+ $fr6->Label(-text=> "QNH (hPa)")->pack(-side=>"left");
+ $fr6->Entry(-textvariable=>\$gpi{'qnh'})->pack(-expand=>"yes",-fill=>"x");
+
+ $fr7->Label(-text=> "Timezone (offset from UTC)")->pack(-side=>"left");
+ $fr7->Entry(-textvariable=>\$gpi{'timezone'})->pack(-expand=>"yes",-fill=>"x");
+
+ $fr8->Label(-text=> "Airfield")->pack(-side=>"left");
+ $fr8->Entry(-textvariable=>\$gpi{'airfield'})->pack(-expand=>"yes",-fill=>"x");
+
+ $fr9->Label(-text=> "Altitude calibration applied: $gpi{'altitude_calibration_type'} (ca. ".int($offset).")")->pack(-side=>"left");
+ $fr9->Button(-text=>"Clear calibration",-command=>sub{
+ $gpi{'altitude_calibration_ref_press'}=0;
+ $gpi{'altitude_calibration_type'}="none";
+ $gpi{'altitude_calibration_point'}=0;
+ $gpi{'altitude_calibration_point_alt'}=0;
+ $offset = 0;
+ Errorbox("To make changes take effect, save information and reload igc-file!");
+ })->pack(-expand=>"yes",-fill=>"x");
+
+ $fr10->Label(-text=> "Logger Device")->pack(-side=>"left");
+ $fr10->Entry(-textvariable=>\$gpi{'logger'})->pack(-expand=>"yes",-fill=>"x");
+ $fr11->Label(-text=> "Remarks1")->pack(-side=>"left");
+ $fr11->Entry(-textvariable=>\$gpi{'remarks'})->pack(-expand=>"yes",-fill=>"x");
+ $fr12->Label(-text=> "Remarks2")->pack(-side=>"left");
+ $fr12->Entry(-textvariable=>\$gpi{'remarks2'})->pack(-expand=>"yes",-fill=>"x");
+ $fr13->Label(-text=> "Remarks3")->pack(-side=>"left");
+ $fr13->Entry(-textvariable=>\$gpi{'remarks3'})->pack(-expand=>"yes",-fill=>"x");
+
+ $bfr->Button(-text=>"Save",-command=>sub{
+ save_gpi();
+ $input->destroy();
+ return;
+ })->pack(-side=>"left");
+ $bfr->Button(-text=>"OK",-command=>sub{
+ $input->destroy();
+
+ # check for changes? offset correction?!
+ return;
+ })->pack(-side=>"left");
+ $bfr->Button(-text=>"cancel",-command=>sub{
+ $input->destroy();
+ %gpi = %oldgpi;
+ return;
+ })->pack(-side=>"right");
+
+ $input -> waitWindow;
+}
+
+
+sub check_config {
+ # find outdated config-keys and inform user
+ print "\ncheck_config\n" if ($config{'DEBUG'});
+ my $YES = 0;
+ my $text = "The following configuration keys are outdated. They will be deleted now. Save the configuration to erase them permanently from your configuration file.\nKeys:\n";
+
+ my @old_keys = qw (optimizer_montecarlo optimizer_metropolis_montecarlo optimizer_cycles open_flight_view_window fvw_show_help
+ flight_view_baro_grid flight_view_window_grid
+ );
+ my $oc;
+
+ foreach $oc (@old_keys) {
+ print "checking: $oc" if ($config{'DEBUG'});
+ if (exists ($config{$oc})) {
+ print "=$config{$oc} FOUND\n" if ($config{'DEBUG'});
+ delete ( $config{$oc});
+ $YES = 1;
+ $text .= "$oc ";
+ } else {
+ print "\n" if ($config{'DEBUG'});
+ }
+ }
+
+ if ($YES) {Errorbox($text);}
+}
+
+
+sub olctaskinfo {
+
+ # departure time (olc) s0
+ # finishing time (olc) s6
+ my $starttime;
+ my $finishtime;
+
+ my $starttimeindex=GPLIGCfunctions::takeoff_detect(\@nonISPEED, 's');
+ my $landtimeindex=GPLIGCfunctions::takeoff_detect(\@nonISPEED, 'l');
+
+ # take-off time (olc) t0
+ my $stime=GPLIGCfunctions::time2human($TIME[$starttimeindex], 't');
+ my $ltime=GPLIGCfunctions::time2human($TIME[$landtimeindex], 't');
+
+ # unpowered filght start, end (olc) fstart ffinish
+ my $fstart=GPLIGCfunctions::time2human($TIME[$task_start_time_index],'t');
+ my $ffinish=GPLIGCfunctions::time2human($TIME[$task_finish_time_index],'t');
+
+ my $maximumheightindex;
+ my $minimumheightindex;
+
+ if ($optimized_for eq "olc-class") {
+
+ # <should be impossible. but = may happen
+ if ($olcFirstWPindex <= $task_start_time_index) { $minimumheightindex=$olcFirstWPindex; $starttime = GPLIGCfunctions::time2human($TIME[$olcFirstWPindex],'t'); }
+ else {
+
+ # get lowest point between task_start_time_index and olcFirstWPindex
+ $minimumheightindex = $olcFirstWPindex;
+
+ for (my $e=$task_start_time_index; $e <= $olcFirstWPindex; $e++) {
+ if ($BARO[$e] < $BARO[$minimumheightindex]) {$minimumheightindex = $e;}
+ }
+
+ $starttime = GPLIGCfunctions::time2human($TIME[$minimumheightindex],'t');
+
+ }
+
+ # > should be impossible. but = may happen
+ if ($olcLastWPindex >= $task_finish_time_index) { $maximumheightindex=$olcLastWPindex; $finishtime = GPLIGCfunctions::time2human($TIME[$olcLastWPindex],'t'); }
+ else {
+
+ # get highest point between task_finish_time_index and olcLastWPindex
+ $maximumheightindex = $olcLastWPindex;
+
+ for (my $e=$olcLastWPindex; $e <= $task_finish_time_index; $e++) {
+ if ($BARO[$e] > $BARO[$maximumheightindex]) {$maximumheightindex = $e;}
+ }
+
+ $finishtime = GPLIGCfunctions::time2human($TIME[$maximumheightindex],'t');
+ }
+ }
+
+ if ($optimized_for eq "olc-phg") {
+ $finishtime = GPLIGCfunctions::time2human($TIME[$olcLastWPindex],'t');
+ $starttime = GPLIGCfunctions::time2human($TIME[$olcFirstWPindex],'t')
+ }
+
+ if ($optimized_for eq "dmst") {
+ $finishtime = GPLIGCfunctions::time2human($TIME[$olcLastWPindex],'t');
+
+ $starttime = GPLIGCfunctions::time2human($TIME[$olcFirstWPindex],'t') if ($BARO[$task_start_time_index] > $BARO[$olcFirstWPindex]);
+ $starttime = GPLIGCfunctions::time2human($TIME[$task_start_time_index],'t') if ($BARO[$task_start_time_index] < $BARO[$olcFirstWPindex]);
+
+ }
+
+ my $message_out = "";
+ $message_out .= "Take-Off time (t0) = ".$stime."\n";
+ $message_out .= "Begin of unpowered flight (fstart) = ".GPLIGCfunctions::time2human($TIME[$task_start_time_index],'t')."\n";
+ $message_out .= "Time of departure (s0) = $starttime\n" if ($optimized_for ne "none");
+
+ $message_out .= "first WP = ".GPLIGCfunctions::time2human($TIME[$olcFirstWPindex],'t')."\n" if (defined $olcFirstWPindex);
+ $message_out .= "last WP = ".GPLIGCfunctions::time2human($TIME[$olcLastWPindex],'t')."\n" if (defined $olcLastWPindex);
+
+ $message_out .= "finishtime (s6/s4) = $finishtime\n" if ($optimized_for ne "none");
+ $message_out .= "End of unpowered flight (ffinish) = ".GPLIGCfunctions::time2human($TIME[$task_finish_time_index],'t')."\n";
+ $message_out .= "Time of landing = $ltime \n";
+
+ my $deltaheight;
+ $deltaheight = $BARO[$minimumheightindex] - $BARO[$maximumheightindex] if ($optimized_for eq "olc-class");
+ $message_out .= "Departure: ".$BARO[$minimumheightindex]."m Finish: ".$BARO[$maximumheightindex]."m Difference: ${deltaheight}m \n" if ($optimized_for eq "olc-class");
+
+ return ($message_out, $stime, $ltime, $fstart, $ffinish, $deltaheight, $starttime, $finishtime);
+}
+
diff --git a/perl/GPLIGCfunctions.pm b/perl/GPLIGCfunctions.pm
new file mode 100644
index 0000000..6d846ff
--- /dev/null
+++ b/perl/GPLIGCfunctions.pm
@@ -0,0 +1,940 @@
+# (c) 2001-2016 Hannes Krueger
+# This file is part of the GPLIGC/ogie package
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>
+
+package GPLIGCfunctions;
+
+#-------------------------------------------------------------------------------
+
+sub igc2dec {
+
+ # converts igc-file-formatted coordinates (D)DDMMMMM(N|S|E|W) into decimal form
+ # DD MM.MMM
+
+ my $igck=shift;
+
+ if (length($igck)==8) { #Latitude DDMMMMM(N|S)
+ my $D=substr($igck,0,2);
+ my $M1=substr($igck,2,2);
+ my $M2=substr($igck,4,3);
+ my $M=$M1.".".$M2;
+ my $hemissphere=substr($igck,7,1);
+ my $latitude=($D+($M/60));
+ if ($hemissphere eq 'S') {$latitude=$latitude*(-1);}
+
+ return ($latitude);
+ }
+
+ if (length($igck)==9) { #Longitude DDDMMMMM(E|W)
+ my $D=substr($igck,0,3);
+ my $M1=substr($igck,3,2);
+ my $M2=substr($igck,5,3);
+ my $M=$M1.".".$M2;
+ my $hemissphere=substr($igck,8,1);
+ my $longitude=($D+($M/60));
+ if ($hemissphere eq 'W') {$longitude=$longitude*(-1);}
+
+ return ($longitude);
+ }
+
+ return ("Fehler in GPLIGCfunctions::igc2dec");
+}
+
+
+sub zan2dec {
+
+ # converts zan-file-formatted coordinates (D)DDMMSS(N|S|E|W) into decimal form
+
+ my $igck=shift;
+
+
+ if (length($igck)==7) { #Latitude DDMMSS(N|S)
+ my $D=substr($igck,0,2);
+ my $M=substr($igck,2,2);
+ my $S=substr($igck,4,2);
+
+ my $hemissphere=substr($igck,6,1);
+ my $latitude=($D+($M/60)+($S/3600));
+ if ($hemissphere eq 'S') {$latitude=$latitude*(-1);}
+
+ return ($latitude);
+ }
+
+ if (length($igck)==8) { #Longitude DDDMMSS(E|W)
+ my $D=substr($igck,0,3);
+ my $M=substr($igck,3,2);
+ my $S=substr($igck,5,2);
+
+ my $hemissphere=substr($igck,7,1);
+ my $longitude=($D+($M/60)+($S/3600));
+ if ($hemissphere eq 'W') {$longitude=$longitude*(-1);}
+
+ return ($longitude);
+ }
+
+ return ("Fehler in GPLIGCfunctions::zan2dec");
+}
+
+
+sub MaxKoor {
+
+ # gibt maximum und minimum des array (ref) zurueck
+
+ my $arrayref = shift;
+
+ my $max=${$arrayref}[0];
+ my $min=$arrayref->[0]; #Verschiedene Moeglichkeiten auf Element eines Arrays ber Referenz zuzugreifen
+
+ foreach (@$arrayref) {
+ if ($max < $_) {$max=$_;}
+ if ($min > $_) {$min=$_;}
+ }
+
+ return ($max, $min);
+}
+
+
+### calculates distance between two points on 'FAI-spheroid'
+sub dist {
+ use Math::Trig;
+ my ($lat1, $lon1, $lat2 ,$lon2) = @_;
+ my $rho = 6371;
+
+ return ($rho * (acos(cos( deg2rad($lat1) ) * cos( deg2rad($lat2) ) * cos( deg2rad($lon2) - deg2rad($lon1) ) + sin( deg2rad($lat1) ) * sin( deg2rad($lat2) ) ) ) );
+}
+
+
+sub setpwd {
+ use File::Basename;
+ return File::Basename::dirname(shift);
+}
+
+#-------------------------------------------------------------------------------
+
+sub time2human {
+### converts time (HHMMSS) to HH:MM:SS
+### or date DDMMYY to DD.MM.YY
+### p=t -> time , p=d -> date
+
+ my ($time, $p) = @_;
+
+ if ($p eq 't') {my $htime = substr($time,0,2).":".substr($time,2,2).":".substr($time,4,2); return $htime;}
+ if ($p eq 'd') {my $htime = substr($time,0,2).".".substr($time,2,2).".".substr($time,4,2); return $htime;}
+
+}
+
+#########################################################
+
+sub pointdist {
+
+#calculates triangular distance of 3 points given by number in arrays of coordinates
+ my ($declat, $declon, $p1, $p2, $p3) = @_;
+
+ my $km=dist(${$declat}[$p1],${$declon}[$p1],${$declat}[$p2],${$declon}[$p2])+dist(${$declat}[$p2],${$declon}[$p2],${$declat}[$p3],${$declon}[$p3])+dist(${$declat}[$p3],${$declon}[$p3],${$declat}[$p1],${$declon}[$p1]);
+
+ return $km;
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub zufall {
+### random integer between $min and $max
+ my ($min, $max) = @_;
+ return (int(rand $max-$min+1)+$min);
+}
+
+#--------------------------------------------------------------------------------
+
+sub zufall2 {
+### random integer between $min and $max (steps of devisor)
+ my ($min, $max, $devisor) = @_;
+ return ( (int(rand(($max-$min+1)/$devisor))* $devisor)+$min );
+}
+
+#-------------------------------------------------------------------------------
+
+sub takeoff_detect {
+
+ ### detects takeoff and landing!
+ my ($speedarrayref, $start_ldg) = @_;
+ my $lasttime=0;
+ my $times=0;
+
+ # check average speed...
+ my $speedsum = 0;
+ my $counter = 0;
+
+ foreach (@$speedarrayref) {
+
+ if ($_ > 5 && $_ < 500) {
+ $speedsum += $_;
+ $counter++;
+ }
+ }
+
+ if ($counter == 0) {print STDERR "GPLIGC: Warning: no data with speed between 5 and 500 km/h!\n"; $counter=1;}
+ my $avspeed=$speedsum/$counter;
+
+ my $limit = 2;
+
+ if ($avspeed > 30) {
+ $limit = 10;
+ }
+
+ if ($avspeed > 80) {
+ $limit = 40;
+ }
+
+ # get take-off time and return
+ if ($start_ldg eq 's'){
+ for (my $z=0; $z<=$#$speedarrayref; $z++) {
+
+ # 4x speed > 40 == takeoff... (takeofftime == time of first point > 40)
+ if ($speedarrayref->[$z]>$limit) {
+ if ($lasttime == 1) {$times++;} else {$lasttime=1;}
+ if ($times == 4) {return($z-4);}
+
+ } else { $lasttime=0;}
+ }
+ }
+
+ # get landing time and return
+ if ($start_ldg eq 'l'){
+ for (my $z=$#$speedarrayref; $z>=0; $z--) {
+ if ($speedarrayref->[$z]>$limit) {
+ if ($lasttime == 1) {$times++;} else {$lasttime=1;}
+ if ($times == 4) {return($z+4);}
+
+ } else { $lasttime=0;}
+ }
+ }
+
+ # if nothing was detected (slow paraglider etc...)
+ #
+ # hier muss noch ein algorithmus rein, der drachen flieger etc abdeckt...
+ # analyse der overall durchschnitsgeschwindigkeit?
+ #
+
+ if ($start_ldg eq 's') {return (0);}
+ if ($start_ldg eq 'l') {return ($#$speedarrayref);}
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub releaseDetect {
+
+ ### tries to detect releaseTime
+ my ($altarrayref, $takeoff_index) = @_;
+ my $counter = $takeoff_index;
+
+ $takeoff_alt = $altarrayref->[$takeoff_index];
+
+ # skip until we climbed at least 150m
+ while ($altarrayref->[$counter] < $altarrayref->[$takeoff_index]+150) {
+ $counter++;
+ if ($counter >= $#$altarrayref) {return $takeoff_index;}
+ }
+
+ my $sinkcounter = 0;
+ for (my $c = $counter; $c <= $#$altarrayref; $c++) {
+ if ($altarrayref->[$c] < $altarrayref->[$c-1]) {$sinkcounter++;}
+ else {$sinkcounter = 0;}
+
+ if ($sinkcounter == 2) {return $c-2;}
+ }
+
+}
+
+sub OxygenStatistics {
+
+ ### determines the Oxygen use according to FAA 91.211 1l/min / 10.000ft
+ my ($altarrayref, $dectimearrayref, $qnh) = @_;
+
+ my $time_100=0;
+ my $time_125=0; # minutes total
+ my $time_125acc=0; # minutes total
+ my $time_140=0;
+ my $time_180=0;
+
+ my $limit_100=3028;
+ my $limit_125=3810;
+ my $limit_140=4267; # 14.000ft
+ my $limit_180=5486; #FL180
+
+ my $free_flag = 1; # once above FL125 there is no free time between 100 an 125 any more
+ my $free_time=0;
+ my $maxalt=0;
+ my $maxpalt=0;
+
+ my $liters_100=0;
+ my $liters_125=0;
+ my $liters_125acc=0;
+ my $liters_140=0;
+ my $liters_180=0;
+
+ #loop
+ for (my $c = 0; $c <= $#$altarrayref; $c++) {
+
+ # check max
+ if ($altarrayref->[$c] > $maxalt) {$maxalt=$altarrayref->[$c]}
+ if (altitude(pressure($altarrayref->[$c],$qnh),1013.25) > $maxpalt) {$maxpalt=altitude(pressure($altarrayref->[$c],$qnh),1013.25)}
+
+ # recommended liumit FL100
+ if (altitude(pressure($altarrayref->[$c],$qnh),1013.24) > $limit_100 && altitude(pressure($altarrayref->[$c],$qnh),1013.24) <= $limit_125) {
+
+ $time_100 += ($dectimearrayref->[$c+1]-$dectimearrayref->[$c]);
+ $liters_100 += (($dectimearrayref->[$c+1]-$dectimearrayref->[$c])*60) * ((altitude(pressure($altarrayref->[$c],$qnh),1013.24)/0.3048)/10000);
+ }
+
+ # softlimit 125
+ if (altitude(pressure($altarrayref->[$c],$qnh),1013.24) > $limit_125 && altitude(pressure($altarrayref->[$c],$qnh),1013.24) <= $limit_140) {
+
+ if ($free_flag) {
+ if ($free_time < 0.5) {
+ $free_time += $dectimearrayref->[$c+1]-$dectimearrayref->[$c];
+ $free_flag=0 if ($free_time >= 0.5);
+ }
+ } else {
+ $time_125acc += ($dectimearrayref->[$c+1]-$dectimearrayref->[$c]);
+ $liters_125acc += (($dectimearrayref->[$c+1]-$dectimearrayref->[$c])*60) * ((altitude(pressure($altarrayref->[$c],$qnh),1013.24)/0.3048)/10000);
+ }
+
+ $time_125 += ($dectimearrayref->[$c+1]-$dectimearrayref->[$c]);
+ $liters_125 += (($dectimearrayref->[$c+1]-$dectimearrayref->[$c])*60) * ((altitude(pressure($altarrayref->[$c],$qnh),1013.24)/0.3048)/10000);
+ }
+
+ if (altitude(pressure($altarrayref->[$c],$qnh),1013.24) > $limit_140 && altitude(pressure($altarrayref->[$c],$qnh),1013.24) <= $limit_180) {
+ $free_flag=0;
+ $time_140 += ($dectimearrayref->[$c+1]-$dectimearrayref->[$c]);
+ $liters_140 += (($dectimearrayref->[$c+1]-$dectimearrayref->[$c])*60) * ((altitude(pressure($altarrayref->[$c],$qnh),1013.24)/0.3048)/10000);
+ }
+
+ if (altitude(pressure($altarrayref->[$c],$qnh),1013.24) > $limit_180) {
+ $free_flag=0;
+ $time_180 += ($dectimearrayref->[$c+1]-$dectimearrayref->[$c]);
+ $liters_180 += (($dectimearrayref->[$c+1]-$dectimearrayref->[$c])*60) * ((altitude(pressure($altarrayref->[$c],$qnh),1013.24)/0.3048)/10000);
+ }
+ }
+
+ $free_time = 0.5 if ($free_time > 0.5);
+
+ #print "Oxygen statistics:\n";
+ #print "above $softlimit m (min): ".($time_above_sl*60)."\n";
+ #print "above $hardlimit m (min): ".($time_above_hl*60)."\n";
+ #print "Liters to be used :".$liters_FAA." ".$liters_Oxymizer."\n";
+
+ return ($maxalt,$maxpalt,$time_100,$time_125,$time_125acc,$time_140,$time_180,$liters_100,$liters_125,$liters_125acc,$liters_140,$liters_180,$free_time);
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub dec2time {
+### converts decimal time in (h)h:mm:ss
+ my $dectime= shift;
+
+ my $hh = int $dectime;
+ my $rest = $dectime - int $dectime;
+ my $mm = int(60 * $rest);
+ $rest= 60 * $rest - $mm;
+ my $ss = int (60*$rest);
+
+ $rest=60 * $rest -$ss;
+ if ($rest > 0.5) {$ss++;}
+
+ if ($ss == 60) {$ss=0;$mm++;}
+
+ # why was hh not 0 padded?
+ # I added this now 100809, side effects?
+
+ if (length($hh) == 1) {$hh = "0"."$hh";}
+ if (length($mm) == 1) {$mm = "0"."$mm";}
+ if (length($ss) == 1) {$ss = "0"."$ss";}
+
+ return ("$hh:$mm:$ss");
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub Ausschnitt2 {
+
+ # only for zoomfunction of FlightViewWindow!
+
+ use Math::Trig;
+ my ($height, $width, $lat, $lon, $kl) = @_;
+ my $halbkilometer=0.004496608;
+ my $sideratio=$width/$height;
+
+ my $xmin=$lon-($kl*$halbkilometer* ( 1/cos(deg2rad($lat)) ));
+ my $xmax=$lon+($kl*$halbkilometer* ( 1/cos(deg2rad($lat)) ));
+ my $ymin=$lat-($kl*$halbkilometer / $sideratio );
+ my $ymax=$lat+($kl*$halbkilometer / $sideratio );
+
+ return ($xmax, $xmin, $ymax, $ymin);
+}
+
+#-------------------------------------------------------------------------------
+
+# calculates data for cylinders viewing in FVW...
+sub zylinder2 {
+
+ use Math::Trig;
+ my ($lat, $lon, $r, $startangle, $angularrange) = @_; ###r=durchmesser
+ my $gpx;
+
+ my $start = deg2rad($startangle);
+ my $range = deg2rad($angularrange);
+
+ my @dlat=();
+ my @dlon=();
+
+ $gpx= $r * 0.0089932161;
+
+ my $step = 0.0314;
+
+ for (my $a=$start;$a<=$start+$range;$a=$a+$step) { # step 0.0314 gives 200 points on full circle
+ push(@dlat, cos($a)*$gpx);
+ push(@dlon, sin($a)*$gpx*(1/cos(deg2rad($lat))));
+ }
+
+ return (\@dlat, \@dlon);
+
+} ###ende zylinder2 andere version fuer FVWindow!
+
+#-------------------------------------------------------------------------------
+
+# calculates sectors or starting line...
+#
+
+# NOT NEEDED, TO BE DELETED..........
+
+sub sector {
+
+ use Math::Trig;
+
+ my ($n, $lat, $lon, $lat_after, $lon_after, $lat_before, $lon_before)= @_;
+
+ # n = 0 -> starting point
+ # n = 1 -> finish
+ # n = 2 -> wp
+ # n < 5 -> n km long starting-line
+
+ my $direction
+
+}
+
+#-------------------------------------------------------------------------------
+
+#Calculates coordianates of a point which is in direction, distance
+# from a given point
+
+sub go {
+
+ use Math::Trig;
+ my ($lat, $lon, $heading, $distance) = @_;
+
+ #distance needs to be in degrees...
+
+ my $c =
+ (360 / (6371 * 2 * 3.141592654) ) * $distance ;
+
+ my $a = 90 - $lat;
+
+ my $beta = $heading;
+
+ # berechnung nach Seitenkosinussatz
+ my $b = rad2deg(acos(
+ cos(deg2rad($c)) * cos(deg2rad($a))
+ + sin(deg2rad($c)) * sin(deg2rad($a)) * cos(deg2rad($beta))
+
+ ));
+
+ my $gamma = rad2deg(asin(
+ ( sin(deg2rad($c)) / sin(deg2rad($b)) ) * sin(deg2rad($beta))
+ ));
+
+ return ( 90 -$b , $lon + $gamma);
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub sectordirection {
+
+ #berechnet den gegenkurs zur winkelhalbierenden
+
+ my ($head1, $head2) = @_;
+
+ if ($head1 < $head2) {
+ my $zw = $head1;
+ $head1 = $head2;
+ $head2 = $zw;
+ }
+
+ my $delta = $head1 - $head2;
+
+ if ($delta > 180) {
+ $delta = 360 - $delta;
+
+ #print "d < 180 ! \n";
+ return gegenkurs($head1)+$delta/2;
+ } else {
+
+ #print "nicht groesser \n";
+
+ my $secdir = gegenkurs($head1)-$delta/2;
+ if ($secdir < 0) { $secdir = $secdir + 360; }
+ return $secdir;
+
+ }
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub gegenkurs {
+ my $kurs = shift;
+ my $gegenk = $kurs - 180;
+ if ($gegenk < 0) {$gegenk = $gegenk + 360;}
+
+ return $gegenk;
+}
+
+#-------------------------------------------------------------------------------
+
+sub kurs {
+
+ # calculates the heading from point 1 to point 2
+ # at point 1
+ #
+ #
+ #
+ #
+ # IV I
+ # -------------
+ # III II
+ #
+
+ my ($lat1, $lon1, $lat2, $lon2) = @_;
+
+ my $b = 90 - $lat1;
+ my $a = 90 - $lat2;
+
+ my $gamma = $lon1 - $lon2;
+
+ if ($gamma < 0) { $gamma = $gamma * -1} ;
+
+ my $c = rad2deg(acos(
+ cos(deg2rad($a)) * cos(deg2rad($b))
+ + sin(deg2rad($a)) * sin(deg2rad($b)) * cos(deg2rad($gamma))
+ ));
+
+ my $alpha = 0;
+
+ if ($c != 0) { # c == 0 if there is no movement ?
+ my $zwischenrechnung = (sin(deg2rad($a)) / sin(deg2rad($c)) ) * sin(deg2rad($gamma));
+
+ if ($zwischenrechnung > 1) {$zwischenrechnung =1;}
+
+ $alpha = rad2deg(asin($zwischenrechnung));
+
+ }
+
+ if ($lat1 >= $lat2 && $lon2 >= $lon1) { $alpha = 180-$alpha ; goto endmarke;} # quadrant 2
+
+ if ($lat1 >= $lat2 && $lon2 <= $lon1) { $alpha = 180+$alpha ; goto endmarke;} # quadrant 3
+
+ if ($lat1 <= $lat2 && $lon1 >= $lon2) { $alpha = 360-$alpha ; goto endmarke;} # quadrant 4
+
+ endmarke:
+
+ return $alpha;
+}
+
+#-------------------------------------------------------------------------------
+
+sub coorconvert {
+
+ # converts decimal coordinates into different formats
+ my ($cor, $lorl, $outformat)=@_;
+
+ #lorl = lat _ or _ lon
+ #outformat:
+ # 'igc' 'igch' 'zan' 'zanh'
+
+ my $wesn;
+ my $deg_digits;
+
+ if ($outformat eq 'deg') {
+ return (sprintf("%.6f",$cor));
+ }
+
+ # determination of hemisphere s,n,w,e
+ if ($lorl eq 'lat') {
+ $deg_digits=2;
+ if (substr($cor,0,1) eq '-') {
+ $wesn='S'; $cor=$cor*(-1);
+ }
+ else
+ {$wesn='N'; }
+
+ }
+
+ if ($lorl eq 'lon') {
+ $deg_digits=3;
+ if (substr($cor,0,1) eq '-') {
+ $wesn='W'; $cor=$cor*(-1);
+ }
+ else
+ {$wesn='E'; }
+ }
+
+ my $deg = int $cor; #degrees
+
+ while ((length $deg) < $deg_digits) { $deg = "0".$deg;}
+
+ #pre-zeros
+
+ my $minigc = ($cor - $deg)*60; #minutes decimal
+ my $minzan = int (($cor - $deg)*60); #only minutes (integer)
+
+ if ((length $minzan) < 2) {$minzan="0".$minzan;} #zanderformatminutes gets filled up with zeros to 2digits
+
+ my $seczan = int(($minigc - $minzan)*60); #only seconds
+
+ #print "laenge ".(length $seczan)."\n";
+
+ my $rest_zan_sec=((($minigc-$minzan)*60)-$seczan); #rest after decimal
+
+ #print "restzansecs $rest_zan_sec \n";
+
+ if ($rest_zan_sec > 0.5) {$seczan++;}
+
+ #round up seconds if necessary
+
+ #print "igc min : $minigc \n";
+
+ my $igc_min_3stell = sprintf("%.3f",$minigc); #igc-minutes m.mmm
+
+ #print "igc_3stell $igc_min_3stell \n";
+
+ if ((substr($igc_min_3stell,2,1)) ne '.') {$igc_min_3stell="0".$igc_min_3stell;}
+
+ my $rest_igc_min = int($minigc * 1000); #cutted rest
+
+#if ($rest_igc_min > 0.5) { $igc_min_3stell += 0.001;print "igc gerundet\n";} #round up if necessary
+
+ if ((length $seczan) < 2) {$seczan="0".$seczan;}
+
+ if ($outformat eq 'igc') {
+ my $igc_min_without_decimal = substr($igc_min_3stell,0,2).substr($igc_min_3stell,3,3);
+ return ("$deg$igc_min_without_decimal$wesn");
+ }
+ if ($outformat eq 'igch') {
+ return ("${deg} $igc_min_3stell\' $wesn");
+ }
+ if ($outformat eq 'zan') {
+ return ("$deg$minzan$seczan$wesn");
+ }
+ if ($outformat eq 'zanh') {
+ return ("${deg} $minzan\' $seczan\" $wesn");
+ }
+
+ return ("no valid outformat in GPLIGCfunctions::coorconv!!! $outformat");
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub pressure {
+
+# calculates the pressure for given altitude and reference pressure, Std-Atmosphere
+ my $stdpress = 1013.25;
+ my $alt = shift;
+ my $p0 = shift;
+ if (defined $p0 && $p0 != 0) {$stdpress=$p0;}
+
+ return ( $stdpress * (1-(0.0065*$alt/288.15))**5.255 );
+}
+
+sub referencepressure {
+
+# calculates the referencepressure p0 for given altitude and pressure, Std-Atmosphere
+# my $stdpress = 1013.25;
+ my $alt = shift;
+ my $p = shift;
+
+ # if (defined $p0 && $p0 != 0) {$stdpress=$p0;}
+
+ return ( $p / ((1-(0.0065*$alt/288.15))**5.255) );
+}
+
+sub altitude {
+
+# calculates an altitude from given pressure and reference pressue, std-atmosphere
+ my $stdpress = 1013.25;
+ my $p = shift;
+ my $p0 = shift;
+ if (defined $p0 && $p0 != 0) {$stdpress=$p0;}
+
+ return ((( 1-($p/$stdpress)**(1/5.255) ) * 288.15)/0.0065);
+}
+
+#-------------------------------------------------------------------------------
+
+sub time2dec {
+ my $time = shift;
+ my $H=substr($time,0,2);
+ my $M=substr($time,2,2);
+ my $S=substr($time,4,2);
+ if (!defined $H || !defined $M || !defined $S) {
+ print "wrong string in time2dec: >$time<\n";
+ }
+ return ($H+(($M+($S/60))/60));
+}
+
+#-------------------------------------------------------------------------------
+
+sub retArrayRef {
+
+ #anonymous arrayreferenz erzeugen
+ my @Array=();
+ return \@Array;
+}
+
+#-------------------------------------------------------------------------------
+
+# this will evaluate the time of a JPEG from exif.
+# single argument is a jpeg-file and return value is decimal time
+# or zero in case of an error
+sub getJPEGtime {
+ my $file = shift;
+ require Image::ExifTool;
+
+ my $info = Image::ExifTool::ImageInfo($file);
+
+ # for full exif tags output!
+ # while ( ($k,$v) = each %$info ) {
+ # print "$k => $v\n";
+ # }
+
+ if (!defined $info) {
+ print "GPLIGCfunctions::getJPEGtime: cant open file $file!\n";
+ return 0;
+ }
+
+ #my $image = $exif -> get_image_info();
+ # my $camera = $exif -> get_camera_info();
+ # my $other = $exif -> get_other_info();
+ # my %complete = (%$other, %$camera, %$image); # merging hashes into one
+ #my %complete = (%$info); # merging hashes into one
+ #print $complete."\n";
+
+ my $val;
+ my @times = ();
+
+ foreach $val ("DateTimeOriginal","CreateDate","Image Created", "Image Generated", "Image Digitized",
+ "DateTime", "Date Time", "Date and Time","ModifyDate", "FileModifyDate") {
+
+ if (exists $info->{$val}) {
+
+ # print $val." found: =>";
+ if ($info->{$val} =~ /(\d+):(\d+):(\d+)\s+(\d+):(\d+):(\d+)/ ){
+ push (@times, "$4$5$6");
+
+ # print "$4$5$6 \n";
+ }
+ }
+ }
+
+ # now we return the first value we found...
+ # maybe we can check here for multiple different times? ===15===
+ return (time2dec($times[0])) if ($#times >= 0);
+ if ($#times < 0) { return 0;}
+}
+
+# very simple geotagging!
+sub geotag {
+
+ require Image::ExifTool;
+ my $file = shift;
+ my $lat = shift;
+ my $lon = shift;
+ my $alt = shift;
+ my $decutc = shift;
+ my $tzshift = shift;
+ my $force_overwrite = shift;
+
+ my $tagsset = 0;
+ my $succ=0;
+ my $err="no error";
+
+ #print "geotag: $file to be treated\n";
+
+ #maybe we should update the time too?
+
+ my $thingy = new Image::ExifTool;
+
+ $tagsset += $thingy -> SetNewValue('GPSLatitude', $lat);
+ $tagsset += $thingy -> SetNewValue('GPSLongitude', $lon);
+
+ $tagsset += $thingy -> SetNewValue('GPSLatitudeRef', 'N');
+ $tagsset += $thingy -> SetNewValue('GPSLongitudeRef', 'E');
+
+ if ($lat < 0) { $thingy -> SetNewValue('GPSLatitudeRef', 'S'); }
+ if ($lon < 0) { $thingy -> SetNewValue('GPSLongitudeRef', 'W'); }
+
+ $tagsset += $thingy -> SetNewValue('GPSAltitude', $alt);
+
+ # complains...
+ #$thingy -> SetNewValue('GPSAltitudeRef', '0');
+
+ # write GPS timeStamp
+ while ($decutc > 24) {$decutc=$decutc-24;}
+ $tagsset += $thingy -> SetNewValue('GPSTimeStamp', $decutc);
+
+ my $local=$decutc+$tzshift;
+ while ($local < 0 ) {$local=$local+24;}
+ while ($local > 24) {$local=$local-24;}
+
+ print "geo-tag: not enough tags set: $tagsset\n" if ($tagsset < 6) ;
+
+ # intercept error messages!
+
+ # check for existence of tags! HERE
+ if ($force_overwrite == 0) {
+ my $thingx = new Image::ExifTool;
+ my $info = $thingx->ImageInfo($file, 'GPSLatitude','GPSLongitude','GPSAltitude','GPSTimeStamp');
+ foreach (sort keys %$info) {
+
+ #print "$_ => $$info{$_}\n";
+ if ($_ eq "GPSLatitude" || $_ eq "GPSLongitude" ||$_ eq "GPSAltitude" || $_ eq "GPSTimeStamp") {
+ return 2; # tags exists!
+ }
+ }
+ }
+
+ ($succ, $err) = $thingy ->WriteInfo($file);
+
+ if ($succ > 0) {return 1};
+ print "geo-tag: error: $err \n";
+ return 0;
+}
+
+sub getFiletime {
+
+ #require File::stat;
+ my $file = shift;
+
+ # print "GetFileTime: $file\n";
+ $x= (stat($file))[9];
+ my ($ss,$mm,$hh) = localtime($x);
+
+ #print "$hh : $mm : $ss \n";
+ my $ret = sprintf("%02d%02d%02d",$hh,$mm,$ss);
+
+ #print "$ret<===\n";
+ return(time2dec($ret));
+}
+
+#-------------------------------------------------------------------------------
+sub get_name_date {
+ my ($ss, $mm, $hh, $dd, $mon, $yyyy) = gmtime ();
+ $mon++; # (dd: 1-31, mon: 0-11, y: yyyy -1900)
+ $yyyy+=1900;
+ $lfn= sprintf("%4d-%02d-%02d", $yyyy,$mon,$dd);
+ return ($lfn);
+}
+
+sub guessdatefromfilename {
+ my $fn = shift;
+ my $y = 0;
+ my $m = 0;
+ my $d = 0;
+
+ my ($name, $p, $suf) = File::Basename::fileparse($fn);
+ if (length($name) == 12 && lc(substr ($name,-3)) eq "igc") {
+ if ( substr($name,0,1) =~ /^\d+$/ ) {$y += substr($name,0,1);
+ $y+=2010;
+ }
+ if ( substr($name,1,1) =~ /^\d+$/ ) {$m = substr($name ,1,1)}
+ else {
+ $m = ord(lc(substr($name,1,1)))-87;
+ $m = 1 if ($m<10 || $m>12);
+ }
+ if ( substr($name,2,1) =~ /^\d+$/ ) {$d = substr($name ,2,1)}
+ else {
+ $d = ord(lc(substr($name,2,1)))-87;
+ $d = 1 if ($d<10 || $d>31);
+ }
+ }
+
+ # igc long format
+ if (length($name) == 25 && lc(substr ($name,-3)) eq "igc") {
+ if ( substr($name,0,4) =~ /^\d+$/ ) {$y = substr($name,0,4)}
+ if ( substr($name,5,2) =~ /^\d+$/ ) {$m = substr($name,5,2)}
+ if ( substr($name,8,2) =~ /^\d+$/ ) {$d = substr($name,8,2)}
+ }
+
+ #printf("%4d-%02d-%02d \n", $y,$m,$d);
+ return ($y,$m,$d);
+}
+
+# some stuff for maps:
+# code from
+# http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
+sub getTileNumber {
+ my ($lat,$lon,$zoom) = @_;
+ my $xtile = int( ($lon+180)/360 *2**$zoom ) ;
+ my $ytile = int( (1 - log(tan(deg2rad($lat)) + sec(deg2rad($lat)))/pi)/2 *2**$zoom ) ;
+ return ($xtile, $ytile);
+}
+sub Project {
+ my ($X,$Y, $Zoom) = @_;
+ my $Unit = 1 / (2 ** $Zoom);
+ my $relY1 = $Y * $Unit;
+ my $relY2 = $relY1 + $Unit;
+
+# note: $LimitY = ProjectF(degrees(atan(sinh(pi)))) = log(sinh(pi)+cosh(pi)) = pi
+# note: degrees(atan(sinh(pi))) = 85.051128..
+#my $LimitY = ProjectF(85.0511);
+
+ # so stay simple and more accurate
+ my $LimitY = pi;
+ my $RangeY = 2 * $LimitY;
+ $relY1 = $LimitY - $RangeY * $relY1;
+ $relY2 = $LimitY - $RangeY * $relY2;
+ my $Lat1 = ProjectMercToLat($relY1);
+ my $Lat2 = ProjectMercToLat($relY2);
+ $Unit = 360 / (2 ** $Zoom);
+ my $Long1 = -180 + $X * $Unit;
+ return ($Lat2, $Long1, $Lat1, $Long1 + $Unit); # S,W,N,E
+}
+sub ProjectMercToLat($){
+ my $MercY = shift;
+ return rad2deg(atan(sinh($MercY)));
+}
+sub ProjectF
+{
+ my $Lat = shift;
+ $Lat = deg2rad($Lat);
+ my $Y = log(tan($Lat) + sec($Lat));
+ return $Y;
+}
+
+1;
diff --git a/perl/Makefile.am b/perl/Makefile.am
new file mode 100644
index 0000000..31f485d
--- /dev/null
+++ b/perl/Makefile.am
@@ -0,0 +1,16 @@
+bin_SCRIPTS = gpligc
+dist_bin_SCRIPTS = gpsp2igcfile.pl gpsp2igc.pl loopviewer.pl
+
+libgpligcdir = $(libdir)/gpligc
+dist_libgpligc_SCRIPTS = GPLIGCfunctions.pm
+
+CLEANFILES = gpligc
+EXTRA_DIST = GPLIGC.pl
+
+do_subst = sed -e 's,zzLIBDIRzz,$(libdir)/gpligc,g' \
+ -e 's,zzDATADIRzz,$(datadir)/gpligc,g'
+
+
+gpligc: GPLIGC.pl Makefile
+ $(do_subst) < $(srcdir)/GPLIGC.pl > gpligc
+ chmod +x gpligc
diff --git a/perl/Makefile.in b/perl/Makefile.in
new file mode 100644
index 0000000..9403727
--- /dev/null
+++ b/perl/Makefile.in
@@ -0,0 +1,567 @@
+# Makefile.in generated by automake 1.15 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2014 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = perl
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(dist_bin_SCRIPTS) \
+ $(dist_libgpligc_SCRIPTS) $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \
+ "$(DESTDIR)$(libgpligcdir)"
+SCRIPTS = $(bin_SCRIPTS) $(dist_bin_SCRIPTS) $(dist_libgpligc_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POW_LIB = @POW_LIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+bin_SCRIPTS = gpligc
+dist_bin_SCRIPTS = gpsp2igcfile.pl gpsp2igc.pl loopviewer.pl
+libgpligcdir = $(libdir)/gpligc
+dist_libgpligc_SCRIPTS = GPLIGCfunctions.pm
+CLEANFILES = gpligc
+EXTRA_DIST = GPLIGC.pl
+do_subst = sed -e 's,zzLIBDIRzz,$(libdir)/gpligc,g' \
+ -e 's,zzDATADIRzz,$(datadir)/gpligc,g'
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign perl/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign perl/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binSCRIPTS: $(bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n' \
+ -e 'h;s|.*|.|' \
+ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+ if (++n[d] == $(am__install_max)) { \
+ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+ else { print "f", d "/" $$4, $$1 } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 's,.*/,,;$(transform)'`; \
+ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
+install-dist_binSCRIPTS: $(dist_bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n' \
+ -e 'h;s|.*|.|' \
+ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+ if (++n[d] == $(am__install_max)) { \
+ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+ else { print "f", d "/" $$4, $$1 } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-dist_binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 's,.*/,,;$(transform)'`; \
+ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
+install-dist_libgpligcSCRIPTS: $(dist_libgpligc_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_libgpligc_SCRIPTS)'; test -n "$(libgpligcdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libgpligcdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libgpligcdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n' \
+ -e 'h;s|.*|.|' \
+ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+ if (++n[d] == $(am__install_max)) { \
+ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+ else { print "f", d "/" $$4, $$1 } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(libgpligcdir)$$dir'"; \
+ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(libgpligcdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-dist_libgpligcSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_libgpligc_SCRIPTS)'; test -n "$(libgpligcdir)" || exit 0; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 's,.*/,,;$(transform)'`; \
+ dir='$(DESTDIR)$(libgpligcdir)'; $(am__uninstall_files_from_dir)
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(SCRIPTS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libgpligcdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dist_libgpligcSCRIPTS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binSCRIPTS install-dist_binSCRIPTS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binSCRIPTS uninstall-dist_binSCRIPTS \
+ uninstall-dist_libgpligcSCRIPTS
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
+ ctags-am distclean distclean-generic distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binSCRIPTS \
+ install-data install-data-am install-dist_binSCRIPTS \
+ install-dist_libgpligcSCRIPTS install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags-am uninstall uninstall-am \
+ uninstall-binSCRIPTS uninstall-dist_binSCRIPTS \
+ uninstall-dist_libgpligcSCRIPTS
+
+.PRECIOUS: Makefile
+
+
+gpligc: GPLIGC.pl Makefile
+ $(do_subst) < $(srcdir)/GPLIGC.pl > gpligc
+ chmod +x gpligc
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/perl/gpsp2igc.pl b/perl/gpsp2igc.pl
new file mode 100755
index 0000000..d98e54c
--- /dev/null
+++ b/perl/gpsp2igc.pl
@@ -0,0 +1,144 @@
+#!/usr/bin/perl -w
+
+# $Id: gpsp2igc.pl 3 2014-07-31 09:59:20Z kruegerh $
+# (c) 2002-2016 Hannes Krueger
+# This file is part of the GPLIGC/ogie package
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>
+
+
+# This little script converts a tracklist file obtained from a Garmin GPS using
+# the gpspoint program into something resembling an IGC file for use with other programs.
+# Script by Jan M. W. Krueger, 1st of March 2004
+#
+
+# put into the GPLIGC/perl CVS repository
+# $Id: gpsp2igc.pl 3 2014-07-31 09:59:20Z kruegerh $
+#
+# revised by Hannes Kruger
+
+
+# usage:
+# gpsp2igc.pl <inputfile.gpspoint >out.igc
+# or
+# gpspoint -dt | gpsp2igc.pl >out.igc
+# should work also
+
+
+
+@lines = <STDIN>;
+@igclines = ();
+
+# flag for new track segment ( 0 is new segment)
+$first = 0;
+
+
+for($tmp=0; $tmp<=$#lines; $tmp++){
+ if($lines[$tmp] =~ /trackpoint/){
+ if($lines[$tmp] =~ /newsegment=\"yes\"/){
+ $lines[$tmp] =~ s/\ \ newsegment=\"yes\"\ //g;
+ #push(@outlines, "\n");
+ push(@igclines, "\n");
+ $first = 0;
+ }
+
+ $lines[$tmp] =~ s/type\=\"trackpoint\"\ \ //g;
+ $lines[$tmp] =~ s/\"/\ /g;
+ $lines[$tmp] =~ s/altitude\=\ //g;
+ $lines[$tmp] =~ s/latitude\=\ //g;
+ $lines[$tmp] =~ s/longitude\=\ //g;
+ $lines[$tmp] =~ s/unixtime\=\ //g;
+
+
+
+ $lines[$tmp] =~ /([\d.-]+)\s*([\d.-]+)\s*([\d.-]+)\s*([\d.-]+)/;
+ $alt = $1;
+ $latitude = $2;
+ $longitude = $3;
+ $unixtime = $4;
+
+ # Put altitude in IGC line format:
+ if($alt<0){
+ $altnew = -$alt;
+ $altnew = sprintf "%5d", $altnew;
+ $altnew =~ s/\ /0/g;
+ $altnew =~ s/0/-/;
+ } else {
+ $altnew = sprintf "%5d", $alt;
+ $altnew =~ s/\ /0/g;
+ }
+
+
+ # Put latitude in IGC line format:
+ if($latitude < 0){
+ $latitudenew = -$latitude;
+ $ns = "S";
+ } else {
+ $latitudenew = $latitude;
+ $ns = "N";
+ }
+ $latint = sprintf "%.0f", $latitudenew-0.5;
+ $latmins = 100000* ($latitudenew - $latint)*60/100;
+ $latint = sprintf "%2.0f", $latint;
+ $latint =~ s/\ /0/g;
+ $latmins = sprintf "%5.0f", $latmins;
+ $latmins =~ s/\ /0/g;
+
+ $latitudestring = $latint.$latmins.$ns;
+
+
+ # Put longitude in IGC line format:
+ if($longitude < 0){
+ $longitudenew = -$longitude;
+ $ew = "W";
+ } else {
+ $longitudenew = $longitude;
+ $ew = "E";
+ }
+ $lonint = sprintf "%.0f", $longitudenew-0.5;
+ $lonmins = 100000* ($longitudenew - $lonint)*60/100;
+ $lonint = sprintf "%3.0f", $lonint;
+ $lonint =~ s/\ /0/g;
+ $lonmins = sprintf "%5.0f", $lonmins;
+ $lonmins =~ s/\ /0/g;
+
+ $longitudestring = $lonint.$lonmins.$ew;
+
+
+ # use gmtime to get GMT from unix-epoch-seconds
+ ($ss, $mm, $hh, $dd, $mon, $yy) = gmtime ($unixtime);
+ $mon++; # (dd: 1-31, mon: 0-11, y: yyyy -1900)
+ $yy+=1900; $yy=substr($yy,2);
+
+
+ # detect new segment and mark with HFDTEddmmyy
+ if($first == 0){
+ push(@igclines, "HFDTE".sprintf("%02d%02d%02d",$dd,$mon,$yy)."\n");
+
+ $first = 1;
+ }
+
+ push(@igclines, "B".sprintf("%02d%02d%02d", $hh,$mm,$ss).$latitudestring.$longitudestring."A".$altnew.$altnew."\n");
+
+ }
+}
+
+
+
+# give out some pseudo-header
+print "AXXX000 garmin2igc.pl ".'$Id: gpsp2igc.pl 3 2014-07-31 09:59:20Z kruegerh $'."\n";
+print "HFFTY FR Type: some Garmin device\n";
+print "HFFSW Software: gpspoint / garmin2igc.pl\n";
+
+print @igclines;
diff --git a/perl/gpsp2igcfile.pl b/perl/gpsp2igcfile.pl
new file mode 100755
index 0000000..06efe1d
--- /dev/null
+++ b/perl/gpsp2igcfile.pl
@@ -0,0 +1,181 @@
+#!/usr/bin/perl -w
+
+# $Id: gpsp2igcfile.pl 3 2014-07-31 09:59:20Z kruegerh $
+# (c) 2002-2016 Hannes Krueger
+# This file is part of the GPLIGC/ogie package
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>
+
+# This little script converts a tracklist file obtained from a Garmin GPS using
+# the gpspoint program into something resembling an IGC file for use with other programs.
+# Script by Jan M. W. Krueger, 1st of March 2004
+
+# put into the GPLIGC/perl CVS repository
+# $Id: gpsp2igcfile.pl 3 2014-07-31 09:59:20Z kruegerh $
+# revised by Hannes Kruger
+
+# usage:
+# gpsp2igc.pl <inputfile.gpspoint
+
+# this will write igcfiles for each day!
+# with more or less igc conform filenames!
+# see also gpsp2igc
+
+# new segment on new day -> new igc file! (well, that may be problematic for australian files...)
+
+# igc naming
+
+$device_id = "000";
+$manufacturer_short="X";
+$manufacturer_long="GAR";
+$filenr=1;
+
+
+@lines = <STDIN>;
+
+
+# flag for new track segment ( 1 is new segment)
+$first = 0;
+$oday ="000000"; # old day!
+
+for($tmp=0; $tmp<=$#lines; $tmp++){
+ if($lines[$tmp] =~ /trackpoint/){
+ if($lines[$tmp] =~ /newsegment=\"yes\"/){
+ $lines[$tmp] =~ s/\ \ newsegment=\"yes\"\ //g;
+ #push(@outlines, "\n");
+ #push(@igclines, "\n");
+ $first = 1;
+ }
+
+ $lines[$tmp] =~ s/type\=\"trackpoint\"\ \ //g;
+ $lines[$tmp] =~ s/\"/\ /g;
+ $lines[$tmp] =~ s/altitude\=\ //g;
+ $lines[$tmp] =~ s/latitude\=\ //g;
+ $lines[$tmp] =~ s/longitude\=\ //g;
+ $lines[$tmp] =~ s/unixtime\=\ //g;
+
+
+
+ $lines[$tmp] =~ /([\d.-]+)\s*([\d.-]+)\s*([\d.-]+)\s*([\d.-]+)/;
+ $alt = $1;
+ $latitude = $2;
+ $longitude = $3;
+ $unixtime = $4;
+
+ # Put altitude in IGC line format:
+ if($alt<0){
+ $altnew = -$alt;
+ $altnew = sprintf "%5d", $altnew;
+ $altnew =~ s/\ /0/g;
+ $altnew =~ s/0/-/;
+ } else {
+ $altnew = sprintf "%5d", $alt;
+ $altnew =~ s/\ /0/g;
+ }
+
+
+ # Put latitude in IGC line format:
+ if($latitude < 0){
+ $latitudenew = -$latitude;
+ $ns = "S";
+ } else {
+ $latitudenew = $latitude;
+ $ns = "N";
+ }
+ $latint = sprintf "%.0f", $latitudenew-0.5;
+ $latmins = 100000* ($latitudenew - $latint)*60/100;
+ $latint = sprintf "%2.0f", $latint;
+ $latint =~ s/\ /0/g;
+ $latmins = sprintf "%5.0f", $latmins;
+ $latmins =~ s/\ /0/g;
+
+ $latitudestring = $latint.$latmins.$ns;
+
+
+ # Put longitude in IGC line format:
+ if($longitude < 0){
+ $longitudenew = -$longitude;
+ $ew = "W";
+ } else {
+ $longitudenew = $longitude;
+ $ew = "E";
+ }
+ $lonint = sprintf "%.0f", $longitudenew-0.5;
+ $lonmins = 100000* ($longitudenew - $lonint)*60/100;
+ $lonint = sprintf "%3.0f", $lonint;
+ $lonint =~ s/\ /0/g;
+ $lonmins = sprintf "%5.0f", $lonmins;
+ $lonmins =~ s/\ /0/g;
+
+ $longitudestring = $lonint.$lonmins.$ew;
+
+
+ # use gmtime to get GMT from unix-epoch-seconds
+ ($ss, $mm, $hh, $dd, $mon, $yyyy) = gmtime ($unixtime);
+ $mon++; # (dd: 1-31, mon: 0-11, y: yyyy -1900)
+ $yyyy+=1900; $yy=substr($yyyy,2);
+
+
+ # detect new segment and mark with HFDTEddmmyy
+ if($first == 1){
+ $first = 0;
+ if (sprintf("%02d%02d%02d",$dd,$mon,$yy) ne $oday) {
+ newfile($yyyy,$mon,$dd);
+ $oday = sprintf("%02d%02d%02d",$dd,$mon,$yy);
+ }
+ }
+
+ print FN "B".sprintf("%02d%02d%02d", $hh,$mm,$ss).$latitudestring.$longitudestring."A".$altnew.$altnew."\n";
+
+ }
+}
+
+
+sub newfile {
+
+ my $y=shift;
+ my $m=shift;
+ my $d=shift;
+
+ my ($igcm, $igcd);
+ my $igcy=substr($y,-1);
+
+ if ($m < 10) {$igcm=$m}
+ if ($m == 10) {$igcm="a"}
+ if ($m == 11) {$igcm="b"}
+ if ($m == 12) {$igcm="c"}
+
+ if ($d < 10) {$igcd=$d} else {
+ $igcd= chr(97+($d-10));
+ }
+
+ filenames:
+ my $fn = "$igcy$igcm$igcd$manufacturer_short${device_id}$filenr.igc";
+ my $lfn= sprintf("%4d-%02d-%02d-$manufacturer_long-$device_id-%02d.igc", $y,$m,$d,$filenr);
+
+ print "IGC file: $lfn ($fn)\n";
+
+ if (-e $lfn) {print "$lfn ($fn) exists!\n"; $filenr++; goto filenames;}
+
+ close FN;
+
+ open(FN, ">$lfn") || die "cannot open $lfn for writing";
+
+ print FN "A$manufacturer_long$device_id ".'$Id: gpsp2igcfile.pl 3 2014-07-31 09:59:20Z kruegerh $'."\n";
+ print FN "HFFTY FR Type: unknown device\n";
+ print FN "HFFSW Software: gpspoint / gpsp2igcfile.pl\n\n";
+
+ my $yy=substr($y,2);
+ print FN "HFDTE".sprintf("%02d%02d%02d",$d,$m,$yy)."\n\n";
+}
diff --git a/perl/loopviewer.pl b/perl/loopviewer.pl
new file mode 100755
index 0000000..422cdd5
--- /dev/null
+++ b/perl/loopviewer.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/perl -w
+
+
+# The loopviewer-script is a tool for viewing lots of igc files as a presentation loop
+# for detailed information see GPLIGC_Manual.pdf
+# this is just a template, parameters in $ogieflags* have to be adjusted for your needs
+
+#uncomment "#goto loop;" for endlss loops
+#comment out one of the system calls for either 2D or 3D only
+
+# start with
+# loopviewer.pl liste
+#
+# liste is a file which has one line for each igc file + comment
+# "path/filename.igc" "1.Place - Name - Class - Glider - points - speed - distance ..."
+
+
+
+my $ogieflags= " --quiet --fullscreen --airfield-elevation=960 --spinning 0.3 --movie --cycles=1 --marker --marker-range --marker-back=700";
+my $ogieflags2D = " --init-ortho-lat=48.06 --init-ortho-lon=8.8 ";
+my $ogieflags3D = " --init-alt=4000 --init-heading=0 --init-lat=47.9514 --init-lon=8.765 --init-dive=-30 ";
+
+my $file = shift;
+open (INFILE,"<$file");
+my @list = <INFILE>;
+close INFILE;
+
+loop:
+ foreach (@list) {
+
+ $_ =~ /^\"(.*)\"\s*\"(.*)\"/;
+
+ #print "$2 >$1\n";
+ system ("ogie $ogieflags $ogieflags3D --text \"$2\" -i \"$1\" ");
+ system ("ogie $ogieflags $ogieflags2D --ortho --text \"$2\" -i \"$1\" ");
+
+
+}
+#goto loop;