Weird Subway Map

This week, we worked a little bit with external data that we could use for data visualizations. I was snooping around NYC’s open data trove and found that every subway station had been mapped and given a longitude and latitude coordinate, all in one CSV file. I thought I could start there and see what I managed to come up with.

Overall, its a fairly simple sketch that I worked out. It makes good use of the matrix transformation functions because the longitude and latitude data was set for maps, not p5 sketches! I also added a zoom slider which manipulates the values being fed into the scale function. Each station is an instance of a class that has an x and y coordinate and a function for drawing a circle and writing its name next to it. They also have an additional function for adding a vertex to the train line.

One issue, of course, is the data isn’t completely formatted correctly. There are train stations that are designated as ‘9’ train stops, and every shuttle train (‘S’) is considered part of the same line, including the train on Staten Island, so it just draws one line all the way across all of them. However, in terms of displaying the available data and not getting too mired down in cleaning it, I think its pretty successful!

let stationData;
let station = [];
let averageX = 40.72180996;
let averageY = -73.947071661;
let trainColor = [];
let zoom;
let spin;

let trainLine = [];

function preload() {
  stationData = loadTable("google_transit/stops.txt",
                       "csv",
                       "header");
}


function setup() {
  let j = 0;
  let k = [];

  createCanvas(600, 600);

  zoom = createSlider(100,400,100);
  zoom.position(20, height - 40);

  trainColor = [color('#00aeef'), color('#ec008c'), color('#fff200'),
                color('#a6ce39'), color('#f8971d'), color('#f0514e'),
                color('#72c8b6'), color('#a1a3a6'), color('#7d2a90') ];


  for (let i = 0; i < stationData.getRowCount(); i++) {
    // console.log(stationData.get(i,'stop_id'));
    let stopID = stationData.get(i,'stop_id');
    let stopTrain = stopID.substring(0,1);
    console.log(stopTrain);

    if (trainLine[j-1] != stopTrain){
      trainLine[j] = stopTrain;
      j++;
    }
  }

  for (let i = 0; i < trainLine.length; i++) {
    station[i] = [];
    k[i] = 0;
  }

  for (let i = 0; i < stationData.getRowCount(); i++) {
    let stopID = stationData.get(i,'stop_id');
    let stopTrain = stopID.substring(0,1);

    for (j = 0; j < trainLine.length; j ++){
      if (stopTrain == trainLine[j]){
        station[j][k[j]] = new stationLocation(stationData.getNum(i, 'stop_lat'),
                                               stationData.getNum(i, 'stop_lon'),
                                               stationData.get(i, 'stop_name'));
        k[j]++;
      }
    }

  }
  // console.log(stationData.getRowCount());
  // console.log(stationData.getNum(49,"stop_lat"));
  // noLoop();
}

function draw() {
  let z = zoom.value() / 100;
  let r = 240 * PI / 180;


  background(0);
  push();
  translate(width / 2 - 2 * z * (mouseX - width / 2), height / 2 - 2 * z * (mouseY - height / 2));
  scale(z,z);
  rotate(r);

  noFill();

  strokeWeight(3 / z);

  for (let i = 0; i < station.length; i++){
    if (i == 0 || i == 1 || i == 2 || i == 7) {stroke(trainColor[1]); }
    if (i == 3 || i == 4 || i == 5) {stroke(trainColor[3]); }
    if (i == 6) {stroke(trainColor[8]); }
    if (i == 8 || i == 11){ stroke(trainColor[0]); }
    if (i == 9 || i == 10 || i == 12 || i == 17) {stroke(trainColor[4]); }
    if (i == 13) {stroke(trainColor[6]); }
    if (i == 14 || i == 15) {stroke(trainColor[5]); }
    if (i == 16 || i == 21) {stroke(trainColor[7]); }
    if (i == 18 || i == 19 || i == 20) {stroke(trainColor[2]); }
    beginShape();
    for (let j = 0; j < station[i].length; j+=3){
      station[i][j].tracks();
    }
    endShape();
    for (let j = 0; j < station[i].length; j+=3){
      fill(255);
      station[i][j].placer(5 / z);
      noFill();
    }
  }
  pop();
}

class stationLocation{
  constructor(x,y,id){
    this.stationX = (x - averageX) * 2000;
    this.stationY = (y - averageY) * 2000;
    this.stationID = id;
  }
  placer(diam){
    this.diameter = diam
    push();
    translate(this.stationX, this.stationY);
    ellipse(0, 0, this.diameter, this.diameter);
    rotate(-240 * PI / 180);
    stroke(0);
    textSize(2);
    text(this.stationID, 2, 2);
    pop();
  }
  tracks(){
    vertex(this.stationX, this.stationY);
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *