User:Aighes/GPX-Track auf Website

From OpenStreetMap Wiki
Jump to: navigation, search

Um einen GPX-Track dynamisch auf einer OSM-Karte darzustellen, muss dieser Code in einer php-Datei gespeichert werden. Neben der Anzeige des Tracks auf einer OSM Karte wird noch die Tracklänge sowie der Anstieg und Abstieg berechnet. Eine Anzeige des Höhenprofils ist auch integriert.

Pfadstruktur

Der folgende Code ist so ausgelegt, dass alle benötigten Dateien in einem Ordener liegen, lediglich die GPX-Dateien werden in dem Unterordner 'gpx' erwartet.

benötigte Dateien

index.php

<?php
function getlatlon($quelle, $suche) {//Funktion zum Auslesen von lat und lon aus der gpx-Datei
	$suche= " ".$suche."=\"";
	if (strpos($quelle, $suche) === false){
		$suche = str_replace("\"","'",$suche);
	}//end if
	$quelle = substr($quelle, strpos($quelle, $suche)+ strlen($suche));
	return str_replace(",",".",substr($quelle, 0, strpos($quelle, "\"")));
}//end function
function getele($quelle) {//Funktion zum Auslesen von ele aus der gpx-Datei
	$quelle = substr($quelle, strpos($quelle, "<ele>")+ strlen("<ele>"));
	return str_replace(",",".",substr($quelle, 0, strpos($quelle, "</ele>")));
}//end function
//ersetzen von Zeichenfolgen im GPX-Dateinamen für die Anzeige; die erste und die letzte Zeile zwischen den {}-Klammern müssen erhalten bleiben, der Rest kann nach belieben verändert werden.
function trackname($name) {
	$name = substr($name, 0, -4);
	$name = str_replace("_", " ", $name);
	$name = str_replace("ae", "ä", $name);
	$name = str_replace("oe", "ö", $name);
	$name = str_replace("-", " - ", $name);
	$name = str_replace("ue", "ü", $name);
        return $name;
}//end function
// Umrechnung Lat/Lon -> interne Koordinaten
function lonToMercator($l) {
        $lon =  $l * 20037508.34 / 180;
        return $lon;
}//end function
function latToMercator($l) {
	// Umrechnung Graß -> rad
        $l = deg2rad($l);
	// Projektion Erdkugel -> Mercator
        $lat = log((1+sin($l)) / (1-sin($l)));
	// Umrechnung rad -> Meter
        $lat = $lat * 20037508.34 / 2 / M_PI;
        return $lat;
}//end function
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de-de">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta name="Description" content="Radroute" />

<link rel="stylesheet" type="text/css" href="./styles.css" media="screen" /><!-- Pfad zur style.css-->

<title>h.scholland - Radroute</title>
<script type="text/javascript" src="./mootools.js"></script><!-- Pfad zur mootools.js-->
<script type="text/javascript" src="./slimbox.js"></script><!-- Pfad zur slimbox.js-->

<script type="text/javascript" src="http://www.openlayers.org/api/OpenLayers.js"></script>
<script type="text/javascript" src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>

<script type="text/javascript" src="./GPX.js"></script><!-- Pfad zur GPX.js-->
<script type="text/javascript">
<?php
if(isset($_GET["track"])){
	$track_name = $_GET["track"];//Dateiname des gpx-Track
	$track = "./gpx/".$track_name; // erstellt die URL des Tracks aus dem Unterordner gpx
	$track_filename = $track_name;
	$track_name = trackname($track_name);
	$track_title = ": ".$track_name;
	if (file_exists($track)) {//prüfen, ob angegebene Datei vorhanden ist

	 //Koordinaten und Höhen in Array schreiben
	         $fp = fopen( $track, "r"); // gpx-Datei öffnen
	         $n=0;
	         $m=0;
	         while (! feof( $fp )) {
	                 $zeile  = fgets( $fp , 4096);
	                 if (strpos($zeile,"<trkpt") !== false) {
	                         $lat[$n] = getlatlon($zeile, "lat");
	                         $lon[$n] = getlatlon($zeile, "lon");
	                         $n++;
		         } //end if
	                 if (strpos($zeile,"<ele>") !== false) {
	                 	$ele[$m] = getele($zeile);
	                 	$m++;
	                 }//end if
	         } //end while
	         fclose($fp); //gpx-Datei schließen

	//Berechnung der Tracklänge
	         $r0 = 6371.0;//Erdradius
	         $laenge = 0.0;
	         for ($i = 0; $i < ($n-1); $i++) {
	                  if($lat[$i] != $lat[$i+1] && $lon[$i] != $lon[$i+1]) {
	                           $a = deg2rad(90.0 - $lat[$i]);
	                           $b = deg2rad(90.0 - $lat[$i+1]);
	                           $gamma = deg2rad(abs($lon[$i+1] - $lon[$i]));
	                           $c = $r0 * acos(cos($a)*cos($b) + sin($a)*sin($b)*cos($gamma));
	                           $laenge += $c;
	                  }//end if
	         }//end for
	         $laenge = round($laenge, 1)." km";
	         $laenge = str_replace(".",",",$laenge);
	//Höhenmeter addieren
	         if ($m > 0) {
	                  $up=0.0;
	                  $down=0.0;
	                  for ($i=0; $i < ($m-1); $i++) {
	                        if ($ele[$i] < $ele[$i+1]) {
	                                $up += $ele[$i+1] - $ele[$i];
	                        }//end if
	                        if ($ele[$i] > $ele[$i+1]) {
	                                $down += $ele[$i] - $ele[$i+1];
	                        }//end if
	                  }//end for
	                  $up = round($up, 1)." m";
	                  $up = str_replace(".",",",$up);
	                  $down = -round($down, 1)." m";
	                  $down = str_replace(".",",",$down);
	                  $b_ele = true;
	         }//end if
	         else {
	                  $down = "n/a";
	                  $up = "n/a";
	                  $b_ele = false;
	         }//end else
         //Berechnung der Bounding Box
		 $minlon = lontoMercator(min($lon));
		 $maxlon = lontoMercator(max($lon));
		 $minlat = lattoMercator(min($lat));
		 $maxlat = lattoMercator(max($lat));
	//Marker-Positionen
	         $s_lon =lontoMercator($lon[0]);
	         $s_lat =lattoMercator($lat[0]);
	         $e_lon =lontoMercator($lon[$n-1]);
	         $e_lat =lattoMercator($lat[$n-1]);
         //Größe der angezeigten Karte
	         $width=760;//Breite in pixel
	         $height=600;//Höhe in pixel
	         $b_track = true;
	}//end if
	else { //Datei nicht vorhanden
	         $laenge = "n/a";
	         $up = "n/a";
	         $down = "n/a";
	         $width = 760;
	         $height = 600;
	         $b_track = false;
		 $b_ele = false;
	}//end else
}//end if
else {//kein Parameter
         $laenge = "n/a";
         $up = "n/a";
         $down = "n/a";
         $width = 760;
         $height = 600;
         $b_track = false;
         $b_ele = false;
}//end else
?>
	            var map; //complex object of type OpenLayers.Map

	            //Initialise the 'map' object
	            function init() {
	                map = new OpenLayers.Map ("map", {
	                    controls:[
	                        new OpenLayers.Control.Navigation(),
	                        new OpenLayers.Control.PanZoomBar(),
	                        new OpenLayers.Control.MousePosition(),
	                        new OpenLayers.Control.LayerSwitcher(),
                                 new OpenLayers.Control.Attribution()],
	                    maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
	                                maxResolution: 156543.0399,
	                    numZoomLevels: 19,
	                    units: 'm',
	                    projection: new OpenLayers.Projection("EPSG:900913"),
	                    displayProjection: new OpenLayers.Projection("EPSG:4326")
	                } );

	                layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
	                map.addLayer(layerMapnik);
	                layerTilesAtHome = new OpenLayers.Layer.OSM.Osmarender("Osmarender");
	                map.addLayer(layerTilesAtHome);
	                layerCycleMap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");
	                map.addLayer(layerCycleMap);

			var markers = new OpenLayers.Layer.Markers("Marker");
			map.addLayer(markers);
	<?php
			if ($b_track) {
				//Marker zeichnen
				echo "var size = new OpenLayers.Size(16,28);\n";
				echo "var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);\n";
				echo "var icon_s = new OpenLayers.Icon(\"./pin_start.png\",size,offset);\n";
				echo "var icon_e = new OpenLayers.Icon(\"./pin_ziel.png\",size,offset);\n";
				echo "markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(".$s_lon.",".$s_lat."),icon_s));\n";//Will man mehrere gleiche Icons auf einer Karte anzeigen, muss man die function icon.clone() verwenden. Hier würde man dann icon_s mit icon_S.clone() verwenden
				echo "markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(".$e_lon.",".$e_lat."),icon_e));\n";
				//gpx-Track
 		                echo "var lgpx = new OpenLayers.Layer.GPX(\"".$track_name."\", \"".$track."\", \"#0000ff\");\n";
		                echo "map.addLayer(lgpx);\n";
				//auf Boundingbox zoomen
	                        echo "var bbox = new OpenLayers.Bounds(".$minlon.",".$minlat.",".$maxlon.",".$maxlat.");\n";
		                echo "map.zoomToExtent(bbox);\n";
		        }//end if
			else {//kein gpx-Track vorhanden
	                	echo "var lonLat = new OpenLayers.LonLat(9.8,51.4).transform(new OpenLayers.Projection(\"EPSG:4326\"), map.getProjectionObject());";//Koordinaten der Default-Position (9.8,51.4)
		                echo "map.setCenter (lonLat, 7);";//Default-Zoomwert (7)
			}//end else
	?>
	            }
	    </script>
<?php
//ENDE DES SKRIPTS
         echo "</head>\n";

         echo "<body onload=\"init();\" id=\"body\">\n";//Funktion init() aufrufen

         echo "<table align=\"center\" style=\"vertical-align:top;\">";
         echo "<tr>";
         echo "<td height=\"600\" width=\"216\">\n";
	         echo "<table align=\"center\" style=\"vertical-align:top;\">";
	         echo "<tr>";
	         echo "<td height=\"400\" width=\"216\" align=\"left\" valign=\"top\">\n";
	         echo "<div style=\"width:216px;height:400px;overflow:auto\">\n";
	         $handle =opendir('gpx'); // ordner mit kategorien öffnen
	         $b = 0;
	         while ($file = readdir ($handle)) {
	                 if ($file != "." && $file != "..") { // ausschließen von ordnern und Dateien
				$temp[$b] = $file;
				$b++;
			 }//end if
	     	 }//end while
	     	 sort($temp);
	     	 for ($c = 0; $c < $b; $c++) {
                           if ("./gpx/".$temp[$c] == $track) {
                                   echo "<nobr><u><a href=\"./index.php?track=".$temp[$c]."\">".trackname($temp[$c])."</a></u></nobr></br>\n";
                           }//end if
                           else {
                                   echo "<nobr><a href=\"./index.php?track=".$temp[$c]."\">".trackname($temp[$c])."</a></nobr></br>\n";
                           }//end else
	         }//end for
	         closedir($handle);//Ordner schließen
	         echo "</div>\n</td></tr>\n<tr><td height=\"100\" width=\"216\" align=\"left\" valign=\"top\" style=\"border-color:#888888; border-width:2px; border-style:solid;\">\n";
	         echo "<u>Trackdaten:</u><br >\n";
		 echo "<table>\n<tr><td width=\"32\" valign=\"top\">\n";
		 if ($b_track) {
		 	echo "<a href=\"./".$track."\" target=\"_blank\"><img src=\"./disk.png\" border=\"0\" alt=\"\" title=\"ausgewählten GPX-Track herunterladen\"></a><br />\n";
			if ($b_ele) echo "<a href=\"./profil.php?track=".$track_filename."\" rel=\"lightbox\"><img src=\"./profil.png\" border=\"0\" alt=\"\" title=\"Höhenprofil anzeigen\"></a>\n";
	         }
	         echo" </td><td width=\"184\" valign=\"top\">\n";
		                   echo "<table>\n";
	                           echo "<tr><td width=\"84\">Tracklänge:</td><td width=\"80\" align=\"right\">".$laenge."</td></tr>\n";
	                           echo "<tr><td width=\"84\">Anstieg:</td><td width=\"80\" align=\"right\">".$up."</td></tr>\n";
	                           echo "<tr><td width=\"84\">Abstieg:</td><td width=\"80\" align=\"right\">".$down."</td></tr>\n";
	                           echo "</table>\n";
	         echo "</td></tr></table>";
	         echo "</td></tr></table>";
         echo "</td><td height=\"600\" width=\"760\">\n";
         echo "<div style=\"width:".$width."; height:".$height."\" id=\"map\"></div>\n"; //DIV für das anzeigen der Karte
         echo "</td></tr>\n</table>\n";
         echo "</body>\n</html>";
?>

gpx.js

Diese Date findet ihr unter DE:OSM_in_Website_für_Gemeinde

styles.css

Vom gleichen Projekt ladet ihr euch das Style-File herunter und benennt es um in styles.css.

phplot.php

Die Datei phplot.php bekommt ihr von PHPplot.

profil.php

<?php
function getlatlon($quelle, $suche) {//Funktion zum Auslesen von lat und lon aus der gpx-Datei
	$suche= " ".$suche."=\"";
	if (strpos($quelle, $suche) === false){
		$suche = str_replace("\"","'",$suche);
	}//end if
	$quelle = substr($quelle, strpos($quelle, $suche)+ strlen($suche));
	return str_replace(",",".",substr($quelle, 0, strpos($quelle, "\"")));
}//end function
function getele($quelle) {//Funktion zum Auslesen von ele aus der gpx-Datei
	$quelle = substr($quelle, strpos($quelle, "<ele>")+ strlen("<ele>"));
	return str_replace(",",".",substr($quelle, 0, strpos($quelle, "</ele>")));
}//end function
function trackname($name) {
	$name = substr($name, 0, -4);
	$name = str_replace("_", " ", $name);
	$name = str_replace("ae", "ä", $name);
	$name = str_replace("oe", "ö", $name);
	$name = str_replace("-", " - ", $name);
	$name = str_replace("ue", "ü", $name);
        return $name;
}//end function

if(isset($_GET["track"])){
	$track_name = $_GET["track"];//Dateiname des gpx-Track
	$track = "./gpx/".$track_name; // erstellt die URL des Tracks aus dem Unterordner gpx
	$track_name = trackname($track_name);

	if (file_exists($track)) {//prüfen, ob angegebene Datei vorhanden ist

	 //Koordinaten und Höhen in Array schreiben
	         $fp = fopen( $track, "r"); // gpx-Datei öffnen
	         $n=0;
	         $m=0;
	         while (! feof( $fp )) {
	                 $zeile  = fgets( $fp , 4096);
	                 if (strpos($zeile,"<trkpt") !== false) {
				 $lang[$zett] = $zeile;//test
	                         $lat[$n] = getlatlon($zeile, "lat");
	                         $lon[$n] = getlatlon($zeile, "lon");
	                         $n++;
		         } //end if
	                 if (strpos($zeile,"<ele>") !== false) {
	                 	$ele[$m] = getele($zeile);
	                 	$m++;
	                 }//end if
	         } //end while
	         fclose($fp); //gpx-Datei schließen
	//Berechnung der Tracklänge
	         $r0 = 6371.0;//Erdradius
	         $laenge = 0.0;
	         for ($i = 0; $i < ($n-1); $i++) {
	                  if($lat[$i] != $lat[$i+1] && $lon[$i] != $lon[$i+1]) {
	                           $a = deg2rad(90.0 - $lat[$i]);
	                           $b = deg2rad(90.0 - $lat[$i+1]);
	                           $gamma = deg2rad(abs($lon[$i+1] - $lon[$i]));
	                           $c = $r0 * acos(cos($a)*cos($b) + sin($a)*sin($b)*cos($gamma));
	                           $laenge += $c;
	                  }//end if
	                  $track_profil[$i] = array("", round($laenge, 2), $ele[$i]);
	         }//end for

	         require_once "phplot.php"; //Include the code
	         $plot = new PHPlot(800,600); //create a PHPlot object with 800x600 pixel image
	         $plot->SetPlotType("lines");
	         $plot->SetDataType("data-data");
	         $plot->SetDataColors("red");
	         $plot->SetNumXTicks(10);
	         $plot->SetTitle($track_name." ".round($laenge, 2)." km");
	         $plot->SetXTitle("Entfernung in km");
	         $plot->SetYTitle("Höhe in m");
	         $plot->SetXDataLabelPos("none");
	         //$plot->SetXTickLabelPos("none");

	         $plot->SetDataValues($track_profil);
	         //Draw it
	         $plot->DrawGraph();
	}//end if
}//end if
?>

Slimbox

Für die Anzeige des Höhenprofils werden zusätzlich einige Komponenten der Slimbox benötigt. Gebraucht werden die Dateien mootools.js, slimbox.js und die 4 gif-Dateien aus dem css-Ordner. Der Inhalt der css-Datei wird einfach an die obige style.css angehangen. Dazu die css-Datei mit einem Text-Editor öffnen, den Text markieren, kopieren und in die vorhandene style.css unterhalb des vorhandenen Texts einfügen.

Bilddateien

Zu guter letzt verwende ich noch 2 Bilddateien mit 16x16px zum herunterladen des Tracks (disk.png) und zum Anzeigen des Höhenprofils (profil.png). Sowie 2 Bilddateien mit 16x28px (pin_start.png und pin_ziel.png) zum Anzeigen von Anfang und Ende der Strecke. Diese müsstet ihr euch selbst erstellen.

Feedback und Probleme

Ich bitte darum auftretende Probleme unter der talk-Seite hier zu diskutieren, damit sich alle Nutzer über die Probleme informieren können und ich nicht mehrfach gleiche Hinweise geben muss. Auch Anregungen bzw. Ergänzungen sind gerne Willkommen.