View Javadoc
1   package org.woehlke.computer.kurzweil.commons.model.fractal;
2   
3   import org.woehlke.computer.kurzweil.tabs.wator.WatorModel;
4   import org.woehlke.computer.kurzweil.commons.model.turing.Point;
5   
6   import java.util.ArrayDeque;
7   import java.util.Deque;
8   //import java.util.logging.Logger;
9   
10  /**
11   * Mandelbrot Set drawn by a Turing Machine.
12   *
13   * (C) 2006 - 2015 Thomas Woehlke.
14   * https://thomas-woehlke.blogspot.com/2016/01/mandelbrot-set-drawn-by-turing-machine.html
15   * @author Thomas Woehlke
16   *
17   * Created by tw on 16.12.2019.
18   */
19  public class GaussianNumberPlane {
20  
21      public final static int YET_UNCOMPUTED = -1;
22      private final static double complexWorldDimensionRealX = 3.2d;
23      private final static double complexWorldDimensionImgY = 2.34d;
24      private final static double complexCenterForMandelbrotRealX = -2.2f;
25      private final static double complexCenterForMandelbrotImgY = -1.17f;
26      private final static double complexCenterForJuliaRealX = -1.6d;
27      private final static double complexCenterForJuliaImgY =  -1.17d;
28      private final Point worldDimensions;
29      public volatile int zoomLevel;
30      private volatile int[][] lattice;
31      private volatile ComplexNumber complexNumberForJuliaSetC;
32      private volatile ComplexNumber complexWorldDimensions;
33      private volatile ComplexNumber complexCenterForMandelbrot;
34      private volatile ComplexNumber complexCenterForJulia;
35      private volatile Deque<ComplexNumber> complexCenterForZoomedMandelbrot = new ArrayDeque<>();
36  
37      private volatile ComplexNumber zoomCenter;
38  
39  
40      //public static Logger log = Logger.getLogger(GaussianNumberPlane.class.getName());
41  
42      public GaussianNumberPlane(WatorModel model) {
43          this.worldDimensions = model.getWorldDimensions();
44          this.lattice = new int[worldDimensions.getWidth()][worldDimensions.getHeight()];
45          this.complexWorldDimensions = new ComplexNumber(
46              complexWorldDimensionRealX,
47              complexWorldDimensionImgY
48          );
49          this.complexCenterForMandelbrot = new ComplexNumber(
50              complexCenterForMandelbrotRealX,
51              complexCenterForMandelbrotImgY
52          );
53          this.complexCenterForJulia = new ComplexNumber(
54              complexCenterForJuliaRealX,
55              complexCenterForJuliaImgY
56          );
57          start();
58      }
59  
60      public void setModeZoom() {
61          this.setZoomLevel(1);
62          this.setZoomCenter(complexCenterForMandelbrot);
63      }
64  
65      public synchronized void start(){
66          zoomLevel = 1;
67          for(int y = 0;y < this.worldDimensions.getY(); y++){
68              for(int x=0; x < worldDimensions.getX(); x++){
69                  lattice[x][y] = YET_UNCOMPUTED;
70              }
71          }
72      }
73  
74      public synchronized int getCellStatusFor(int x,int y){
75          return (lattice[x][y])<0?0:lattice[x][y];
76      }
77  
78      private synchronized ComplexNumber getComplexNumberFromLatticeCoordsForJulia(Point turingPosition) {
79          double realX = complexCenterForJulia.getReal()
80              + (complexWorldDimensions.getReal()*turingPosition.getX())/worldDimensions.getX();
81          double imgY = complexCenterForJulia.getImg()
82              + (complexWorldDimensions.getImg()*turingPosition.getY())/worldDimensions.getY();
83          return new ComplexNumber(realX,imgY);
84      }
85  
86      private synchronized ComplexNumber getComplexNumberFromLatticeCoordsForMandelbrot(Point turingPosition) {
87          double realX = (
88              complexCenterForMandelbrot.getReal()
89              + ( complexWorldDimensions.getReal() * turingPosition.getX() )
90              / worldDimensions.getX()
91          );
92          double imgY = (
93              complexCenterForMandelbrot.getImg()
94              + ( complexWorldDimensions.getImg() * turingPosition.getY() )
95              / worldDimensions.getY()
96          );
97          return new ComplexNumber(realX,imgY);
98      }
99  
100     private synchronized ComplexNumber getComplexNumberFromLatticeCoordsForZoomedMandelbrot(Point turingPosition) {
101         double realX = (
102             ( complexCenterForMandelbrot.getReal() / this.getZoomLevel() )
103             + getZoomCenter().getReal()
104             + ( complexWorldDimensions.getReal() * turingPosition.getX() )
105             / ( worldDimensions.getX() * this.getZoomLevel() )
106         );
107         double imgY = (
108             ( complexCenterForMandelbrot.getImg() / this.getZoomLevel() )
109             + getZoomCenter().getImg()
110             + ( complexWorldDimensions.getImg() * turingPosition.getY() )
111             / ( worldDimensions.getY() * this.getZoomLevel() )
112         );
113         return new ComplexNumber(realX,imgY);
114     }
115 
116     public synchronized boolean isInZooomedMandelbrotSet(Point turingPosition) {
117         ComplexNumber position = this.getComplexNumberFromLatticeCoordsForZoomedMandelbrot(turingPosition);
118         lattice[turingPosition.getX()][turingPosition.getY()] = position.computeMandelbrotSet();
119         return position.isInMandelbrotSet();
120     }
121 
122     public synchronized boolean isInMandelbrotSet(Point turingPosition) {
123         ComplexNumber position = this.getComplexNumberFromLatticeCoordsForMandelbrot(turingPosition);
124         lattice[turingPosition.getX()][turingPosition.getY()] = position.computeMandelbrotSet();
125         return position.isInMandelbrotSet();
126     }
127 
128     public synchronized void fillTheOutsideWithColors(){
129         for(int y=0;y<worldDimensions.getY();y++){
130             for(int x=0;x<worldDimensions.getX();x++){
131                 if(lattice[x][y] == YET_UNCOMPUTED){
132                     this.isInMandelbrotSet(new Point(x, y));
133                 }
134             }
135         }
136     }
137 
138     private synchronized void computeTheJuliaSetForC(ComplexNumber c) {
139         for(int y = 0; y < worldDimensions.getY(); y++) {
140             for (int x = 0; x < worldDimensions.getX(); x++) {
141                 Pointer/kurzweil/commons/model/turing/Point.html#Point">Point zPoint = new Point(x, y);
142                 ComplexNumber z = this.getComplexNumberFromLatticeCoordsForJulia(zPoint);
143                 lattice[x][y] = z.computeJuliaSet(c);
144             }
145         }
146     }
147 
148     public synchronized void computeTheJuliaSetFor(Point pointFromMandelbrotSet) {
149         ComplexNumber c = getComplexNumberFromLatticeCoordsForMandelbrot(pointFromMandelbrotSet);
150         this.complexNumberForJuliaSetC = c;
151         computeTheJuliaSetForC(c);
152     }
153 
154     public void zoomIntoTheMandelbrotSet(Point zoomPoint) {
155         //log.info("zoomIntoTheMandelbrotSet: "+ zoomPoint +" - old:  "+this.getZoomCenter());
156         this.inceaseZoomLevel();
157         if(this.getZoomLevel() == 2){
158             ComplexNumbermons/model/fractal/ComplexNumber.html#ComplexNumber">ComplexNumber complexCenter = new ComplexNumber(this.complexCenterForMandelbrot);
159             complexCenterForZoomedMandelbrot.push(complexCenter);
160             this.setZoomCenter(getComplexNumberFromLatticeCoordsForMandelbrot(zoomPoint));
161         } else {
162             this.setZoomCenter(getComplexNumberFromLatticeCoordsForZoomedMandelbrot(zoomPoint));
163         }
164         complexCenterForZoomedMandelbrot.push(this.getZoomCenter());
165         //log.info("zoomPoint:     "+ zoomPoint);
166         //log.info("zoomCenterNew: " + this.getZoomCenter() + " - zoomLevel:  "+ this.getZoomLevel());
167         for(int y = 0; y < worldDimensions.getY(); y++){
168             for(int x = 0; x < worldDimensions.getX(); x++){
169                 Pointomputer/kurzweil/commons/model/turing/Point.html#Point">Point p = new Point(x, y);
170                 this.isInZooomedMandelbrotSet(p);
171             }
172         }
173     }
174 
175     public void zoomOutOfTheMandelbrotSet() {
176         //log.info("zoomOutOfTheMandelbrotSet: " + this.getZoomCenter());
177         if(this.getZoomLevel()>1){
178             this.deceaseZoomLevel();
179             this.setZoomCenter(complexCenterForZoomedMandelbrot.pop());
180         }
181         //log.info("zoomCenter: " + this.getZoomCenter() + " - zoomLevel:  "+ this.getZoomLevel());
182         for(int y = 0; y < worldDimensions.getY(); y++){
183             for(int x = 0; x < worldDimensions.getX(); x++){
184                 Pointomputer/kurzweil/commons/model/turing/Point.html#Point">Point p = new Point(x, y);
185                 this.isInZooomedMandelbrotSet(p);
186             }
187         }
188     }
189 
190     public void zoomIntoTheJuliaSetFor(Point zoomPoint) {
191         ComplexNumber c = this.complexNumberForJuliaSetC;
192         computeTheJuliaSetForC(c);
193     }
194 
195     public void zoomOutOfTheJuliaSet() {
196     }
197 
198     public synchronized int getZoomLevel() {
199         return zoomLevel;
200     }
201 
202     public synchronized void setZoomLevel(int zoomLevel) {
203         this.zoomLevel = zoomLevel;
204     }
205 
206     public synchronized int inceaseZoomLevel() {
207         return zoomLevel *= 2;
208     }
209 
210     public synchronized int deceaseZoomLevel() {
211         return zoomLevel /= 2;
212     }
213 
214     public synchronized ComplexNumber getZoomCenter() {
215         return zoomCenter;
216     }
217 
218     public synchronized void setZoomCenter(ComplexNumber zoomCenter) {
219         this.zoomCenter = zoomCenter;
220     }
221 
222 }