Openlayers und Gpx-Track

Hallo Forengemeinde,

mein Ziel ist es mit Openlayers einen Gpx-Track und einige damit verbundene Infos darzustellen.
Das Einbinden des eigentlichen Tracks funktioniert auch ohne Probleme, allerdings würde ich gerne auch das Höhenprofil (oder genauer gesagt die jeweilige Höhe an einer Position) mit einer bestimmten Farbe darstellen.
Ich habe das jetzt erstmal wie in dem folgenden Minimalbeispiel gelöst.
Die Infos für die einzelnen Punkte erzeuge ich mir über ein kleines Python-Skript aus dem gpx-File.
Frage meinerseits wäre jetzt, ist dieser Ansatz überhaupt zielführend? Denn es können ja je nach Länge des Tracks weit über 1000 Punkte zusammenkommen. (Für das Beispiel habe ich erstmal nur jeden 20. Punkt genommen)
Oder gibt es da bereits etwas fertiges in Openlayers das ich bis jetzt übersehen habe?

Weiterhin würde ich die Informationen für die Punkte (es gibt auch popups, die habe ich hier wegen der Übersichtlichkeit aber erstmal entfernt) gerne aus einer CSV oder Textdatei laden,
aber bis jetzt habe ich kein Beispiel gefunden wie das für OpenLayers.Feature.Vector funktioniert. (Für die einzelnen Punkte nutze ich OpenLayers.Geometry.Point)
Hat jemand so etwas schon mal realisiert oder ein Beispiel für einen solchen Fall?

Danke,
Marcus


<html>
<head>
	<title>TEST</title>
	<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
	<script src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
 
	<script type="text/javascript">
		// Start position for the map
		var LatCenter=49.773768;
		var LonCenter=12.388962;
		var zoom=12;
		var proj1=new OpenLayers.Projection("EPSG:4326");
        var proj2=new OpenLayers.Projection("EPSG:900913");
 		var map;

       		function init(){
            	map = new OpenLayers.Map('map',
                    { numZoomLevel: 19,
                      units: 'm',
                      projection: new OpenLayers.Projection("EPSG:900913"),
                      displayProjection: new OpenLayers.Projection("EPSG:4326"),
                      controls: []
                    });

		// Kontrollelemente hinzufügen
            	map.addControl(new OpenLayers.Control.LayerSwitcher());
				map.addControl(new OpenLayers.Control.Navigation());
            	map.addControl(new OpenLayers.Control.MousePosition());
				map.addControl(new OpenLayers.Control.ScaleLine({geodesic:true,maxWidth:200, bottomOutUnits: "", bottomInUnits: ""}));
 
		// Layer für den Kartenhintergrund definieren
            	var LayerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
            	var LayerCyclemap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");
            	map.addLayers([LayerMapnik, LayerCyclemap]);

		// Layer für die Punkte erstellen
		var PointLayer = new OpenLayers.Layer.Vector("Punkte");
		var p100 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.385197, 49.784192).transform(proj1,proj2),{title:"15.91km",description:"696.3m<br>Info"},{fillColor: "#870078" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p101 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.385877, 49.782992).transform(proj1,proj2),{title:"16.05km",description:"722.4m<br>Info"},{fillColor: "#980067" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p102 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.386784, 49.782008).transform(proj1,proj2),{title:"16.19km",description:"732.3m<br>Info"},{fillColor: "#9E0061" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p103 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.387623, 49.780942).transform(proj1,proj2),{title:"16.33km",description:"751.7m<br>Info"},{fillColor: "#AA0055" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p104 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388276, 49.779842).transform(proj1,proj2),{title:"16.46km",description:"760.0m<br>Info"},{fillColor: "#AF0050" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p105 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.389533, 49.778821).transform(proj1,proj2),{title:"16.61km",description:"765.6m<br>Info"},{fillColor: "#B3004C" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p106 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.389276, 49.777521).transform(proj1,proj2),{title:"16.76km",description:"764.4m<br>Info"},{fillColor: "#B2004D" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p107 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388382, 49.776341).transform(proj1,proj2),{title:"16.91km",description:"769.1m<br>Info"},{fillColor: "#B5004A" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p108 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388568, 49.774945).transform(proj1,proj2),{title:"17.07km",description:"774.5m<br>Info"},{fillColor: "#B90046" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p109 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388962, 49.773768).transform(proj1,proj2),{title:"17.21km",description:"759.6m<br>Info"},{fillColor: "#AF0050" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p110 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.389004, 49.772624).transform(proj1,proj2),{title:"17.35km",description:"775.2m<br>Info"},{fillColor: "#B90046" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p111 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388476, 49.771688).transform(proj1,proj2),{title:"17.49km",description:"786.2m<br>Info"},{fillColor: "#C0003F" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p112 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388463, 49.770478).transform(proj1,proj2),{title:"17.63km",description:"810.2m<br>Info"},{fillColor: "#CF0030" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p113 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388795, 49.769212).transform(proj1,proj2),{title:"17.77km",description:"815.9m<br>Info"},{fillColor: "#D3002C" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p114 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388633, 49.76803).transform(proj1,proj2),{title:"17.91km",description:"825.6m<br>Info"},{fillColor: "#D90026" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p115 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388432, 49.766764).transform(proj1,proj2),{title:"18.05km",description:"837.2m<br>Info"},{fillColor: "#E0001F" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p116 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388348, 49.76551).transform(proj1,proj2),{title:"18.19km",description:"847.8m<br>Info"},{fillColor: "#E70018" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p117 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388041, 49.764289).transform(proj1,proj2),{title:"18.34km",description:"857.5m<br>Info"},{fillColor: "#ED0012" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p118 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.38771, 49.763122).transform(proj1,proj2),{title:"18.47km",description:"870.6m<br>Info"},{fillColor: "#F5000A" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p119 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.38784, 49.761771).transform(proj1,proj2),{title:"18.62km",description:"867.3m<br>Info"},{fillColor: "#F3000C" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		var p120 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(12.388792, 49.760619).transform(proj1,proj2),{title:"18.77km",description:"886.0m<br>Info"},{fillColor: "#FF0000" , pointRadius: 4,fillOpacity: 1.0,strokeWidth:0});
		PointLayer.addFeatures([p100,p101,p102,p103,p104,p105,p106,p107,p108,p109,p110,p111,p112,p113,p114,p115,p116,p117,p118,p119,p120]);
	
		map.addLayers([PointLayer]);
 
		// Ansicht auf vorgegebenen Punkt mit gewähltem Zoom zentrieren
		map.setCenter(new OpenLayers.LonLat(LonCenter,LatCenter).transform(proj1,proj2),zoom);	
			
		}
	</script>
 
</head>
<body onload="init();">
	<div style="width:100%; height:100%" id="map"></div>
</body>
</html>

Dein Beispiel stellt nur lediglich ein paar Punkte dar, während ein Track Linien zeichnen müsste. Mir ist kein Beispiel bekannt, in dem eine Webseite das Höhenprofil via Farbe der Tracklinie darstellt, aber im Grunde hast Du m.E. nur eine Möglichkeit: Eben wie es Deine Punkte tun einzelnen “Höhenebenen” eine Farbe zuweisen - sprich, den Track splitten in eine bestimmte Anzahl an Farben, und diese einzeln anzeigen.

Aber: Werfe mal einen Blick auf QLandkarte GT, das Programm kann das neuerdings. Ich habs als nette Spielerei registriert und gleich wieder deaktiviert, da Tracks so meines erachtens sehr viel schlechter erfassbar sind. Eine definierte Farbe kann sich viel besser von den wechselnden Farben eine Karte abheben.

Ansonsten kann Openlayers 3 GPX nativ lesen und darstellen.
Edit: Hier ein zweites, schöneres Beispiel :wink:

Bunte Tracks habe ich auch nicht, aber vielleicht ist das hier was zum Ausschlachten zur Darstellung von GPX und Popups (hier sind die Popups die Waypoints der GPX-Datei).

Grüße, Max

Hallo,

erstmal danke für die Hinweise, aber ich glaube ich konnte nicht ganz klar machen was ich eigentlich will.
(Bitte vielleicht mal das Beispiel anschauen, dann sieht mans glaub ich ganz gut)
Das ein Track aus einer Linie besteht ist mir schon klar (dafür gibt es ja im vollständigen Skript dann auch den Track als separaten Layer), aber je mehr Punkte man auf die Karte zeichnet um so näher kommt es einer Linie.
Mir geht es hauptsächlich darum grob das Höhenprofil darstellen zu könnnen, der niedrigste Punkt blau, der höchste rot, dazwischen entsprechend mischen.
Das zuordnen der Farbe ist auch kein Problem, ich suche wie gesagt ein Möglichkeit nicht jeden Punkt hart in die html zu schreiben sondern diese aus einer csv/txt zu laden.

@maxbe: Danke das Beispiel kannte ich schon, hab mich für die popups daran orientiert. Für das Minimalbeispiel hab ich diesen Codeteil der Übersicht wegen entfernt.

http://www.netzwolf.info/kartografie/openlayers/

Hier findest Du genügend Beispiele, die aus CSV- / GPX-Dateien lesen, und Punkte setzen und/oder Linien zeichnen. Aber die Abstände von Punkten in GPX Tracks sind in aller Regel unregelmäßig - viele Punkte werden je nach Zoomlevel nicht unbedingt zur gewünschten Ansicht führen. Da wirst Du die GPX-Datei entsprechend aufbereiten müssen, damit sie zur Darstellung taugt.

Hallo Joachim,

hab die Seite schon durch, allerdings bezieht sich das doch immer auf OpenLayers.Layer.PopupMarker?
Ich habe es bis jetzt einfach nicht hinbekommen das Prinzip auf einen Vector Layer zu übertragen…

Vielleicht kommtst du damit weiter. Liest Punkte in ein Layer.Vector und stellt sie mit einem vordefinierten Stil dar. Ich habs auf die Schnelle nicht geschafft, z.B. “fillColor” in die Textdatei zu schreiben, aber ich vermute, mit new OpenLayers.Format.Text({…,extractStyles: true} kann man das irgendwie, schliesslich kann man da auch Icons ändern… Kann das aber im Moment nicht ausprobieren, sorry

Danke, ich schaus mir mal an!
Eine Frage noch, wie geb ich den “Link” zur Textdatei an wenn ich html und txt lokal auf dem Rechner hab?

Moins,

Etwa so?

Gruß Wolf

Hallo Netzwolf,

vielen Dank!
Habs grade mal mit nem eigenen Track probiert, läuft soweit, einen Abschnitt allerdings zeigt er rot an, obwohl der blau sein müsste.
Muss mich mal in dein Skript vertiefen, aber da ich bis jetzt noch nix mit Javascript gemacht habe, wird das wohl ein bisschen dauern…
Eine Lösung für das Problem des auslesens einer txt für Vektor features würde mich aber trotzdem noch interessieren, bin bis jetzt mit meinen Versuchen nicht wirklich weitergekommen.
Bin aber grade dabei das Beispiel von maxbe mal durchzuarbeiten, mal schaun wie weit ich komme…

Btw: Kann man hier auch Dateien anhängen?

Ich würde ja Wolfs Code nehmen…

Aber wenn Dus lieber anders hast: Du kannst so ziemlich alles in die Textdatei schreiben, musst nur das Feld in der ersten Zeile benennen (im Beispiel “ele” und “fuellfarbe”) und hast dann im JavaScript diesen Wert in “feature.attributes.fuellfarbe”. Mit der Fuktion “prefeatureInsert” kannst Du diese Attribute erstmal intepretieren und den Stil des Features anpassen, bevor es auf die Karte gemalt wird.

Hier z.B. kommt die Farbe aus der Datei und die Dicke der Kreise ergibt sich aus der ele der Datei. Ich hatte keine Lust, ele in Farbverlauf zu übersetzen, deshalb gibt es nur 2 Farben (Wechsel irgendwo in der Mitte, unabhängig von der Höhe, Wert kommt aus der txt-Datei) und drei Dicken für <1500m,<2000m und >2000m (Ergibt sich aus dem Feld “ele”).

Grüße, Max

Nahmd,

Ich habe den Code modifiziert: die Farbskala wird jetzt an Minimalhöhe und Maximalhöhe aus dem GPX angepasst.

Max hat das am Beispiel sehr gut erklärt.

Hier noch ein Code-Schnipsel zur Farberzeugung:


var min = 100;
var max = 400;
var ele = ... zu verarbeitenden Höhe ...

// lineare Transformation von min..max nach 0..1

var factor = (ele - min) / (max - min);

// Werte außerhalb des Bereiches

if (factor<0) factor = 0;    // oder Alarmfarbe oder ...
if (factor>1) factor = 1;    // oder Alarmfarbe oder ...

// Bestimmung der Farbkomponenten im Bereich 0..255
// als Integer, daher Math.round(...)

// rot: von 0 am Anfang der Skala bis 255 am Ende der Skala
var red = Math.round (255 * factor);

// grün: 0
var green = 0;

// blau: von 255 am Anfang der Skala bis 0 am Ende der Skala
var blue = Math.round (255 * (1-factor));

// RGB-Wert zusammenfügen

var value = (red<<16) | (green<8) | blue;

// Umwandeln nach hex.
// weil Number.toString() keine führenden 0en erzeugt,
// stelle eine Ziffer voran (1<<14) und schneide sie weg (substring(1)).

var hexcolor = ((1<<24)|value).toString(16).substring(1)

// Mit einem '#' davor entsteht ein gültiger Farbwert.

return '#' + hexcolor;

Man kann auch aus Styles auf Felder der Quelldatei zugreifen (und dann per SelectFeature weiteren Unfug anstellen), das ist aber für den Einstieg eine Nummer zu groß (und es gibt keinen Support).

Gruß Wolf

Hallo Ihr beiden,

nochmal ein großes Dankeschön für eure Hilfe!
Das letzte Beispiel vom Wolf schau ich mir bei Gelegenheit mal an, muss mich wie gesagt dafür dann auch mal bisschen mit Javascript befassen, da hab ich im Moment noch keine wirkliche Ahnung.
Aber an sich gefällt mir die Variante mit dem Track schon echt gut!

Dank des Tipps und Beispiel von Max hat es dann auch mit dem auslesen aus einer txt funktioniert.

Werde jetzt nach und nach mal alles versuchen zu verstehen und einarbeiten, sind ja jede Menge interessante Ansätze dabei.
Ziel ist irgendwann ein kleines Script in Python das mir alle Tracks in einem Verzeichnis zusammen mit ein paar Metadaten auflistet (will mir ein kleines Archiv anlegen und die Tracks auch bisschen kommentieren) und mit einem weiteren Klick den gewählten Track auf einer Karte darstellt. Und dabei habe ich halt an den Track an sich, einen entsprechend des Höhenprofils eingefärbten Track und einen entsprechend der Geschwindigkeit gefärbten Track gedacht. Und evtl. dazu noch eine Anzeige der Kilometrierung, also so alle 1-2km ein Marker oder so. Spätestens nach der WM ist dann auch wieder bisschen mehr Zeit für dieses Projekt. :slight_smile:

Danke,
Marcus

hallo.

hab auch mal mit höhenprofile herumprobiert:

http://www.kaspressknoedel.com/media/map/karte2.php?var=miemingerplateau

ich lese auch die höhendaten aus dem gpx raus und stelle sie im graph dar. per maus kann sich dann den entsprechenden punkt auf der karte anzeigen lassen