View Javadoc
1   package org.woehlke.computer.kurzweil.tabs.dla;
2   
3   import lombok.Getter;
4   import lombok.extern.log4j.Log4j2;
5   import org.woehlke.computer.kurzweil.commons.model.LatticeNeighbourhood;
6   import org.woehlke.computer.kurzweil.commons.model.LatticePoint;
7   import org.woehlke.computer.kurzweil.commons.tabs.TabModel;
8   
9   import java.util.ArrayList;
10  import java.util.List;
11  import java.util.concurrent.ForkJoinTask;
12  
13  @Log4j2
14  @Getter
15  public class DiffusionLimitedAggregationModel extends ForkJoinTask<Void> implements TabModel {
16  
17      private final DiffusionLimitedAggregationContext tabCtx;
18      private final int initialNumberOfParticles;
19      private final int worldX;
20      private final int worldY;
21  
22      private int[][] worldMap;
23      private int age = 1;
24      private long steps;
25      private Boolean running;
26      private List<LatticePoint> particles = new ArrayList<>();
27  
28      private final int directions = 4;
29      private final int directionsFirst = 0;
30      private final static int startX = 0;
31      private final static int startY = 0;
32  
33      public DiffusionLimitedAggregationModel(
34          DiffusionLimitedAggregationContext tabCtx
35      ) {
36          this.tabCtx = tabCtx;
37          running = Boolean.FALSE;
38          worldX = this.tabCtx.getCtx().getWorldDimensions().getX();
39          worldY = this.tabCtx.getCtx().getWorldDimensions().getY();
40          this.initialNumberOfParticles = this.tabCtx.getCtx().getProperties().getDla().getControl().getNumberOfParticles();
41          this.worldMap = new int[this.worldX][this.worldY];
42          int x;
43          int y;
44          //create moving Particles
45          for(int i=0; i < this.initialNumberOfParticles; i++){
46              x = this.tabCtx.getCtx().getRandom().nextInt(this.worldX);
47              y = this.tabCtx.getCtx().getRandom().nextInt(this.worldY);
48              x = x >= 0 ? x : -x;
49              y = y >= 0 ? y : -y;
50              particles.add(new LatticePoint(x , y));
51          }
52          //place first dendrite Particle
53          x = this.worldX / 2;
54          y = this.worldY / 2;
55          worldMap[x][y]=age;
56          age++;
57      }
58  
59      public void start() {
60          log.info("start");
61          synchronized (running) {
62              running = Boolean.TRUE;
63          }
64          log.info("started "+this.toString());
65      }
66  
67      public void stop() {
68          log.info("stop");
69          synchronized (running) {
70              running = Boolean.FALSE;
71          }
72          log.info("stopped "+this.toString());
73      }
74  
75      public void step() { }
76  
77      public int getAgeFor(int x, int y) {
78          return this.worldMap[x][y];
79      }
80  
81      @Override
82      protected boolean exec() {
83          boolean doIt = false;
84          synchronized (running) {
85              doIt = running.booleanValue();
86          }
87          if(doIt) {
88              steps++;
89              //log.info("step "+steps);
90              List<LatticePoint> newParticles = new ArrayList<LatticePoint>();
91              int x;
92              int y;
93              for (LatticePoint particle : particles) {
94                  x = particle.getX() + this.worldX;
95                  y = particle.getY() + this.worldY;
96                  //Todo: make Enum
97                  int newDirection = this.tabCtx.getCtx().getRandom().nextInt(directions);
98                  switch (newDirection >= directionsFirst ? newDirection : -newDirection) {
99                      case 0:
100                         y--;
101                         break;
102                     case 1:
103                         x++;
104                         break;
105                     case 2:
106                         y++;
107                         break;
108                     case 3:
109                         x--;
110                         break;
111                 }
112                 x %= this.worldX;
113                 y %= this.worldY;
114                 particle.setX(x);
115                 particle.setY(y);
116                 if (!this.hasDendriteNeighbour(x, y)) {
117                     newParticles.add(particle);
118                 }
119             }
120             particles = newParticles;
121         }
122         //log.info("stepped");
123         return doIt;
124     }
125 
126     public boolean hasDendriteNeighbour( int myX , int myY){
127         //log.info("hasDendriteNeighbour. age="+age);
128         if(worldMap[myX][myY]==0){
129             LatticePoint[] neighbours = LatticeNeighbourhood.get(worldX,worldY, myX, myY);
130             for(LatticePoint neighbour:neighbours){
131                 if(worldMap[neighbour.getX()][neighbour.getY()]>0){
132                     worldMap[myX][myY]=age;
133                     age++;
134                     return true;
135                 }
136             }
137             return false;
138         } else {
139             return true;
140         }
141     }
142 
143 
144     @Override
145     public Void getRawResult() {
146         return null;
147     }
148 
149     @Override
150     protected void setRawResult(Void value) {
151 
152     }
153 
154 }