Writing Ultra Fractal Calculation Formulas

Instructor: Kerry Mitchell

Lesson 5: Other Formula Types


Pixel

Sometimes, what we want to do in an image isn't really cut out for an iterative formula. Or maybe we need to have more information for the coloring formula than we can pass through the z variable. In these cases, we can use a Pixel formula. These formulas essentially just move the action from the calculation formula to the coloring formula. They are simple enough that we won't concentrate on writing them. If you need a Pixel formula, here are a few to try:


Non-Escaping Formulas

Many iterative formulas neither escape to infinity or to a final answer. An example is the Popcorn algorithm, in which two complex variables (a and b) are related:

an+1 = an – real(0.01 sin(bn + tan(3bn))) – imag(0.01 sin(an + tan(3an)))
bn+1 = bn – real(0.01 sin(an + tan(3an))) – imag(0.01 sin(bn + tan(3bn)))

(If you know calculus, this is similar to a discrete integration of a nonlinear differential equation. If you don’t know calculus, this is similar to “blah, blah, blah.”)

Because of the construction of the equations, a and b very rarely get large. Instead, they wander around the complex plane chaotically. Typically, this kind of formula is used to make an image by counting how many times one of the variables lands on a particular pixel or according to some characteristic of one of the variables.

Regardless of the coloring, this formula has some similarities with more traditional fractal formulas, in that variables are initialized and iterated. Two major differences are the z variable and the bailout condition. There’s no one best choice for z. Some possibilities are:

What others can you come up with?

Since neither a nor b get very large, there’s no bailout per se. Of course, you are free to write any bailout condition you wish, but how do you force the formula to run until the maximum iterations for every pixel? Since the Bailout section evaluates the truth of a logical statement, all we need to do is come up with a logical statement that is always true. That way, the iterating will never stop early. A couple of ways to do this are:

Another area of non-escaping formulas is the scientific simulation variety. Many problems of interest to scientists are dynamical in nature, that is, watching the evolution in time of some phenomenon. Calculations of these problems are often carried out in which time is broken down into discrete steps. If the time step is small enough, then the calculations can simulate continuous time. It turns out that simple versions of such problems can be implemented in UF, by writing appropriate formulas and having each iteration be a step in time. An example of this is my simulation of vortical flow, which you can read about here.

Other problems are relatively easily modeled using Ultra Fractal, for example, the gravitational field between multiple stars (Gravity 2, -3, and -4 in lkm.ufm) or the chaotic bouncing of a ball on an oscillating piston head (Piston in lkm.ufm). Quite often, these formulas allow for great flexibility in implementation (read: not easy to write), and generally require many iterations.


Embossing and Lighting

Other types of formulas may be escape-time or of another kind, written to be used with specific coloring formulas. A prime example of this is an embossing formula. Embossing formulas are named for the effect that you might see with embossed paper (like from the seal of a Notary Public); the color doesn’t change, but the shadows and highlights indicate depth. Some sample embossed images are shown in Figure 11.


Mandelbrot

Fouth-Order Newton
Figure 11: Examples of Emboss Fractals with Emboss Coloring

The embossed effect can be approximated through a judicious use of layering, but is best done through an embossing formula in conjunction with the Embossed coloring (in lkm.ucl or standard.ucl). The basic structure of an embossed escape-time formula is:

  1. Initialize two variables, each slightly different from, and on opposite sides of, the actual pixel value.
  2. Iterate the escape-time function as normal for each variable.
  3. Color by the difference between the number of iterations to bailout for the first variable and the number of iterations to bailout for the second variable:
    • black if the first is less than the second
    • gray if both counts are the same
    • white if the first is more than the second
Of course, this basic scheme can be modified greatly, for example, using the number of times the real part is positive. The key is to have a quantity that can be quantized into discrete levels (integer values instead of floating point values). You wouldn’t typically use a continuous quantity like the magnitude, because, in practice, the two magnitudes would never be equal. In such cases, you could round the quantity, which would then make it into an integer value.

Another series of such formulas is the Slope (Mandelbrot, Julia, or Newton) formulas by Damien Jones in dmj.ufm and standard.ufm. Here, three points are iterated for each pixel and then are used to create a three-dimensional surface. A vector perpendicular to that surface is used as the z variable and is passed to the coloring routine. When a Slope formula is used with the Lighting coloring, the result resembles a fractal surface being illuminated from above and to the side. Examples of Slope-Lighting images are shown in Figure 12.


Mandelbrot

Fouth-Order Newton
Figure 12: Examples of Slope Fractals with Lighting Colorin

Naturally, when you create a formula like one of these that iterates multiple points per pixel, the calculation time increases accordingly.


Homework

  1. Create a formula that implements the Popcorn algorithm. Replace the constants of 0.01 and 3 with user-specified parameters. Replace the sin() function with a choice of sin(), cos(), or tan(). Replace the tan() function with a user-specified function. Use an enumerated parameter for the choice of z, with at least four choices: z = a, z = b, and two of your own choosing.
  2. Add embossing to your Cubic Connectedness Locus Mandelbrot formula. Feel free to study any of the embossing formulas in lkm.ufm for guidance.
  3. (Extra!) Implement the non-linear oscillator formula (see below). Allow the pixel value to be used as: time step, initial position, initial velocity, As, ns, Ad, or nd, through an enumerated parameter. Have the user input the rest. Use the “visible” feature to hide the parameter input that is handled by the pixel value. Allow z to be the final position, velocity, or acceleration. Don’t worry about understanding the physics or numerical analysis if you don’t already. Concentrate on programming the formulas.

Non-Linear Oscillator

In the standard linear harmonic oscillator, a weight hangs on the end of a spring. The weight either has an initial position away from the equilibrium point, or an initial velocity, or both. The force in the spring is proportional to how much the spring is stretched or compressed from the equilibrium point and is directed opposite of the position (so if the weight is pushed up, the spring pushes down). Without friction, the weight would bob up and down indefinitely. Typically, a dampening (friction) force is added, whose magnitude is proportional to the speed of the weight, and whose direction opposes the velocity, so that it always acts to slow the motion. In this problem, we’re going the make the spring force vary with the stretch or compression to some power, and the dampening force vary with a power of the velocity. To deal with the velocity and acceleration of the weight, we’re going to use the position at different points in time. Each iteration of the formula corresponds to one step forward in time.

The equations to be implemented are:

Initialization:

  1. Set the position (z0) to the desired initial position.
  2. Set the velocity to the desired initial velocity.
  3. Determine the next position (z1) by using the velocity:
    z1 = z0 + velocity × time step.
Loop:
  1. Find the portion of the weight’s acceleration due to the spring:
    spring = As × (z1 ^ ns)
  2. Find the weight’s velocity:
    velocity = (z1 – z0) ÷ time step
  3. Find the portion of the weight’s acceleration due to the dampening:
    dampening = Ad × (velocity ^ nd)
  4. Find the total acceleration:
    acceleration = spring + dampening
  5. Find the position at the next time step:
    z2 = acceleration × (time step)2 - z0 + 2z1
  6. Update the previous positions:
    z0 = z1, z1 = z2
Bailout:

Copyright 2007 Kerry Mitchell