Source code: com/arranger/jarl/test/frac/FractalCalculator.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // FractalCalculator Class /////////////////////////////////////////////////////
3 ////////////////////////////////////////////////////////////////////////////////
4 // Copyright 2000 - David Leberknight - Anyone may use this code for any reason
5 // at any time, provided that they give an appropriate reference to this source,
6 // and send David some email ( david@leberknight.com ).
7 //
8 // FractalCalculator is an abstract class generalizing all fractal calculators.
9 // This class uses the "Template Method" Design Pattern; the entire algorithm
10 // for creating a new fractal image is defined in calcFractal(), which uses
11 // getColor(), which in turn uses the abstract method testPoint(), which is
12 // implemented differently by MandelbrotCalculator and JuliaClaculator.
13 // The method getColor() is overriden by FastColorsCalculator.
14
15 package com.arranger.jarl.test.frac;
16
17 import java.awt.*;
18
19 import com.arranger.jarl.test.FracTest;
20
21 public abstract class FractalCalculator {
22 private Color[] colorMap;
23 private int[][] colorNumbers;
24 private double delta;
25 private FracTest fractal;
26 private Image image;
27 private double iRangeMax;
28 private double iRangeMin;
29 private int maxIterations;
30 private Drawing newDrawing;
31 private ComplexRectangle newRect;
32 private int numColors;
33 private int imageHeight;
34 private int imageWidth;
35 private double rRangeMax;
36 private double rRangeMin;
37 private boolean stopRequested;
38
39 protected FractalCalculator(FracTest fractal, Drawing newDrawing) {
40 this.fractal = fractal;
41 this.newDrawing = newDrawing;
42 image = newDrawing.getImage();
43 maxIterations = newDrawing.getMaxIterations();
44 newRect = newDrawing.getComplexRect();
45 imageWidth = fractal.getImageWidth();
46 imageHeight = fractal.getImageHeight();
47 colorMap = fractal.getCurrentColorMap();
48 numColors = colorMap.length;
49 rRangeMin = newRect.getRMin();
50 rRangeMax = newRect.getRMax();
51 iRangeMin = newRect.getIMin();
52 iRangeMax = newRect.getIMax();
53 delta = (rRangeMax - rRangeMin) / (double) imageWidth;
54 colorNumbers = null; // set this up later.
55 stopRequested = false;
56 }
57
58 private boolean calcFractal() throws Throwable {
59 // Assign a color to every pixel ( x , y ) in the Image, corresponding to
60 // one point, z, in the imaginary plane ( zr, zi ).
61 Graphics imageGraphics = null;
62 try {
63 colorNumbers = getColorNumbers();
64 fractal.setStatus2(" 0% Complete.");
65
66 // Get the Graphics object for the Image. This is necessary
67 // for "double buffering" of the calculated image.
68 imageGraphics = image.getGraphics();
69
70 /*RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
71 renderingHints.add(new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC));
72 renderingHints.add(new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY));
73 renderingHints.add(new RenderingHints(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON));
74 renderingHints.add(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
75 Graphics2D graphics2D = (Graphics2D) imageGraphics;
76 graphics2D.setRenderingHints(renderingHints);*/
77
78 imageGraphics.setPaintMode();
79
80 // For each pixel...
81 for (int x = 0; x < imageWidth; x++) {
82 for (int y = 0; y < imageHeight; y++) {
83 Color c = getColor(x, y);
84
85 imageGraphics.setColor(c);
86 imageGraphics.drawLine(x, y, x, y);
87
88 }
89 fractal.setStatus2(" " + 100 * x / imageWidth + "% Complete.");
90 }
91 newDrawing.setColorNumbers(colorNumbers);
92 fractal.setStatus2(" 100% Complete.");
93 return true;
94 } finally {
95 if (imageGraphics != null) {
96 imageGraphics.dispose(); // garbage.
97 }
98 }
99 }
100
101 protected Color getColor(int x, int y) {
102 Color c = Color.black;
103 colorNumbers[x][y] = -1; // -1 indicates black.
104 double zR = rRangeMin + ((double) x) * delta;
105 double zI = iRangeMin + ((double) (imageHeight - y)) * delta;
106
107 // Is the point inside the set?
108 int numIterations = testPoint(zR, zI, maxIterations);
109
110 if (numIterations != 0) {
111 // The point is outside the set. It gets a color based on the number
112 // of iterations it took to know this.
113 int colorNum = (int) ((float) numColors * (1.0 -
114 (float) numIterations / (float) maxIterations));
115 colorNum = (colorNum == numColors) ? 0 : colorNum;
116
117 // Save this information, to the slight detriment of this calculator's
118 // speed, in order to greatly increase the performance for creating
119 // future Drawings, when only the color scheme has been changed.
120 colorNumbers[x][y] = colorNum;
121 c = colorMap[colorNum];
122 }
123 return c;
124 }
125
126 protected int[][] getColorNumbers() {
127 // Beware: out of memory! Save the colorNumber data with the drawing
128 // in order to be able to use the FastColorsCalculator later on.
129 return new int[imageWidth][imageHeight];
130 }
131
132 public void run() throws Throwable {
133 calcFractal();
134 }
135
136 // Subclasses must implement this method:
137 protected abstract int testPoint(double r, double i, int maxIterations);
138 }