OpenLayers GPX – Extracting Coordinates from .gpx File

gpxjavascriptopenlayers

I have a simple drag and drop event assigned to my OpenLayers map. This allows me to take a .gpx file, drag & drop it on top of my map which results in the route being visualized on the map.

The code looks like this (taken from the official OpenLayers examples docs):

import 'ol/ol.css';
import DragAndDrop from 'ol/interaction/DragAndDrop';
import Map from 'ol/Map';
import View from 'ol/View';
import {GPX, GeoJSON, IGC, KML, TopoJSON} from 'ol/format';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {Vector as VectorSource, XYZ} from 'ol/source';

const key = 'Get your own API key at https://www.maptiler.com/cloud/';
const attributions =
  '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
  '<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';

const map = new Map({
  layers: [
    new TileLayer({
      source: new XYZ({
        attributions: attributions,
        url:
          'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
        maxZoom: 20,
      }),
    }),
  ],
  target: 'map',
  view: new View({
    center: [0, 0],
    zoom: 2,
  }),
});

const extractStyles = document.getElementById('extractstyles');
let dragAndDropInteraction;

function setInteraction() {
  if (dragAndDropInteraction) {
    map.removeInteraction(dragAndDropInteraction);
  }
  dragAndDropInteraction = new DragAndDrop({
    formatConstructors: [
      GPX,
      GeoJSON,
      IGC,
      // use constructed format to set options
      new KML({extractStyles: extractStyles.checked}),
      TopoJSON,
    ],
  });
  dragAndDropInteraction.on('addfeatures', function (event) {
    const vectorSource = new VectorSource({
      features: event.features,
    });
    map.addLayer(
      new VectorLayer({
        source: vectorSource,
      })
    );
    map.getView().fit(vectorSource.getExtent());
  });
  map.addInteraction(dragAndDropInteraction);
}
setInteraction();

My question is: how can I get an array of all of the coordinates from the .gpx file? Is there a JS library that would allow me to extract the lat and long from the .gpx file in-browser, without having to send the xml to the server for processing?

An ideal output would look like this:
{[lat, lon], [lat, lon], [lat, lon]}

Best Answer

You can get coordinates from feature geometry with the .getCoordinates() method, and you can get feature geometry from feature with the .getGeometry() method.

To get all arrays of coordinates to a global variable allCoords, you just have to add some code to dragAndDropInteraction.on event processing function.

Relevant part of the code could look something like this:

var allCoords;

dragAndDropInteraction.on('addfeatures', function (event) {
  allCoords = [];
  event.features.forEach(function(feature) {
     var featureCoords = feature.getGeometry().getCoordinates();
     featureCoords.forEach(function(sectionCoords) {
       allCoords.push(sectionCoords);
     });
  });
  .
  .
  .
});

This way allCoords would contain coordinates in the map projection, which in this case is Web Mercator, i.e. 'EPSG:3857'.

If you want to get coordinates in [lon, lat] format, conversion with the ol.proj.toLonLat method is needed:

var allCoords;

dragAndDropInteraction.on('addfeatures', function (event) {
  allCoords = [];
  event.features.forEach(function(feature) {
     var featureCoords = feature.getGeometry().getCoordinates();
     featureCoords.forEach(function(sectionCoords) {
       for (var i = 0; i < sectionCoords.length; i++) {
         sectionCoords[i] = ol.proj.toLonLat(sectionCoords[i]);
       }
       allCoords.push(sectionCoords);
     });
  });
  .
  .
  .
});