Radreise-Wiki:Km.pl
Aus Radreise-Wiki
Version vom 24. Mai 2011, 17:12 Uhr von Aighes (Diskussion | Beiträge)
Das Perl-Skript km.pl wird mit dem Streckennamen als Parameter aufgerufen. Die zugehörige Streckendatei muss bereits im text- und die Trackdatei im track-Verzeichnis vorhanden sein. Beispiel für einen Aufruf:
perl km.pl Donau
Das Skript berechnet die Kilometrierung und speichert das Ergebnis als Datei im Output-Verzeichis (siehe ini.pl). Die Datei "Donau_new.tx" enthält das neue Roadbook kann mit einem UTF8-fähigen Editor geöffnet und direkt in das Edit-Fenster des Streckenartikels kopiert werden. Die Datei "Donau_ret.tx" beinhaltet ein neues Retour-Roadbook und wird nur gebraucht, wenn ein neues Retour-Roadbook erstellt werden soll.
use strict; # Encoding Stuff use Encode qw(encode decode); my $encoding = 'utf-8'; my $encOut; $encOut = 'cp1252'; # Windows Ansi $encOut = 'cp850' ; # DOS Fenster use URI::Escape qw( uri_escape_utf8 ); # Default Directories require "ini.pl"; my ($baseDir, $outDir, $username, $password) = getIni(); my $routeFileName = ""; if ($#ARGV != -1) { $routeFileName = join " ", @ARGV; if ($routeFileName =~ / \($/) { $routeFileName .= "retour)"; } } else { my @content; open FIN, "$baseDir/RouteList.txt" or die "$! : $baseDir/RouteList.txt"; while (<FIN>) { push @content, decode $encoding, $_; } close (FIN); my @content_s = reverse sort @content; my ($dateTXT, $dateKML, $type, $name, $url) = split " :: ", $content_s[0]; $routeFileName = $name; } my $routeFileName_e = encode 'cp1252', $routeFileName; #=================== # Reading Trackfile print encode $encOut, "\nReading $routeFileName:\n\n"; open FIN, "$baseDir/tracks/$routeFileName_e.txt" or die "$! : $baseDir/tracks/$routeFileName_e.txt"; my $rawTrack = <FIN>; close (FIN); my @rawTrack = split " ", $rawTrack; my @track = (); foreach (@rawTrack) { my ($lon, $lat, $alt) = split ","; my @zeile = ( $lat, $lon, $alt ); my $ref_zeile = \@zeile; push @track, $ref_zeile; } #========================== # x-fache Glättung der Höhen for (my $j = 1; $j <= 12; $j++) { for (my $i = 1; $i < $#track ; $i++) { my $avgAlt = ($track[$i-1][2] + $track[$i][2] + $track[$i+1][2]) / 3; $track[$i][2] = $avgAlt; } } #===================== # Tracklänge berechnen my $length_0 = getDistance ( $track[0][0], # Erster Punkt : lat $track[0][1], # Erster Punkt : lon $track[$#rawTrack][0], # Letzter Punkt: lat $track[$#rawTrack][1] # Letzter Punkt: lon ); my $length_1 = 0; for (my $i = 0; $i < $#track ; $i++) { my $dist = getDistance ( $track[$i][0], $track[$i][1], $track[$i+1][0], $track[$i+1][1] ); $length_1 += $dist; } #============================= # Gesamt-Höhenmeter berechnen my ($HmSumUp, $HmSumDn) = getHmSum (0, $#track); #============================= # Ausgabe der Track-Statistik print "Trackpunkte : ", $#track + 1, "\n"; printf "Luftlinie : %4.0f km\n", $length_0; printf "Strecke : %4.0f km\n", $length_1; #unless ($length_0) { printf "Ratio : %6.1f\n", $length_1 / $length_0; } printf "Hm auf : %4.0f m\n", $HmSumUp; printf "Hm ab : %4.0f m\n\n",$HmSumDn; # ============================ # Get $routeFileName Textfile my $ucontent = ""; open FILE, "$baseDir/text/$routeFileName_e.txt" or die "$baseDir/text/$routeFileName_e.txt: $!"; while (<FILE>) { $ucontent .= $_; } close FILE; my $fileContent = decode ($encoding, $ucontent); # ============ # Get Infobox if ( $fileContent =~ /(\{\{Infobox.*?\}\})/s ) { my $infobox = $1; print encode $encOut, "$infobox\n\n"; } # ============= # Get Roadbook my $pre_Roadbook; my $Roadbook; my $post_Roadbook; if ( $fileContent =~ /(.*?== Roadbook ==.*?)(===.*?)(\n== .*)/s ) { $pre_Roadbook = $1; $Roadbook = $2; $post_Roadbook = $3; } else { die "Wrong Roadbook Format\n"; } my @Roadbook = split "\n", $Roadbook; # =============== # Get Placemarks my @Placemarks = (); my $placemark = ""; my @PlacemarksRaw = (); my $placemarkRaw = ""; foreach my $line (@Roadbook) { if ($line =~ /^=== .* ===$/) { if ($placemark ne "") { push @Placemarks , $placemark; push @PlacemarksRaw, $placemarkRaw; } $placemarkRaw = "$line\n"; $placemark = $line ; } else { $placemarkRaw .= "$line\n"; $placemark .= $line ; } } push @Placemarks , $placemark; push @PlacemarksRaw, $placemarkRaw; # ================= # Check Placemarks my @PlaceName ; my @TouriInfo ; my @GeoData ; my @TrackPoint; my @Distance ; my @RoadInfo ; my @Kilometer ; my @RealKilo ; for (my $i=0; $i<=$#Placemarks; $i++) { my $placeName; my $touriInfo; my $geoData ; my $roadInfo ; my $kilometer; my $rest; my $lat; my $lon; my $alt; my $info; my $deltaKilo; my $sumKilo; if ( $Placemarks[$i] =~ / ^===\ (.*)\ === # placeName (.*) # touriInfo {{Geodaten\|(.*)}} # geoData (.*) # roadInfo {{Kilometrierung[Hm]*\|(.*)}}(.*)$ # kilometer /x ) { $placeName = $1; $touriInfo = $2; $geoData = $3; $roadInfo = $4; $kilometer = $5; $rest = $6; # =============== # Check: geoData if ($geoData =~ /^([-]?\d+\.\d+)\|([-]?\d+\.\d+)\|([-]?\d+)\|([^\|]+)$/) { $lat = $1; $lon = $2; $alt = $3; $info = $4; } else { print "Error in geoData: $geoData\n"; exit; } # ================= # Check: Kilometer if ($kilometer =~ /([\d,]+)\|([\d]+)/) { $deltaKilo = $1; $sumKilo = $2; } else { print "Error in kilometer: $kilometer\n"; exit; } } elsif (( $i == $#Placemarks ) and ( $Placemarks[$i] =~ / ^===\ (.*)\ === # placeName (.*) # touriInfo {{Geodaten\|(.*)}} # geoData (.*) # roadInfo /x )) { $placeName = $1; $touriInfo = $2; $geoData = $3; $roadInfo = $4; # =============== # Check: geoData if ($geoData =~ /(.*)\|(.*)\|(.*)\|(.*)/) { $lat = $1; $lon = $2; $alt = $3; $info = $4; } else { print "Error in geoData: $geoData\n"; exit; } # ================== # Kilometer Dummies $deltaKilo = " "; $sumKilo = " "; } elsif ( $Placemarks[$i] =~ / ^===\ (.*)\ === # placeName (.*) # touriInfo {{Geodaten\|(.*)}} # geoData (.*) # roadInfo /x ) { $placeName = $1; $touriInfo = $2; $geoData = $3; $roadInfo = $4; # =============== # Check: geoData if ($geoData =~ /(.*)\|(.*)\|(.*)\|(.*)/) { $lat = $1; $lon = $2; $alt = $3; $info = $4; } else { print "Error in geoData: $geoData\n"; exit; } # ================== # Kilometer Dummies $deltaKilo = "x,x"; $sumKilo = "x"; } else { print encode $encoding, "Untreated Error: $Placemarks[$i]\n"; exit; } my ($trackPoint, $distance) = getClosestPoint ( $lat, $lon ); if ($distance < 200) { #$distance = " "; } else { $distance .= "!!!"; } push @PlaceName , $placeName; push @TouriInfo , $touriInfo; push @GeoData , sprintf "%10.7f %10.7f", $lat, $lon; push @TrackPoint, sprintf "%5d", $trackPoint; push @Distance , sprintf "%3.0f m", $distance; push @RoadInfo , $roadInfo; push @Kilometer , sprintf "%4s %4s", $deltaKilo, $sumKilo; } # ========================= # Calculate real Distances my $sum; my $HmTotSumUp; my $HmTotSumDn; for (my $i=0; $i < $#Placemarks; $i++) { my $length; for (my $j = $TrackPoint[$i]; $j < $TrackPoint[$i+1] ; $j++) { my $dist = getDistance ( $track[$j][0], $track[$j][1], $track[$j+1][0], $track[$j+1][1] ); $length += $dist; } $sum += $length; my $realKilo = sprintf "%4.1f %4.0f", $length, $sum; $realKilo =~ s/\./,/; if ($Kilometer[$i] eq $realKilo) { $realKilo = " "; $Kilometer[$i] = " "; } push @RealKilo, $realKilo; my ($HmSumUp, $HmSumDn) = getHmSum ($TrackPoint[$i], $TrackPoint[$i+1]); printf "%s;%0.0f;%0.0f;%0.0f;%0.0f\n", encode ($encOut, $PlaceName[$i]),$length,$HmSumUp,$HmSumDn,$track[$TrackPoint[$i]][2]; $HmTotSumUp += $HmSumUp; $HmTotSumDn += $HmSumDn; } push @RealKilo, " "; printf "GesamtHm: %0.0f;%0.0f\n", $HmTotSumUp,$HmTotSumDn; print "\n"; # ===================================== # Check ascending order of TrackPoints for (my $i=0; $i<$#Placemarks; $i++) { if ( $TrackPoint[$i] <= $TrackPoint[$i+1] ) { #ok } else { print encode $encOut, "Error: Wrong TrackPoint Order in:\n"; print encode $encOut, "$PlaceName[$i] :: $GeoData[$i] :: $TrackPoint[$i]\n"; print encode $encOut, "$PlaceName[$i+1] :: $GeoData[$i+1] :: $TrackPoint[$i+1]\n"; #exit(1); } } # ===================== # Show Change Overview for (my $i=0; $i<=$#Placemarks; $i++) { my $s = sprintf "%s %s %s %s %s\n", $TrackPoint[$i], $Distance[$i], $Kilometer[$i], $RealKilo[$i], substr($PlaceName[$i], 0, 52); print encode $encOut, $s; } print "\n"; # ====================== # Perform Changes on File my $change = 0; for (my $i=0; $i<=$#Placemarks; $i++) { if ( $RealKilo[$i] !~ /^\s*$/ ) { print encode $encOut, "Change: $PlaceName[$i]\n"; my $deltaKiloNew; my $sumKiloNew; if ( $RealKilo[$i] =~ /^\s*([0-9,]+)\s+([0-9]+)$/ ) { $deltaKiloNew = $1; $sumKiloNew = $2; } else { print " No Match: >$RealKilo[$i]<\n"; exit; } my $deltaKiloOld; my $sumKiloOld; if ( $Kilometer[$i] =~ /^\s*([0-9,]+)\s+([0-9]+)$/ ) { $deltaKiloOld = $1; $sumKiloOld = $2; if ($fileContent =~ s/{{Kilometrierung\|$deltaKiloOld\|$sumKiloOld}}/{{Kilometrierung\|$deltaKiloNew\|$sumKiloNew}}/s) { print " $deltaKiloOld->$deltaKiloNew\n"; print " $sumKiloOld->$sumKiloNew\n"; $change = 1; } else { print " No Match in km!\n"; exit; } } elsif ( $Kilometer[$i] =~ /^\s*x,x\s+x$/ ) { if ($fileContent =~ s/=== $PlaceName[$i+1] ===/{{Kilometrierung\|$deltaKiloNew\|$sumKiloNew}}\n\n=== $PlaceName[$i+1] ===/s) { print " No Kilometrierung ->$deltaKiloNew\n"; print " No Kilometrierung ->$sumKiloNew\n"; $change = 1; } else { print " No Match! $PlaceName[$i+1]\n{{Kilometrierung\|$deltaKiloNew\|$sumKiloNew}}\n"; #exit; } } else { print " No Match: >$Kilometer[$i]<\n"; exit; } } } if ($change) { open FOUT, "> $outDir/${routeFileName_e}_new.tx" or die $!; print FOUT encode ($encoding, $fileContent); close FOUT; } # ================================== # Generate Retour-Roadbook with Track my $content; $content .= "{{Tour|$routeFileName}}\n\n"; $content .= $pre_Roadbook; for (my $i=$#Placemarks; $i>=0; $i--) { my $placemark = $PlacemarksRaw[$i]; if ( $placemark =~ /(.+{{Geodaten.*?}})/s ) { $placemark = $1; } else { print "No match in Placemark: $placemark\n"; exit; } if ($i > 0) { $placemark .= "\n\n{{Kilometrierung|0,0|0}}\n"; } $content .= "$placemark\n"; } $content .= $post_Roadbook; $content =~ s/\n\n\n/\n\n/g; $rawTrack = join " ", reverse @rawTrack; $content .= "\n$routeFileName (retour) :: $routeFileName\_%28retour%29 :: $rawTrack\n"; open FOUT, "> $outDir/${routeFileName_e}_ret.tx" or die $!; print FOUT encode ($encoding, $content); close FOUT; exit; #========================================================== #========================================================== sub getDistance { use POSIX qw(acos); my ($tp1_lat, $tp1_lon, $tp2_lat, $tp2_lon) = @_; my $PI = 3.1415926; my $lat1 = $tp1_lat / 180 * $PI; my $lon1 = $tp1_lon / 180 * $PI; my $lat2 = $tp2_lat / 180 * $PI; my $lon2 = $tp2_lon / 180 * $PI; my $val = sin($lat1) * sin($lat2) + cos($lat1) * cos($lat2) * cos($lon2-$lon1); if ($val > +1) { $val = +1; #print " ACOS-Error: $tp1_lon,$tp1_lat !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; } if ($val < -1) { $val = -1; #print " ACOS-Error: $tp1_lon,$tp1_lat !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; } my $dist = acos($val) * 6378.137; # radius of the equator in km #if (Double.isNaN(dist)) dist = 0; return $dist; } #========================================================== sub getClosestPoint { my ($tp_lat, $tp_lon) = @_; my $minDist = 111111111; my $point = -1; for (my $i = 0; $i <= $#track ; $i++) { my $dist = getDistance ( $track[$i][0], $track[$i][1], $tp_lat, $tp_lon ); if ($dist < $minDist) { $minDist = $dist; $point = $i; } } return ($point, $minDist*1000); } #========================================================== sub getHmSum { my ($tp_begin, $tp_end) = @_; if ($tp_end >= $#track) { $tp_end = $#track-1; } my $HmSumUp = 0; my $HmSumDn = 0; for (my $i = $tp_begin; $i <= $tp_end ; $i++) { my $alt_0 = $track[$i][2]; my $alt_1 = $track[$i+1][2]; my $diff = $alt_1 - $alt_0; if ($diff < 0) { $HmSumDn += $diff * (-1); } if ($diff > 0) { $HmSumUp += $diff * (+1); } } return ($HmSumUp, $HmSumDn); }