blob: dddfbd4200044bf2466c12bbd91748f5984154d2 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.chemistry.opencmis.util.content.fractal;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.Arrays;
final class FractalCalculator {
private int[] colorMap;
protected int[][] noIterations;
private double delta;
private double iRangeMax;
private double iRangeMin;
private int maxIterations;
private ComplexRectangle newRect;
private int numColors;
private int imageHeight;
private int imageWidth;
private double rRangeMax;
private double rRangeMin;
// For Julia set:
private double cJuliaPointR = 0.0; // Real
private double cJuliaPointI = 0.0; // Imaginary
boolean useJulia = false;
public FractalCalculator(ComplexRectangle complRect, int maxIters, int imgWidth, int imgHeight, int[] colMap,
ComplexPoint juliaPoint) {
maxIterations = maxIters;
newRect = complRect;
imageWidth = imgWidth;
imageHeight = imgHeight;
colorMap = Arrays.copyOf(colMap, colMap.length);
numColors = colorMap.length;
rRangeMin = newRect.getRMin();
rRangeMax = newRect.getRMax();
iRangeMin = newRect.getIMin();
iRangeMax = newRect.getIMax();
delta = (rRangeMax - rRangeMin) / imageWidth;
if (null != juliaPoint) {
cJuliaPointR = juliaPoint.getReal();
cJuliaPointI = juliaPoint.getImaginary();
useJulia = true;
}
}
public int[][] calcFractal() {
noIterations = new int[ imageWidth ][ imageHeight ];
// For each pixel...
for (int x = 0; x < imageWidth; x++) {
for (int y = 0; y < imageHeight; y++) {
double zR = rRangeMin + x * delta;
double zI = iRangeMin + (imageHeight - y) * delta;
// Is the point inside the set?
if (useJulia) {
noIterations[x][y] = testPointJuliaSet(zR, zI, maxIterations);
} else {
noIterations[x][y] = testPointMandelbrot(zR, zI, maxIterations);
}
}
}
return noIterations;
}
public BufferedImage mapItersToColors(int[][] iterations) {
// Assign a color to every pixel ( x , y ) in the Image, corresponding
// to
// one point, z, in the imaginary plane ( zr, zi ).
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_3BYTE_BGR );
// For each pixel...
for (int x = 0; x < imageWidth; x++) {
for (int y = 0; y < imageHeight; y++) {
int color = getColor(iterations[x][y]);
image.setRGB(x, y, color);
}
}
return image;
}
protected int getColor(int numIterations) {
int c = Color.black.getRGB();
if (numIterations != 0) {
// The point is outside the set. It gets a color based on the number
// of iterations it took to know this.
int colorNum = (int) (numColors * (1.0 - (float) numIterations / (float) maxIterations));
colorNum = (colorNum == numColors) ? 0 : colorNum;
c = colorMap[colorNum];
}
return c;
}
private int testPointMandelbrot(double cR, double cI, int maxIterations) {
// Is the given complex point, (cR, cI), in the Mandelbrot set?
// Use the formula: z <= z*z + c, where z is initially equal to c.
// If |z| >= 2, then the point is not in the set.
// Return 0 if the point is in the set; else return the number of
// iterations it took to decide that the point is not in the set.
double zR = cR;
double zI = cI;
for (int i = 1; i <= maxIterations; i++) {
// To square a complex number: (a+bi)(a+bi) = a*a - b*b + 2abi
double zROld = zR;
zR = zR * zR - zI * zI + cR;
zI = 2 * zROld * zI + cI;
// We know that if the distance from z to the origin is >= 2
// then the point is out of the set. To avoid a square root,
// we'll instead check if the distance squared >= 4.
double distSquared = zR * zR + zI * zI;
if (distSquared >= 4) {
return i;
}
}
return 0;
}
private int testPointJuliaSet(double zR, double zI, int maxIterations) {
// Is the given complex point, (zR, zI), in the Julia set?
// Use the formula: z <= z*z + c, where z is the point being tested,
// and c is the Julia Set constant.
// If |z| >= 2, then the point is not in the set.
// Return 0 if the point is in the set; else return the number of
// iterations it took to decide that the point is not in the set.
for (int i = 1; i <= maxIterations; i++) {
double zROld = zR;
// To square a complex number: (a+bi)(a+bi) = a*a - b*b + 2abi
zR = zR * zR - zI * zI + cJuliaPointR;
zI = 2 * zROld * zI + cJuliaPointI;
// We know that if the distance from z to the origin is >= 2
// then the point is out of the set. To avoid a square root,
// we'll instead check if the distance squared >= 4.
double distSquared = zR * zR + zI * zI;
if (distSquared >= 4) {
return i;
}
}
return 0;
}
}