I left off with two nice pictures that used a bit more complex fold functions. So, a natural question is, what other functions can we use? In the backing programming language I added some functions that represent graph primitives. These functions are “circle(center, radius, point)”, “line(p1, p2, point)” and “box(lu, rl, point)”. “line” is a line through p1 and p2, “box” ist the rectangle with left upper corner lu and right lower corner rl. The functions return the distance of “point” from these graphic primitives. You can use the complex-function preset to visualize them. For “min(circle(1:0, 1, c), box(-1.5:1, -0.5:0, c), line(-1:-1, 0:-1.5, c))” you obtain the following function plot:

What happens if we use these primitives in the fold preset? First, remember that the function that we sum up in fold should converge to 0 if z increases to obtation a continuous gradient. So, let’s use the reciprocate of the distance from a primitive, and let’s start our experiment with a box: foldfn is “/box(-2:-1.5, 2:1.5, znext) + foldvalue” and the result is the following:

Simple and astonishing results.

In the next one I used a simple line. It is a zoom into the seahorse valley.

So, there is a lot of room for experiments to combine boxes with circle and lines. For the green antenna image on DeviantArt I used one simple circle btw, apart from that, no magic.

In the third part I will show you how to make even more use of this by using different bailoutvalues (I will definitely rename that to bailoutheigth in some future release) than bailouttransfers. Good night and finally, the code of this final picture.

{ "scale": [ 1.5967631071452336E-5, 4.3266139225037626E-4, -4.3266139225037626E-4, 1.5967631071452336E-5, -0.7429302714898326, -0.1277124882391435 ], "source": [ "\/\/ Fold", "var x int, y int, color int;", "", "", "extern maxdepth int = 120;", "", "\/\/ some further arguments", "extern juliaset bool = false;", "extern juliapoint cplx =-0.8:0.16;", "", "\/\/ c: coordinates, breakcondition: a function whether we should stop,", "\/\/ value: a real variable to return some kind of value", "\/\/ used in 3d-types for the height.", "\/\/ returns a quat representing the color", "func escapetime(c, breakcondition) {", " var i int = 0,", " p cplx = juliapoint if juliaset else c,", " zlast cplx = 0,", " z cplx,", " znext cplx = 0;", "", " extern mandelinit expr = \"0\";", "", " z = c if juliaset else mandelinit;", "", " extern function expr = \"mandelbrot(z, p)\";", "", " var color quat;", "", " while {", " znext = function;", " not breakcondition(i, znext, z, zlast, c, p, color)", " } do {", " \/\/ advance to next values", " zlast = z;", " z = znext;", " }", "", " \/\/ return color", " color", "}", "", "\/\/ everything that is drawn must have a get_color-function.", "", "\/\/ c = coordinates (scaled)", "\/\/ value is a real variable for z-information in 3D", "\/\/ but also otherwise convenient to separate drawing", "\/\/ algorithm from transfer", "\/\/ returns color.", "func get_color(c, value) {", "", " \/\/ if the fractal accumulates some values", " \/\/ like in traps or addends, here is a got place to do it.", " extern foldinit expr = \"0\";", " var foldvalue cplx = foldinit;", "", " func breakcondition(i, znext, z, zlast, c, p, color) {", "", " extern foldfn expr = \"\/cosh rad znext + foldvalue\";", "", " func bailoutcolor() {", " extern bailout real = 65536;", " extern max_power real = 2; \/\/ just for compatibility", "", " \/\/ the next ones are only used in 3d-fractals", " extern bailoutvalue expr = \"log(1 + foldvalue.x)\";", " value = bailoutvalue ;", "", " extern bailouttransfer expr = \"value\";", "", " extern bailoutpalette palette = [", " [#0f8, #080, #ff8, #f80, #f20, #008]];", "", " color = bailoutpalette bailouttransfer", " }", "", " func lakecolor() {", " extern epsilon real = 1e-9;", "", " \/\/ the next ones are only used in 3d-fractals", " extern lakevalue expr = \"log(1 + rad znext)\";", " value = lakevalue;", "", " extern laketransfer expr = \"arcnorm znext : value\";", "", " extern lakepalette palette = [", " [#000, #000, #000, #000, #000, #000],", " [#0f8, #080, #ff8, #f80, #f20, #008],", " [#4fa, #3a3, #ffa, #fa3, #f63, #33a],", " [#fff, #fff, #fff, #fff, #fff, #fff]];", "", " color = lakepalette laketransfer", " }", "", " { lakecolor() ; true } if not next(i, maxdepth) else", " true if radrange(znext, z, bailout, epsilon, bailoutcolor(), lakecolor()) else", " { foldvalue = foldfn; false }", " }", "", " escapetime(c, breakcondition)", "}", "", "", "\/\/ ******************************************", "\/\/ * Next are just drawing procedures. They *", "\/\/ * should be the same for all drawings. *", "\/\/ ******************************************", "", "extern supersampling bool = false;", "extern light bool = false;", "", "\/\/ drawpixel for 2D", "func drawpixel_2d(x, y) {", " var c cplx = map(x, y);", " var value real;", " get_color(c, value) \/\/ value is not used", "}", "", "\/\/ drawpixel for 3D", "func drawpixel_3d(x, y) {", " var c00 cplx = map(x, y),", " c10 cplx = map(x + 1, y + 0.5),", " c01 cplx = map(x + 0.5, y + 1);", "", " var h00 real, h10 real, h01 real; \/\/ heights", "", " \/\/ color is already kinda super-sampled", " var color = (get_color(c00, h00) + get_color(c10, h10) + get_color(c01, h01)) \/ 3;", "", " \/\/ get height out of value", " func height(value) {", " extern valuetransfer expr = \"value\";", " valuetransfer", " }", "", " h00 = height h00; h01 = height h01; h10 = height h10;", "", " \/\/ get the normal vector (cross product)", " var xp = c10 - c00, xz = h10 - h00;", " var yp = c01 - c00, yz = h01 - h00;", "", " var np cplx = (xp.y yz - xz yp.y) : (xz yp.x - xp.x yz);", " var nz real = xp.x yp.y - xp.y yp.x;", "", " \/\/ normalize np and nz", " var nlen = sqrt(rad2 np + sqr nz);", " np = np \/ nlen; nz = nz \/ nlen;", "", " \/\/ get light direction", " extern lightvector cplx = -0.667 : -0.667; \/\/ direction from which the light is coming", " def lz = sqrt(1 - sqr re lightvector - sqr im lightvector); \/\/ this is inlined", "", " \/\/ Lambert's law.", " var cos_a real = dot(lightvector, np) + lz nz;", "", " \/\/ diffuse reflexion with ambient factor", " extern lightintensity real = 1;", " extern ambientlight real = 0.5;", "", " \/\/ if lumen is negative it is behind,", " \/\/ but I tweak it a bit for the sake of the looks:", " \/\/ cos_a = -1 (which is super-behind) ==> 0", " \/\/ cos_a = 0 ==> ambientlight", " \/\/ cos_a = 1 ==> lightintensity", "", " \/\/ for a mathematically correct look use the following:", " \/\/ if cos_a 0 then", " color.a = color.a + 100 * specularintensity * spec_refl ^ shininess;", "", " color", "}", "", "func do_pixel(x, y) {", " \/\/ two or three dimensions?", " def drawpixel = drawpixel_3d if light else drawpixel_2d;", "", " func drawaapixel(x, y) {", " 0.25 (", " drawpixel(x - 0.375, y - 0.125) +", " drawpixel(x + 0.125, y - 0.375) +", " drawpixel(x + 0.375, y + 0.125) +", " drawpixel(x - 0.125, y + 0.375)", " );", " }", "", " \/\/ which function to apply?", " def fn = drawpixel if not supersampling else drawaapixel;", "", " color = lab2int fn(x, y)", "}", "", "\/\/ and finally call the draing procedure", "do_pixel(x, y)" ], "arguments": { "ints": { "maxdepth": 1200 }, "cplxs": { "lightvector": [ 0.667, -0.667 ] }, "exprs": { "valuetransfer": "value\/999", "lakevalue": "0", "foldfn": "\/line(1:1, 0:0, znext) + foldvalue", "bailoutvalue": "log(5 + foldvalue.x)" }, "bools": { "light": true }, "palettes": { "bailoutpalette": { "height": 1, "width": 8, "colors": [ -16711621, -15, -1, -7783841, -4426, -12713896, -7143390, -1074 ] } } } }

Pingback: Fractview Release of 3.2.2, DeviantArt-Group and perspectives | Fractview for Android

Hey Karl thanks so much for making this. I just started playing around with your app on my galaxy and I LOVE IT! More so then others on the app store. Still a steep learning curve for me since I am not good at math…loll I would like to know if you can help with to create the seahorse valley photo above, I really like that? Thanks,

Anthony

LikeLike