Radreise-Wiki:MakeGoogleMapsOverview.pl: Unterschied zwischen den Versionen

Aus Radreise-Wiki
Zeile 18: Zeile 18:
# Important Control-Flags
# Important Control-Flags


my $showNodes = 1;
my $showNodes = 0;
my $accuracy  = 000;
my $accuracy  = 1000;


#==================
#==================

Version vom 17. November 2012, 21:20 Uhr

Das Perl-Skript makeGoogleMapsOverview.pl generiert ein KMZ-File mit der Übersicht aller Wiki-Strecken des Hauptnetzes. Zusätzlich wird die Konsistenz der Knotenpunkte (Anschlüsse) überprüft. Mit der erzeugten Radfernwege_Übersicht.kml können fehlende Anschlusspunkte schnell gefunden werden.

Einstellungen:

  • my $showNodes = 0; Es werden keine Ortspunkte im Output-File gespeichert
  • my $accuracy = 1000; Auflösung der Tracks in Meter.

Die generierte Datei kann als KMZ ins Wiki hochgeladen werden (siehe Datei:Radfernwege Übersicht.kmz).

Quellcode des Skripts:

use strict;

use Encode qw(encode decode);

#=========================
# Important Control-Flags

my $showNodes = 0;
my $accuracy  = 1000;

#==================
# Default Settings

require "ini.pl";
my ($baseDir, $outDir, $username, $password, $encoding, $encAnsi, $encOut) = getIni();

my $dir_txt = "$baseDir/text";
my $dir_kml = "$baseDir/kml";

#==========================
# Parsing aller Routefiles

my $fileCounter = 0;

my $routeName;
my $routeFileName;
my $routeURL;
my $category;

# ==================
# Reading RouteList

my @routeList;

open FIN, "$baseDir/RouteList.txt" or die "$! : $baseDir/RouteList.txt";
while (<FIN>) { push @routeList, decode $encoding, $_; }
close (FIN);

my @routeFile               = ();
my @Fluss_Radfernweg        = ();
my @Anderer_Radfernweg      = ();
my @Querverbindung          = ();
my @Direktverbindung        = ();
my @Regionaler_Radwanderweg = ();

my @AnschlussPlacemarks     = ();
my @RestPlacemarks          = ();

foreach my $line (@routeList) {

	(my $dateTXT, my $dateKML, my $type, $routeName) = split " :: ", $line;

	if ($type eq "H") {

		chomp($routeName);

		$routeFileName = encode $encAnsi, $routeName;

		$routeURL = encodeRouteNameURL($routeFileName);

		&process_txt_file;
		&saveRouteFile;
	}
}

print "\n   $fileCounter Route-Files found\n\n";

#==========================================================
# Generieren des Overview-Files

my   @rfwAllFile = ();

push @rfwAllFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
push @rfwAllFile, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n";
push @rfwAllFile, "<Document>\n";

push @rfwAllFile, "<Style id=\"green_site\">\n";
push @rfwAllFile, "	<IconStyle>\n";
push @rfwAllFile, "		<color>ff00f00f</color>\n";
push @rfwAllFile, "		<scale>0.8</scale>\n";
push @rfwAllFile, "		<Icon>\n";
push @rfwAllFile, "			<href>D:/a/data/Radfernwege-Wiki/Tracks/placemark_circle.png</href>\n";
push @rfwAllFile, "		</Icon>\n";
push @rfwAllFile, "	</IconStyle>\n";
push @rfwAllFile, "	<LabelStyle>\n";
push @rfwAllFile, "		<scale>0.5</scale>\n";
push @rfwAllFile, "	</LabelStyle>\n";
push @rfwAllFile, "</Style>\n";

push @rfwAllFile, "	<name>Radfernwege_Übersicht</name>\n";
push @rfwAllFile, "	<open>1</open>\n";

