Commit a2ae34ad authored by Mathieu Bosi's avatar Mathieu Bosi
Browse files

Added 'MandelbrotOrbits' sketch.

parent 9b6f7700
// Maximum number of iterations for each point on the complex plane
int gMaxiterations = 256;
import java.util.ArrayList;
PImage mandelBkg;
void setup()
{
size(1800, 1200);
computeBackgroundMandelbrot();
smooth(1);
}
// 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 mandelW = 3*2;
float mandelH = 2*2;
// Start at negative half the width and height
float xmin = -mandelW / 1.75;
float ymin = -mandelH / 2.0;
// x goes from xmin to xmax
float xmax = xmin + mandelW;
// y goes from ymin to ymax
float ymax = ymin + mandelH;
Point2 pedro = new Point2(0,0);
final float invPI2 = 0.5 / PI;
int getIterationsCountForPoint(float cx, float cy, final int maxiterations, ArrayList<Point2> trajectory, Point2 lastPoint, boolean cull)
{
if (cull && isForSureInMandelbrotSet(cx, cy)) return maxiterations;
float a = cx;
float b = cy;
int n = 0;
if (trajectory != null) trajectory.add(new Point2(cx, cy));
while (n < maxiterations)
{
float a2 = a * a;
float b2 = b * b;
if (a2 + b2 > 64.0)
{
break; // Bail
}
// Next point
float twoab = 2.0 * a * b;
a = a2 - b2 + cx;
b = twoab + cy;
if (trajectory != null) trajectory.add(new Point2(a, b));
n++;
}
if (lastPoint != null) { lastPoint.x = a; lastPoint.y = b; }
return n;
}
float getTrajectoryLength(ArrayList<Point2> traj)
{
float d = 0;
for(int i = 0; i < traj.size()-1; i++)
{
Point2 p1 = traj.get(i);
Point2 p2 = traj.get(i+1);
d+= dist(p1.x, p1.y, p2.x, p2.y);
}
return d;
}
int getColorForPoint(float x, float y, boolean cull)
{
ArrayList<Point2> traj = null;//new ArrayList<Point2>();
int n = getIterationsCountForPoint(x, y, gMaxiterations, traj, pedro, cull);
// We color each pixel based on how long it takes to get to infinity
// If we never got there, let's pick the color black
if (n >= gMaxiterations)
{
int coff =
(int)map(atan2(pedro.y - y, pedro.x - x), -PI, PI, 0, 255);
return color(coff);
}
else
{
float norm = map(n, 0, gMaxiterations, 0, 1);
int coff = atan2(pedro.y, pedro.x) > 0.0 ? 1 : 0;
int c = (int)map(sqrt(norm), 0, 1, 0, 255);
c = coff > 0 ? color(c) : color(255 - c);
return c;
}
}
int getAverageColor(int ... colors)
{
float r = 0, g = 0, b = 0;
for (int c: colors) {
r += (c >> 16 & 0xFF);
g += (c >> 8 & 0xFF);
b += (c & 0xFF);
}
float kn = 1.0 / (float)colors.length;
return color(r * kn, g * kn, b * kn);
}
void computeBackgroundMandelbrot()
{
mandelBkg = new PImage(width, height, RGB);
mandelBkg.loadPixels();
// Calculate amount we increment x,y for each pixel
float dx = (xmax - xmin) / (mandelBkg.width);
float dy = (ymax - ymin) / (mandelBkg.height);
float dx2 = dx * 0.5;
float dy2 = dy * 0.5;
boolean cull = false;
// Start y
float y = ymax;
for (int j = 0, off = 0; j < mandelBkg.height; j++) {
// Start x
float x = xmin;
for (int i = 0; i < mandelBkg.width; i++, off++) {
//mandelBkg.pixels[off] = getColorForPoint(x, y, cull);
// /*
mandelBkg.pixels[off] = getAverageColor(
getColorForPoint(x, y, cull),
getColorForPoint(x-dx2, y-dy2, cull),
getColorForPoint(x-dx2, y+dy2, cull),
getColorForPoint(x+dx2, y-dy2, cull),
getColorForPoint(x+dx2, y+dy2, cull));
// */
x += dx;
}
y -= dy;
}
mandelBkg.updatePixels();
}
class Point2 {
public Point2(float x, float y)
{
this.x = x;
this.y = y;
}
public float x;
public float y;
}
boolean isForSureInMandelbrotSet(float x, float y)
{
float k = (x - 0.25);
float y2 = y*y;
float q = k*k + y2;
return q * (q + x - 0.25) < 0.25 * y2;
}
float moveToLastX;
float moveToLastY;
void moveTo(float x, float y)
{
moveToLastX = x;
moveToLastY = y;
}
void lineTo(float x, float y)
{
line(moveToLastX, moveToLastY, x, y);
moveTo(x, y);
}
void draw()
{
colorMode(RGB, 255);
noFill();
tint(255);
image(mandelBkg, 0, 0, width, height);
float x = map(mouseX, 0, width, xmin, xmax);
float y = map(mouseY, 0, height, ymax, ymin);
ArrayList<Point2> t = new ArrayList<Point2>();
colorMode(HSB, gMaxiterations, 1.0, 1.0, 1.0);
stroke(255, 0, 0);
tint(200);
getIterationsCountForPoint(x, y, gMaxiterations, t, null, false);
if (t.size() >= 2)
{
for (int i = 0; i < t.size(); i++)
{
strokeWeight(map(i, 0, gMaxiterations-1, 2, 0.1));
stroke(i, gMaxiterations-i, 1.0, 0.75);
Point2 p = t.get(i);
float tx = map(p.x, xmin, xmax, 0, width);
float ty = map(p.y, ymax, ymin, 0, height);
if (i == 0)
moveTo(tx, ty);
else
lineTo(tx, ty);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment