一、项目思路
在本次项目中,将读取各个地铁站点每分钟的进出站客流并进行动态可视化。
1.1 地图背景使用卫星地图图片,地铁站点用ellipse()展示,地铁线路用line()绘制,站点和线路的的颜色分别使用fill()和stroke()控制。
1.2 在setup()函数中完成一些初始化工作,如读取数据、读取背景图片、加载字体等。
1.3 由于每分钟提供一次数据汇总,因此需要60x24共计1440帧,在每帧的draw()中使用对应的数据重新绘制画布,用ellipse()的大小来表示客流量的多少。
二、项目实现
2.1 新建草图
2.2 新建Table变量
Table是一种类似二维数组的变量类型,定义table变量用于存储站点数据,link变量用于存储线路数据、traffic变量用于存储客流数据。
N等于1440,表示一天一共有1440分钟,interval为每帧对应的时间,即1分钟。
current为当前帧对应的时间,由于凌晨零点至五点地铁尚未运营,所以这里选择从五点开始展示。
2.3 setup()函数
编辑setup()函数以完成一些初始化工作,包括设置画布大小、启用平滑处理、设置背景颜色、设置填充色、启用圆角绘图、设置帧频等。
2.4 数据保存在data文件夹
将背景图片和地铁线路数据存放在data文件夹
2.5 loadTable()函数加载csv数据并赋值给三个Table变量
2.6 使用loadImage()函数加载背景图片并赋值给PImage变量
2.7 设置字体
使用createFont()函数生成一个字体,并使用textFont()函数将生成的字体设置为当前绘图所用的字体。
Table table;
Table link;
Table traffic;
PImage beijing;
int R;
int C;
float w = 1280;
float h = 720;
float minLng = 134.6412879;
float maxLng = 135.9199972;
float minLat = 35.9535469;
float maxLat = 36.6819062;
int interval = 1;
int N = 24 * 60 / interval;
int current = 5 * 60;
int offset = 1;
void setup(){
size(1280, 720);
smooth();
background(250);
fill(102);
strokeCap(ROUND);
frameRate(60);
table = loadTable("stations_with_geo.csv");
link = loadTable("links_with_geo.csv");
traffic = loadTable("oneday_traffic.csv");
beijing = loadImage("beijing.png");
textFont(createFont("MicrosoftYaHei", 13));
}
void draw(){
drawBackground();
for (int i = 0; i < 304; i++){
float lat = traffic.getFloat(current, i * 7);
float lng = traffic.getFloat(current, i * 7 + 1);
int cr = traffic.getInt(current, i * 7 + 2);
int cg = traffic.getInt(current, i * 7 + 3);
int cb = traffic.getInt(current, i * 7 + 4);
float entry;
if (offset == 0) {
entry = traffic.getFloat(current, i * 7 + 5) * 3;
}
else {
entry = traffic.getFloat(current, i * 7 + 6) * 3;
}
fill(cr, cg, cb, 120);
ellipse(w*(lng-minLng)/(maxLng-minLng), h*(maxLat-lat)/(maxLat-minLat), entry, entry);
}
// saveFrame("frames/####.tif");
current = current + 1;
if (current == N) {
// current = 5 * 60;
exit();
}
}
void drawBackground(){
image(beijing, 0, 0, 1280, 720);
int bg = 250;
// background(bg);
int hour = current / 60;
int minute = current % 60;
fill(bg);
textSize(30);
if (hour < 10 && minute < 10) {
text('0' + str(hour) + ":0" + str(minute), 950, 60);
}
else if (hour >= 10 && minute < 10) {
text(str(hour) + ":0" + str(minute), 950, 60);
}
else if (hour < 10 && minute >= 10) {
text('0' + str(hour) + ':' + str(minute), 950, 60);
}
else {
text(str(hour) + ':' + str(minute), 950, 60);
}
textSize(18);
if (offset == 0) {
text("Entries / per 3m", 1050, 60);
}
else {
text("Exits / per 3m", 1050, 60);
}
textSize(12);
int tmp = 0;
for (int i = 0; i < 10; i++){
String s = traffic.getString(N + current - current % 10, 10 * 2 * offset + i * 2);
int number = traffic.getInt(N + current - current % 10, 10 * 2 * offset + i * 2 + 1);
if (number >= 20) {
textAlign(RIGHT);
fill(bg);
text(s, 1020, 96 + 20 * tmp);
textAlign(LEFT);
text(number, 1050 + number / 5, 96 + 20 * tmp);
noStroke();
fill(bg, 255 - tmp * 20);
rect(1040, 96 + 20 * tmp - 9, number / 5, 10);
tmp += 1;
}
}
R = link.getRowCount();
C = link.getColumnCount();
for (int i = 0; i < R; i++){
float latO = link.getFloat(i, 1);
float lngO = link.getFloat(i, 2);
float latD = link.getFloat(i, 4);
float lngD = link.getFloat(i, 5);
int cr = link.getInt(i, 7);
int cg = link.getInt(i, 8);
int cb = link.getInt(i, 9);
stroke(cr, cg, cb);
strokeWeight(2);
line(w*(lngO-minLng)/(maxLng-minLng), h*(maxLat-latO)/(maxLat-minLat), w*(lngD-minLng)/(maxLng-minLng), h*(maxLat-latD)/(maxLat-minLat));
}
R = table.getRowCount();
C = table.getColumnCount();
for (int i = 0; i < R; i++){
//String name = table.getString(i, 0);
float lat = table.getFloat(i, 1);
float lng = table.getFloat(i, 2);
int category = table.getInt(i, 4);
if (category == 1) {
fill(204);
noStroke();
ellipse(w*(lng-minLng)/(maxLng-minLng), h*(maxLat-lat)/(maxLat-minLat), 6, 6);
}
else {
fill(204);
noStroke();
ellipse(w*(lng-minLng)/(maxLng-minLng), h*(maxLat-lat)/(maxLat-minLat), 3, 3);
}
}
}
三、总结
通过“北京地铁的一天”这一实战项目,巩固了Processing中常用的一些语法和知识点,也掌握了使用Processing实现动态可视化的基本思想:准备好不同时间对应的数据,在draw()中根据当前时间获取对应的数据,使用点、线、圆形、矩形等绘图元素进行可视化。
四、成果展示
五、参考文献
张宏伦 [上海交通大学] 实战 上海地铁的一天动态可视化