#!/usr/bin/perl -w # (C) Jochen Puchalla 2005-2010 $steigdist=200; # minimum distance for climbing percentage calculation # $deltat=20; # seconds between points $g=9.81; # gravitation $cw=0.4; # air resistance $rho=1.2; # air density $roll=0.003; # roll resistance $minspeed=1.4; # ignore lower speeds than 1.4 m/s (5 km/h) $mindeltah=1.5; # ignore height noise use GD::Simple; foreach $file (@ARGV) { if (! open(INPUT,"<$file") ) { print STDERR "Can't open input file $file\n"; next; } $filecore=$file; $filecore =~ s/.tour$//g; if ($file eq $filecore) { print STDERR "$file is not a tour file\n"; $bad++; next; } # open output file: if (! open(OUTPUT,">$filecore.png") ) { print STDERR "Can't open output file $filecore.png\n"; $bad++; next; } print "Generating $filecore.png\n"; # open gnuplot data file: if (! open(GOUTPUT,">gnuplot.dat") ) { print STDERR "Can't open output file gnuplot.dat\n"; $bad++; next; } printf GOUTPUT ("#Dist Alt Speed Power Rollpower Climbpower Accelpower Airpower\n"); print "Generating $filecore-data.png\n"; $distdiff=2000; # resolution for numbered length scale # set values to 0 for every new file: $sums=0; $sumt=0; $sumh=0; $work=0; $count=0; $maxcount=0; $h_max=10; $s_max=0; $shift=0; $minus=-1; # initialize some values: $v[1]=0; $power[1]=0; $rollp[1]=0; $airp[1]=0; $climbp[1]=0; $accelp[1]=0; $seconds[0]=0; $maxspeed=50; # km/h to display while ($line=) { if ($line =~ /^Date=/) { @temp = split(/=/, $line); $date=$temp[1]; chop $date; if ($date =~ /^$/) {$date="unknown date";} } if ($line =~ /^Title=/) { @temp = split(/=/, $line); $title=$temp[1]; chop $title; if ($title =~ /^$/) {$title="untitled";} } if ($line =~ /^Start=/) { @temp = split(/=/, $line); $start=$temp[1]; chop $start; if ($start =~ /^$/) {$start="untitled";} } if ($line =~ /^Finish=/) { @temp = split(/=/, $line); $finish=$temp[1]; chop $finish; if ($finish =~ /^$/) {$finish="untitled";} } if ($line =~ /^Weight=/) { @temp = split(/=/, $line); $W=$temp[1]; chop $W; } if ($line =~ /^Speed=/) { @temp = split(/=/, $line); @temp2 = split(/;/, $temp[1]); $topspeed=$temp2[0]; if ($topspeed > $maxspeed) {$maxspeed = sprintf ("%.0f", $topspeed/10)*11;} # print "$maxspeed"; } if ($line =~ /^Temperature=/) { @temp = split(/=/, $line); @temp = split(/;/, $temp[1]); $celsius=$temp[1]; # take medium value } if ($line =~ /#Pulse/) # data starts { while ($line=) # read all data into buffer { # if ($line =~ /\d/) {printf("%s hallo\n",$line);last;} @value = split(/\t/, $line); #split at tabs if ($line =~ /^$/) {last;} $count++; $h[$count]=$value[3]; # Höhe $s[$count]=$value[7]; # Strecke $time[$count]=$value[12]; # Zeitinfo @part = split(/\:/, $time[$count]); #split at : $seconds[$count]=$part[0]*3600+$part[1]*60+$part[2]; # Sekunden # print $seconds[$count]." "; $deltat=$seconds[$count]-$seconds[$count-1]; $s_max=$s[$count]; # total distance if($h[$count]>$h_max){$h_max=$h[$count];} # maximum height if($h[$count]<$minus*$shift) {$shift=$minus*$h[$count];} # negative heights? if ($count>1) # ab 2. Datenpunkt { $v[$count]=($s[$count]-$s[$count-1])/$deltat; # speed if ($v[$count]>$minspeed){$sums=$sums+($s[$count]-$s[$count-1]);$sumt=$sumt+$deltat;} # if v > minimum speed sum up distance if ($h[$count]-$h[$count-1]>$mindeltah){$sumh=$sumh+($h[$count]-$h[$count-1]);} # if delta h > x m count height $climbp[$count]=($h[$count]-$h[$count-1])*$g*$W/$deltat; # climb $accelp[$count]=$W/2*($v[$count]**2-$v[$count-1]**2)/$deltat; # accel $airp[$count]=$cw/2*$rho*$v[$count]**3; # air $rollp[$count]=$roll*$W*$g*$v[$count]; # roll $power[$count]=$climbp[$count]+$accelp[$count]+$airp[$count]+$rollp[$count]; # total power if ($power[$count]<0){$power[$count]=0;} # negative power means braking! if ($v[$count]>$minspeed){$work=$work+$power[$count]*20;} # if v > minimum speed sum up work } printf GOUTPUT ("%.2f $h[$count] %.2f $power[$count] $rollp[$count] $climbp[$count] $accelp[$count] $airp[$count] \n",$s[$count]/1000,$v[$count]*3.6); } } } if($sumt<600){unlink("$filecore.png"); printf STDOUT "Too little data to plot\n"; next;} # too little data to plot! # Durchschnittsgeschw.: $geschw=int($sums/$sumt*360)/100; # Durchschnittsleistung: $leistung=int($work/$sumt); # NO NEGATIVE HEIGHTS! $i=0; while ($i < $count) { $i++; $h[$i]=$h[$i]+$shift; } $h_max=$h_max+$shift; ########################### print with libgd here: # Picture Sizes: $xoff=20; # left offset $legend=110; # key width $xres=$s_max/50+$xoff+$legend; # picture width if ($xres<$xoff+$legend+360){$xres=$xoff+$legend+360;} # minimum picture width $xpart=$xres-$xoff-$legend; # drawing width $ypart=sqrt($h_max)*20; # drawing height $yres=$ypart+80; # picture height if ($yres<260){$yres=260;} # minimum picture height $yoff=$yres-40; # bottom offset # create a new image $img = GD::Simple->new($xres,$yres); $img->bgcolor('white'); $img->fgcolor('blue'); # allocate some colors $col1= $img->colorAllocate(0,16,48); #<-11 $col2= $img->colorAllocate(0,8,128); #-10 $col3= $img->colorAllocate(0,0,255); #-8 $col4= $img->colorAllocate(0,128,255); #-6 $col5= $img->colorAllocate(0,192,224); #-4 $col6= $img->colorAllocate(48,224,224); #-2 $col7= $img->colorAllocate(224,224,224); #0 $col8= $img->colorAllocate(224,224,48); #+2 gelb $col9= $img->colorAllocate(224,192,0); #+4 orange $col10= $img->colorAllocate(255,128,0); #+6 $col11= $img->colorAllocate(255,0,0); #+8 rot $col12= $img->colorAllocate(128,8,0); #+10 $col13= $img->colorAllocate(48,16,0); #>+11 #START NAME AND HEIGHT: $img->angle(-90); $img->fgcolor('black');$img->bgcolor('black'); $img->moveTo($xoff-1,$yoff+22); $img->string('- ' . $start . " - " . $h[1] . "m"); $img->angle(0); #TITLE AND HM: $img->fgcolor('black');$img->bgcolor('black'); $img->moveTo($xres*0.5-210,15); $img->string($date . " - " . $title . " - " . $sumh . " Hm" . " " . $geschw . " km/h" . " " . $leistung . " W" . " " . $celsius . " C"); $h_finish=$h[$count]; $maxcount=$count; $count=0; $minsteig=0; $maxsteig=0; $h[0]=$h[1]; $s[0]=$s[1]; $olds=$s[1]; $oldh=$h[1]; #PRINT PROFILE: while ($count < $maxcount) { $count++; if($s[$count]-$olds < $steigdist){next;} # Teilstrecke lang genug f�r Plot? $steig[$count] = ($h[$count]-$oldh) / ($s[$count]-$olds) *100 ; # Steigung if($steig[$count] < $minsteig){$minsteig=$steig[$count]} # maximales Gef�lle if($steig[$count] > $maxsteig){$maxsteig=$steig[$count]} # maximale Steigung $img->fgcolor($col1);$img->bgcolor($col1); if ($steig[$count]>-11){$img->fgcolor($col2);$img->bgcolor($col2);} if ($steig[$count]>-9){$img->fgcolor($col3);$img->bgcolor($col3);} if ($steig[$count]>-7){$img->fgcolor($col4);$img->bgcolor($col4);} if ($steig[$count]>-5){$img->fgcolor($col5);$img->bgcolor($col5);} if ($steig[$count]>-3){$img->fgcolor($col6);$img->bgcolor($col6);} if ($steig[$count]>-1){$img->fgcolor($col7);$img->bgcolor($col7);} if ($steig[$count]>1){$img->fgcolor($col8);$img->bgcolor($col8);} if ($steig[$count]>3){$img->fgcolor($col9);$img->bgcolor($col9);} if ($steig[$count]>5){$img->fgcolor($col10);$img->bgcolor($col10);} if ($steig[$count]>7){$img->fgcolor($col11);$img->bgcolor($col11);} if ($steig[$count]>9){$img->fgcolor($col12);$img->bgcolor($col12);} if ($steig[$count]>11){$img->fgcolor($col13);$img->bgcolor($col13);} my $poly = new GD::Polygon; # print "s_max=$s_max xpart=$xpart h_max=$h_max ypart=$ypart s(count)=$s[$count]\n"; # debug $poly->addPt($xoff+($s[$count]/$s_max*$xpart),$yoff-($h[$count]/$h_max*$ypart)); #ro $poly->addPt($xoff+($olds/$s_max*$xpart),$yoff-($oldh/$h_max*$ypart)); #lo $poly->addPt($xoff+($olds/$s_max*$xpart),$yoff); #lu $poly->addPt($xoff+($s[$count]/$s_max*$xpart),$yoff); #ru $img->penSize(1,1); $img->polygon($poly); $olds=$s[$count]; $oldh=$h[$count]; } #PRINT SPEED 0-$maxspeed km/h: $img->fgcolor($col12); $count=1; $olds=$s[1]; $oldv=$v[1]; while ($count < $maxcount) { $count++; $img->moveTo($xoff+($olds/$s_max*$xpart),$yoff-($oldv/$maxspeed*3.6*$ypart)); $img->lineTo($xoff+($s[$count]/$s_max*$xpart),$yoff-($v[$count]/$maxspeed*3.6*$ypart)); # speed # print "s_max=$s_max xpart=$xpart h_max=$h_max ypart=$ypart s(count)=$s[$count]\n"; # debug $olds=$s[$count]; $oldv=$v[$count]; } #HIGHT LINES AND SPEED: $img->fgcolor('black'); $height=0; $hdiff=20; # Linienabstand Höhenmeter if($h_max>200){$hdiff=int($h_max/100)*10;} if($h_max>1000){$hdiff=int($h_max/1000)*100;} while ($height < $h_max-$hdiff/2) { $img->moveTo($xoff+0,$yoff-($height/$h_max*$ypart)); $img->string($height . 'm' . ' ' . int($height/$h_max*$maxspeed) . 'km/h'); $img->lineTo($xres-$legend,$yoff-($height/$h_max*$ypart)); $height=$height+$hdiff; } #PRINT HIGHEST AND LOWEST SLOPES $count=0; $alt=1; $h[0]=$h[1]; $s[0]=$s[1]; $olds=$s[1]; $oldh=$h[1]; $img->angle(-90); while ($count < $maxcount) { $count++; if($s[$count]-$olds < $steigdist){next;} $steig[$count] = ($h[$count]-$oldh) / ($s[$count]-$olds) *100 ; #Steigung if($steig[$count]>$maxsteig*0.9 || $steig[$count]<$minsteig*0.9 || abs($steig[$count])>9.9999) { $steig=abs(int($steig[$count]*10)/10); # if($steig<2){break;} $img->fgcolor('white'); $img->moveTo($xoff+9+($olds/$s_max*$xpart),$yoff-1); $img->string($steig . '%'); $img->moveTo($xoff+7+($olds/$s_max*$xpart),$yoff-1); $img->string($steig . '%'); $img->moveTo($xoff+9+($olds/$s_max*$xpart),$yoff+1); $img->string($steig . '%'); $img->moveTo($xoff+7+($olds/$s_max*$xpart),$yoff+1); $img->string($steig . '%'); $img->fgcolor('black'); $img->moveTo($xoff+8+($olds/$s_max*$xpart),$yoff); $img->string($steig . '%'); $alt=$alt*(-1); } $olds=$s[$count]; $oldh=$h[$count]; } $img->angle(0); #H_MAX: $img->moveTo($xoff+0,$yoff-($ypart)); $img->string($h_max . 'm' . ' ' . $maxspeed . 'km/h'); $img->lineTo($xres-$legend,$yoff-($ypart)); #KM: $img->fgcolor('black'); $img->angle(-90); $dist=0; $bw=1; while ($dist < $s_max-$distdiff) { #LINIE UND ZAHL: $img->fgcolor('black');$img->bgcolor('black'); $img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+32); $img->string($dist/1000); $img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+28); #unten $img->lineTo($xoff+$dist/$s_max*$xpart,$yoff); #oben #EISENBAHNFELD: my $poly = new GD::Polygon; if($bw<0){$img->bgcolor('white');} $poly->addPt($xoff+$dist/$s_max*$xpart,$yoff); #lo $poly->addPt($xoff+($dist+$distdiff)/$s_max*$xpart,$yoff); #ro $poly->addPt($xoff+($dist+$distdiff)/$s_max*$xpart,$yoff+5); #ru $poly->addPt($xoff+$dist/$s_max*$xpart,$yoff+5); #lu $img->penSize(1,1); $img->polygon($poly); $bw=$bw*(-1); #B/W-Flag #WEITERGEHEN: $dist=$dist+$distdiff; } #LETZTE LINIE UND ZAHL: $img->fgcolor('black');$img->bgcolor('black'); $img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+32); $img->string($dist/1000); $img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+28); #unten $img->lineTo($xoff+$dist/$s_max*$xpart,$yoff); #oben #LETZTES EISENBAHNFELD: my $poly = new GD::Polygon; if($bw<0){$img->bgcolor('white');} $poly->addPt($xoff+$dist/$s_max*$xpart,$yoff); #lo $poly->addPt($xoff+$s_max/$s_max*$xpart,$yoff); #ro $poly->addPt($xoff+$s_max/$s_max*$xpart,$yoff+5); #ru $poly->addPt($xoff+$dist/$s_max*$xpart,$yoff+5); #lu $img->penSize(1,1); $img->polygon($poly); #S_MAX UND FINISH NAME AND HEIGHT: $img->fgcolor('black');$img->bgcolor('black'); $img->moveTo($xoff+14+$xpart,$yoff+32); $img->string($s_max/1000 . 'km - ' . $finish . " - " . $h_finish . "m"); $img->moveTo($xoff+$s_max/$s_max*$xpart,$yoff+28); $img->lineTo($xoff+$s_max/$s_max*$xpart,$yoff); #LEGENDE: $img->angle(0); my $poly2 = new GD::Polygon; $img->fgcolor($col1);$img->bgcolor($col1); $poly2->addPt($xres-20,0); $poly2->addPt($xres,0); $poly2->addPt($xres,20); $poly2->addPt($xres-20,20); $img->polygon($poly2); $img->fgcolor('black'); $img->moveTo( $xres-60,17 ); $img->string('< -11%'); my $poly3 = new GD::Polygon; $img->fgcolor($col2);$img->bgcolor($col2); $poly3->addPt($xres-20,20); $poly3->addPt($xres,20); $poly3->addPt($xres,40); $poly3->addPt($xres-20,40); $img->polygon($poly3); $img->fgcolor('black'); $img->moveTo( $xres-90,37 ); $img->string('-11% - -9%'); my $poly4 = new GD::Polygon; $img->fgcolor($col3);$img->bgcolor($col3); $poly4->addPt($xres-20,40); $poly4->addPt($xres,40); $poly4->addPt($xres,60); $poly4->addPt($xres-20,60); $img->polygon($poly4); $img->fgcolor('black'); $img->moveTo( $xres-90,57 ); $img->string('-9% - -7%'); my $poly5 = new GD::Polygon; $img->fgcolor($col4);$img->bgcolor($col4); $poly5->addPt($xres-20,60); $poly5->addPt($xres,60); $poly5->addPt($xres,80); $poly5->addPt($xres-20,80); $img->polygon($poly5); $img->fgcolor('black'); $img->moveTo( $xres-84,77 ); $img->string('-7% - -5%'); my $poly6 = new GD::Polygon; $img->fgcolor($col5);$img->bgcolor($col5); $poly6->addPt($xres-20,80); $poly6->addPt($xres,80); $poly6->addPt($xres,100); $poly6->addPt($xres-20,100); $img->polygon($poly6); $img->fgcolor('black'); $img->moveTo( $xres-84,97 ); $img->string('-5% - -3%'); my $poly7 = new GD::Polygon; $img->fgcolor($col6);$img->bgcolor($col6); $poly7->addPt($xres-20,100); $poly7->addPt($xres,100); $poly7->addPt($xres,120); $poly7->addPt($xres-20,120); $img->polygon($poly7); $img->fgcolor('black'); $img->moveTo( $xres-84,117 ); $img->string('-3% - -1%'); my $poly8 = new GD::Polygon; $img->fgcolor($col7);$img->bgcolor($col7); $poly8->addPt($xres-20,120); $poly8->addPt($xres,120); $poly8->addPt($xres,140); $poly8->addPt($xres-20,140); $img->polygon($poly8); $img->fgcolor('black'); $img->moveTo( $xres-84,137 ); $img->string('-1% - +1%'); my $poly9 = new GD::Polygon; $img->fgcolor($col8);$img->bgcolor($col8); $poly9->addPt($xres-20,140); $poly9->addPt($xres,140); $poly9->addPt($xres,160); $poly9->addPt($xres-20,160); $img->polygon($poly9); $img->fgcolor('black'); $img->moveTo( $xres-84,157 ); $img->string('+1% - +3%'); my $poly10 = new GD::Polygon; $img->fgcolor($col9);$img->bgcolor($col9); $poly10->addPt($xres-20,160); $poly10->addPt($xres,160); $poly10->addPt($xres,180); $poly10->addPt($xres-20,180); $img->polygon($poly10); $img->fgcolor('black'); $img->moveTo( $xres-84,177 ); $img->string('+3% - +5%'); my $poly11 = new GD::Polygon; $img->fgcolor($col10);$img->bgcolor($col10); $poly11->addPt($xres-20,180); $poly11->addPt($xres,180); $poly11->addPt($xres,200); $poly11->addPt($xres-20,200); $img->polygon($poly11); $img->fgcolor('black'); $img->moveTo( $xres-84,197 ); $img->string('+5% - +7%'); my $poly12 = new GD::Polygon; $img->fgcolor($col11);$img->bgcolor($col11); $poly12->addPt($xres-20,200); $poly12->addPt($xres,200); $poly12->addPt($xres,220); $poly12->addPt($xres-20,220); $img->polygon($poly12); $img->fgcolor('black'); $img->moveTo( $xres-84,217 ); $img->string('+7% - +9%'); my $poly13 = new GD::Polygon; $img->fgcolor($col12);$img->bgcolor($col12); $poly13->addPt($xres-20,220); $poly13->addPt($xres,220); $poly13->addPt($xres,240); $poly13->addPt($xres-20,240); $img->polygon($poly13); $img->fgcolor('black'); $img->moveTo( $xres-90,237 ); $img->string('+9% - +11%'); my $poly14 = new GD::Polygon; $img->fgcolor($col13);$img->bgcolor($col13); $poly14->addPt($xres-20,240); $poly14->addPt($xres,240); $poly14->addPt($xres,260); $poly14->addPt($xres-20,260); $img->polygon($poly14); $img->fgcolor('black'); $img->moveTo( $xres-60,257 ); $img->string('> +11%'); print OUTPUT $img->png; close OUTPUT; close GOUTPUT; close INPUT; if (-z "$filecore.png"){remove("$filecore.png")}; ########################### print with gnuplot here: open(GNUPLOT,"|gnuplot ") || die("can't call gnuplot \n"); GNUPLOT->autoflush(1); print GNUPLOT <<"--END--"; set term png enhanced large size 1280,800 set out "gnuplot.png" set grid set mxtics 5 set lmargin 5 set rmargin 4 set tmargin 0 set bmargin 2 set style data lines set multiplot set size 1,0.32 set origin 0,0 plot "gnuplot.dat" using 1:4 title "Leistung [W]" linewidth 3 lt 2 replot "gnuplot.dat" using 1:4 smooth bezier title "ca. Leistung [W]" linewidth 3 lt 1 #unset xtics set origin 0,0.32 plot "gnuplot.dat" using 1:3 title "Geschw. [km/h]" linewidth 3 lt 3 set origin 0,0.64 set title "$date $title (von $start nach $finish) $sumh Hm $geschw km/h $leistung W $celsius C" 0,-1 plot "gnuplot.dat" using 1:2 title 'Hoehe [m]' linewidth 3 lt -1 #replot "gnuplot.dat" using 1:5 title "Rollwiderstand [W]" linewidth 3 #replot "gnuplot.dat" using 1:6 title "Steigleistung [W]" linewidth 3 #replot "gnuplot.dat" using 1:7 title "Beschl.leistung [W]" linewidth 3 #replot "gnuplot.dat" using 1:8 title "Luftwiderstand [W]" linewidth 3 --END-- close(GNUPLOT); rename "gnuplot.png","$filecore-data.png"; unlink("gnuplot.dat"); } exit(0);