This project has retired. For details please refer to its Attic page.
FractalCalculator xref

1   ////////////////////////////////////////////////////////////////////////////////
2   ////////////////////////////////////////////////////////////////////////////////
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.chemistry.opencmis.util.content.fractal;
23  
24  import java.awt.Color;
25  import java.awt.image.BufferedImage;
26  
27  final class FractalCalculator {
28      private int[] colorMap;
29      protected int[][] noIterations;
30      private double delta;
31      private double iRangeMax;
32      private double iRangeMin;
33      private int maxIterations;
34      private ComplexRectangle newRect;
35      private int numColors;
36      private int imageHeight;
37      private int imageWidth;
38      private double rRangeMax;
39      private double rRangeMin;
40      // For Julia set:
41      private double cJuliaPointR = 0.0; // Real
42      private double cJuliaPointI = 0.0; // Imaginary
43      boolean useJulia = false;
44  
45      public FractalCalculator(ComplexRectangle complRect, int maxIters, int imgWidth, int imgHeight, int[] colMap,
46              ComplexPoint juliaPoint) {
47          maxIterations = maxIters;
48          newRect = complRect;
49          imageWidth = imgWidth;
50          imageHeight = imgHeight;
51          colorMap = colMap;
52          numColors = colorMap.length;
53          rRangeMin = newRect.getRMin();
54          rRangeMax = newRect.getRMax();
55          iRangeMin = newRect.getIMin();
56          iRangeMax = newRect.getIMax();
57          delta = (rRangeMax - rRangeMin) / imageWidth;
58          if (null != juliaPoint) {
59              cJuliaPointR = juliaPoint.getReal();
60              cJuliaPointI = juliaPoint.getImaginary();
61              useJulia = true;
62          }
63      }
64  
65      public int[][] calcFractal() {
66          noIterations = new int[ imageWidth ][ imageHeight ];
67  
68          // For each pixel...
69          for (int x = 0; x < imageWidth; x++) {
70              for (int y = 0; y < imageHeight; y++) {
71                  double zR = rRangeMin + x * delta;
72                  double zI = iRangeMin + (imageHeight - y) * delta;
73  
74                  // Is the point inside the set?
75                  if (useJulia)
76                      noIterations[x][y] = testPointJuliaSet(zR, zI, maxIterations);
77                  else
78                      noIterations[x][y] = testPointMandelbrot(zR, zI, maxIterations);            
79              }
80          }
81          return noIterations;
82      }
83  
84      public BufferedImage mapItersToColors(int[][] iterations) {
85  
86          // Assign a color to every pixel ( x , y ) in the Image, corresponding
87          // to
88          // one point, z, in the imaginary plane ( zr, zi ).
89          BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_3BYTE_BGR );
90  
91          // For each pixel...
92          for (int x = 0; x < imageWidth; x++) {
93              for (int y = 0; y < imageHeight; y++) {
94                  int color = getColor(iterations[x][y]);
95                  image.setRGB(x, y, color);
96              }
97          }
98          return image;
99      }
100 
101     protected int getColor(int numIterations) {
102         int c = Color.black.getRGB();
103 
104         if (numIterations != 0) {
105             // The point is outside the set. It gets a color based on the number
106             // of iterations it took to know this.
107             int colorNum = (int) (numColors * (1.0 - (float) numIterations / (float) maxIterations));
108             colorNum = (colorNum == numColors) ? 0 : colorNum;
109 
110             c = colorMap[colorNum];
111         }
112         return c;
113     }
114 
115     private int testPointMandelbrot(double cR, double cI, int maxIterations) {
116         // Is the given complex point, (cR, cI), in the Mandelbrot set?
117         // Use the formula: z <= z*z + c, where z is initially equal to c.
118         // If |z| >= 2, then the point is not in the set.
119         // Return 0 if the point is in the set; else return the number of
120         // iterations it took to decide that the point is not in the set.
121         double zR = cR;
122         double zI = cI;
123 
124         for (int i = 1; i <= maxIterations; i++) {
125             // To square a complex number: (a+bi)(a+bi) = a*a - b*b + 2abi
126             double zROld = zR;
127             zR = zR * zR - zI * zI + cR;
128             zI = 2 * zROld * zI + cI;
129 
130             // We know that if the distance from z to the origin is >= 2
131             // then the point is out of the set. To avoid a square root,
132             // we'll instead check if the distance squared >= 4.
133             double distSquared = zR * zR + zI * zI;
134             if (distSquared >= 4) {
135                 return i;
136             }
137         }
138         return 0;
139     }
140 
141     private int testPointJuliaSet(double zR, double zI, int maxIterations) {
142         // Is the given complex point, (zR, zI), in the Julia set?
143         // Use the formula: z <= z*z + c, where z is the point being tested,
144         // and c is the Julia Set constant.
145         // If |z| >= 2, then the point is not in the set.
146         // Return 0 if the point is in the set; else return the number of
147         // iterations it took to decide that the point is not in the set.
148         for (int i = 1; i <= maxIterations; i++) {
149             double zROld = zR;
150             // To square a complex number: (a+bi)(a+bi) = a*a - b*b + 2abi
151             zR = zR * zR - zI * zI + cJuliaPointR;
152             zI = 2 * zROld * zI + cJuliaPointI;
153             // We know that if the distance from z to the origin is >= 2
154             // then the point is out of the set. To avoid a square root,
155             // we'll instead check if the distance squared >= 4.
156             double distSquared = zR * zR + zI * zI;
157             if (distSquared >= 4) {
158                 return i;
159             }
160         }
161         return 0;
162     }
163 }