//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* * 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.inmemory.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; } }