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
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
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
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
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
123 return doIt;
124 }
125
126 public boolean hasDendriteNeighbour( int myX , int myY){
127
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 }