GPXParser.min.js 8.7 KB

12345678
  1. /*
  2. https://github.com/Luuka/GPXParser.js
  3. GPXParser.js v3.0.8 07/07/2024
  4. Copyright (c) 2018 Lucas Trebouet Voisin
  5. */
  6. let gpxParser=function(){this.xmlSource="";this.metadata={};this.waypoints=[];this.tracks=[];this.routes=[]};gpxParser.prototype.parse=function(gpxstring){let keepThis=this;let domParser=new window.DOMParser();this.xmlSource=domParser.parseFromString(gpxstring,'text/xml');let metadata=this.xmlSource.querySelector('metadata');if(metadata!=null){this.metadata.name=this.getElementValue(metadata,"name");this.metadata.desc=this.getElementValue(metadata,"desc");this.metadata.time=this.getElementValue(metadata,"time");let author={};let authorElem=metadata.querySelector('author');if(authorElem!=null){author.name=this.getElementValue(authorElem,"name");author.email={};let emailElem=authorElem.querySelector('email');if(emailElem!=null){author.email.id=emailElem.getAttribute("id");author.email.domain=emailElem.getAttribute("domain")}let link={};let linkElem=authorElem.querySelector('link');if(linkElem!=null){link.href=linkElem.getAttribute('href');link.text=this.getElementValue(linkElem,"text");link.type=this.getElementValue(linkElem,"type")}author.link=link}this.metadata.author=author;let link={};let linkElem=this.queryDirectSelector(metadata,'link');if(linkElem!=null){link.href=linkElem.getAttribute('href');link.text=this.getElementValue(linkElem,"text");link.type=this.getElementValue(linkElem,"type");this.metadata.link=link}}var wpts=[].slice.call(this.xmlSource.querySelectorAll('wpt'));for(let idx in wpts){var wpt=wpts[idx];let pt={};pt.name=keepThis.getElementValue(wpt,"name");pt.sym=keepThis.getElementValue(wpt,"sym");pt.lat=parseFloat(wpt.getAttribute("lat"));pt.lon=parseFloat(wpt.getAttribute("lon"));let floatValue=parseFloat(keepThis.getElementValue(wpt,"ele"));pt.ele=isNaN(floatValue)?null:floatValue;pt.cmt=keepThis.getElementValue(wpt,"cmt");pt.desc=keepThis.getElementValue(wpt,"desc");let time=keepThis.getElementValue(wpt,"time");pt.time=time==null?null:new Date(time);keepThis.waypoints.push(pt)}var rtes=[].slice.call(this.xmlSource.querySelectorAll('rte'));for(let idx in rtes){let rte=rtes[idx];let route={};route.name=keepThis.getElementValue(rte,"name");route.cmt=keepThis.getElementValue(rte,"cmt");route.desc=keepThis.getElementValue(rte,"desc");route.src=keepThis.getElementValue(rte,"src");route.number=keepThis.getElementValue(rte,"number");let type=keepThis.queryDirectSelector(rte,"type");route.type=type!=null?type.innerHTML:null;let link={};let linkElem=rte.querySelector('link');if(linkElem!=null){link.href=linkElem.getAttribute('href');link.text=keepThis.getElementValue(linkElem,"text");link.type=keepThis.getElementValue(linkElem,"type")}route.link=link;let routepoints=[];var rtepts=[].slice.call(rte.querySelectorAll('rtept'));for(let idxIn in rtepts){let rtept=rtepts[idxIn];let pt={};pt.lat=parseFloat(rtept.getAttribute("lat"));pt.lon=parseFloat(rtept.getAttribute("lon"));let floatValue=parseFloat(keepThis.getElementValue(rtept,"ele"));pt.ele=isNaN(floatValue)?null:floatValue;let time=keepThis.getElementValue(rtept,"time");pt.time=time==null?null:new Date(time);routepoints.push(pt)}route.distance=keepThis.calculDistance(routepoints);route.elevation=keepThis.calcElevation(routepoints);route.slopes=keepThis.calculSlope(routepoints,route.distance.cumul);route.points=routepoints;keepThis.routes.push(route)}var trks=[].slice.call(this.xmlSource.querySelectorAll('trk'));for(let idx in trks){let trk=trks[idx];let track={};track.name=keepThis.getElementValue(trk,"name");track.cmt=keepThis.getElementValue(trk,"cmt");track.desc=keepThis.getElementValue(trk,"desc");track.src=keepThis.getElementValue(trk,"src");track.number=keepThis.getElementValue(trk,"number");let type=keepThis.queryDirectSelector(trk,"type");track.type=type!=null?type.innerHTML:null;let link={};let linkElem=trk.querySelector('link');if(linkElem!=null){link.href=linkElem.getAttribute('href');link.text=keepThis.getElementValue(linkElem,"text");link.type=keepThis.getElementValue(linkElem,"type")}track.link=link;let trackpoints=[];let trkpts=[].slice.call(trk.querySelectorAll('trkpt'));for(let idxIn in trkpts){var trkpt=trkpts[idxIn];let pt={};pt.lat=parseFloat(trkpt.getAttribute("lat"));pt.lon=parseFloat(trkpt.getAttribute("lon"));let floatValue=parseFloat(keepThis.getElementValue(trkpt,"ele"));pt.ele=isNaN(floatValue)?null:floatValue;let time=keepThis.getElementValue(trkpt,"time");pt.time=time==null?null:new Date(time);trackpoints.push(pt)}track.distance=keepThis.calculDistance(trackpoints);track.elevation=keepThis.calcElevation(trackpoints);track.slopes=keepThis.calculSlope(trackpoints,track.distance.cumul);track.points=trackpoints;keepThis.tracks.push(track)}};gpxParser.prototype.getElementValue=function(parent,needle){let elem=parent.querySelector(needle);if(elem!=null){return elem.innerHTML!=undefined?elem.innerHTML:elem.childNodes[0].data}return elem};gpxParser.prototype.queryDirectSelector=function(parent,needle){let elements=parent.querySelectorAll(needle);let finalElem=elements[0];if(elements.length>1){let directChilds=parent.childNodes;for(idx in directChilds){elem=directChilds[idx];if(elem.tagName===needle){finalElem=elem}}}return finalElem};gpxParser.prototype.calculDistance=function(points){let distance={};let totalDistance=0;let cumulDistance=[];for(var i=0;i<points.length-1;i+=1){totalDistance+=this.calcDistanceBetween(points[i],points[i+1]);cumulDistance[i]=totalDistance}cumulDistance[points.length-1]=totalDistance;distance.total=totalDistance;distance.cumul=cumulDistance;return distance};gpxParser.prototype.calcDistanceBetween=function(wpt1,wpt2){let latlng1={};latlng1.lat=wpt1.lat;latlng1.lon=wpt1.lon;let latlng2={};latlng2.lat=wpt2.lat;latlng2.lon=wpt2.lon;var rad=Math.PI/180,lat1=latlng1.lat*rad,lat2=latlng2.lat*rad,sinDLat=Math.sin((latlng2.lat-latlng1.lat)*rad/2),sinDLon=Math.sin((latlng2.lon-latlng1.lon)*rad/2),a=sinDLat*sinDLat+Math.cos(lat1)*Math.cos(lat2)*sinDLon*sinDLon,c=2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a));return 6371000*c};gpxParser.prototype.calcElevation=function(points){var dp=0,dm=0,ret={};for(var i=0;i<points.length-1;i+=1){let rawNextElevation=points[i+1].ele;let rawElevation=points[i].ele;if(rawNextElevation!==null&&rawElevation!==null){let diff=parseFloat(rawNextElevation)-parseFloat(rawElevation);if(diff<0){dm+=diff}else if(diff>0){dp+=diff}}}var elevation=[];var sum=0;for(var i=0,len=points.length;i<len;i+=1){let rawElevation=points[i].ele;if(rawElevation!==null){var ele=parseFloat(points[i].ele);elevation.push(ele);sum+=ele}}ret.max=Math.max.apply(null,elevation)||null;ret.min=Math.min.apply(null,elevation)||null;ret.pos=Math.abs(dp)||null;ret.neg=Math.abs(dm)||null;ret.avg=sum/elevation.length||null;return ret};gpxParser.prototype.calculSlope=function(points,cumul){let slopes=[];for(var i=0;i<points.length-1;i+=1){let point=points[i];let nextPoint=points[i+1];let elevationDiff=nextPoint.ele-point.ele;let distance=cumul[i+1]-cumul[i];let slope=(elevationDiff*100)/distance;slopes.push(slope)}return slopes};gpxParser.prototype.toGeoJSON=function(){var GeoJSON={"type":"FeatureCollection","features":[],"properties":{"name":this.metadata.name,"desc":this.metadata.desc,"time":this.metadata.time,"author":this.metadata.author,"link":this.metadata.link}};for(idx in this.tracks){let track=this.tracks[idx];var feature={"type":"Feature","geometry":{"type":"LineString","coordinates":[]},"properties":{}};feature.properties.name=track.name;feature.properties.cmt=track.cmt;feature.properties.desc=track.desc;feature.properties.src=track.src;feature.properties.number=track.number;feature.properties.link=track.link;feature.properties.type=track.type;for(idx in track.points){let pt=track.points[idx];var geoPt=[];geoPt.push(pt.lon);geoPt.push(pt.lat);geoPt.push(pt.ele);feature.geometry.coordinates.push(geoPt)}GeoJSON.features.push(feature)}for(idx in this.routes){let track=this.routes[idx];var feature={"type":"Feature","geometry":{"type":"LineString","coordinates":[]},"properties":{}};feature.properties.name=track.name;feature.properties.cmt=track.cmt;feature.properties.desc=track.desc;feature.properties.src=track.src;feature.properties.number=track.number;feature.properties.link=track.link;feature.properties.type=track.type;for(idx in track.points){let pt=track.points[idx];var geoPt=[];geoPt.push(pt.lon);geoPt.push(pt.lat);geoPt.push(pt.ele);feature.geometry.coordinates.push(geoPt)}GeoJSON.features.push(feature)}for(idx in this.waypoints){let pt=this.waypoints[idx];var feature={"type":"Feature","geometry":{"type":"Point","coordinates":[]},"properties":{}};feature.properties.name=pt.name;feature.properties.sym=pt.sym;feature.properties.cmt=pt.cmt;feature.properties.desc=pt.desc;feature.geometry.coordinates=[pt.lon,pt.lat,pt.ele];GeoJSON.features.push(feature)}return GeoJSON};if(typeof module!=='undefined'){require('jsdom-global')();module.exports=gpxParser}