push @rfwAllFile, "	<Folder>\n";
push @rfwAllFile, "		<name>Fluss-Radfernweg</name>\n";
push @rfwAllFile, "		<open>0</open>\n";
push @rfwAllFile, @Fluss_Radfernweg;
push @rfwAllFile, "	</Folder>\n";

push @rfwAllFile, "	<Folder>\n";
push @rfwAllFile, "		<name>Anderer Radfernweg</name>\n";
push @rfwAllFile, "		<open>0</open>\n";
push @rfwAllFile, @Anderer_Radfernweg;
push @rfwAllFile, "	</Folder>\n";

push @rfwAllFile, "	<Folder>\n";
push @rfwAllFile, "		<name>Querverbindung</name>\n";
push @rfwAllFile, "		<open>0</open>\n";
push @rfwAllFile, @Querverbindung;
push @rfwAllFile, "	</Folder>\n";

push @rfwAllFile, "	<Folder>\n";
push @rfwAllFile, "		<name>Direktverbindung</name>\n";
push @rfwAllFile, "		<open>0</open>\n";
push @rfwAllFile, @Direktverbindung;
push @rfwAllFile, "	</Folder>\n";

#=============================
# Bestimmung der Knotenpunkte

if ($showNodes) {

	my %nodes;
	my $warning = 0;

	push @rfwAllFile, "	<Folder>\n";
	push @rfwAllFile, "		<name>Knotenpunkte</name>\n";
	push @rfwAllFile, "		<open>0</open>\n";

	for (my $i=0; $i<=$#AnschlussPlacemarks; $i++) {

		#unless ($warning) { print $#AnschlussPlacemarks-$i, "\n"; }

		for (my $j=0; $j<$i; $j++) {

			if ($AnschlussPlacemarks[$i][0] ne $AnschlussPlacemarks[$j][0]) {

				my $dist = getDistance ( $AnschlussPlacemarks[$i][2], $AnschlussPlacemarks[$i][3], $AnschlussPlacemarks[$j][2], $AnschlussPlacemarks[$j][3] );

				if ($dist < 20) {
					push @rfwAllFile, "			<Placemark>\n";
					push @rfwAllFile, "				<name>$AnschlussPlacemarks[$i][1] :: $AnschlussPlacemarks[$i][0]</name>\n";
					push @rfwAllFile, "				<styleUrl>green_site</styleUrl>\n";
					push @rfwAllFile, "				<visibility>0</visibility>\n";
					push @rfwAllFile, "				<Point>\n";
					push @rfwAllFile, "					<coordinates>\n";
					push @rfwAllFile, "						$AnschlussPlacemarks[$i][3],$AnschlussPlacemarks[$i][2]\n";
					push @rfwAllFile, "					</coordinates>\n";
					push @rfwAllFile, "				</Point>\n";
					push @rfwAllFile, "			</Placemark>\n";

					push @rfwAllFile, "			<Placemark>\n";
					push @rfwAllFile, "				<name>$AnschlussPlacemarks[$j][1] :: $AnschlussPlacemarks[$j][0]</name>\n";
					push @rfwAllFile, "				<styleUrl>green_site</styleUrl>\n";
					push @rfwAllFile, "				<visibility>0</visibility>\n";
					push @rfwAllFile, "				<Point>\n";
					push @rfwAllFile, "					<coordinates>\n";
					push @rfwAllFile, "						$AnschlussPlacemarks[$j][3],$AnschlussPlacemarks[$j][2]\n";
					push @rfwAllFile, "					</coordinates>\n";
					push @rfwAllFile, "				</Point>\n";
					push @rfwAllFile, "			</Placemark>\n";

					my $co_1 = sprintf "%.4f %.4f", $AnschlussPlacemarks[$i][2],$AnschlussPlacemarks[$i][3];
					my $co_2 = sprintf "%.4f %.4f", $AnschlussPlacemarks[$j][2],$AnschlussPlacemarks[$j][3];

					if ($co_1 ne $co_2) {
						print "   Koordinaten: $co_1\n   $co_2\n\n";
						$warning = 1;
					}

					if ($AnschlussPlacemarks[$i][1] ne $AnschlussPlacemarks[$j][1]) {
						print "   Namen: $co_1\n   $co_2\n\n";
						$warning = 1;
					}

					if (defined $nodes{$co_1}) {

					} else {

					}
				}
			}
		}
	}
	push @rfwAllFile, "	</Folder>\n";

	# ===============================================
	# Write all Anschluss-Placemarks in extra Folder

	push @rfwAllFile, "	<Folder>\n";
	push @rfwAllFile, "		<name>Anschluss-Placemarks</name>\n";
	push @rfwAllFile, "		<open>0</open>\n";

	for (my $i=0; $i<=$#AnschlussPlacemarks; $i++) {

		push @rfwAllFile, "			<Placemark>\n";
		push @rfwAllFile, "				<name>$AnschlussPlacemarks[$i][1]</name>\n";
		push @rfwAllFile, "				<visibility>0</visibility>\n";
		push @rfwAllFile, "				<description>\n";
		push @rfwAllFile, "					<![CDATA[<a href=\"http://radreise-wiki.de/$AnschlussPlacemarks[$i][4]#$AnschlussPlacemarks[$i][5]\">$AnschlussPlacemarks[$i][0]</a>]]> \n";
		push @rfwAllFile, "				</description>\n";
		push @rfwAllFile, "				<Point>\n";
		push @rfwAllFile, "					<coordinates>\n";
		push @rfwAllFile, "						$AnschlussPlacemarks[$i][3],$AnschlussPlacemarks[$i][2]\n";
		push @rfwAllFile, "					</coordinates>\n";
		push @rfwAllFile, "				</Point>\n";
		push @rfwAllFile, "			</Placemark>\n";
	}
	push @rfwAllFile, "	</Folder>\n";

	# ==========================================
	# Write all Rest-Placemarks in extra Folder

	push @rfwAllFile, "	<Folder>\n";
	push @rfwAllFile, "		<name>Rest-Placemarks</name>\n";
	push @rfwAllFile, "		<open>0</open>\n";

	for (my $i=0; $i<=$#RestPlacemarks; $i++) {

		push @rfwAllFile, "			<Placemark>\n";
		push @rfwAllFile, "				<name>$RestPlacemarks[$i][1]</name>\n";
		push @rfwAllFile, "				<visibility>0</visibility>\n";
		push @rfwAllFile, "				<description>\n";
		push @rfwAllFile, "					<![CDATA[<a href=\"http://radreise-wiki.de/$RestPlacemarks[$i][4]#$RestPlacemarks[$i][5]\">$RestPlacemarks[$i][0]</a>]]> \n";
		push @rfwAllFile, "				</description>\n";
		push @rfwAllFile, "				<Point>\n";
		push @rfwAllFile, "					<coordinates>\n";
		push @rfwAllFile, "						$RestPlacemarks[$i][3],$RestPlacemarks[$i][2]\n";
		push @rfwAllFile, "					</coordinates>\n";
		push @rfwAllFile, "				</Point>\n";
		push @rfwAllFile, "			</Placemark>\n";
	}
	push @rfwAllFile, "	</Folder>\n";
}

