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 }