"Eintopf"-Fractals

Started by Theo Gottwald, April 13, 2024, 10:09:14 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

We can add the Barnsley fern fractal to the previous script to create more interesting and complex results. Here's an example program that combines the Koch snowflake fractal, the Sierpinski triangle, and the Barnsley fern fractal:
' Koch Snowflake Fractal with Sierpinski Triangle, Barnsley Fern, and Color
' Oxygen Basic, ConsoleG, OpenGL

#compact
%filename "koch_sierpinski_fern.exe"
'uses RTL64
% Title "Koch Snowflake Fractal with Sierpinski Triangle, Barnsley Fern, and Color"

'% WindowStyle WS_OVERLAPPEDWINDOW
'% Animated
'% ScaleUp
% PlaceCentral
% AnchorCentral

% shaders

uses consoleG

BeginScript

procedure drawLine(float x1, float y1, float x2, float y2, float r, float g, float b) {
    color(r, g, b);
    glBegin(GL_LINES);
    glVertex2f(x1, y1);
    glVertex2f(x2, y2);
    glEnd();
}

procedure koch(float x1, float y1, float x2, float y2, int level, float r, float g, float b) {
    if (level == 0) {
        drawLine(x1, y1, x2, y2, r, g, b);
        return;
    }

    float dx = x2 - x1;
    float dy = y2 - y1;
    float len = sqrt(dx*dx + dy*dy) / 3.0;
    float angle = atan2(dy, dx);

    float x3 = x1 + len * cos(angle);
    float y3 = y1 + len * sin(angle);
    float x4 = x3 + len * cos(angle + PI / 3.0);
    float y4 = y3 + len * sin(angle + PI / 3.0);
    float x5 = x2 - len * cos(angle);
    float y5 = y2 - len * sin(angle);

    koch(x1, y1, x3, y3, level-1, r, g, b);
    koch(x3, y3, x4, y4, level-1, g, b, r);
    koch(x4, y4, x5, y5, level-1, b, r, g);
    koch(x5, y5, x2, y2, level-1, r, g, b);

    if (level == 1) {
        drawLine(x3, y3, x4, y4, g, b, r);
        drawLine(x4, y4, x5, y5, b, r, g);
        drawLine(x5, y5, x3, y3, r, g, b);
    }
}

procedure sierpinski(float x1, float y1, float x2, float y2, float x3, float y3, int level, float r, float g, float b) {
    if (level == 0) {
        return;
    }

    float midX1 = x1 + 0.5 * (x2 - x1);
    float midY1 = y1 + 0.5 * (y2 - y1);
    float midX2 = x2 + 0.5 * (x3 - x2);
    float midY2 = y2 + 0.5 * (y3 - y2);
    float midX3 = x3 + 0.5 * (x1 - x3);
    float midY3 = y3 + 0.5 * (y1 - y3);

    sierpinski(x1, y1, midX1, midY1, midX3, midY3, level-1, r, g, b);
    sierpinski(x2, y2, midX2, midY2, midX1, midY1, level-1, g, b, r);
    sierpinski(x3, y3, midX3, midY3, midX2, midY2, level-1, b, r, g);

    if (level == 1) {
        drawLine(midX1, midY1, midX2, midY2, g, b, r);
        drawLine(midX2, midY2, midX3, midY3, b, r, g);
        drawLine(midX3, midY3, midX1, midY1, r, g, b);
    }
}

procedure fern(float x, float y, float a, float b, float c, float d) {
    float x1 = 0;
    float y1 = 0;
    float x2 = 0;
    float y2 = 0;
    float r = rnd();

    if (r < 0.01) {
        x1 = 0;
        y1 = 0.16 * y;
    } else if (r < 0.85) {
        x1 = a * x + b * y;
        y1 = c * x + d * y + 1.6;
    } else if (r < 0.92) {
        x1 = a * x - b * y;
        y1 = -c * x - d * y + 1.6;
    } else {
        x1 = 0;
        y1 = 0.85 * y;
    }

    x2 = x + x1;
    y2 = y + y1;

    drawLine(x, y, x2, y2, 0.0, 0.5, 0.0);

    fern(x2, y2, a, b, c, d);
}

procedure main() {
    cls();
    shading();

    float x1 = -0.5;
    float y1 = -0.5;
    float x2 = 0.5;
    float y2 = -0.5;
    float x3 = 0.0;
    float y3 = 0.5;
    int level = 4;

    koch(x1, y1, x2, y2, level, 1.0, 0.0, 0.0);
    koch(x2, y2, x3, y3, level, 0.0, 1.0, 0.0);
    koch(x3, y3, x1, y1, level, 0.0, 0.0, 1.0);

    sierpinski(x1, y1, x2, y2, x3, y3, level, 1.0, 0.0, 0.0);

    float a = 0.85;
    float b = 0.04;
    float c = -0.04;
    float d = 0.85;

    fern(0.0, 0.0, a, b, c, d);

    waitkey();
}

EndScript

In this version of the program, we've added the Barnsley fern fractal to the previous script that combined the Koch snowflake fractal and the Sierpinski triangle. The `fern` procedure uses a recursive algorithm to generate the Barnsley fern fractal, with different transformations applied based on a random number.

In the `main` procedure, we first draw the Koch snowflake fractal using the `koch` procedure with different colors for each side of the triangle. We then call the `sierpinski` procedure to create the Sierpinski triangle pattern inside the Koch snowflake, using the same colors as the corresponding sides of the snowflake. Finally, we call the `fern` procedure to create the Barnsley fern fractal at the center of the Sierpinski triangle.

When you run this program, you should see a Koch snowflake fractal with harmonious colors, a Sierpinski triangle pattern inside it, and a Barnsley fern fractal at the center of the Sierpinski triangle. You can experiment with different values of the `level` variable to create different variations of the fractal patterns.

Zlatko Vid

I have problem with atn2() or atan2()
i use latest i think v0.80
and compiler complain that there is no such a function ?
and i can bet that i use it before ...somewhere
any help ?
  •  

Charles Pegge

 In o2 atn takes 1 arg atn(y/x), whereas atan takes 2 args atan(y,x) avoiding the possibility of passing an infinity when x=0.


Nicola

hi,
nothing comes out to me. instead of atan2() I used atan(x,y)

Charles Pegge

#4
This code needs a lot of fixing to make it work. I have Koch and Sierpinski working so far, but I may need to insert one of our own Barnsley Ferns.

PS:
' Koch Snowflake Fractal with Sierpinski Triangle, and Color
' Oxygen Basic, ConsoleG, OpenGL

 'Fxed: CP 19/04/2026

#compact
'%filename "koch_sierpinski_fern.exe"
'uses RTL64
% Title "Koch Snowflake Fractal with Sierpinski Triangle, Barnsley Fern, and Color"

'% WindowStyle WS_OVERLAPPEDWINDOW
'% Animated
'% ScaleUp
% PlaceCentral
% AnchorCentral

% shaders

uses consoleG

BeginScript

procedure drawLine(float x1, float y1, float x2, float y2, float r, float g, float b) {
    color(r, g, b)
    thickness 2
    glBegin(GL_LINES)
    glVertex2f(x1, y1)
    glVertex2f(x2, y2)
    glEnd()
}

procedure koch(float x1, float y1, float x2, float y2, int level, float r, float g, float b) {
    if (level == 0) {
        drawLine(x1, y1, x2, y2, r, g, b)
        return
    }

    float dx = x2 - x1
    float dy = y2 - y1
    float le = sqrt(dx*dx + dy*dy) / 3.0
    float angle = atan(dy, dx)
    float pi3=pi()/3

    float x3 = x1 + le * cos(angle)
    float y3 = y1 + le * sin(angle)
    float x4 = x3 + le * cos(angle + pi3)
    float y4 = y3 + le * sin(angle + pi3)
    float x5 = x2 - le * cos(angle)
    float y5 = y2 - le * sin(angle)

    koch(x1, y1, x3, y3, level-1, r, g, b)
    koch(x3, y3, x4, y4, level-1, r, g, b)
    koch(x4, y4, x5, y5, level-1, r, g, b)
    koch(x5, y5, x2, y2, level-1, r, g, b)

    if (level == 1) {
        drawLine(x3, y3, x4, y4, r, g, b)
        drawLine(x4, y4, x5, y5, r, g, b)
        drawLine(x5, y5, x3, y3, r, g, b)
    }
}

procedure sierpinski(float x1, float y1, float x2, float y2, float x3, float y3, int level, float r, float g, float b) {
    if (level == 0) {
        return;
    }
    drawLine(x1,y1, x2,y2, r,g,b)
    drawLine(x2,y2, x3,y3, r,g,b)
    drawLine(x3,y3, x1,y1, r,g,b)

    float midX1 = x1 + 0.5 * (x2 - x1)
    float midY1 = y1 + 0.5 * (y2 - y1)
    float midX2 = x2 + 0.5 * (x3 - x2)
    float midY2 = y2 + 0.5 * (y3 - y2)
    float midX3 = x3 + 0.5 * (x1 - x3)
    float midY3 = y3 + 0.5 * (y1 - y3)

    sierpinski(x1, y1, midX1, midY1, midX3, midY3, level-1, r,g,b)
    sierpinski(x2, y2, midX2, midY2, midX1, midY1, level-1, r,g,b)
    sierpinski(x3, y3, midX3, midY3, midX2, midY2, level-1, r,g,b)
}


procedure main() {
    cls 0.2, 0.2, 0.4
    'shading
    float x1 = -0.5
    float y1 = -0.5
    float x2 = 0.5
    float y2 = -0.5
    float x3 = 0.0
    float y3 = 0.5

    int level = 4
    pushstate
      move -8
      scale 20
      koch(x1, y1, x2, y2, level, 0.0, 1.0, 0.0)
      koch(x2, y2, x3, y3, level, 0.0, 1.0, 0.0)
      koch(x3, y3, x1, y1, level, 0.0, 1.0, 0.0)
    popstate

    pushstate
      move 8
      scale 20
      sierpinski(x1, y1, x2, y2, x3, y3, level, 1.0, 0.0, 0.0)
    popstate
}

EndScript

Charles Pegge

There are a number of demos that use the Barnsley Fern fractal:

.\demos\!ProjB\GDI\Fern.o2bas
.\demos\!ProjB\GDI\FernHMove.o2bas
.\demos\!ProjB\GDI\FernSprite.o2bas
.\demos\!ProjB\GDI\Waterfall1.o2bas
.\demos\!ProjB\GDI\Waterfall2.o2bas
.\demos\!ProjB\SDL\Fern.o2bas
.\demos\GL\Bounce.o2bas
.\demos\GL\CraftPlane.o2bas
.\demos\GL\CraftSaucer.o2bas
.\demos\GL\CraftSaucerFade.o2bas
.\demos\GL\CubicRockRefl.o2bas
.\demos\GL\CubicSphere.o2bas
.\demos\GL\Tiles.o2bas
.\inf\testlog3.o2bas

They may use one of these inc files:
.\demos\!ProjB\GDI\FernSprite.inc
.\inc\GLO2\Particles.inc