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