Welcome to Fractal Forums

Fractal Math, Chaos Theory & Research => IFS - Iterated Function Systems => Topic started by: msltoe on March 16, 2016, 04:46:40 AM




Title: L-system fractals with a twist
Post by: msltoe on March 16, 2016, 04:46:40 AM
I've decided to explore "generative" fractals vs. escape-time because of a particular limitation that escape-time fractals run into.
To best describe this issue, think of a kaleidoscopic fractal, at the first iteration, space is partitioned. At the next iteration, space is partitioned further.
Without some really fancy partitioning scheme, the partitions are going to be simple, geometric, tilings (e.g. pyramids, cubes)
This somewhat prevents us from exploring more natural type objects such as trees, where branches may intertwine or at least
run into each other in seemingly arbitrary places.

If any of you want details of my L-system program, I can provide the source code here. The program is not too long (certainly less KB than an image). But basically, I'm making a trees of spheres, where each branching point adds in some rotations. Furthermore - and this is common, rotations are added in proportion to the angle of the branch from the Y-axis. The spheres are rendered with a simple but fast ray-tracing program called Tachyon  http://jedi.ks.uiuc.edu/~johns/raytracer/

Here is a more elaborate example of what I've been to generate so far. I think there's quite a bit to explore. The one caveat is that it won't be plug@play into the popular Mandelbulb codes, but others should be able to get up and running without too much effort.

(http://nocache-nocookies.digitalgott.com/gallery/18/803_16_03_16_4_31_59.png)


Title: Re: L-system fractals with a twist
Post by: mclarekin on March 17, 2016, 05:09:26 AM
I would be very interested to see your code :) To advance my knowledge of other types of fractals.


Title: Re: L-system fractals with a twist
Post by: msltoe on March 17, 2016, 05:26:12 AM
The same "program" can make something similar to Romanesco broccoli:
(http://nocache-nocookies.digitalgott.com/gallery/18/803_17_03_16_5_22_06.png)


Title: Re: L-system fractals with a twist
Post by: msltoe on March 19, 2016, 07:30:25 PM
Same program, different function calls:
(http://nocache-nocookies.digitalgott.com/gallery/18/803_19_03_16_7_23_18.png)

Here's the code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

double pi = 3.1415926535;
struct point {
 double x;
 double y;
 double z;
};

struct quaternion {
 double a;
 double b;
 double c;
 double d;
};

quaternion div (quaternion q1, double r){

 quaternion s =
        {q1.a/r,q1.b/r,q1.c/r,q1.d/r};

 return(s);
}

quaternion add(quaternion q1, quaternion q2){

 quaternion s =
        {q1.a+q2.a,
         q1.b+q2.b,
         q1.c+q2.c,
         q1.d+q2.d};

 return(s);
}

quaternion mult(quaternion q1, quaternion q2){

 quaternion s =
        {q1.a*q2.a-q1.b*q2.b-q1.c*q2.c-q1.d*q2.d,
         q1.a*q2.b+q2.a*q1.b+q1.c*q2.d-q1.d*q2.c,
         q1.a*q2.c-q2.d*q1.b+q1.c*q2.a+q1.d*q2.b,
         q1.a*q2.d+q2.c*q1.b-q1.c*q2.b+q1.d*q2.a};

 return(s);

}

quaternion inv(quaternion q){

 double r = q.a*q.a+q.b*q.b+q.c*q.c+q.d*q.d;
// if (r<0.001) {r=0.001;}
 quaternion s = {q.a/r,-q.b/r,-q.c/r,-q.d/r};
 return(s);

}

double norm(quaternion q){

 double r = q.a*q.a+q.b*q.b+q.c*q.c+q.d*q.d;
 if (r > 0.0001)
 return(sqrt(r));
 else
 return(1);
}

int iterate(point p,
            point shift,
            double r, double scale, quaternion q,
            point shift0,
            FILE *f1, int depth, int ctr) {

 int DEPTH_MAX = 1000;
 double minrad = 0.0025;//25;
 point p1;

 quaternion q1,q2,q3,q4;

 double c5 = cos(((double) depth) * pi/8);
 double s5 = sin(((double) depth) * pi/8);

 q1 = {0.0,shift0.x,shift0.y,shift0.z}; // original branch
 q2 = {0.0,shift.x,shift.y,shift.z}; // next branch

 double cosine =
(shift.x*shift0.x+
 shift.y*shift0.y+
 shift.z*shift0.z)/(norm(q1)*norm(q2));

 // cross-product
 q1.a = 0.0;
 q1.b = shift0.y*shift.z-shift0.z*shift.y;
 q1.c = shift0.z*shift.x-shift0.x*shift.z;
 q1.d = shift0.x*shift.y-shift0.y*shift.x;
 q1 = div(q1,norm(q1));

 double theta = acos(cosine);
 //printf("theta = %f\n",theta);
 if (fabs(theta)>-0.0001) {
  double s =   sin(theta*0.5);
  q2 = {cos(theta*0.5),s*q1.b,s*q1.c,s*q1.d};

  // rotate shift to reference frame
  q1 = {0,shift.x,shift.y,shift.z};
  q4 = mult(q,mult(q1,inv(q)));
 } else {
  q4 = q1;
 }
 point shift1 = {q4.b,q4.c,q4.d};

 p1.x = p.x + shift1.x*scale;
 p1.y = p.y + shift1.y*scale;
 p1.z = p.z + shift1.z*scale;

 double r1 = r*scale;

 // rotate reference frame
 q = mult(q,q2);

 fprintf(f1,"%s %f %f %f %s %f %s%d\n",
        "sphere center",
        p1.x,p1.y,p1.z,
        "rad",
        r1, "t",1+(ctr % 7));

 if ((depth < DEPTH_MAX)&&(r1>minrad)) {

  double y1,z1;
  quaternion q1 = q;

  q3 = q;

  shift = {0,1,0};
  double factor = 0.3;
  point s1;
  q2 = {c5,0,s5,0};

  s1 = {0.15,0.3,0.025};
  double t  = iterate(p1,s1,r,scale*0.9,q3,shift,f1,depth+1,ctr+1);

  s1 = {-0.7,0,0};
  q1 = {0.0,s1.x,s1.y,s1.z};
  q4 = mult(q2,mult(q1,inv(q2)));
  s1 = {q4.b,q4.c,q4.d};
  double t1  = iterate(p1,s1,r,scale*factor,q3,shift,f1,depth+1,ctr);

  s1 = {+0.7,0.0,0.0};
  q1 = {0.0,s1.x,s1.y,s1.z};
  q4 = mult(q2,mult(q1,inv(q2)));
  s1 = {q4.b,q4.c,q4.d};
  double t5 = iterate(p1,s1,r,scale*factor,q3,shift,f1,depth+1,ctr);

  s1 = {0.0,0.0,-0.7};
  q1 = {0.0,s1.x,s1.y,s1.z};
  q4 = mult(q2,mult(q1,inv(q2)));
  s1 = {q4.b,q4.c,q4.d};
  double t6 = iterate(p1,s1,r,scale*factor,q3,shift,f1,depth+1,ctr);

  s1 = {0.0,0,+0.7};
  q1 = {0.0,s1.x,s1.y,s1.z};
  q4 = mult(q2,mult(q1,inv(q2)));
  s1 = {q4.b,q4.c,q4.d};
  double t7 = iterate(p1,s1,r,scale*factor,q3,shift,f1, depth+1,ctr);

 }

}

int main() {

 FILE *f1;
 f1 = fopen("temp.dat","w");
 
 point P = {0,-0.35,0};
 point S = {0,0.1,0};
 double c = cos(pi/15);
 double s = sin(pi/15);
 quaternion q = {c,0,s,0};
 quaternion q2 = {c,s,0,0};

// q = mult(q,q2);

 iterate(P,S,0.2,1.0,q,{0,1,0},f1,0,3);

 fclose(f1);

 system("cat header.dat temp.dat > temp2.dat");
 system("./tachyon temp2.dat");
 system("gimp outfile.tga");
}
           


Title: Re: L-system fractals with a twist
Post by: mclarekin on March 19, 2016, 11:30:29 PM
Thanks for posting code. :) Now the fun begins with trying to get my head around it all ;D



Title: Re: L-system fractals with a twist
Post by: msltoe on March 20, 2016, 12:38:45 AM
@mclarekin: The general idea is that I'm calling a function recursively. The function always outputs one sphere, then calls the function several times to make a bunch of branches.

The "q"s are quaternions. Quaternions rotate space using angle/axis. The axis is specified by the last three numbers. The angle is encoded by cosine of the angle for the first number, and the sine of the angle multiplied by the three axis numbers. Rotations are computed as x' = qxq^-1. Quaternions can be combined like rotations q3 = q1 * q2;
The one crazy thing I'm doing which escape time fractals do for free, is rotating the reference frame so that the direction of each branch becomes the new y-axis. This is the part where I have to compute a cross-product and a dot product.

Even without knowledge of how the code works at first, you should be able to compile and generate a sphere file - commenting out the system calls at the end. Oh and gnu-C requires a special flag to handle my { } notations. The compilation error will show you what that flag is.

Good luck!


Title: Re: L-system fractals with a twist
Post by: KRAFTWERK on March 26, 2016, 11:42:31 AM
You come up with the most beautiful ideas msltoe!  That first image is crazy!  :alien:
I understand now it might be hard to implement in MB3D (?)


Title: Re: L-system fractals with a twist
Post by: msltoe on March 26, 2016, 01:22:22 PM
KRAFTWERK: You remember when the Mandelbulb first came out in 2010? There weren't any easy-to-use programs to render it.
I guess the same thing could be said with my new fractals. They aren't escape-time like the Mandelbulb/Mandelbox.
I'm using two programs: a sphere list maker (that I posted above) and a ray-tracing program.
I suppose it will be up to interest from the community to make my new creations more accessible.


Title: Re: L-system fractals with a twist
Post by: msltoe on March 28, 2016, 04:22:57 AM
Here's another surreal one:
(http://i.imgur.com/aHGCKA2.png)


Title: Re: L-system fractals with a twist
Post by: KRAFTWERK on March 28, 2016, 10:57:17 AM
KRAFTWERK: You remember when the Mandelbulb first came out in 2010? There weren't any easy-to-use programs to render it.
I guess the same thing could be said with my new fractals. They aren't escape-time like the Mandelbulb/Mandelbox.
I'm using two programs: a sphere list maker (that I posted above) and a ray-tracing program.
I suppose it will be up to interest from the community to make my new creations more accessible.


I suspected that... I'll include your hint from the gallery here msltoe, in case someone with the skills read it... :

"It should be possible to do Julia set roots in an escape time framework. In fact my old escapetime fractal program made similar pictures like this one. Note to fractal program developers: the key is to switch formulas when r = x*x+y*y+z*z is below a certain threshold."

I love that last image ^^^ :beer:


Title: Re: L-system fractals with a twist
Post by: msltoe on April 10, 2016, 06:17:46 PM
I animated the growth of a Romanesco-like fractal:

https://www.youtube.com/watch?v=E9kPX5I5gWg (https://www.youtube.com/watch?v=E9kPX5I5gWg)


Title: Re: L-system fractals with a twist
Post by: Chillheimer on April 10, 2016, 08:05:34 PM
hehe, just upvoted it on reddit and thought that username sounds familiar.. ;)
nicely done!


Title: Re: L-system fractals with a twist
Post by: msltoe on April 10, 2016, 11:08:57 PM
Thanks Chillheimer. I must be spamming the Internet fractal haunts :)
-michael