Aus Gpx Track Streckenlänge berechnen

Hallo,

wollte aus einem GPX-Track die Streckenlänge in javascript errechnen und habe folgendes Script erstellt:

if (window.ActiveXObject) {
var request = OpenLayers.Request.GET({
url: window.file_name,
async: false
});
} else {

request = new XMLHttpRequest();
request.overrideMimeType(“text/xml”);
request.open(“GET”, window.file_name, false);
request.send(null);
}

//function ausgeben() {
// if (http.readyState == 4) {
//alert(request.responseXML);

var daten = request.responseXML;
var ergebnisse = daten.getElementsByTagName(“ele”);
var punkte = daten.getElementsByTagName(“trkpt”);//[0].getAttribute(“lon”);
var hoehen = new Array();
var dataPt = new Array(6);
var radius = 6378.137 ; // earth radius in kilometer
var DE2RA = 0.01745329252; // degre to radian conversion

// return the distance between (lat1,lon1) and (lat2,lon2) in kilometer.
function GCDistance(lat1, lon1, lat2, lon2) {
if (lat1 == lat2 && lon1 == lon2) return 0;
lat1 *= DE2RA;
lon1 *= DE2RA;
lat2 *= DE2RA;
lon2 *= DE2RA;
var d = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2);
return (radius * Math.acos(d));
};

dataPt[0] = new Array ()
for (var j = 0; j < ergebnisse.length; j++) {
dataPt[0].push(parseFloat(ergebnisse[j].childNodes[0].nodeValue));
}

dataPt[1] = new Array ()
for (var k = 0; k < punkte.length; k++) {
dataPt[1].push(punkte[k].getAttribute(“lon”));
}

dataPt[2] = new Array ()
for (var m = 0; m < punkte.length; m++) {
dataPt[2].push(punkte[m].getAttribute(“lat”));
}
//Errechnung der Strecke zwischen zwei Punkten

dataPt[3] = new Array ()
for (var n = 0; n < punkte.length-1; n++) {
dataPt[3].push(GCDistance(dataPt[1][n],dataPt[2][n],dataPt[1][n+1],dataPt[2][n+1])
); // track lenghts
}
//Aufsummierung der Punkte

dataPt[4] = new Array ()
for (var p = 0; p < dataPt[3].length; p++) {
dataPt[4][0] = 0;
dataPt[4].push(dataPt[4][p] + dataPt[3][p]);
}

Ich habe das folgende Problem.

Bei kurzen gpx Tracks ist die Stecke zu kurz
Bei langen gpx Tracks ist die Strecke zu lange.

Hat jemand eine Idee woran es liegen kann

Den Fehler kann ich mir nicht erklären. Ich würde einen Unterschied zwischen nordsüd- und westost-gerichteten Wegen vermuten. Du schreibst nämlich

dataPt[1].push(punkte[k].getAttribute(“lon”));
und
dataPt[2].push(punkte[m].getAttribute(“lat”));
und
GCDistance(dataPt[1][n],dataPt[2][n] …)

Die Funktion ist aber “GCDistance(lat1, lon1, lat2, lon2)” und “lat1” sollte deshalb in dataPt[2] stecken, da müsstest also lat und lon umdrehen.

Bei den vielen Schleifen und pushs bin ich mir nicht sicher, ob du den ersten oder den letzten Wert unter den Tisch fallen lässt, oder ob es stimmt. Zumindest bei “dataPt[4]” vermute ich stark, dass du um 1 über die Anzahl deiner Punkte rausschiesst. Du belegst ja “dataPt[4][0]” ganz oft mit 0 und machst dann noch “p = 0; p < dataPt[3].length” pushs. Das ist einer zu viel, glaube ich.

Grüße, Max

Hab übrigens das Problem mit folgender Funktion gelöst.

