User:Aighes/GPX-Track auf Website
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.