Here's an example program that uses recursion to draw a Koch snowflake fractal:
' Koch Snowflake Fractal
' Oxygen Basic, ConsoleG, OpenGL
#compact
%filename "koch.exe"
'uses RTL64
% Title "Koch Snowflake Fractal"
'% WindowStyle WS_OVERLAPPEDWINDOW
'% Animated
'% ScaleUp
% PlaceCentral
% AnchorCentral
% shaders
uses consoleG
BeginScript
procedure drawLine(float x1, float y1, float x2, float y2) {
glBegin(GL_LINES);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glEnd();
}
procedure koch(float x1, float y1, float x2, float y2, int level) {
if (level == 0) {
drawLine(x1, y1, x2, y2);
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);
koch(x3, y3, x4, y4, level-1);
koch(x4, y4, x5, y5, level-1);
koch(x5, y5, x2, y2, level-1);
}
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);
koch(x2, y2, x3, y3, level);
koch(x3, y3, x1, y1, level);
waitkey();
}
EndScript
In this program, we define a `drawLine` procedure that takes four arguments specifying the coordinates of the two endpoints of a line, and draws the line using OpenGL. We also define a `koch` procedure that takes the same four arguments as `drawLine`, as well as an additional `level` argument that specifies the level of recursion to use when drawing the Koch snowflake.
The `koch` procedure works by first calculating the length and angle of the line segment, and then dividing the line segment into three equal parts. It then calculates the coordinates of the four vertices of the equilateral triangle that forms the middle part of the Koch snowflake, and recursively calls itself four times to draw smaller Koch snowflakes inside the original line segment, with each smaller snowflake having its vertices at the endpoints of the original line segment and the vertices of the equilateral triangle. The recursion continues until the specified `level` is reached.
When you run this program, you should see a Koch snowflake fractal with the specified level of recursion. You can experiment with different values of `level` to see how they affect the appearance of the fractal. Note that larger values of `level` will result in a more detailed fractal, but will also take longer to draw.
More colorful version:
And, we can definitely improve the Koch snowflake fractal to make it more detailed and colorful! Here's an updated version of the program that uses color interpolation and increases the level of recursion to create a more intricate and visually interesting fractal:
' Koch Snowflake Fractal with Color Interpolation
' Oxygen Basic, ConsoleG, OpenGL
#compact
%filename "koch_color.exe"
'uses RTL64
% Title "Koch Snowflake Fractal with Color Interpolation"
'% WindowStyle WS_OVERLAPPEDWINDOW
'% Animated
'% ScaleUp
% PlaceCentral
% AnchorCentral
% shaders
uses consoleG
BeginScript
procedure drawLine(float x1, float y1, float x2, float y2, float r1, float g1, float b1, float r2, float g2, float b2) {
float dx = x2 - x1;
float dy = y2 - y1;
float len = sqrt(dx*dx + dy*dy);
float angle = atan2(dy, dx);
float dx2 = len * cos(angle);
float dy2 = len * sin(angle);
float dr = r2 - r1;
float dg = g2 - g1;
float db = b2 - b1;
glBegin(GL_LINES);
for (int i = 0; i <= 1; i++) {
float x = x1 + i * dx2;
float y = y1 + i * dy2;
float r = r1 + i * dr;
float g = g1 + i * dg;
float b = b1 + i * db;
color(r, g, b);
glVertex2f(x, y);
}
glEnd();
}
procedure koch(float x1, float y1, float x2, float y2, int level, float r1, float g1, float b1, float r2, float g2, float b2) {
if (level == 0) {
drawLine(x1, y1, x2, y2, r1, g1, b1, r2, g2, b2);
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);
float r3 = (r1 + 2 * r2) / 3.0;
float g3 = (g1 + 2 * g2) / 3.0;
float b3 = (b1 + 2 * b2) / 3.0;
float r4 = (2 * r1 + r2) / 3.0;
float g4 = (2 * g1 + g2) / 3.0;
float b4 = (2 * b1 + b2) / 3.0;
koch(x1, y1, x3, y3, level-1, r1, g1, b1, r3, g3, b3);
koch(x3, y3, x4, y4, level-1, r3, g3, b3, r4, g4, b4);
koch(x4, y4, x5, y5, level-1, r4, g4, b4, r2, g2, b2);
koch(x5, y5, x2, y2, level-1, r2, g2, b2, r3, g3, b3);
}
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 = 6;
float r1 = 1.0;
float g1 = 0.0;
float b1 = 0.0;
float r2 = 0.0;
float g2 = 1.0;
float b2 = 0.0;
koch(x1, y1, x2, y2, level, r1, g1, b1, r2, g2, b2);
koch(x2, y2, x3, y3, level, r2, g2, b2, r1, g1, b1);
koch(x3, y3, x1, y1, level, r1, g1, b1, r2, g2, b2);
waitkey();
}
EndScript
```
In this version of the program, we've added color interpolation to the `drawLine` procedure, which now takes six additional arguments specifying the RGB values of the start and end colors of the line. The `koch` procedure has also been updated to take these additional color arguments and interpolate the colors between recursive calls.
We've also increased the level of recursion to 6 to create a more detailed fractal, and adjusted the initial RGB values to create a more colorful and visually interesting result.
When you run this program, you should see a colorful and intricate Koch snowflake fractal with smooth color gradations between adjacent lines. You can experiment with different initial RGB values and levels of recursion to create different variations of the fractal.
Use Triangle-thinning:
We can combine the Koch snowflake fractal with the triangle thinning algorithm to create a more complex and interesting script! Here's an example program that does just that:
' Koch Snowflake Fractal with Triangle Thinning
' Oxygen Basic, ConsoleG, OpenGL
' frank bruebach, 12-04-2024
#compact
%filename "koch_triangle.exe"
'uses RTL64
% Title "Koch Snowflake Fractal with Triangle Thinning"
'% WindowStyle WS_OVERLAPPEDWINDOW
'% Animated
'% ScaleUp
% PlaceCentral
% AnchorCentral
% shaders
uses consoleG
BeginScript
procedure drawLine(float x1, float y1, float x2, float y2) {
glBegin(GL_LINES);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glEnd();
}
procedure koch(float x1, float y1, float x2, float y2, int level) {
if (level == 0) {
drawLine(x1, y1, x2, y2);
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);
koch(x3, y3, x4, y4, level-1);
koch(x4, y4, x5, y5, level-1);
koch(x5, y5, x2, y2, level-1);
if (level == 1) {
drawLine(x3, y3, x4, y4);
drawLine(x4, y4, x5, y5);
drawLine(x5, y5, x3, y3);
}
}
procedure thinTriangle(float x1, float y1, float x2, float y2, float x3, float y3, float threshold) {
float dx1 = x2 - x1;
float dy1 = y2 - y1;
float dx2 = x3 - x2;
float dy2 = y3 - y2;
float dx3 = x1 - x3;
float dy3 = y1 - y3;
float len1 = sqrt(dx1*dx1 + dy1*dy1);
float len2 = sqrt(dx2*dx2 + dy2*dy2);
float len3 = sqrt(dx3*dx3 + dy3*dy3);
float midX1 = x1 + 0.5 * dx1;
float midY1 = y1 + 0.5 * dy1;
float midX2 = x2 + 0.5 * dx2;
float midY2 = y2 + 0.5 * dy2;
float midX3 = x3 + 0.5 * dx3;
float midY3 = y3 + 0.5 * dy3;
if (len1 >= threshold && len2 >= threshold && len3 >= threshold) {
drawLine(midX1, midY1, midX2, midY2);
drawLine(midX2, midY2, midX3, midY3);
drawLine(midX3, midY3, midX1, midY1);
thinTriangle(x1, y1, midX1, midY1, midX3, midY3, threshold * 0.5);
thinTriangle(x2, y2, midX2, midY2, midX1, midY1, threshold * 0.5);
thinTriangle(x3, y3, midX3, midY3, midX2, midY2, threshold * 0.5);
}
}
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;
float threshold = 0.01;
koch(x1, y1, x2, y2, level);
koch(x2, y2, x3, y3, level);
koch(x3, y3, x1, y1, level);
thinTriangle(x1, y1, x2, y2, x3, y3, threshold);
waitkey();
}
EndScript
```
In this version of the program, we've combined the Koch snowflake fractal with the triangle thinning algorithm from the previous example. The `koch` procedure is the same as before, but we've added a new `thinTriangle` procedure that recursively subdivides a triangle and thins its edges based on a threshold value.
In the `main` procedure, we first draw the Koch snowflake fractal using the `koch` procedure, and then call the `thinTriangle` procedure to subdivide and thin the edges of the triangle formed by the three outer vertices of the snowflake.
When you run this program, you should see a Koch snowflake fractal with thin, intricate edges that form a complex pattern inside the triangle. You can experiment with different values of the `level` and `threshold` variables to create different variations of the fractal and the thinning pattern.