Leaflet GPX – How to Separate Multiple Tracks and Segments in Single GPX File Using Leaflet-gpx Plugin

gpxleafletleaflet-plugins

I'm using leaflet-gpx to plot a .gpx file containing multiple tracks but I can't get it to distinguish between each track of the file:

This is the basic structure of the file:

 <gpx>
  <trk> 
     <name>track 1</name>  <!-- track 1 has 1 segments-->
     <trkseg>
       <trkpt> ... </trkpt>
     </trkseg>
   </trk>
  <trk> 
     <name>track 2</name>  <!-- track 2 has 2 segments-->
     <trkseg>
       <trkpt>....</trkpt> 
     </trkseg>
     <trkseg>
       <trkpt>....</trkpt>
     </trkseg>
   </trk>

And while I can plot all the tracks and segments using leaflet-gpx:

var gpxfile='testgpx.gpx';

new L.GPX(gpxfile,{
        async: true,
        marker_options: {
                  startIconUrl:  'pin-icon-start.png',
                  endIconUrl:  false,
                  shadowUrl:   false,
                },
        gpx_options: {
                    joinTrackSegments: false
                }, 
    }).on('loaded', function(e) {
        var track = e.target;
                
        control.addOverlay(track,track.get_name()) // adds a tickbox in the control panel of the map
        console.log(track.get_name())              // to see in the browser console
        console.log('distance = '+track.get_distance())
        console.log('max ele =' + track.get_elevation_max())
    }).addTo(mymap)  

The 2 tracks, 3 segments are drawn, each with a start icon, but:

  • the track.get_name() returns track 1
  • the distance is the sum of the distance of each segments
  • the value for get_elevation_max() is inside the first segment of track 2.
  • there is only one box in the control box, to select/deselect all the tracks of the file (when I plot 2 files, each file has a different box)

So it seems that it just treats each track a separate segment of the first track.

According to the documentation, the joinTrackSegments option should allow to combine the segments into one, but I get the same results setting it to true or false.

Is there a way to get a handle to each track of the file? Or should I split the file first, and then send each track individually to the new L.GPX constructor?
I want the distance calculation and the checkbox to be for each track.

And why does the joinTrackSegments option seem to not do anything?

2 tracks, 3 segments

Best Answer

Look at the source code of leaflet.gpx plugin reveals that plugin does not deal with separate tracks, it just takes track name from the first track and the rest is just one track for it.

One possible solution is to read GPX file separately and then feed tracks one by one to L.GPX track layer creation.

Code for this could look something like this (AJAX part is taken from plugin itself):

function loadGPX(gpx) {
  new L.GPX(gpx,{
      async: true,
      marker_options: {
        startIconUrl:  'pin-icon-start.png',
        endIconUrl:  false,
        shadowUrl:   false,
      },
      gpx_options: {
          joinTrackSegments: false
      }, 
  }).on('loaded', function(e) {
    var track = e.target;         
    control.addOverlay(track,track.get_name()) // adds a tickbox in the control panel of the map
    console.log(track.get_name())              // to see in the browser console
    console.log('distance = '+track.get_distance())
    console.log('max ele =' + track.get_elevation_max())
  }).addTo(mymap)
}

var req = new window.XMLHttpRequest();
req.open('GET', url, true);
try {
  req.overrideMimeType('text/xml');
} catch(e) {}
req.onreadystatechange = function() {
  if (req.readyState != 4) return;
  if(req.status == 200) {
    var xml = req.responseXML;
    var tracks = xml.getElementsByTagName('trk');
    var serializer = new XMLSerializer();
    for (var i = 0; i < tracks.length; i++) {
      loadGPX(serializer.serializeToString(tracks[i]));
    }
  }
};
req.send(null);