function distanceBetweenPoints(latlng1, latlng2){
var point1 = new OpenLayers.Geometry.Point(latlng1.lon, latlng1.lat).transform(Geographic, Mercator);
var point2 = new OpenLayers.Geometry.Point(latlng2.lon, latlng2.lat).transform(Geographic, Mercator);
return point1.distanceTo(point2)/1478;
}

Erzeugung des Array mit der Liste der Enfernungen:

dataPt[3] = new Array ()
for (var n = 0; n < punkte.length-1; n++) {
dataPt[3].push(distanceBetweenPoints(new OpenLayers.LonLat( dataPt[1][n], dataPt[2][n] ),
new OpenLayers.LonLat(dataPt[1][n+1],dataPt[2][n+1])
)
); // distance beetwenn two points

und kumulierte werte:

dataPt[4] = new Array ()
for (var p = 0; p < dataPt[3].length; p++) {
dataPt[4][0] = 0;
dataPt[4].push(dataPt[4][p] + dataPt[3][p]);
}

Frage:

Es funktioniert jetzt gut. Aber weiß leider nicht wieso man hier

function distanceBetweenPoints(latlng1, latlng2){
var point1 = new OpenLayers.Geometry.Point(latlng1.lon, latlng1.lat).transform(Geographic, Mercator);
var point2 = new OpenLayers.Geometry.Point(latlng2.lon, latlng2.lat).transform(Geographic, Mercator);
return point1.distanceTo(point2)/1478;
}

durch 1478 dividieren muss. Das würde mich noch interessieren.

Die Funktion distanceTo rechnet in Mercatorprojektion. Die “Meter” in dieser Projektion sind um den Faktor 1/cos(Breitengrad) gestreckt gegenüber den Metern in der echten Welt. Du müsstest also eigentlich durch 1000/cos(Breitengrad) teilen, um auf echte Kilometer zu kommen.

Für 47.4° Nord passt der Wert 1487, aber du solltest keine Tracks aus Afrika oder Skandinavien damit vermessen. Um sicher zu gehen würde ich stattdessen 1000/cos(latlng1.lat * PI/180) nehmen. Geht bei grossen Nord-Süd-Distanzen zwischen 2 Punkten auch nicht gut, aber Trackpunkte liegen ja nicht 1000 km auseinander.

Grüße, Max

Hallo!

habs mal so probiert:

function distanceBetweenPoints(latlng1, latlng2){
var point1 = new OpenLayers.Geometry.Point(latlng1.lon, latlng1.lat).transform(Geographic, Mercator);
var point2 = new OpenLayers.Geometry.Point(latlng2.lon, latlng2.lat).transform(Geographic, Mercator);
return point1.distanceTo(point2)/(1000/Math.cos(latlng1.lat * Math.PI/180));

bekomme aber immer noch überhöhte Werte

– gelöscht, hat sich durch letzten Edit erledig –

Bin selber draugekommen:

function distanceBetweenPoints(latlng1, latlng2){
var point1 = new OpenLayers.Geometry.Point(latlng1.lon, latlng1.lat).transform(Geographic, Mercator);
var point2 = new OpenLayers.Geometry.Point(latlng2.lon, latlng2.lat).transform(Geographic, Mercator);
return point1.distanceTo(point2)/1000Math.cos(latlng1.latMath.PI/180);

so gehts gut. Oder?

Ich glaub schon

du schreibst

1000/cos(latlng1.lat * PI/180)

das war falsch

1000*cos(latlng1.lat * PI/180)

hab besser gepasst

Die Lösung hat schon in deinem Text gesteckt:

Die “Meter” in dieser Projektion sind um den Faktor 1/cos(Breitengrad) gestreckt

wenn man zurückrechnet muss man multiplizieren nicht dividieren

Du hast ja zwischen #5 und #7 auch die Klammern verändert und Mercator/[1000/cos(Breite)]=Mercator/1000*cos(Breite) …

Egal… Es muss halt das kleinere rauskommen :wink: