1

I have a little OL script to display GPX Routes in a OSM map. That works so far, even with a little gimmick.

What I miss is a continuous distance. So from trkpt 0 to trkpt 1 + (trkpt 1 to trkpt 2) + (trkpt 2 to trkpt 3) etc.

For the gimmick I use the array keys. Each array key is an (internal) point where data is calculated. In OpenLayers is an array with all coordinates + the elevation. I would like to extend this array by the distance. Whether the array values should be the continuous distance or that from last-trkpt to next-trkpt, I would have to think twice. Maybe a value with last-trkpt to next-trkpt is probably better.

Is there a solution without OL npm. I use only the ol.css and ol.js v5.3.0.

HTML:

<input type="file" id="files" name="files[]" >
<div id="map" class="map"></div>

Javascript:

var gpxFormat = new ol.format.GPX();
var gpxFeatures;
var coordsarray = [];
var GPXgeometry = [];
function handleFileSelect(evt) {

gpxLayer.getSource().clear();

var files = evt.target.files;

var output = [];
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.readAsText(files[i], "UTF-8");
reader.onload = function (evt) {
gpxFeatures = gpxFormat.readFeatures(evt.target.result,{
dataProjection:'EPSG:4326',
featureProjection:'EPSG:3857'
});
gpxLayer.getSource().addFeatures(gpxFeatures);

var features = gpxLayer.getSource().getFeatures();
features.forEach(function(feature) {
GPXgeometry = feature.getGeometry();
coordsarray = feature.getGeometry().getCoordinates();
});

//--- ??? Start

var i = 0;
var distance = 0;
coordsarray[0][i].push(distance):

// for ???

var lat0 = coordsarray[0][i][0];
var lon0 = coordsarray[0][i][1];
var latlon0 = [lat0, lon0];
i++;
var lat1 = coordsarray[0][i][0];
var lon1 = coordsarray[0][i][1];
var latlon1 = [lat1, lon1];

// calculate distance
// ???

coordsarray[0][i].push(distance):
i--;

//--- ??? End

}


var gpxLayer = new ol.layer.Vector({
source: new ol.source.Vector({

})
});


var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
gpxLayer
]
});

document.getElementById('files').addEventListener('change', handleFileSelect, false);

Example of var coordsarray:

console.log(coordsarray[0][0][0]); // -37937.014545402875
console.log(coordsarray[0][0][1]); // 5354259.990656373
console.log(coordsarray[0][0][2]); // 188.5
console.log(coordsarray[0][1][0]); // -37936.012669985736
console.log(coordsarray[0][1][1]); // 5354231.092259876
console.log(coordsarray[0][1][2]); // 188.5

EDIT
GPX Example (near equador)

<?xml version="1.0" encoding="UTF-8"?>
<!-- track-length = 1323 filtered ascend = 0 plain-ascend = -1 cost=4036 energy=.0kwh time=9.9m -->
<gpx 
 xmlns="http://www.topografix.com/GPX/1/1" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" 
 creator="BRouter-1.4.11" version="1.1">
 <trk>
  <name>brouter_trekking_0</name>
  <trkseg>
   <trkpt lon="11.487967" lat="0.332443"><ele>319.0</ele></trkpt>
   <trkpt lon="11.488969" lat="0.332369"><ele>318.0</ele></trkpt>
   <trkpt lon="11.494446" lat="0.331905"><ele>309.0</ele></trkpt>
   <trkpt lon="11.499806" lat="0.331473"><ele>317.0</ele></trkpt>
  </trkseg>
 </trk>
</gpx>

Javascript:

var startpoint = 0;
var endpoint = startpoint + 2;
var distance = new ol.geom.LineString(coordsarray[0].slice(startpoint,endpoint)).transform('EPSG:4326','EPSG:3857').getLength();
console.log(distance); // 13065083.453663955 ???
2

Try

var distance = new ol.geom.LineString(coordsarray[0].slice(0,i+1)).transform('EPSG:4326','????').getLength();

Ideally transform to a local projection such as UTM which will give meaningful meter distances.

To scale EPSG:3857 units to a latitude you can use point resolution:

var center = ol.geom.LineString(coordsarray[0].slice(startpoint,endpoint)).getCoordinateAt(0.5);
var units = new ol.geom.LineString(coordsarray[0].slice(startpoint,endpoint)‌​).getLength();
var distance = ol.proj.getPointResolution('EPSG:3857', units, center);

Over long distances spherical geometry should give a more accurate result, see https://openlayers.org/en/latest/apidoc/module-ol_sphere.html

var distance = ol.sphere.getLength(new ol.geom.LineString(coordsarray[0].slice(startpoint,endpoint)‌​));
  • Hi Mike. Sorry, i don't understand it. var distance = new ol.geom.LineString(coordsarray[0].slice(0,i+1)).transform('EPSG:4326','EPSG:3857').getLength(); console.log(distance); // example: 1234567.123456789. Is there a distance for the complete GPX route in inch? – Suka Apr 12 at 13:38
  • .getLength will return the distance in the units of the projection you transform the geometry to. For EPSG:3857 the units are meters, but as the scale of EPSG:3857 is true only at the equator it wouldn't give an accurate true distance anywhere outside the tropics and in somewhere like Greenland it would be meaningless. To convert meters to inches divide by 0.0254. coordsarray[0].slice(0,i+1) is the route from start to current point, coordsarray[0].slice(i-1,i+1) would be previous point to current point – Mike Apr 12 at 13:55
  • Yes, by slice there must be (i,i+2). But, the distance is never correct. I have a example of 160 meters, and var distance = 3986643.790377662? – Suka Apr 12 at 14:31
  • I have add a GPX example. – Suka Apr 12 at 14:43
  • Your coordinates were already transformed to EPSG:3857 by readFeatures so (near the equator) var distance = new ol.geom.LineString(coordsarray[0].slice(startpoint,endpoint)).getLength(); will return meters – Mike Apr 12 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.