nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

commit 9d3c908e4737c9e60b71e73b37078ef4f710cc05
parent 309c261f0a86bb4c7fea32a29c196c09c2d0c37c
Author: Sergey Orlov <wladimirych@gmail.com>
Date:   Fri, 22 May 2020 09:43:29 +0200

track list: add feature: save GPX with added elevations, fixes #298

Diffstat:
Msrc/lib/leaflet.control.track-list/lib/geo_file_exporters.js | 13+++++++++----
Msrc/lib/leaflet.control.track-list/track-list.js | 38+++++++++++++++++++++++++++++++++++++-
2 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/src/lib/leaflet.control.track-list/lib/geo_file_exporters.js b/src/lib/leaflet.control.track-list/lib/geo_file_exporters.js @@ -2,7 +2,7 @@ import utf8 from 'utf8'; import escapeHtml from 'escape-html'; import {saveNktk} from './parsers/nktk'; -function saveGpx(segments, name, points, withElevations=false) { +function saveGpx(segments, name, points, withElevations = false) { const gpx = []; const fakeTime = '1970-01-01T00:00:01.000Z'; @@ -18,7 +18,7 @@ function saveGpx(segments, name, points, withElevations=false) { label = utf8.encode(label); gpx.push(`\t<wpt lat="${marker.latlng.lat.toFixed(6)}" lon="${marker.latlng.lng.toFixed(6)}">`); gpx.push(`\t\t<name>${label}</name>`); - if (withElevations) { + if (withElevations && marker.latlng.alt !== null) { gpx.push(`\t\t<ele>${marker.latlng.alt.toFixed(1)}</ele>`); } gpx.push('\t</wpt>'); @@ -36,7 +36,8 @@ function saveGpx(segments, name, points, withElevations=false) { for (let point of segment) { let x = point.lng.toFixed(6); let y = point.lat.toFixed(6); - const elevation = withElevations ? `<ele>${point.alt.toFixed(1)}</ele>ele>` : ''; + const elevation = (withElevations && point.alt !== null) + ? `<ele>${point.alt.toFixed(1)}</ele>` : ''; // time element is not necessary, added for compatibility to Garmin Connect only gpx.push(`\t\t\t<trkpt lat="${y}" lon="${x}"><time>${fakeTime}</time>${elevation}</trkpt>`); } @@ -48,6 +49,10 @@ function saveGpx(segments, name, points, withElevations=false) { return gpx.join('\n'); } +function saveGpxWithElevations(segments, name, points) { + return saveGpx(segments, name, points, true); +} + function saveKml(segments, name, points) { const kml = []; @@ -99,5 +104,5 @@ function saveKml(segments, name, points) { return kml.join('\n'); } -export default {saveGpx, saveKml, saveToString: saveNktk}; +export default {saveGpx, saveGpxWithElevations, saveKml, saveToString: saveNktk}; diff --git a/src/lib/leaflet.control.track-list/track-list.js b/src/lib/leaflet.control.track-list/track-list.js @@ -25,6 +25,7 @@ import config from '~/config'; import md5 from 'blueimp-md5'; import {wrapLatLngToTarget, wrapLatLngBoundsToTarget} from '~/lib/leaflet.fixes/fixWorldCopyJump'; import {splitLinesAt180Meridian} from "./lib/meridian180"; +import {ElevationProvider} from '~/lib/elevations'; const TRACKLIST_TRACK_COLORS = ['#77f', '#f95', '#0ff', '#f77', '#f7f', '#ee5']; @@ -454,6 +455,11 @@ L.Control.TrackList = L.Control.extend({ {text: 'Save as GPX', callback: this.saveTrackAsFile.bind(this, track, geoExporters.saveGpx, '.gpx')}, {text: 'Save as KML', callback: this.saveTrackAsFile.bind(this, track, geoExporters.saveKml, '.kml')}, {text: 'Copy link for track', callback: this.copyTrackLinkToClipboard.bind(this, track)}, + {text: 'Extra', separator: true}, + { + text: 'Save as GPX with added elevation (SRTM)', + callback: this.saveTrackAsFile.bind(this, track, geoExporters.saveGpxWithElevations, '.gpx', true), + }, ]; track._actionsMenu = new Contextmenu(items); }, @@ -533,7 +539,7 @@ L.Control.TrackList = L.Control.extend({ this.copyTracksLinkToClipboard([track], mouseEvent); }, - saveTrackAsFile: function(track, exporter, extension) { + saveTrackAsFile: async function(track, exporter, extension, addElevations = false) { this.stopActiveDraw(); var lines = this.getTrackPolylines(track) .map(function(line) { @@ -553,6 +559,36 @@ L.Control.TrackList = L.Control.extend({ return; } + if (addElevations) { + const request = [ + ...points.map((p) => p.latlng), + ...lines.reduce((acc, cur) => { + acc.push(...cur); + return acc; + }, []) + ]; + let elevations; + try { + elevations = await new ElevationProvider().get(request); + } catch (e) { + logging.captureException(e, 'error getting elevation for gpx'); + notify(`Failed to get elevation data: ${e.message}`); + } + let n = 0; + for (let p of points) { + // we make copy of latlng as we are changing it + p.latlng = L.latLng(p.latlng.lat, p.latlng.lng, elevations[n]); + n += 1; + } + for (let line of lines) { + for (let p of line) { + // we do not need to create new LatLng since splitLinesAt180Meridian() have already done it + p.alt = elevations[n]; + n += 1; + } + } + } + var fileText = exporter(lines, name, points); var filename = name + extension; saveAs(blobFromString(fileText), filename, true);