Display population data from a CSV file onto a map

Hi,

I am trying to plot population data (from three years) from a CSV file onto a map of the UK but am not sure how to do this. I have gathered the X and Y coordinates (and they correspond correctly to the map) of each city in the CSV files, but I am not sure how to plot this onto the map in processing (I would like to do something like a 3D bar chart). I would also like to switch between the years.

Here is the csv:

Here is the code:

import peasy.*;

PImage map;
Table data;
PeasyCam camera;
PVector position;

void setup() {
  
  size(800, 800, P3D);
  map = loadImage("map.jpg");

  camera = new PeasyCam(this, 3000); 
  camera.setMinimumDistance(100);
  camera.setMaximumDistance(3500);
  position = new PVector(-map.width/2, 200, -map.height/2);

  data = loadTable("Data.csv", "header");
}

void draw() {
  
  background (#000000);
  mapSetup();
  adjustCamera();
  plot();
  
}

void mapSetup() {
  pushMatrix();
  translate(position.x, position.y, position.z);
  rotateX(radians(90));
  image (map, 0, 0);
  popMatrix();  
}

void adjustCamera() {
  camera.setRotations(radians(25), radians((((float)mouseX/width) * 90) - 45), 0);
}

**void plot() {**

**}**
void keyPressed() {
  
  if (key == CODED) {
    if (keyCode == UP) {
      position.z += 50;
    }
    
    if (keyCode == DOWN) {
      position.z -= 50;
    }
    
    if (keyCode == LEFT) {
      position.x += 50;
    }
    
    if (keyCode == RIGHT) {
      position.x -= 50;
    }
  } 
}

Any help with this would be greatly appreciated.

Y

Here is my example

As you can see, use “+” and “-” to change the year (catch it when the index for the array is too high in keyPressed() - to do)

I had to move plot(); into mapsetup (please give the function a new name - to do)

use a for-loop to loop over all cities

You can change year with + and - OR show three bars next to each other for each city

I also displayed the City name

instead of a small bar to show the population size, you could also use sphere.

It’s debatable why you use PeasyCam because the normal camera can do similar stuff.

import peasy.*;

PImage map;
Table data;
PeasyCam camera;
PVector position;

// array - use with currentyear
String[] years =
  {
  "1991", "2001", "2011"
};
int currentyear = 0; // used for the array 

//-------------------------------------------------------------------------

void setup() {

  size(800, 800, P3D);

  map = loadImage("map.jpg");

  camera = new PeasyCam(this, 3000); 
  camera.setMinimumDistance(100);
  camera.setMaximumDistance(3500);

  position = new PVector(-map.width/2, 200, -map.height/2);

  data = loadTable("Data.csv", "header");
}

void draw() {
  background (#000000);
  noLights();

  adjustCamera();
  mapSetup();
}

void mapSetup() {
  pushMatrix();

  translate(position.x, position.y, position.z);
  rotateX(radians(90));
  image (map, 0, 0);

  lights();
  plot();

  popMatrix();
}

void adjustCamera() {
  camera.setRotations(radians(25), radians((((float)mouseX/width) * 90) - 45), 0);
}

void plot() {
  //** 
  // Make a for-loop for all ROWS : TableRow row1=data.getRow(i);   // using i here 
  TableRow row1=data.getRow(0); 

  // get data of this row 
  String city1=row1.getString( "City" );
  int x=row1.getInt("X");
  int y=row1.getInt("Y");
  int heightBox=row1.getInt(years[currentyear]);  // population 

  // use data 
  pushMatrix();

  // the box 
  translate(x, y, heightBox/2);
  fill(255, 0, 0); // red 
  box(19, 19, heightBox);

  // the text - City name
  translate(12, 0, heightBox/2);
  rotateX(-radians(90));
  fill(255); // white
  textSize(52);
  textMode(SHAPE); 
  text(city1, 0, 0);

  popMatrix();
  //  **
}
//**
void keyPressed() {

  if (key == CODED) {
    if (keyCode == UP) {
      position.z += 50;
    }

    if (keyCode == DOWN) {
      position.z -= 50;
    }

    if (keyCode == LEFT) {
      position.x += 50;
    }

    if (keyCode == RIGHT) {
      position.x -= 50;
    }
  } else {
    switch(key) {
    case'+':
      currentyear++;
      break; 

    case'-':
      currentyear--;
      break;
    }//switch
  }//else
  if (currentyear<0)
    currentyear=2; // also check   if (currentyear>2) currentyear=0; 
  //
}//func 
//

My csv file (use your own):

when you use your own csv data, you need to use a scale factor, because a population of 7 Million would be to big for the screen, so maybe * (1/10000) or something to get the pixels for the height

City,1991,2001,2011,X,Y
London,175,8000000,900000,276,245

Regards,

Chrisir

Since this thread currently has no title to click with the mouse (As of 8:22 AM, Eastern Daylight Time in New York, USA), it was quite challenging to open it. As of that time, it had been edited twice; perhaps the title was removed by accident. When we start or edit a thread, we should make sure we give the thread a title, and to be careful not to remove it.

I could edit the thread myself to add a title, but would rather leave that up to the user who initiated it.

Screen shot:

EDIT (April 15, 2021, 8:45 AM):

What units are represented by the X and Y fields?

1 Like

wow without title it’s hard to get here!

If you share the image and example of CSV file that would be super helpful and otherwise we can only give high level comments but I guess Chrisir posted works if X and Y corresponds to the pixel coordinate of the map image. Also Dan made videos on mapping longitude/latitude to an image:

I wrote a title now to this thread…

2 Likes

Thanks Chris - this worked a treat.

2 Likes