Skip to content

Instantly share code, notes, and snippets.

@thomascorrie
Last active July 10, 2020 12:39
Show Gist options
  • Save thomascorrie/9378502 to your computer and use it in GitHub Desktop.
Save thomascorrie/9378502 to your computer and use it in GitHub Desktop.
Redundant now that OpenPaths is no longer active. Processing script to create map from OpenPaths csv file using Ordnance Survey coordinates. Requires Jcoord 1.0 and Java SimpleDateFormat
// PREREQUISITES
// Requires Jcoord 1.0 http://www.jstott.me.uk/jcoord/api/1.0/
// and Java SimpleDateFormat http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
// Requires the following csv files
// openpaths.csv
// csv exported from OpenPaths
// select.csv
// Name Left Right Bottom Top Width
// London 520000 540000 174000 190000 1000
// Britain 0 700000 0 1000000 700
// Allows different areas to be selected. The coordinates are OS grid references measured in metres from the false origin. Width is width of desired image in pixels.
// omit.csv
// Simple list of openpath points to omit (for gps noise etc) in the A:A column. Can be empty but is required to exist
// Requires folder within sketch folder called "output" for saving final images
// Requires "background" folder containing background images for each of the select options, i.e. London.jpg for London setup
// SET VARIABLES
int selectNum = 1; //1 for London, 2 for Britain, 3 for South East etc
String[] select;
//DOTS OR LINES?
int format = 0; //0 for dots, 1 for lines between points
int mode = 0; //0 for normal, 1 for debug // Debug mode shows the gps point numbers and shows omitted points
//CHOOSE START AND END DATES
String dsStart = "2013-01-01 00:00:00"; //Start Date
String dsEnd = "2013-12-31 23:59:59"; //End Date
//CHOOSE COLOURS
color ln = color(240,240,240,40); //color(240,240,240,40);
color grid = color(255,0,0,50); //color(230,230,230,20);
color txt = color(220,220,220,255); //color(255,255,255,80);
color txtd = color(220,0,0,255); //color(255,255,255,80);
color back = color(100,100,100); //color(75,70,70);
//Import Utilities
import java.util.*;
import java.text.*;
import java.text.SimpleDateFormat;
//DATES
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dDate;
Date dStart;
Date dEnd;
int numFrame;
//Data
String[] data;
int[] omit;
//Image
PImage b;
//Map
float mapGeoLeft;
float mapGeoRight;
float mapGeoBottom;
float mapGeoTop;
float mapScreenWidth,mapScreenHeight; // Dimension of map in pixels.
String selectN;
//SETUP
void setup() {
//SELECT
select = loadStrings("select.csv"); //Load locations
String[] selectF = splitTokens(select[selectNum],",");
//Map Size
mapGeoLeft = int(selectF[1]); //Longitude West
mapGeoRight = int(selectF[2]); //Longitude East
mapGeoBottom = int(selectF[3]); //Latitude South
mapGeoTop = int(selectF[4]); //Latitude North
selectN = selectF[0];
//DATES
try {
dStart = df.parse(dsStart);
println(dStart);
}
catch(ParseException e) {
println(e);
}
try {
dEnd = df.parse(dsEnd);
println(dEnd);
}
catch(ParseException e) {
println(e);
}
//Format Dates
String dStartY = new SimpleDateFormat("yy").format(dStart);
String dEndY = new SimpleDateFormat("yy").format(dEnd);
String dStartM = new SimpleDateFormat("MMM").format(dStart);
String dEndM = new SimpleDateFormat("MMM").format(dEnd);
String dStartD = new SimpleDateFormat("dd").format(dStart);
String dEndD = new SimpleDateFormat("dd").format(dEnd);
String dFormat;
if (dStartY.equals(dEndY) == true) {
if (dStartM.equals(dEndM) == true) {
if (dStartD.equals(dEndD) == true) {
dFormat = dEndD+" "+dEndM.toUpperCase()+" "+dEndY; //One Day
} else {
dFormat = dStartD+" - "+dEndD+" "+dEndM.toUpperCase()+" "+dEndY; //One Month
}
} else {
dFormat = dStartD+" "+dStartM.toUpperCase()+" - "+dEndD+" "+dEndM.toUpperCase()+" "+dEndY; //One Year
}
} else {
dFormat = dStartD+" "+dStartM.toUpperCase()+" "+dStartY+" - "+dEndD+" "+dEndM.toUpperCase()+" "+dEndY;
}
//Image Setup
int xWidth = int(selectF[5]);
int yHeight = int((xWidth/(mapGeoRight-mapGeoLeft))*(mapGeoTop-mapGeoBottom)); //int((mapGeoTop-mapGeoBottom)*scaleMap);
size(xWidth,yHeight);
smooth();
background(back);
mapScreenWidth = width;
mapScreenHeight = height;
frameRate(30);
data = loadStrings("openpaths.csv"); //Load locations
omit = int(loadStrings("omit.csv")); //Load Omissions
numFrame = data.length;
b = loadImage("backgrounds/"+selectF[0]+".jpg");
image(b, 0, 0);
//Fonts
PFont font;
font = loadFont("Pixel_Caps-8.vlw");
fill(txt);
textFont(font);
text("MY MOVEMENT AROUND "+selectF[0].toUpperCase(), 5, 10, 400, 200);
text(dFormat, 5, 20, 400, 200);
text(str(int(mapGeoLeft))+" E", 5, height-20, 50, 200);
text(str(int(mapGeoBottom))+" N", 5, height-10, 50, 200);
textAlign(RIGHT);
text(str(int(mapGeoRight))+" E", width-5-50, 10, 50, 200);
text(str(int(mapGeoTop))+" N", width-5-50, 20, 50, 200);
text("BY THOMAS CORRIE / RECORDED USING OPENPATHS.CC / BUILT WITH PROCESSING", width-5-500, height-20, 500, 200);
text("CONTAINS ORDNANCE SURVEY DATA (C) CROWN COPYRIGHT AND DATABASE RIGHT 2011", width-5-500, height-10, 500, 200);
}
//DRAW
void draw() {
//Draw vectors
noFill();
stroke(ln);
strokeWeight(2.0);
PVector p1 = new PVector(0,0);
PVector p2 = new PVector(0,0);
int omitSwitch = 0;
noLoop();
int omitCount = 0;
int startCount = 0;
for (int i=1;i<numFrame;i++) {
String[] pieces2 = splitTokens(data[i],",");
try {
dDate = df.parse(pieces2[3]);
}
catch(ParseException e) {
println(e);
}
if(dDate.after(dStart) && dDate.before(dEnd)) {
if (startCount == 0) {
//Point 1
String[] pieces1 = splitTokens(data[i-1],",");
float x1 = float(pieces1[1]);
float y1 = float(pieces1[0]);
p1 = geoToPixelOSGB(new PVector(x1,y1));
if (i > omit[omit.length-1]) {
println(omit[omit.length-1]);
omitSwitch = 1;
} else if (i > omit[omitCount]) {
while (i > omit[omitCount] && omitCount < omit.length-1) {
omitCount++;
}
}
}
//Point 2
float x2 = float(pieces2[1]);
float y2 = float(pieces2[0]);
p2 = geoToPixelOSGB(new PVector(x2,y2));
if (omitSwitch == 1 || (omitCount+1 > omit.length) || i < omit[omitCount]) {
if (mode == 1) { //debug
textAlign(LEFT);
text(str(i), p2.x, p2.y, 400, 200);
}
if (format == 1) {
line(p1.x,p1.y,p2.x,p2.y);
} else {
noStroke();
fill(ln);
ellipse(p2.x,p2.y,5,5);
}
p1 = new PVector(p2.x,p2.y); //Send this point to next
} else if (i == omit[omitCount]) {
omitCount += 1;
if (mode == 1 /*&& int(dHour) < 8*/) { //debug
textAlign(LEFT);
fill(txtd);
text(str(i), p2.x, p2.y, 400, 200);
fill(txt);
}
}
startCount += 1;
}
}
//Save image
if (format == 1) {
save("output/"+selectN+"_image_lines.gif"); //Save lines
} else {
save("output/"+selectN+"_image_dots.gif"); //Save dots
}
}
// Adapted from code posted to http://forum.processing.org/one/topic/using-a-world-map-in-processing.html
// Converts geographical coordinates into screen coordinates.
// Useful for drawing geographically referenced items on screen.
public PVector geoToPixel(PVector geoLocation)
{
return new PVector(mapScreenWidth*(geoLocation.x-mapGeoLeft)/(mapGeoRight-mapGeoLeft),
mapScreenHeight - mapScreenHeight*(geoLocation.y-mapGeoBottom)/(mapGeoTop-mapGeoBottom));
}
// Converts geographical coordinates from WGS84 to OS Ref and into screen coordinates.
public PVector geoToPixelOSGB(PVector geoLocation)
{
LatLng LL = new LatLng(geoLocation.y,geoLocation.x);
LL.toOSGB36();
OSRef OS = LL.toOSRef();
return new PVector(mapScreenWidth*((float)OS.getEasting()-mapGeoLeft)/(mapGeoRight-mapGeoLeft),
mapScreenHeight - mapScreenHeight*((float)OS.getNorthing()-mapGeoBottom)/(mapGeoTop-mapGeoBottom));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment