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