Hello,
Here is a very simple idea that perhaps gives interesting results for many fractals, in both 2D and 3D.
On the Mandelbrot Set, suppose that you consider every iteration as a photon path that goes from the previous iteration to the next.
Now suppose that you put a mirror between two consecutive iterations. The mirror will make a reflection and the value will end in another place.
This simple approach changes the iteration values and the overall shape of the fractal.
For those who are using the abs based fractals (The Burning ship and the others), the abs function actually acts like a mirror, reflecting the orbit.
But it's centered on the origin, its infinite and can only be oriented in right angles. Other angles, positions and sizes can create interesting patterns.
My approach is very simple:
Since a 2D mirror is just a line, I define the starting and ending points of this line segment
Also, every iteration is considered a line segment that start from the previous iteration value.
The program tests if both line segments intersects,
If there's an intersection point, the new iteration value is calculated from the reflection angle and the length of the iteration line segment from the intersection point.
This procedure is repeated until the bailout count is reached. This changes the iteration position but no the length, since it only a reflection
The program is very simple (int C) because I only want to show the theory. It saves the resulting image in a ppm format that you can read in any graphics program.
On it you can set the mirror position and the angle, then it will calculate a Mandelbrot set using the above procedure.
Some of the abs based Mandelbrots can be seen if you set the mirror in a right angle.
Now the question is, how it looks if you add more than one mirror (Mandelbrot optics?) or if you move it into 3D.
I tried other mirror types (circles) and refractions but without much luck, but any idea is as always welcomed.
Later I will post an animation of rotating mirrors, but I suppose that someone can build a shader on where you can interactively add mirrors and positions them (perhaps.. no idea)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define PI 3.14159265358979
bool intersection(
double mp0_x, double mp0_y, double mp1_x, double mp1_y,//mirror segment
double ip0_x, double ip0_y, double ip1_x, double ip1_y, //iteration segment
double *i_x, double *i_y //intersection point
)
{
const double s1_x = mp1_x - mp0_x;
const double s1_y = mp1_y - mp0_y;
const double s2_x = ip1_x - ip0_x;
const double s2_y = ip1_y - ip0_y;
const double denom= (-s2_x * s1_y + s1_x * s2_y);
const double s = (-s1_y * (mp0_x - ip0_x) + s1_x * (mp0_y - ip0_y)) / denom;
const double t = ( s2_x * (mp0_y - ip0_y) - s2_y * (mp0_x - ip0_x)) / denom;
if (s >= 0 && s < 1 && t >= 0 && t < 1)
{
//intersection
*i_x = mp0_x + (t * s1_x);
*i_y = mp0_y + (t * s1_y);
return true;
}
return false; // no intersection
}
//Intructions:
//Put the mirror in any point of the mandelbrot set and set the angle and the diameter.
//It will reflect the iteration values if the iteration line segment intersects the mirror.
//When the calculation is complete,the program will save the result in a graphics file
//called "Mirror.ppm"
int main(int argc, char* argv[])
{
//Simple PPM file output, use your favorite graphics program for visualizing it.
FILE *outputfile;
printf("Mirror in the Mandebrot Set\n");
printf("Intructions:\n");
printf("Position the mirror in any point of the Mandelbrot set and set both the\n");
printf("rotation angle and the mirror length. It will reflect the current iteration\n");
printf("value if the line segment between two consecutive iterations intersects\n");
printf("the mirror.\n");
printf("When the calculation is complete,the program will save the result in a\n");
printf("graphics file called \"Mirror.ppm\"\n");
outputfile=fopen("Mirror.ppm","wb");
//Very simple ppm file header
fprintf(outputfile,"P6 1024 1024 255 ");
printf("Calculating..\n");
unsigned char color;
//Mirror Parameters
double mposx=-1.0; //Mirror Position X
double mposy=0.0; //Mirror Position Y
double mangle=90; //Mirror Angle in degrees
double mlength=50000; //length of the mirror, use very large values for an infinite reflecting line
double x,y;
double mx[2],my[2]; //starting and ending segments of the mirror
double tx[2],ty[2]; //starting and ending points of the iteration
double ipointx,ipointy; //intersection point
//mirror normal
double nx,ny;
//iteration normal
double anglex;
double angley;
mangle*=(PI/180.0);//convert from degrees to radians
mlength*=0.5;//calculate the mirror radius
const float rightangle=(PI/180.0)*90;
//calculate the mirror starting and ending point
mx[0]=mposx+sin(mangle+rightangle)*mlength;
my[0]=mposy+cos(mangle+rightangle)*mlength;
mx[1]=mposx+sin(mangle-rightangle)*mlength;
my[1]=mposy+cos(mangle-rightangle)*mlength;
//mirror normal
nx=sin(mangle);
ny=cos(mangle);
int Counter;
for(int jc=0;jc<1024;jc++)
for(int ic=0;ic<1024;ic++)
{
const double ik=(float(ic-512)/512.0)*2-0.75;
const double jk=(float(jc-512)/512.0)*2;
x=0;
y=0;
//iteration loop
for(Counter=0;Counter<100;Counter++){
//get the first iteration segment
tx[0]=x;
ty[0]=y;
//calculate the mandelbrot set
const float xp=x*x-y*y+ik;
const float yp=2*x*y+jk;
//get the second iteration segment
tx[1]=xp;
ty[1]=yp;
//check if the resulting iteration segment intersects the mirror and stores the result if it intersect
if(intersection(mx[0],my[0],mx[1],my[1],tx[0],ty[0],tx[1],ty[1],&ipointx,&ipointy)){
//calculate the distance between the intersection point and the mandelbrot iteration
const double ndistance=sqrt((ipointx-tx[1])*(ipointx-tx[1])+(ipointy-ty[1])*(ipointy-ty[1]));
//calculates the dot product between the intersection point and the the first iteration segment
anglex=ipointx-tx[0];
angley=ipointy-ty[0];
const double langle=1.0/sqrt(anglex*anglex+angley*angley);
anglex*=langle;
angley*=langle;
const double dot = anglex*nx+angley*ny;
//calculates the actual reflected point
const double resx=anglex-2*nx*dot;
const double resy=angley-2*ny*dot;
//use the resulting angle and the distance between the intersection point and the last iteration value to
//calculate the reflected iteration point
x=ipointx+resx*ndistance;
y=ipointy+resy*ndistance;
} else {
//if there's no intersection, the iteration continues with the mandelbrot values
x=xp;
y=yp;
}
if(sqrt(x*x+y*y)>10)break;
}
//use the iteration count as a grayscale gradient
if(Counter<100) color=(unsigned char)Counter; else color=0;
//write to the output file
fputc (color,outputfile);
fputc (color,outputfile);
fputc (color,outputfile);
}
fclose(outputfile);
printf("Calculation finished..\n\n");
return 0;
}
Hope you like it.
Aexion
ps. Try it in other fractals..
pps. Here's an animation of a rotating mirror centered at (-1,0i):