Skip to content

Instantly share code, notes, and snippets.

@ClemRz
Last active September 2, 2024 11:55
Show Gist options
  • Save ClemRz/4b7b525bb4e7405b7f3937a695ded310 to your computer and use it in GitHub Desktop.
Save ClemRz/4b7b525bb4e7405b7f3937a695ded310 to your computer and use it in GitHub Desktop.
This is how you download a KML from alltrails.com without needing a PRO account.
(function () {
const API_KEY = '3p0t5s6b5g4g0e8k3c1j3w7y5c3m4t8i';
const URL = 'https://www.alltrails.com/api/alltrails/trails/';
const DETAILS_LEVEL = 'medium';
function decoded_objects_from_polyline(t) {
var e = [5, 5];
length = t.length,
dimensions = e.length;
var i = 0
, n = 0
, a = 0
, r = 0;
for (buffer = new Array(dimensions * length,0),
bufferCount = 0; i < length; ) {
r = null;
for (var s = 0; s < dimensions; s++) {
a = 0,
n = 0;
do {
if (i >= length)
break;
r = t.charCodeAt(i++) - 63,
a |= (31 & r) << n,
n += 5
} while (r >= 32);delta = 0 != (1 & a) ? ~(a >> 1) : a >> 1,
lastValue = 0 == bufferCount ? 0 : buffer[(bufferCount - 1) * dimensions + s],
buffer[bufferCount * dimensions + s] = Math.round((lastValue + Math.pow(10, -e[s]) * delta) * Math.pow(10, e[s])) / Math.pow(10, e[s])
}
bufferCount += 1
}
return buffer = buffer,
rows = bufferCount,
res = [],
buffer.each_slice(dimensions, function(t) {
res.push(t)
}),
res
}
function download(obj) {
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob([obj.text], {type: 'text/xml'}));
a.download = obj.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
function createKml(obj) {
var kml = '<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><name>' + obj.name + '</name><Placemark><name>' + obj.name + '</name><LineString><altitudeMode>relativeToGround</altitudeMode><coordinates>';
kml += obj.pointsData.map(function (p) {
return p.reverse().join() + ',0';
}).join(' ');
kml += '</coordinates></LineString></Placemark></Document></kml>';
return {name:obj.name.replace(/[^\w]/ig,'')+'.kml', text:kml};
}
function processResponse(response) {
var trail = response.trails[0];
var pointsData = decoded_objects_from_polyline(trail.defaultMap.routes[0].lineSegments[0].polyline.pointsData);
return {name:trail.name, url:document.location.href, pointsData:pointsData};
}
function getTrailsData(trailId) {
return $.ajax({
url: URL + trailId + '?detail=' + DETAILS_LEVEL,
type: "GET",
beforeSend: function (xhr) {
xhr.setRequestHeader('x-at-key', API_KEY);
}
});
}
function getTrailId() {
var dfd = jQuery.Deferred();
var alternateEl = $('link[rel="alternate"]')[0];
var data = $('li.favorite-menu').attr('data-react-props');
if (alternateEl) {
dfd.resolve($('link[rel="alternate"]')[0].href.split('/').pop());
} else if (data) {
dfd.resolve(JSON.parse(data).trailId);
} else {
dfd.reject('Could not identify the trail ID. Please enter a trail specific page.');
}
return dfd.promise();
}
function init() {
getTrailId().then(getTrailsData, console.error)
.then(processResponse)
.then(createKml)
.then(download);
}
Array.prototype.each_slice = function(t, e) {
for (var i = 0, n = this.length; i < n; i += t) e.call(this, this.slice(i, i + t));
}
init();
})();
//Go to https://www.alltrails.com/trail/new and copy the response obtained from osmsegments
(function () {
function decoded_objects_from_polyline(t) {
var e = [5, 5];
length = t.length,
dimensions = e.length;
var i = 0, n = 0, a = 0, r = 0;
for (buffer = new Array(dimensions * length,0),
bufferCount = 0; i < length; ) {
r = null;
for (var s = 0; s < dimensions; s++) {
a = 0,
n = 0;
do {
if (i >= length)
break;
r = t.charCodeAt(i++) - 63,
a |= (31 & r) << n,
n += 5
} while (r >= 32);delta = 0 != (1 & a) ? ~(a >> 1) : a >> 1,
lastValue = 0 == bufferCount ? 0 : buffer[(bufferCount - 1) * dimensions + s],
buffer[bufferCount * dimensions + s] = Math.round((lastValue + Math.pow(10, -e[s]) * delta) * Math.pow(10, e[s])) / Math.pow(10, e[s])
}
bufferCount += 1
}
return buffer = buffer,
rows = bufferCount,
res = [],
buffer.each_slice(dimensions, function(t) {
res.push(t)
}),
res
}
function download(obj) {
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob([obj.text], {type: 'text/xml'}));
a.download = obj.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
function createKml(obj) {
var kml = '<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><name>' + obj.name + '</name>';
obj.pointsDatas.forEach(function (pointsData, index) {
kml += '<Placemark><name>' + obj.name + '_' + index + '</name><LineString><altitudeMode>relativeToGround</altitudeMode><coordinates>';
kml += pointsData.map(function (p) {
return p.reverse().join() + ',0';
}).join(' ');
kml += '</coordinates></LineString></Placemark>';
});
kml += '</Document></kml>';
return {name:obj.name.replace(/[^\w]/ig,'')+'.kml', text:kml};
}
function processLineSegments(lineSegments) {
var pointsDatas = [];
lineSegments.forEach(function (lineSegment) {
pointsDatas.push(decoded_objects_from_polyline(lineSegment.polyline.pointsData));
});
download(createKml({
name: 'trail',
url: document.location.href,
pointsDatas: pointsDatas
}));
}
function init() {
processLineSegments([paste lineSegments here]);
}
Array.prototype.each_slice = function(t, e) {
for (var i = 0, n = this.length; i < n; i += t) e.call(this, this.slice(i, i + t));
}
init();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment