/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.ZcJ7L0TOgs5/rev.1889
*
* authors:
*
* frederic.vernier
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
/* @pjs preload="/static/uploaded_resources/p.2418/logoUPSUD.png"; */
/* @pjs preload="/static/uploaded_resources/p.2418/villes40.csv,/static/uploaded_resources/p.2418/villes41.csv,/static/uploaded_resources/p.2418/villes42.csv,/static/uploaded_resources/p.2418/depts.csv"; */
static class Dept{
static Dept deptList[] = new Dept[100];
float maxx = 0;
float minx = 0;
float maxy = 0;
float miny = 0;
int nb = 0;
int bigger = -1;
String name;
int count = 0;
Dept(String line[]){
if (line[1].equals("2A")) {
this.nb = 20;this.name="Corse";}
else if (line[1].equals("2B")) {
this.nb = 20;this.name="Corse";
} else {
this.nb = int(line[1]);
this.name = line[2];
}
if (this.nb<100)
deptList[this.nb] = this;
}
int mapX(float xi, int width){
return int(map(xi, this.minx, this.maxx, 0, width));
}
int mapY(float yi, int height){
return int(map(yi, miny, maxy, height, 0));
}
}
static class Place{
int postalCode, inseecode, altitude, dept;
String name;
float x;
float y;
int population;
float surface;
int id;
static Place placeList[];
static Place sortedPlaceList[];
static float maxx = 0;
static float minx = 0;
static float maxy = 0;
static float miny = 0;
static int maxa = 0;
static int mina = 0;
static int maxp = 0;
static int minp = 0;
static float maxs = 0;
static float mins = 0;
static int nb = 0;
Place(String line[]){
this.inseecode = int(line[0]);
this.altitude = int(line[2]);
if (line[3].startsWith("2A")) {
this.postalCode=20000+int(line[3].substring(2));
} else if (line[3]=="2B") {
this.postalCode=20000+int(line[3].substring(2));
} else if (line[3].indexOf("|")>=0) {
this.postalCode = int(line[3].substring(0, line[3].indexOf("|")));
} else
this.postalCode = int(line[3]);
this.dept = int(postalCode/1000);
this.name = line[1];
//if (dept==26 && Dept.deptList[this.dept].bigger>=0) println(nb+" "+name+" "+population+"hab : bigger was "+Dept.deptList[this.dept].bigger+":"+Place.placeList[Dept.deptList[this.dept].bigger].name);
this.x = float(line[4]);
this.y = float(line[5]);
this.population = int(line[6]);
if (Dept.deptList[this.dept]!=null){
if (Dept.deptList[this.dept].bigger==-1)
Dept.deptList[this.dept].bigger = nb;
else if (Place.placeList[Dept.deptList[this.dept].bigger].population<population)
Dept.deptList[this.dept].bigger = nb;
if(Dept.deptList[this.dept].count==0){
Dept.deptList[this.dept].maxx = this.x;
Dept.deptList[this.dept].minx = this.x;
Dept.deptList[this.dept].maxy = this.y;
Dept.deptList[this.dept].miny = this.y;
} else{
Dept.deptList[this.dept].miny = min(Dept.deptList[this.dept].miny, y);
Dept.deptList[this.dept].maxy = max(Dept.deptList[this.dept].maxy, y);
Dept.deptList[this.dept].minx = min(Dept.deptList[this.dept].minx, x);
Dept.deptList[this.dept].maxx = max(Dept.deptList[this.dept].maxx, x);
}
Dept.deptList[this.dept].count++;
} else
println("problem with dept |"+this.dept+"|");
this.surface = float(line[7]);
if (nb==0){
miny = y;
maxy = y;
minx = x;
maxx = x;
} else {
miny = min(miny, y);
maxy = max(maxy, y);
minx = min(minx, x);
maxx = max(maxx, x);
minp = min(minp, this.population);
maxp = max(maxp, this.population);
mins = min(mins, this.surface);
maxs = max(maxs, this.surface);
mina = min(mina, this.altitude);
maxa = max(maxa, this.altitude);
}
placeList[nb] = this;
id = nb;
nb++;
}
}
PImage img;
int labelindex = -1;
// min/max boundary of all points
float minX, maxX;
float minY, maxY;
int totalCount; // total number of places
int maxdisp = 0;
int focus = -1;
int mapX(float xi){
return int(map(xi, Place.minx, Place.maxx, 0, width));
}
int mapY(float yi){
return int(map(yi, Place.miny, Place.maxy, height, 0));
}
int mapS(float si){
return int(map(si, Place.mins, Place.maxs, 3, 255));
}
// permute 2 villes dans la liste
void permute(Place[] list, int i, int j){
Place tmp = list[i];
list[i]= list[j];
list[j]=tmp;
}
// quicksort the cities according to population
void sort(Place[] list, int min, int max){
if (min<max) {
permute(list, min, max);
int li = min;
for (int i=min; i<max; i++){
if (list[i].population<list[max].population) {
permute(list, i, li); li++;
}
}
permute(list, li, max);
sort(list, min, li-1);
sort(list, li+1, max);
}
}
// Calculates the base-10 logarithm of a number
float log10 (int x) {
return (log(x) / log(10));
}
void setup(){
size(800,800);
String lines1[], lines2[], lines3[], lines4[];
//if(online) {
img = loadImage("/static/uploaded_resources/p.2418/logoUPSUD.png");
lines1 = loadStrings("/static/uploaded_resources/p.2418/villes40.csv");
lines2 = loadStrings("/static/uploaded_resources/p.2418/villes41.csv");
lines3 = loadStrings("/static/uploaded_resources/p.2418/villes42.csv");
lines4 = loadStrings("/static/uploaded_resources/p.2418/depts.csv");
//} else {
// img = loadImage("logoUPSUD.png");
// lines1 = loadStrings("villes40.csv");
// lines2 = loadStrings("villes41.csv");
// lines3 = loadStrings("villes42.csv");
// lines4 = loadStrings("depts.csv");
//}
Place.placeList = new Place[lines1.length+lines2.length+lines3.length-1];
Place.sortedPlaceList = new Place[lines1.length+lines2.length+lines3.length-1];
for(int i=0; i<lines4.length; i++)
new Dept(split(lines4[i], ';'));
for(int i=1; i<lines1.length; i++)
new Place(split(lines1[i], ';'));
for(int i=0; i<lines2.length; i++)
new Place(split(lines2[i], ';'));
for(int i=0; i<lines3.length; i++)
new Place(split(lines3[i], ';'));
for(int i=Place.placeList.length-1; i>=0; i--)
Place.sortedPlaceList[i] = Place.placeList[i];
sort(Place.sortedPlaceList, 0, Place.sortedPlaceList.length-1);
// println("07 "+Dept.deptList[7].name+" : "+Dept.deptList[7].bigger+" "+Place.placeList[Dept.deptList[7].bigger].name);
println("x " +Place.minx+" - "+Place.maxx);
//println("y " +Place.miny+" - "+Place.maxy);
//println("s " +Place.mins+" - "+Place.maxs);
//println("p " +Place.minp+" - "+Place.maxp+" => "+log10(Place.maxp));
smooth();
maxdisp = Place.placeList.length;
noLoop();
}
void draw(){
if (focus==-1)
drawFrance();
else
drawDept(focus);
image(img, 0, 0, 80, 40);
text ("36550 cities of France",5, 60);
}
void drawFrance(){
background(255);
colorMode(HSB, 255, 255, 255);
//for(Place p:listPlaces){
for(int i=Place.sortedPlaceList.length-maxdisp; i<Place.sortedPlaceList.length; i++){
Place p = Place.sortedPlaceList[i];
stroke(128, 128, 128);
int w = mapS(p.surface);
int po = int(log10(p.population+2));
//line(mapX(p.x), mapY(p.y), mapX(p.x), mapY(p.y)-int(p.altitude/100));
strokeWeight(po);
randomSeed(p.dept);random(255);
if (p.id == Dept.deptList[p.dept].bigger){
po = po*2;
fill(255, 0, 255);
strokeWeight(1);
stroke(0, 0, 0);
rect(mapX(p.x)-textWidth(p.name)/2, mapY(p.y)-11-po, textWidth(p.name)+2, 12);
fill(0, 0, 0);
text (p.name, mapX(p.x)-textWidth(p.name)/2+1, mapY(p.y)-po);
}
else fill(int(random(255)), 255-p.altitude/20, 255-po*40);
noStroke();
ellipse(mapX(p.x), mapY(p.y), po, po);
//ellipse(mapX(p.x), mapY(p.y), p.population/10000, p.population/10000);
}
if (labelindex>=0) {
Place p = Place.sortedPlaceList[labelindex];
colorMode(RGB, 255, 255, 255);
fill(255, 255, 255);
strokeWeight(1);
stroke(0, 0, 0);
rect(mapX(p.x), mapY(p.y)-11, 2+textWidth(p.postalCode +" "+p.name), 12*4);
fill(0, 0, 0);
text (p.postalCode +" "+p.name, 1+mapX(p.x), mapY(p.y)+12*0);
text (p.altitude +" m", 1+mapX(p.x), mapY(p.y)+12*1);
text (p.population +" hab.", 1+mapX(p.x), mapY(p.y)+12*2);
text (p.surface+" ha", 1+mapX(p.x), mapY(p.y)+12*3);
}
if (maxdisp==Place.placeList.length){
noLoop();
} else {
maxdisp = min(maxdisp+5000, Place.placeList.length);
}
}
void drawDept(int dept){
Dept dd = Dept.deptList[dept];
println("draw "+dept+" "+dd.minx+"-"+dd.maxx);
background(255);
colorMode(HSB, 255, 255, 255);
//for(Place p:listPlaces){
for (int i=0; i<Place.sortedPlaceList.length; i++){
Place p = Place.sortedPlaceList[i];
stroke(128, 128, 128);
int w = mapS(p.surface);
int po = 1+int(log10(p.population+2));
//line(mapX(p.x), mapY(p.y), mapX(p.x), mapY(p.y)-int(p.altitude/100));
strokeWeight(po);
randomSeed(p.dept);random(255);
if (p.dept==dept &&p.id == Dept.deptList[p.dept].bigger){
po = po*2;
fill(255, 0, 255);
strokeWeight(1);
stroke(0, 0, 0);
rect(dd.mapX(p.x, width)-textWidth(p.name)/2, dd.mapY(p.y, height)-11-po, textWidth(p.name)+2, 12);
fill(0, 0, 0);
text (p.name, dd.mapX(p.x, width)-textWidth(p.name)/2+1, dd.mapY(p.y, height)-po);
}
else fill(int(random(255)), 255-p.altitude/20, 255-po*40);
noStroke();
if (p.dept==dept)
ellipse(dd.mapX(p.x, width), dd.mapY(p.y, height), po, po);
//ellipse(mapX(p.x), mapY(p.y), p.population/10000, p.population/10000);
}
if (labelindex>=0) {
Place p = Place.sortedPlaceList[labelindex];
colorMode(RGB, 255, 255, 255);
fill(255, 255, 255);
strokeWeight(1);
stroke(0, 0, 0);
rect(dd.mapX(p.x, width), dd.mapY(p.y, height)-11, 2+textWidth(p.postalCode +" "+p.name), 12*4);
fill(0, 0, 0);
text (p.postalCode +" "+p.name, 1+dd.mapX(p.x, width), dd.mapY(p.y, height)+12*0);
text (p.altitude +" m", 1+dd.mapX(p.x, width), dd.mapY(p.y, height)+12*1);
text (p.population +" hab.", 1+dd.mapX(p.x, width), dd.mapY(p.y, height)+12*2);
text (p.surface+" ha", 1+dd.mapX(p.x, width), dd.mapY(p.y, height)+12*3);
}
if (maxdisp==Place.placeList.length){
noLoop();
} else {
maxdisp = min(maxdisp+5000, Place.placeList.length);
}
}
void keyTyped(){
println(""+key+" "+keyCode);
}
void keyPressed(){
if(key=='+'){
println("+");
} else if(key=='-'){
println("-");
} else if(keyCode==LEFT){
println("L");
} else if(keyCode==RIGHT){
println("R");
} else if(keyCode==UP){
println("U");
} else if(keyCode==DOWN){
println("D");
}
}
void mouseClicked(){
float mind = 10000;
if (focus>0){
Dept dd = Dept.deptList[focus];
for(int i=Place.sortedPlaceList.length-1; i>=0; i--){
Place p = Place.sortedPlaceList[i];
int po = int(log10(p.population+2));
float d = dist(dd.mapX(p.x, width), dd.mapY(p.y, height), mouseX, mouseY);
if (d<po){labelindex = i;maxdisp=1651;loop();break;}
if (d<mind) {mind=d; labelindex = i;}
}
} else
for(int i=Place.sortedPlaceList.length-1; i>=0; i--){
Place p = Place.sortedPlaceList[i];
int po = int(log10(p.population+2));
float d = dist(mapX(p.x), mapY(p.y), mouseX, mouseY);
if (d<po){labelindex = i;maxdisp=1651;loop();break;}
if (d<mind) {mind=d; labelindex = i;}
}
redraw();
}