﻿#!/usr/local/bin/perl -w

use strict;
use XML::Simple;
use Data::Dumper;

# Datei für die Ausgabe
my $datei;	
if ($ARGV[0] =~ /(.*)\..*/) {	# Dem Namen der Quelldatei...
	$datei = $1.".osm";}		# wird '.osm' angehängt


my $xml_file = $ARGV[0];		# übergebene Quelldatei

my $svg = XMLin($xml_file,KeyAttr => [ 'id' ]);#, ForceArray => 1 ,KeyAttr => [ 'id' ]);	# Hash-Ref-Präsentation der Quelldatei einlesen
#print Dumper($svg);

my $counter = -1;	# Counter für IDs; neue Objekte bekommen negative ID
my %points;			# Hash für die einzelnen Punkte
my %ways;			# Array für die Wege
my $bound = 9;	# Toleranz-Bereich für das Zusammenfassen von einzelnen Punkten

my $Xt0 = 6.1123607;
my $Xtmax = 8.5081187;
my $Yt0 = 48.9664903;
my $Ytmax = 50.9423256;

my $op = 0.00001;
# my $xoffset = ($svg -> {'metadata'} -> {'sfw'} -> {'sliceSourceBounds'} -> {'height'}); 
# my $yoffset = ($svg -> {'metadata'} -> {'sfw'} -> {'sliceSourceBounds'} -> {'width'}); 
my $xoffset = 0;#(split(/p/,($svg -> {'height'})))[0] * 1000; 
my $yoffset = 0;#(split(/p/,($svg -> {'width'})))[0] * 1000; 
my $xmove = $Xt0;#6.0598186363180273655729182125389;
my $ymove = $Yt0;#48.96675;
my $xscale = 1;#0.22094002495090722302913205119244;
my $yscale = 1;#0.14253259328335299271675824592552;

# {Node id=323674752 version=1 V lat=50.9399869,lon=7,7863774}
# {Node id=-892413 version=0 V lat=13,84411,lon=7,7336}-1,9527
#1,9732369	-0,4135326
#{Node id=323819272 version=2 V lat=50.2192956,lon=6,166803}			{Node id=660910430 version=1 V lat=49.7678655,lon=8,4744133} 2,3076103
#{Node id=-1004791 version=0 V lat=8,84328,lon=0,44394}				{Node id=-1002671 version=0 V lat=5.62563,lon=10,88845}10,44451
# {Node id=323465585 version=1 V lat=50.9403419,lon=7.8132735}
# {Node id=-879087 version=0 V lat=13.84454,lon=7.81777}

#print $xoffset,", ",$yoffset,"\n";

#my @borders = (@{$svg -> {'switch'} -> {'g'} -> {'g'} -> {'Gemeinden_1_'} -> {'polygon'}});	# die Gemeindeumrisse aus der Quelldatei in Array einlesen

my @borders = (@{$svg -> {'g'} -> {'Gemeinden_1_'} -> {'polygon'}}); #Ortsgemeinden RLP

# my @borders = (@{$svg -> {'switch'} -> {'g'} -> {'g'}});
# foreach my $hashref (@borders){
	# if ($$hashref{'id'} eq 'Gemeinden_1_'){
		# @borders = (@{$hashref -> {'polygon'}});
		# last;
		# }
	# }
#			   @{$svg -> {'switch'} -> {'g'} -> {'g'} -> {'Kreise_Borders'} -> {'polygon'}});

# Gemeindegrenzen einlesen
print "Punkte & Wege einlesen\n";
my %roughpoints;
my %simpleways;
my %pointcount;
foreach my $polygon (@borders){			# aktuelle Grenze
	my $points = $$polygon{'points'};	# String mit Grenzpunkten einlesen
	my @points = split(/\s+/,$points); 	# Punkte an den Leerzeichen aufteilen
	push (@points,$points[0]); 			# ersten Eintrag wiederholen um Grenzeverlauf zu schließen
	
	# Punkte & Wege einlesen	
	
	for(my $i = 0;$i < @points;$i++){

		#Eng beieinander liegende Punkte zusammen fassen
		my @tp = split(/,/,$points[$i]); 							# aktuellen Punkt in Koordinaten aufteilen
		 											# temporäre Variable für Punktereferenz
		for (0,1) {$tp[$_] = $tp[$_] * 1000;}
		if ($tp[0] > $xoffset) {$xoffset = $tp[0];}
		if ($tp[1] > $yoffset) {$yoffset = $tp[1];}
		my @compare = @tp;
		push (@compare,($tp[0]  + $bound,
					  $tp[1]  + $bound,
					  $tp[0]  - $bound,
					  $tp[1]  - $bound));
		foreach my $tp (@compare){chop $tp;}
		#print $points[$i],"\n";
		#print "\t",@compare,"\n";
		my $tp = undef;
		for my $k1 (0,2,4){
			for my $k2 (1,3,5){
				my $pkey = ($compare[$k1]).($compare[$k2]);
				#print "\t",$pkey,"\n";
				if (defined($roughpoints{$pkey})){
					$tp = $roughpoints{$pkey};
					last;
					}
				}
			}
			
		if (defined($tp)){											# ist der Punkt vorhanden...
			$points[$i] = $tp;										# ...benutzen wir diesen
			}	
		else {														# falls nicht...
			$points{$counter} = \@tp;								# ...legen wir neuen Punkt mit den Koordinaten an.
			$points[$i] = $counter;									# wir merken uns die Referenz
			$roughpoints{($compare[0]).($compare[1])} = $counter;
			$counter--;												# und drehen den Zähler für die IDs weiter
			}
		
		# foreach my $otherpoint (keys (%points)){					# Suche nach bereits erfassten Punkten im Toleranzbereich
			# if (($tp[0] > ($points{$otherpoint}[0] - $bound)) &&
				# ($tp[0] < ($points{$otherpoint}[0] + $bound)) &&
				# ($tp[1] > ($points{$otherpoint}[1] - $bound)) &&
				# ($tp[1] < ($points{$otherpoint}[1] + $bound))
				# ){
				# $tp = $otherpoint;									# wurde ein passender Punkt gefunden: Referenz merken...
				# last;												# ...und Suche beenden
				# }
			# }
		# if (defined($tp)){											# ist der Punkt vorhanden...
			# $points[$i] = $tp;										# ...benutzen wir diesen
			# }	
		# else {														# falls nicht...
			# $points{$counter} = \@tp;								# ...legen wir neuen Punkt mit den Koordinaten an.
			# $points[$i] = $counter;									# wir merken uns die Referenz
			# $counter--;												# und drehen den Zähler für die IDs weiter
			# }
		
		#Doppelte einfache Wege entfernen
		#my $twice = '';												# boolean ist zuächst mal false
		if ($i > 0){												# Startknoten lassen wir aus (=Endknoten)
			# foreach (@ways){
				# if ((($$_[0] eq $points[$i-1]) 						# ist der Weg vorhanden...
						# && ($$_[1] eq $points[$i])) 
					# || 
					# (($$_[0] eq $points[$i]) 						# ...bzw. in entgegen gesetzter Richtung...
						# && ($$_[1] eq $points[$i-1])))
					# {$twice = '1';last;}							# ...merken wir uns das und verlassen die Suche
				# }
			# if ($twice){next;}										# Ist der Weg vorhanden, vergessen wir den aktuellen...
			my $waykey1 = $points[$i-1].",".$points[$i];
			my $waykey2 = $points[$i].",".$points[$i-1];
			if ((defined($simpleways{$waykey1}))
				 || (defined($simpleways{$waykey2}))){next;}
			else{
				$ways{$counter} = [$points[$i-1],$points[$i]];			# ansonsten legen wir einen neuen Weg an
				$simpleways{$waykey1} = $counter;
				
				#print "Weg ",$counter,"\n";
				for my $tp ($points[$i-1],$points[$i]){
					if (defined($pointcount{$tp})){
						push(@{$pointcount{$tp}},$counter);
						}
					else {$pointcount{$tp} = [$counter];}
				#	print "\t",$tp,"\n";
					}
				$counter--;
				}
			
			}
		}
	#push (@polygon_matrix,[@points]);
	}



# Links auf Knoten zählen für das Zusammenfassen von Wegen
# print "Links auf Knoten zählen\n";
# my %pointcount;

# foreach my $way (@ways){ #jeden Weg betrachten
	# foreach my $node (@$way){
		# if (defined($pointcount{$node})){$pointcount{$node} = $pointcount{$node} + 1;} 	# vorhandenen Zähler erhöhen oder...
		# else {$pointcount{$node} = 1;}													# ...Zähler anlegen
		# }
	# }

# my $onecount = 0;
# foreach my $point (keys (%pointcount)){
	# if (@{$pointcount{$point}} == 1){$onecount++}
	# #print $point," : ",@{$pointcount{$point}},"\n";
	# }
# print $onecount,"\n";	
# Wege zusammenfassen zu Einzelgrenzen zwischen zwei Gemeinden
print "Wege zusammenfassen\n";


foreach my $point (keys (%pointcount)){
	my $begin;
	if (@{$pointcount{$point}} < 3){
		#print $point,"\n";
		my $w1 = (@{$pointcount{$point}}[0]);
		#print "\t",@{$ways{$w1}},",";
		my $w2 = (@{$pointcount{$point}}[1]);
		#print @{$ways{$w2}},"\n";
		if (@{$ways{$w1}}[0] eq $point){
			splice (@{$ways{$w1}},0,1);
			$begin='1';
			}
		else{#elsif (@{$ways{$w1}}[@{$ways{$w1}}-1] eq $point){
			pop(@{$ways{$w1}});
			$begin='';
			}
		if (@{$ways{$w2}}[0] eq $point){
			if ($begin){
				unshift(@{$ways{$w2}},reverse(@{$ways{$w1}}));
				}
			else{
				unshift(@{$ways{$w2}},@{$ways{$w1}});
				}
			}
		else{#elsif (@{$ways{$w2}}[@{$ways{$w1}}-1] eq $point){
			if ($begin){
				push (@{$ways{$w2}},@{$ways{$w1}});
				}
			else{
				push (@{$ways{$w2}},reverse(@{$ways{$w1}}));
				}
			}
		#print "\t",@{$ways{$w1}},",";
		#print @{$ways{$w2}},"\n";
		#print "\t";
		# foreach (@{$ways{$w1}})
			# {print $_,",";}
		# print "\n";	
		
		my $pc;
		if ($begin){$pc = pop(@{$ways{$w1}});}
		else {$pc = @{$ways{$w1}}[0];}
		for my $tway (@{$pointcount{$pc}}){
			#print @{$pointcount{$pc}},"\t",$tway,"\n";
			#if (!defined(@{$pointcount{$pc}}[$tway])){print"ARRGH!tway\n";}
			if ($tway eq $w1)
				{$tway = $w2;}
			}
			
		delete $ways{$w1};
		# for (my $i = 0; $i < @ways; $i++){
			# if (!defined($ways[$i])){next;}
			# for my $h (0,@{$ways[$i]}-1){
				# if (($ways[$i][$h]) == $point){
					# for (my $f = $i+1; $f < @ways; $f++){
						# if (!defined($ways[$f])){next;}
						# for my $g (0,@{$ways[$f]}-1){
							# if ($ways[$f][$g] == $point){
								# splice (@{$ways[$i]},$h,1);
								# if ($g == 0){
									# if ($h == 0) {unshift(@{$ways[$f]},reverse(@{$ways[$i]}));}
									# else {unshift(@{$ways[$f]},@{$ways[$i]});}
									# } 
								# else {
									# if ($h == 0){push (@{$ways[$f]},@{$ways[$i]});}
									# else {push (@{$ways[$f]},reverse(@{$ways[$i]}));}
									# }
								# splice (@ways,$i,1);
								# #$ways[$i] = undef; #Element löschen
								# $i--; #Zähler verringern, da Array kleiner
								# $gefunden = '1';
								# last;
								# }
							# }
						# if ($gefunden){last;}
						# }
					# }
				# if ($gefunden){last;}
				# }
			# if ($gefunden){last;}
			# }
		}
}

$xoffset = $xoffset * $op;
$yoffset = $yoffset * $op;


my $At = $Xtmax - $Xt0;
my $Ct = $Ytmax - $Yt0;
my $Bt = 90 - $Yt0;

my $Et = $At - $At*$Ct/$Bt;

my $As = $xoffset;
my $Es = $As*$Et/$At;

$xscale = ($At/$xoffset);
$yscale = ($Ct/$yoffset);

# Ausgabe als OSM/XML-Datei

open(SCHREIBEN,"> $datei")										# Datei öffnen
  or die "Fehler beim Öffnen von Datei: $!\n";

# Schreiben
print "Schreiben\n";
print SCHREIBEN "<?xml version='1.0' encoding='UTF-8'?>";		# Header schreiben
print SCHREIBEN "<osm version='0.6' generator='perl script'>";	# Root-Element öffnen

foreach (keys (%points)){										# Punkte schreiben
	my @tp = split(/,/,$_);
	my $x = ($points{$_}[0]) * $op;
	my $y = $yoffset - ($points{$_}[1]) * $op;
	#$x = ($As/2) * (2*$x/$As - 1) * ($Es/2 + ($As/2 - $Es/2) * (1 - $y/$yoffset));

	print SCHREIBEN "<node id='".$_."' visible='true' lat='".($y * $yscale + $ymove)."' lon='".($x * $xscale + $xmove)."' />";
	}
	
foreach (keys (%ways)){												# Wege schreiben
	print SCHREIBEN "<way id='".$_."' visible='true'>";
    foreach my $point (@{$ways{$_}}){
		print SCHREIBEN "<nd ref='".$point."' />";
		}
	print SCHREIBEN "</way>";
	#$counter--;
	}
print SCHREIBEN "</osm>";										# Root-Element schließen

close(SCHREIBEN)												# Datei schließen
  or die "Fehler beim Schließen von Datei: $! \n";