#============================
# Write Footer and save File

push @rfwAllFile, "</Document>\n";
push @rfwAllFile, "</kml>\n";

my $content = "";
foreach my $line (@rfwAllFile) {
	$content .= $line;
}

my $fileName = "Radfernwege_Übersicht.kml";

&saveFileIfChangedOrNew ("$baseDir/", $fileName, encode ($encoding, $content), 1);

exit;

#==========================================================
#==========================================================

sub saveRouteFile {

	if ($routeName ne "") {

		my   @routeFileAll = ();

		push @routeFileAll, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		push @routeFileAll, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n";
		push @routeFileAll, "<Document>\n";

		push @routeFileAll, @routeFile;

		push @routeFileAll, "</Document>\n";
		push @routeFileAll, "</kml>\n";

		my $content = "";
		foreach my $line (@routeFileAll) {
			$content .= $line;
		}

		if      ($category eq "Fluss-Radfernweg") {

			push @Fluss_Radfernweg, "		<Folder>\n";
			push @Fluss_Radfernweg, @routeFile;
			push @Fluss_Radfernweg, "		</Folder>\n";

		} elsif ($category eq "Anderer Radfernweg") {

			push @Anderer_Radfernweg, "		<Folder>\n";
			push @Anderer_Radfernweg, @routeFile;
			push @Anderer_Radfernweg, "		</Folder>\n";

		} elsif ($category eq "Querverbindung") {

			push @Querverbindung, "		<Folder>\n";
			push @Querverbindung, @routeFile;
			push @Querverbindung, "		</Folder>\n";

		} elsif ($category eq "Direktverbindung") {

			push @Direktverbindung, "		<Folder>\n";
			push @Direktverbindung, @routeFile;
			push @Direktverbindung, "		</Folder>\n";

		} elsif ($category eq "Regionaler Radwanderweg") {

			@Regionaler_Radwanderweg = ();

		} elsif ($category eq "Routenplaner Testroute") {

			# do nothing

		} else {
			print "Error: No matching Category: $category\n";
			exit;
		}
	}
}

