|
@@ -0,0 +1,271 @@
|
|
|
+package main.java.com.lotkavolterra;
|
|
|
+
|
|
|
+import processing.core.PFont;
|
|
|
+import processing.core.PApplet;
|
|
|
+
|
|
|
+public class PopulationModel extends Graphs {
|
|
|
+
|
|
|
+ // Distributions
|
|
|
+ Densities densities = new Densities(0.,0.,0.5,0.5);
|
|
|
+ Bar fox_bar;
|
|
|
+ Bar rabbit_bar;
|
|
|
+ Button start;
|
|
|
+ Button restart;
|
|
|
+ Slider speed;
|
|
|
+
|
|
|
+
|
|
|
+ // visualization
|
|
|
+
|
|
|
+
|
|
|
+ PFont f;
|
|
|
+ int box = -1 ;
|
|
|
+ double time = 0;
|
|
|
+ boolean INIT_TODO = true;
|
|
|
+ boolean RUN_SIMULATION = false;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void settings() {
|
|
|
+ size(WIDTH, HEIGHT);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setup() {
|
|
|
+ SIZE =HEIGHT/n_boxes;
|
|
|
+ set_traces(densities);
|
|
|
+ load_image();
|
|
|
+ f = createFont("Arial",16,true);
|
|
|
+ for (int t = 0; t < 4; t += 1) {
|
|
|
+ colors[t] = new Structs.Box(SIZE*n_boxes+PIC_SIZE*2*(t+1), PIC_SIZE/2, t, PIC_SIZE);
|
|
|
+ } // for
|
|
|
+ strokeWeight(3);
|
|
|
+ fox_bar = new Bar(WIDTH * 1 / 4, HEIGHT * 1 / 2, WIDTH / 2, PIC_SIZE);
|
|
|
+ rabbit_bar = new Bar(WIDTH * 1 / 4, HEIGHT * 1 / 2 +100, WIDTH / 2, PIC_SIZE);
|
|
|
+ start = new Button("Start", WIDTH * 3/4-100, HEIGHT * 3/4, WIDTH/4, PIC_SIZE);
|
|
|
+ speed = new Slider("Speed", WIDTH* 85/100, HEIGHT* 3/10, WIDTH*1/10);
|
|
|
+ restart = new Button("Restart", WIDTH* 85/100, (float)(HEIGHT* 3/10 + PIC_SIZE), WIDTH*1/10, PIC_SIZE);
|
|
|
+ } // setup()
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void draw() {
|
|
|
+ if (INIT_TODO){
|
|
|
+ background(255);
|
|
|
+ fill(0);
|
|
|
+ stroke(0);
|
|
|
+ textSize(40);
|
|
|
+ textAlign(CENTER);
|
|
|
+ text("Scegli la percentuale di volpi e conigli", WIDTH/2, HEIGHT/2 -200);
|
|
|
+ image(images_g[1], WIDTH*1/4 - PIC_SIZE -5 , HEIGHT*1/2 +100);
|
|
|
+ image(images_g[0], WIDTH*1/4 - PIC_SIZE -5, HEIGHT*1/2 );
|
|
|
+ draw_box(fox_bar);
|
|
|
+ draw_box(rabbit_bar);
|
|
|
+ draw_button(start);
|
|
|
+ if (mousePressed){
|
|
|
+ fox_bar.MouseIsOver(mouseX, mouseY);
|
|
|
+ rabbit_bar.MouseIsOver(mouseX, mouseY);
|
|
|
+ if (start.MouseIsOver(mouseX, mouseY)){
|
|
|
+ INIT_TODO = false;
|
|
|
+ densities.foxes= fox_bar.get_value();
|
|
|
+ densities.rabbits= rabbit_bar.get_value();
|
|
|
+ println(densities.desert, densities.foxes, densities.grass, densities.rabbits);
|
|
|
+ initialize();
|
|
|
+ println(densities.foxes, densities.rabbits);
|
|
|
+ println(counter);
|
|
|
+ }
|
|
|
+
|
|
|
+ mousePressed = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if (keyPressed == true) {
|
|
|
+ if (key == 'q' || key == 'Q') {
|
|
|
+ background(0);
|
|
|
+ INIT_TODO = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ time += 5*speed.get_speed();
|
|
|
+ delay(20);
|
|
|
+ if (mousePressed) {
|
|
|
+ box = get_clicked_box(mouseX, mouseY);
|
|
|
+ if (box > -1) boxes[box].type = ROAD;
|
|
|
+ speed.MouseIsOver(mouseX, mouseY);
|
|
|
+ if (restart.MouseIsOver(mouseX, mouseY)) {INIT_TODO = true;}
|
|
|
+ }
|
|
|
+
|
|
|
+ if (time >10)
|
|
|
+ {
|
|
|
+ time=0;
|
|
|
+ update_grid();
|
|
|
+ update_traces();
|
|
|
+ }
|
|
|
+ background(255);
|
|
|
+ draw_slider(speed);
|
|
|
+ draw_button(restart);
|
|
|
+
|
|
|
+
|
|
|
+ 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 normalize_densities(Densities d) {
|
|
|
+ d.rabbits = d.rabbits/2;
|
|
|
+ d.foxes = d.foxes/2;
|
|
|
+ d.desert = 0.25;
|
|
|
+ d.grass = 0.25;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int weighted_type(Densities d) {
|
|
|
+ float r = random(0, 1);
|
|
|
+ if (r < d.foxes) {
|
|
|
+ return FOX;
|
|
|
+ } else if (r < d.rabbits + d.foxes) {
|
|
|
+ return RABBIT;
|
|
|
+ } else if (r < d.rabbits + d.foxes + d.grass) {
|
|
|
+ return GRASS;
|
|
|
+ } else {
|
|
|
+ return DESERT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initialize() {
|
|
|
+ normalize_densities(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(densities);
|
|
|
+ boxes[k] = new Structs.Box(i * SIZE, j * SIZE, type);
|
|
|
+ neighs[k] = new Structs.Neighbours(i, j);
|
|
|
+ k++;
|
|
|
+ } // for
|
|
|
+ } // for
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //===============================================================
|
|
|
+ // Evolution algorithm
|
|
|
+ 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) {
|
|
|
+ for (int j = 0; j < n_boxes; j += 1) {
|
|
|
+ if (boxes[j+i].x < x && x < + boxes[j+i].xend){
|
|
|
+ box = j+i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return box;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main (String... args) {
|
|
|
+ PopulationModel pt = new PopulationModel();
|
|
|
+ runSketch(new String[]{"PopulationModel"}, pt);
|
|
|
+ }
|
|
|
+// public static void main(String[] passedArgs) {
|
|
|
+// String[] appletArgs = new String[] { "PopulationModel" };
|
|
|
+// PApplet.main(appletArgs);
|
|
|
+// }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|