commit f2e9bfb2c6aaaa18eef1375207bae7c78fd01df8 Author: alessio.quaresima Date: Mon Jan 25 16:39:27 2021 +0100 Predator model diff --git a/src/Predator.java b/src/Predator.java new file mode 100644 index 0000000..5845f32 --- /dev/null +++ b/src/Predator.java @@ -0,0 +1,504 @@ +import processing.core.PApplet; +import processing.core.PFont; +import processing.core.PImage; + +public class Predator extends PApplet{ + + String[] myFileArray = {"pictures/fox.jpeg", "pictures/rabbit.jpeg", "pictures/grass.jpeg", "pictures/desert.jpeg", "pictures/road.jpeg"}; // picture names,, add more + String[] myNames = {"fox", "rabbit", "grass", "desert"}; // picture names,, add more + + int n_boxes = 30; + int nn = n_boxes *n_boxes; + boolean DIAGONAL = false; + Box [] boxes = new Box[nn]; + Neighbours [] neighs = new Neighbours[nn] ; + + double rabbits= 0.3; + double foxes = 0.3; + double desert = 0.15; + double grass = 0.15; + int FOX = 0; + int RABBIT = 1; + int GRASS = 2; + int DESERT = 3; + int ROAD = 4; + + // visualization + PImage[] images = new PImage[5]; + PImage[] images_g = new PImage[5]; + Box [] colors = new Box[5]; + int WIDTH = 1900; + int HEIGHT = 1000; + int SIZE = 50; + int PIC_SIZE = 80; + int TRACES = 40; + PFont f; + int[] counter = new int[5]; + int[][] traces = new int[4][TRACES]; + int box = -1 ; + int time = 0; + boolean INIT_TODO = true; + +// @Override +// public void mouseClicked() +// { +// print("ciao"); +// INIT_TODO = false; +// } + @Override + public void settings() { + size(WIDTH, HEIGHT); + } + private void normalize_densities() { + double total = 0.5 / (rabbits + foxes); + rabbits *= total; + foxes *= total; + desert = 0.25; + grass = 0.25; + + } + + + @Override + public void setup() { + // smooth(); + SIZE = HEIGHT/n_boxes; + set_traces(); + load_image(); + f = createFont("Arial",16,true); + + for (int t = 0; t < 4; t += 1) { + colors[t] = new Box(SIZE*n_boxes+PIC_SIZE*2*(t+1), PIC_SIZE/2, t, PIC_SIZE); + } // for + } // setup() + + private void initialize() { + get_values(); + normalize_densities(); + int k=0; + for (int j = 0; j < n_boxes; j += 1) { + // run over the ys + for (int i = 0; i < n_boxes; i += 1) { + int type = weighted_type(); + boxes[k] = new Box(i * SIZE, j * SIZE, type); + neighs[k] = new Neighbours(i, j); + k++; + } // for + } // for + } + private void get_values(){ + + + } + + private int weighted_type(){ + float r = random(0,1); + if (r < foxes) { return FOX;} + else if (r < rabbits+foxes) {return RABBIT;} + else if (r < rabbits+foxes+grass) {return GRASS;} + else {return DESERT;} + + + } + + + @Override + public void draw() { + if (INIT_TODO){ + background(255); + fill(255); + stroke(0); + textSize(60); + rect(WIDTH*1/4 ,HEIGHT*1/2,WIDTH/2, PIC_SIZE); + fill(0); + textAlign(CENTER); + text("Scegli la percentuale di volpi e conigli", WIDTH/2, HEIGHT/2 -100); + image(images_g[1], WIDTH*1/4 -2 - PIC_SIZE, HEIGHT*1/2 ); + image(images_g[0], WIDTH*3/4 +2, HEIGHT*1/2 ); + if (mousePressed){ + INIT_TODO = false; + rect(WIDTH*1/4,HEIGHT*1/2,mouseX -WIDTH/4, PIC_SIZE); + rabbits = (float) (mouseX - WIDTH *1/4); + rabbits /= WIDTH/2; + print(rabbits); + print("\n"); + initialize(); + mousePressed = false; + } + } + else{ + if (keyPressed == true) { + if (key == 'b' || key == 'B') { + background(0); + INIT_TODO = true; + } + } + delay(20); + time += 1; + if (mousePressed) { + box = get_clicked_box(mouseX, mouseY); + if (box > -1) boxes[box].type = ROAD; + print("the box", box, " "); + print("\n"); + } + if (time > 4) { + time = 0; + update_grid(); + update_traces(); + } + background(255); + + + plot_traces(); + for (int k = 0; k < 4; k++) { + colors[k].make_borders(); + image(images_g[k],SIZE*n_boxes+PIC_SIZE*2*(k+1), PIC_SIZE/2); + } + for (int i = 0; i < nn; i++) { + boxes[i].display(boxes[i].type); + } // for + +// print("size"); +// print(boxes[0].x); +// print(boxes[0].x+boxes[0].w); + } + } // draw() + +// =============================================================== + private void count_boxes(){ + for (int n=0; n<5; n++) { + counter[n] = 0; + } + for (int i = 0; i < nn; i++) { + counter[boxes[i].type] +=1; + } + } + + private void set_traces(){ + for (int i = 0; i < TRACES; i += 1) { + traces[FOX][i] = (int) foxes; + } + for (int i = 0; i < TRACES; i += 1) { + traces[RABBIT][i] = (int) rabbits; + } + for (int i = 0; i < TRACES; i += 1) { + traces[GRASS][i] = (int) grass; + } + for (int i = 0; i < TRACES; i += 1) { + traces[DESERT][i] = (int) desert; + } + } + + private void update_traces(){ + count_boxes(); + for (int j = 0; j < 4; j += 1) { + if (TRACES - 1 >= 0) { + System.arraycopy(traces[j], 1, traces[j], 0, TRACES - 1); + traces[j][TRACES-1] = counter[j]; + } else { + traces[j][TRACES-1] = counter[j]; + } + } + } + public void arrow(int x1, int y1, int x2, int y2) { + line(x1, y1, x2, y2); + pushMatrix(); + translate(x2, y2); + float a = atan2(x1-x2, y2-y1); + rotate(a); + line(0, 0, -10, -10); + line(0, 0, 10, -10); + popMatrix(); + } + + + private void plot_traces() { +// float scale = 40 * PIC_SIZE; + float mean; + strokeWeight((float) 2.5); + + textSize(20); + textAlign(LEFT); + stroke(182,22,63); + text("Volpi", WIDTH/2 + 2*PIC_SIZE, 2*PIC_SIZE ); + arrow(WIDTH/2 + 2* PIC_SIZE, HEIGHT/2, WIDTH/2 + 2*PIC_SIZE, 2*PIC_SIZE); + stroke(4,54,84); + arrow(WIDTH/2 + 2* PIC_SIZE, HEIGHT/2, WIDTH- 2*PIC_SIZE, HEIGHT/2); + text("Conigli", WIDTH - 2*PIC_SIZE + 5, HEIGHT/2 ); + stroke(0); + for (int i = 0; i < TRACES-1; i += 1) { + if (traces[RABBIT][i] > 0) { + line(WIDTH/2+ 2*PIC_SIZE +WIDTH/2 *traces[RABBIT][i]/nn, + HEIGHT/2 *(nn-traces[FOX][i])/nn, + WIDTH/2+ 2*PIC_SIZE + WIDTH/2 *traces[RABBIT][i+1]/nn , + HEIGHT/2*(nn-traces[FOX][i + 1])/nn); + } + } + + for (int j = 0; j < 4; j += 1) { + mean = 0; + for (int i = 0; i < TRACES-1; i += 1) { + mean += traces[j][i]; + } + mean /= TRACES; + if (j==GRASS) {stroke(77,137,99);} + else if (j==FOX) {stroke(182,22,63);} + else if (j==DESERT) {stroke(244,148,0);} + else if (j==RABBIT) {stroke(4,54,84);} + + strokeWeight((float) 2.5); + for (int i = 0; i < TRACES-1; i += 1) { + if (traces[j][i] > 0) { + line(HEIGHT + 200 +i*15, + HEIGHT/2 +PIC_SIZE +(10 * PIC_SIZE * (traces[j][i] )/nn), + HEIGHT + 200 +i*15+15, + HEIGHT/2+ +PIC_SIZE +(10 * PIC_SIZE * (traces[j][i + 1])/nn)); + } + } + } + } + + private void load_image(){ + PImage im ; + PImage im_g; + for (int x=0; x < 5; x++ ) { + im = loadImage(myFileArray[x]); + im.resize(SIZE, SIZE); + images[x] = im; + } + + for (int x=0; x < 5; x++ ) { + im_g = loadImage(myFileArray[x]); + im_g.resize(PIC_SIZE, PIC_SIZE); + images_g[x] = im_g; + } + } + + private void update_grid(){ + + int k =0; + //for each box evolve by the rules + //run over xs and ys + boolean starve; + for (int j = 0; j < n_boxes; j += 1) { + for (int i = 0; i < n_boxes; i += 1) { + // run over the ys + // death conditions + // fox dies if no rabbits + if (boxes[k].type == ROAD) { + boxes[k].next = ROAD; + } + if (boxes[k].type == FOX) { + starve = true; + for (int n = 0; n < neighs[k].surround.length; n++) { + if (boxes[neighs[k].surround[n]].type == RABBIT) { + // there is AT LEAST a rabbit, no starvation + starve = false; + break; + } + if (boxes[neighs[k].surround[n]].type == DESERT) { + // there is AT LEAST a desert, starvation +// break; + } + } + if (starve) {boxes[k].next = DESERT;} + } + // rabbit dies if no grass + if (boxes[k].type == RABBIT) { + starve = true; + for (int n = 0; n < neighs[k].surround.length; n++) { + if (boxes[neighs[k].surround[n]].type == GRASS) { + // there is AT LEAST a grass, no starvation + starve = false; + break; + } + } + if (starve) {boxes[k].next = DESERT;} + } + // birth conditions + // fox is born eating rabbit + if (boxes[k].type == RABBIT) { + for (int n = 0; n < neighs[k].surround.length; n++) { + if (boxes[neighs[k].surround[n]].type == FOX) { + boxes[k].next = FOX; + break; + } + } + } + // rabbit is born eating grass + if (boxes[k].type == GRASS) { + for (int n = 0; n < neighs[k].surround.length; n++) { + if (boxes[neighs[k].surround[n]].type == RABBIT) { + boxes[k].next = RABBIT; + break; + } + } + } + // grass grows where desert + if (boxes[k].type == DESERT) { + for (int n = 0; n < neighs[k].surround.length; n++) { + if (boxes[neighs[k].surround[n]].type == GRASS) { + boxes[k].next = GRASS; + break; + } + } + } + k++; + } + } + k = 0; + for (int j = 0; j < n_boxes; j += 1) { + // run over the ys + for (int i = 0; i < n_boxes; i += 1) { + boxes[k].type = boxes[k].next; + k++; + } + } + } + + private int get_clicked_box(int x, int y){ + int box =-1; + for (int i = 0; i < nn; i += n_boxes) { + if (boxes[i].y < y && y < +boxes[i].yend) { + print(i); + for (int j = 0; j < n_boxes; j += 1) { + if (boxes[j+i].x < x && x < + boxes[j+i].xend){ + box = j+i; + print(boxes[j+i].y, " ", y, " ", boxes[j+i].yend, i, " "); + print(boxes[j+i].x, " ", x, " ", boxes[j+i].xend, i, " "); + print("\n"); + break; + } + } + } + } + return box; + + } + + class Box { + + float x; + float y; + float xend; + float yend; + + float w=SIZE; + float h=SIZE; + + int type; + int next; + + + // constr + + Box ( float x, float y, int type, int size) { + this.x=x; + this.y=y; + this.w = size; + this.h = size; + this.xend=x+size; + this.yend=y+size; + this.type =type; + this.next =type; + } // constr + Box ( float x, float y, int type) { + this.x=x; + this.y=y; + this.type =type; + this.next =type; + this.xend=x+this.w; + this.yend=y+this.h; + } // constr + + void make_borders() { + int j = type; + if (j==GRASS) {stroke(77,137,99);} + else if (j==FOX) {stroke(182,22,63);} + else if (j==DESERT) {stroke(244,148,0);} + else if (j==RABBIT) {stroke(4,54,84);} + strokeWeight(10); + rect(x, y, w, h); + } + + void display(int n) { +// fill(50*type, 32, 0); +// stroke(0); +// rect (x, y, w, h); +// print(n); + image(images[n], x, y); +// image(images[type], x,y); + + + // println (x); + } // method + } // class + + class Neighbours { + int x; + int y; + int [] surround; + + Neighbours( int x, int y) { + this.x = x; + this.y = y; + if (DIAGONAL) { + int N = 8; + int[] xs= new int[N]; + int[] ys= new int[N]; + + ys[0] = (n_boxes + y-1)%n_boxes; + ys[1] = ys[0]; + ys[2] = ys[0]; + ys[3] = y; ys[4] = y; + ys[5] = (y+1)%n_boxes; + ys[6] = ys[5]; + ys[7] = ys[5]; + + xs[0] = (n_boxes + x-1)%n_boxes; + xs[1] = x; + xs[2] = (x+1) %n_boxes; + xs[3] = xs[0]; xs[4] =xs[2]; + xs[5] = xs[0]; + xs[6] = x; + xs[7] = xs[2]; + + this.surround = new int[N]; + + for (int i=0; i