I was looking at this bunch of fractals from the Wikipedia page "Frattale" (just the italian for Fractal).
So I thought "Hey, I should write a program that lets me generate every fractal I want in the complex plane!!" and, after a few weeks of coding, here I am, asking for help... kinda/ish.
The results look like this:
The results are "meh" though they are kinda right: notice there's the similar "hole" in the real z=z^2 + c and in mine. Take a look at this
You can see the two results are kinda similar
I don't really know if this is a mathematical issue or a programming one so I'll post this both on mathematics and Stack Overflow.
uh and here's my code in Processing 3 (Java):
( the mathematical part is inside the void draw's while. Don't bother about the interface part. In the code I :
- compute the magnitude / modulus of a complex number number and its relative phase
- take the power of the complex number
- Check if it is greater the 2 (if it's greater than 2 then the number tends towards infinity)
- Recompute the x and y component of the number
- Iterate
**** WARNING CRITICAL PART ****
I think the program breaks when I add x and y to, respectively the x and y component of the number, though I am not that sure. Please let me know if I am stupid.
**** WARNING CRITICAL PART ****
)
int COLORS = 1;
int ITERATIONS = 100;
GUIController guiController;
IFTextField textField;
IFLabel ifLabel;
Button drawButton;
CloseButton exitButton;
boolean render=false;
float writtenPower;
void setup() {
//fullScreen();
size(1280,720);
colorMode(RGB, COLORS);
guiController = new GUIController(this);
textField = new IFTextField("Text Field", 25, 30, 150);
ifLabel = new IFLabel("", 25, 70);
drawButton = new Button(width-40,10);
exitButton = new CloseButton(width-85,10);
guiController.add(textField);
guiController.add(ifLabel);
textField.addActionListener(this);
}
void draw() {
stroke(0,0,0);
drawButton.display();
exitButton.display();
if(render){
// Establish a range of values on the complex plane
// A different range will allow us to "zoom" in or out on the fractal
// It all starts with the width, try higher or lower values
float w = 4;
float h = (w * height) / width;
// Start at negative half the width and height
float xmin = -w/2;
float ymin = -h/2;
// Make sure we can write to the pixels[] array.
// Only need to do this once since we don't do any other drawing.
loadPixels();
// x goes from xmin to xmax
float xmax = xmin + w;
// y goes from ymin to ymax
float ymax = ymin + h;
// Calculate amount we increment x,y for each pixel
float dx = (xmax - xmin) / (width);
float dy = (ymax - ymin) / (height);
float y = ymin;
for (int j = 0; j < height; j++) {
// Start x
float x = xmin;
for (int i = 0; i < width; i++) {
// Now we test, as we iterate z = z^2 + cm does z tend towards infinity?
float modulus;
float phase = arctan(x,y);
float a = x;
float b = y;
int n=0;
while (n < ITERATIONS) {
modulus = sqrt(pow(a,2) + pow(b,2));
phase *= writtenPower;
modulus = pow(modulus,writtenPower);
if (modulus > 2)
break; // Bail
a=modulus*cos(phase) + x;
b=modulus*sin(phase) + y;
n++;
}
// We color each pixel based on how long it takes to get to infinity
if (n == ITERATIONS) {
pixels[i+j*width] = color(0);
} else {
pixels[i+j*width] = color(sqrt(float(n) / ITERATIONS));
}
x += dx;
}
y += dy;
}
updatePixels();
}else{
stroke(0);
textSize(16);
background(cos(2*PI*0.001*mouseX),0.8,sin(2*PI*0.001*mouseY));
text("KALEIODOSCIENZA",width/2,height/2);
drawButton.display();
exitButton.display();
}
}
void actionPerformed(GUIEvent e) {
if (e.getMessage().equals("Completed")) {
ifLabel.setLabel(textField.getValue());
writtenPower=Float.valueOf(textField.getValue());
}
}
void mousePressed() {
if (exitButton.isClicked(mouseX, mouseY))
exit();
if (drawButton.isClicked(mouseX, mouseY)){
if(render){
render=false;
}
else
render=true;
}
}
float arctan(float a, float b){
float processingIsStupid = b/a;
if(a<0 && b>0 || a<0 && b<0){
return PI + atan(processingIsStupid);
} else{
return atan(processingIsStupid);
}
}
// a button with side equal to 30 pixels
class Button
{
int minX, minY, side;
Button(int x1, int y1)
{
minX = x1; minY = y1; side = 30;
}
boolean isClicked( int x, int y)
{
if (( x >= minX) && (x <= (minX+side)) && ( y >= minY) && (y <= (minY+side)))
return true;
else
return false;
}
void display()
{
rectMode(CORNER);
rect( minX, minY, side, side);
}
}
class CloseButton extends Button
{
CloseButton(int x1, int y1)
{
super(x1, y1);
}
void display()
{
super.display();
strokeWeight(2);
ellipse(minX+15,minY+15,20,20);
strokeWeight(1);
}
}
So yeah, I don't really know what I should do. Let me know if you didn't really get something (or if I didn't).
To test the code Download Processing 3 and paste both snippets in two different tabs (i.e. in two different files in the project folder)
Thanks in advance !!
https://processing.org/reference/atan2_.html can replace your
arctan.The issue with your code is that you need to recalculate the phase inside the loop: