-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMandelbrotGUI.java
More file actions
368 lines (288 loc) · 8.05 KB
/
MandelbrotGUI.java
File metadata and controls
368 lines (288 loc) · 8.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
public class MandelbrotGUI extends JFrame {
/*
* Essentially, the MandebrotGUI class simply holds together the 3 panels
* that make this program. The main three parts are the Mandelbrot itself,
* the Julia set, and the editor.
*/
MandelPanel mandel;
JuliaPanel julia;
MandelEditor editor;
public MandelbrotGUI(String title) {
super(title);
init();
}
public void init() {
// Setting the layout for the 3 panels.
this.setSize(1600, 900);
Container c = new Container();
c = this.getContentPane();
c.setLayout(new BorderLayout(5, 5));
// the main panel takes up 1000 of the 1600 width, more of it on screen
// than the other two
mandel = new MandelPanel(1000, 900);
TitledBorder mandelBorder;
mandelBorder = BorderFactory.createTitledBorder("Mandelbrot");
mandel.setBorder(mandelBorder);
c.add(mandel, BorderLayout.CENTER);
JPanel right = new JPanel();
right.setLayout(new GridLayout(2, 1));
c.add(right, BorderLayout.LINE_END);
julia = new JuliaPanel();
mandelBorder = BorderFactory.createTitledBorder("Julia Set");
julia.setBorder(mandelBorder);
right.add(julia);
editor = new MandelEditor(mandel, julia);
right.add(editor);
mandelBorder = BorderFactory.createTitledBorder("Editor");
editor.setBorder(mandelBorder);
this.setResizable(true);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
MandelbrotGUI mb = new MandelbrotGUI("Fractal Viewer");
}
}
class MandelPanel extends JPanel {
/*
* The MandelPanel is the main Mandelbrot image. Generally, the MandelPanel
* only accepts data from the MandelEditor, and displays the image. All
* mathsy calculations are done in here, calculated from the raw information
* given by the editor.
*/
// used in drawing the image
private int iterations;
private BufferedImage bi;
private Complex c, z;
private FractalFormula fractal;
private String formula;
// used in zooming and drawing the rectangle over the image
private Point rectStart, rectEnd;
private boolean hasDragged = false;
// colour stuff, read from 3 sliders
private int colour;
private int red;
private int green;
private int blue;
// max and min values for the axis. X is real numbers, Y is complex numbers
private double maxX, maxY, minX, minY;
public MandelPanel(int width, int height) {
// sets the default values
this.maxX = 2.0;
this.maxY = 1.6;
this.minX = -2.0;
this.minY = -1.6;
this.setSize(width, height);
this.iterations = 50;
fractal = new FractalFormula();
formula = "Mandelbrot";
}
// getters and setters
public double getMaxX() {
return maxX;
}
public String getFormula() {
return formula;
}
public void setTheFormula(String formula) {
this.formula = formula;
}
public void setMaxX(double maxWidth) {
this.maxX = maxWidth;
}
public double getMaxY() {
return maxY;
}
public void setMaxY(double maxHeight) {
this.maxY = maxHeight;
}
public double getMinX() {
return minX;
}
public void setMinX(double minWidth) {
this.minX = minWidth;
}
public double getMinY() {
return minY;
}
public void setMinY(double minHeight) {
this.minY = minHeight;
}
public void setIterations(int iterations) {
this.iterations = iterations;
}
public int getIterations() {
return this.iterations;
}
public void setDragged(boolean what) {
hasDragged = what;
}
public boolean getDragged() {
return hasDragged;
}
public void setStart(Point points) {
this.rectStart = points;
System.out.println("start is now " + points.getX());
}
public void setEnd(Point points) {
this.rectEnd = points;
System.out.println("end is now " + points.getX());
}
public Point getStart() {
return rectStart;
}
public Point getEnd() {
return rectEnd;
}
public int getColour() {
return colour;
}
public void setColour(int colour) {
this.colour = colour;
}
public int getRed() {
return red;
}
public void setRed(int red) {
this.red = red;
}
public int getGreen() {
return green;
}
public void setGreen(int green) {
this.green = green;
}
public int getBlue() {
return blue;
}
public void setBlue(int blue) {
this.blue = blue;
}
// method that calculates the image
public void calcImage() {
// creates a colour from the RGB values
Color tempColour = new Color(red, green, blue);
// buffered image takes RGB integer, so convert is needed
colour = tempColour.getRGB();
bi = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
// scrolls through all of the pixels in the panel
for (int x = 0; x < this.getWidth(); x++) {
for (int y = 0; y < this.getHeight(); y++) {
// int curIterations = 0;
// converts the pixel to complex number, no matter what the
// scale is
double creal = (maxX - minX) * (x / (double) this.getWidth()) + minX;
double cimag = (maxY - minY) * (y / (double) this.getHeight()) + minY;
z = new Complex(0, 0);
// creates the complex based on pixel coord
c = new Complex(creal, cimag);
// keeps carrying out formula until the modulus rises above 2,
// or runs out of iterations
// to carry out
int curIterations = fractal.calcFractal(c, z, this.iterations, formula);
// sets the colour based on the amount of iterations
if (curIterations == iterations) {
bi.setRGB(x, y, 0);
} else {
bi.setRGB(x, y, colour / (curIterations + 1));
}
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Doesnt calculate the image while drawing rectangle, stops lag
if (!hasDragged) {
calcImage();
}
// Draws the image
g.drawImage(bi, 0, 0, this);
// Drag to draw rectangle
if (hasDragged) {
g.setColor(Color.blue);
// The absolute values and min values make the rectangle work in 4
// directions.
g.drawRect(Math.min(rectStart.x, rectEnd.x), Math.min(rectStart.y, rectEnd.y),
Math.abs(rectEnd.x - rectStart.x), Math.abs(rectEnd.y - rectStart.y));
}
}
}
class JuliaPanel extends JPanel {
private int iterations;
private BufferedImage bi;
private Complex c, z;
private FractalFormula fractal;
private String formula;
private boolean liveUpdate;
private double maxX, maxY, minX, minY;
public JuliaPanel() {
this.maxX = 2.0;
this.maxY = 1.6;
this.minX = -2.0;
this.minY = -1.6;
this.setSize(600, 450);
this.iterations = 100;
this.z = new Complex(0, 0);
formula = "Mandelbrot";
fractal = new FractalFormula();
liveUpdate = true;
}
public boolean isLiveUpdate() {
return liveUpdate;
}
public void setLiveUpdate(boolean liveUpdate) {
this.liveUpdate = liveUpdate;
}
public String getFormula() {
return formula;
}
public void setTheFormula(String formula) {
this.formula = formula;
}
public void setComplex(Complex z) {
this.z = z;
}
public Complex getComplex() {
return z;
}
public BufferedImage getBi() {
return bi;
}
// same calculations for mandelbrot, but uses an initial complex input
// instead of 0,0
public void calcImage() {
bi = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < this.getWidth(); x++) {
for (int y = 0; y < this.getHeight(); y++) {
double creal = (maxX - minX) * (x / (double) this.getWidth()) + minX;
double cimag = (maxY - minY) * (y / (double) this.getHeight()) + minY;
c = new Complex(creal, cimag);
int curIterations = fractal.calcFractal(z, c, this.iterations, formula);
// sets the colour based on iterations
if (curIterations == iterations) {
bi.setRGB(x, y, 0);
} else {
bi.setRGB(x, y, 51455 / (curIterations + 1));
}
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
calcImage();
g.drawImage(bi, 0, 0, this);
}
}