#==========================================================

sub process_txt_file {

	if (open(FILE, "$baseDir/text/$routeFileName.txt")) { # legal file found

		print encode $encOut, "$routeName\n";

		my $trackData = "";
		my @placeList = ();

		$fileCounter++;

		my $ucontent = "";
		while (<FILE>) { $ucontent .= $_; }
		close FILE;
		my $content = decode ($encoding, $ucontent);

		if ($content !~ /

			{{TOC_Radfernweg}}\n
			.*
			\n==\ Roadbook\ ==\n
			.*
			\n==\ GPS-Tracks\ ==\n
			.*
			\[\[Kategorie:\s*(
				Fluss-Radfernweg|
				Anderer\ Radfernweg|
				Querverbindung|
				Radweit-Strecke|
				Radreise|
				Regionaler\ Radwanderweg|
				Streckenvorschlag|
				Direktverbindung|
				Stadtrundfahrt
			)

			/xs) {

			print encode $encOut, "Chapters in $routeName are not correct!\n"; 
			exit(1);
		}

		$category = $1;

		if ($category eq "Regionaler Radwanderweg") {
			$category = "Querverbindung";
		}
		if ($category eq "Streckenvorschlag") {
			$category = "Querverbindung";
		}
		if ($category eq "Stadtrundfahrt") {
			$category = "Querverbindung";
		}
		if ($category eq "Radweit-Strecke") {
			$category = "Direktverbindung";
		}
		if ($category eq "Radreise") {
			$category = "Anderer Radfernweg";
		}

		my $color = "ffffffff";

		if ($category eq "Fluss-Radfernweg") {
			$color = "ffff0000"; # Blau
		}
		if ($category eq "Anderer Radfernweg") {
			$color = "ff00ff00"; # Grün
		}
		if ($category eq "Querverbindung") {
			$color = "ff00ffff"; # Gelb
		}
		if ($category eq "Direktverbindung") {
			$color = "ff0000ff"; # Rot
		}

		my @content   = split "\n", $content;

		     @routeFile = ();
		push @routeFile, "			<name>$routeName</name>\n";
		push @routeFile, "			<Metadata>\n";
		push @routeFile, "				<![CDATA[<!--$routeURL-->]]>\n";
		push @routeFile, "			</Metadata>\n";
		push @routeFile, "			<open>0</open>\n";

		my $roadBook   = 0;
		my $place      = 0;
		my $touri      = 0;
		my $geo        = 0;
		my $lon        = 0;
		my $lat        = 0;
		my $alt        = 0;
		my $road       = 0;
		my $kilo       = 0;

		my $placeName  = "";
		my $touriInfo  = "";
		my $geoData    = "";
		my $roadInfo   = "";
		my $kilometer  = "";

		foreach my $line (@content) {

			# Last Placemark is finished, Roadbook is finished
			if (($roadBook) and ($line =~ /^== .* ==$/)) {

				# Status-Übersicht
				if ($touriInfo ne "") { $touri = 1; }
				if ($roadInfo  ne "") { $road  = 1; }

				my $placeNameURL = encodePlaceNameURL($placeName);

				if ($touriInfo =~ /\* Anschl[u|ü]ss[^\n]*\[\[/) {

					my @info      = ( $routeName, $placeName, $lat, $lon, $routeURL, $placeNameURL);
					my $ref_zeile = \@info;
					push @AnschlussPlacemarks, $ref_zeile;
					push @placeList, $ref_zeile;

				} else {

					my @info      = ( $routeName, $placeName, $lat, $lon, $routeURL, $placeNameURL);
					my $ref_zeile = \@info;
					push @RestPlacemarks, $ref_zeile;
					push @placeList, $ref_zeile;
				}

				$trackData .= "$lon,$lat,$alt ";

				$roadBook  = 0;
				$place     = 0;
				$touri     = 0;
				$geo       = 0;
				$lon       = 0;
				$lat       = 0;
				$alt       = 0;
				$road      = 0;
				$kilo      = 0;

				$placeName  = "";
				$touriInfo  = "";
				$geoData    = "";
				$roadInfo   = "";
				$kilometer  = "";

			# Start of Roadbook
			} elsif ($line =~ /^== Roadbook ==$/) {

				$roadBook = 1;

			# A new Place within the Roadbook
			} elsif ($roadBook and ($line =~ /^=== (.*) ===$/)) {

				if ($place and not $kilo) {
					print "   No Kilometers: $routeName :: $placeName\n";
					#exit;
				}

				# Save previous place
				if ($place) {

					# Status-Übersicht
					if ($touriInfo ne "") { $touri = 1; }
					if ($roadInfo  ne "") { $road  = 1; }

					my $placeNameURL = encodePlaceNameURL($placeName);

					if ($touriInfo =~ /\* Anschl[u|ü]ss[^\n]*\[\[/) {

						my @info      = ( $routeName, $placeName, $lat, $lon, $routeURL, $placeNameURL);
						my $ref_zeile = \@info;
						push @AnschlussPlacemarks, $ref_zeile;
						push @placeList, $ref_zeile;

					} else {

						my @info      = ( $routeName, $placeName, $lat, $lon, $routeURL, $placeNameURL);
						my $ref_zeile = \@info;
						push @RestPlacemarks, $ref_zeile;
						push @placeList, $ref_zeile;
					}

					$trackData .= "$lon,$lat,$alt ";
				}

				$place     = 1;
				$touri     = 0;
				$geo       = 0;
				$lon       = 0;
				$lat       = 0;
				$alt       = 0;
				$road      = 0;
				$kilo      = 0;

				$placeName  = $1;
				$touriInfo  = "";
				$geoData    = "";
				$roadInfo   = "";
				$kilometer  = "";

			# Geodata within the Placemark
			} elsif ($place and ($line =~ /^{{Geodaten\|(.*)}}$/)) {

				$geo     = 1;
				$geoData = $1;

				if ($geoData =~ /^([-]?\d+\.\d+)\|([-]?\d+\.\d+)\|([-]?\d+)\|([^\|]+)$/) {

					$lat  = $1;
					$lon  = $2;
					$alt  = $3;

				} else {
					print "Error in Geodata: $routeName :: $placeName: $geoData\n";
					exit;
				}

			# Kilometrierung within Placemark
			} elsif ($place and ($line =~ /^{{Kilometrierung[Hm6]*\|(.*)}}$/)) {

				if (not $geo) {
					print "No Coordinates: $routeName :: $placeName\n";
					exit;
				}

				if ($kilo) {
					print "   Multiple Kilometers: $routeName :: $placeName\n";
					#exit;
				}

				$kilo      = 1;
				$kilometer = $1;

				#print "      $kilometer\n";

			# Empty Line
			} elsif ($line =~ /^\s*$/) {

			} elsif ($line =~ /<br style="clear:both" \/>/) {

			} elsif ($line =~ /\[\[Bild/) {

			} elsif ($place and not $geo and not $kilo) {

				$touriInfo .= "$line\n";

			} elsif ($place and $geo and not $kilo) {

				$roadInfo .= "$line\n";
			}
		}
		
		if (($accuracy) and (open(FILE, "$baseDir/tracks/$routeFileName.txt"))) {

			my $rawTrack = <FILE>;
			close FILE;
			
			my @rawTrack = split " ", $rawTrack;
			my @track    = ();
			my @trackNew = ();

			foreach (@rawTrack) {

				my ($lon, $lat, $alt) = split ",";

				my @zeile     = ( $lat, $lon, $alt );
				my $ref_zeile = \@zeile;

				push @track, $ref_zeile;
			}
			
			my @zeile     = ( $track[0][1], $track[0][0] );
			my $ref_zeile = \@zeile;
			push @trackNew, $ref_zeile;
			
			
			my $length = 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 += $dist;

				if ($length > $accuracy) {
				
					my @zeile     = ( $track[$i+1][1], $track[$i+1][0] );
					my $ref_zeile = \@zeile;
					push @trackNew, $ref_zeile;
					
					$length = 0;
				}
			}
			
			my @zeile     = ( $track[$#track][1], $track[$#track][0] );
			my $ref_zeile = \@zeile;
			push @trackNew, $ref_zeile;
			
			for (my $i = 0; $i <= $#placeList ; $i++) {

			 	my $minDist = 111111111;
			 	my $point   = -1;
			 
			 	for (my $j = 0; $j <= $#trackNew ; $j++) {
			 
			 		my $dist = getDistance ( 
						$trackNew[$j][1], 
						$trackNew[$j][0], 
						$placeList[$i][2], 
						$placeList[$i][3]
					);
			 
			 		if ($dist < $minDist) {
			 
			 			$minDist = $dist;
			 			$point   = $j;
			 		}
			 	}
				
				$trackNew[$point][1] = $placeList[$i][2];
				$trackNew[$point][0] = $placeList[$i][3];
			}

			$trackData = "";

			for (my $i = 0; $i <= $#trackNew ; $i++) {

				$trackData .= sprintf "%.4f,%.4f ", $trackNew[$i][0], $trackNew[$i][1];
			}
		}

		push @routeFile, "			<Placemark>\n";
		push @routeFile, "				<name>$routeName</name>\n";
		push @routeFile, "				<description>\n";
		push @routeFile, "					<![CDATA[<a href=\"http://radreise-wiki.de/$routeURL\">Wiki</a>]]> \n";
		push @routeFile, "				</description>\n";
		push @routeFile, "				<Style>\n";
		push @routeFile, "					<LineStyle>\n";
		push @routeFile, "						<color>$color</color>\n";
		push @routeFile, "						<colorMode>random</colorMode>\n";
		push @routeFile, "						<width>2</width>\n";
		push @routeFile, "					</LineStyle>\n";
		push @routeFile, "				</Style>\n";
		push @routeFile, "				<LineString>\n";
		push @routeFile, "					<tessellate>1</tessellate>\n";
		push @routeFile, "					<coordinates>\n";
		push @routeFile, "						$trackData\n";
		push @routeFile, "					</coordinates>\n";
		push @routeFile, "				</LineString>\n";
		push @routeFile, "			</Placemark>\n";
	}
}

#==========================================================

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*1000;
}

#==========================================================

sub del_double {

	my %all = ();

	@all{@_} = 1;

	return (keys %all);
}