Skip to content

Instantly share code, notes, and snippets.

@ippsketch
Last active April 30, 2021 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ippsketch/2e9cae5898a81f5dfae8dfbf1d32349a to your computer and use it in GitHub Desktop.
Save ippsketch/2e9cae5898a81f5dfae8dfbf1d32349a to your computer and use it in GitHub Desktop.
GPS routes in p5js

The two files you need to sketch GPS routes with p5.js are below

More information can be found here: https://ippsketch.com/posts/gps-running-routes-with-p5js/

To make this work, you need to:

  1. Copy these files to a directly
  2. Make a subfolder called js and place p5.min.js into it. You can download that here: https://p5js.org/download/
  3. Put ccapture.all.min.js into that js subfolder as well if you want to record png files. That can be found here: https://github.com/spite/ccapture.js/
  4. Place your GPS files into the directory
  5. Put the filenames into the sketchGPSroutes.js file (see line 15 of that file for notes)
  6. Adjust the latitude/longitude scale variable ```scaleLL` on line 13 and translation on line 49 until the routes fit on the sketch.

Note: the way this is currently configured, everything is plotted as an offset from the first data point of the first file ([0][0]). This really only looks good if you're routes start around the same location.

<html lang="en">
<head>
<meta charset="utf-8">
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
<meta name="viewport" content="width=device-width" />
<title>working</title>
</head>
<body>
<script src="./js/p5.min.js"></script>
<script src="./js/CCapture.all.min.js"></script>
<script src="sketchGPSroutes.js"></script>
</body>
</html>
// for capturing to png (must load ccapture)
var cap = true; // change this to create a gif and change stop condition
if (cap){var capturer = new CCapture( { format: 'png' } );}
var PERIOD = 600; //adjust this for capturing pngs, depending on file length
// init 2D arrays for latitude, longitude, and speed
var latRoutes = [];
var lonRoutes = [];
var speedRoutes =[];
// scale the latitude and logitude, adjust to make the lines fit on the page
var scaleLL = 12000;
// there is probably a better way to do this...
// cmd dir /b read *.gpx
// to get list, paste here
files = ['filename1.gpx',
'filename2.gpx',
'filename3.gpx']
var colorSlow;
var colorFast;
//load the data from the gpx files
function preload(){
// get the latitude, longitutde, and speed from the .gpx files
for (let i=0;i<files.length;i++){
[latRoutes[i], lonRoutes[i], speedRoutes[i]] = loadMap(files[i])
}
}
function setup() {
createCanvas(750, 750);
pixelDensity(1)
colorMode(HSB,360,100,100,100);
colorSlow = color(0,100,100,100);
colorFast = color(120,100,100,100);
}
function draw() {
if (frameCount == 1 && (cap)){capturer.start(); start=true;}
background(255)
//adjust these until everything is in the center of the screen
translate(width/2-100,height/2-90);
// this assumes all routes have the same starting point
xstart = latRoutes[0][0];
ystart = lonRoutes[0][0];
for (j=0;j<files.length;j++){
push();
var latr = latRoutes[j];
var lonr = lonRoutes[j];
noStroke();
var dist = (frameCount-1)*2;
if (dist <= 0){dist = 1}
for (k=0;k<dist+1;k++){
// uncomment to plot colors instead
// var speedmin = 1.5;
// var speedmax = 3;
// var colors = lerpColor(colorSlow,colorFast,2*(speedr[k] - speedmin)/(speedmax-speedmin))
// colors.setAlpha(15)
// var rad = 5;
var colors = color(0)
colors.setAlpha(30)
var rad = 2;
fill(colors)
ellipse(4*scaleLL*(lonr[k]-ystart),-4*scaleLL*(latr[k]-xstart),rad,rad)
}
fill(0)
ellipse(4*scaleLL*(lonr[dist]-ystart),-4*scaleLL*(latr[dist]-xstart),8,8)
pop();
}
if (cap){capturer.capture( canvas );}
if (cap){ if ((frameCount-1) == PERIOD){capturer.stop(); capturer.save(); noLoop();}}
}
// load data from files
function loadMap(file) {
var latPoints = [];
var lonPoints = [];
var speedPoints = [];
fetch(file)
.then(response => response.text())
.then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
.then(doc => {
const nodes = [...doc.getElementsByTagName('trkpt')];
nodes.forEach(node =>
{
latPoints.push(node.getAttribute("lat"));
lonPoints.push(node.getAttribute("lon"));
})
const speeds = doc.getElementsByTagName('speed');
for (let i= 0; i < speeds.length; i++) {
speedPoints.push(speeds[i].innerHTML);
}
})
return [latPoints,lonPoints,speedPoints]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment