Fractals/Iterations in the complex plane/triangle ineq

algorithm for coloring exterior of the set ( Mandelbrot or Julia)

TIA

Names

edit

family of algorithms : Branching Average Coloring Algorithms (" because calculate an average of a function evaluated at all points in a truncated orbit ")[1]

  • the Triangle Inequality Average Coloring algorithm = TIA = Trippie. " linear interpolation and was designed for the Mandelbrot set. Discontinuous at some points that are mapped to zero"
  • Curvature Average Coloring Algorithm ( developed by Damien M. Jones for Ultra Fractal in 1999, continuous at points that are mapped to zero )

Variants

edit
  • Fibers coloring method ( from Jux program) : " First, I prefer a running average with a weight parameter (0 - 0.999), which avoids any possible precision issues and lets you adjust detail. Second, I use sin or cos instead of the plain angle, and add a frequency parameter. And some other variations" xenodreambuie

History

edit
  • Kerry Mitchell 1999.02.05
  • Damien M. Jones 2000.04.02

Explanation

edit

"The triangle inequality is basically a cheap way to calculate an angle. TIA is averaging the angle over all iterations to get a smooth result. So there is some initialization and some calculations per iteration to do the sum. It has to store the sum at the previous iteration before adding the next one so you can interpolate between them to get a continuous function between iteration bands (in the same way that continuous potential is usually interpolated). This interpolation is done after the iterations bail out." xenodreambuie [2]

"creates smoothly colored ... large flame-like patterns that extend from the fractal outwards" (from UltraFractal by Frederik Slijkerman )[3]

Parameters

edit
  • escape radius : "Use very large bail-out values (1E20 = 10^20)) for good results." Ultra Fractal
  • iteration Max = 2500

Software

edit

Examples

edit

Code

edit

Ultrafractal

edit
/* 
http://formulas.ultrafractal.com/

comment {
  dmj-pub.ucl 2.1
  Coloring methods for Ultra Fractal 2
  by Damien M. Jones
  April 2, 2000

  For more information about this formula collection,
  please visit its home page:
  
      http://www.fractalus.com/ultrafractal/dmj-pub-uf.htm

  Many of these coloring algorithms are general-purpose tools
  which work with a variety of fractals. A few are more
  specialized. Huge portions of this compilation build upon
  the techniques explored by others.
}
*/
dmj-Triangle {
;
; This coloring method implements a variation of Kerry
; Mitchell's Triangle Inequality Average coloring
; method.  Because the smoothing used in this formula
; is based on the dmj-Smooth formula, which only works
; for z^n+c and derivates, the smoothing here will only
; work for those types as well.
;
init:
  float sum = 0.0
  float sum2 = 0.0
  float ac = cabs(#pixel)
  float il = 1/log(@power)
  float lp = log(log(@bailout)/2.0)
  float az2 = 0.0
  float lowbound = 0.0
  float f = 0.0
  BOOL first = true
  float ipower = 1/@apower

loop:
  sum2 = sum
  IF (!first)
    az2 = cabs(#z - #pixel)
    lowbound = abs(az2 - ac)
    IF (@aflavor == 0)
      sum = sum + ((cabs(#z) - lowbound) / (az2+ac - lowbound))^@apower
    ELSEIF (@aflavor == 1)
      sum = sum + 1-(1-(cabs(#z) - lowbound) / (az2+ac - lowbound))^ipower
    ENDIF
  ELSE
    first = false
  ENDIF

final:
  sum = sum / (#numiter)
  sum2 = sum2 / (#numiter-1)
  f = il*lp - il*log(log(cabs(#z)))
  #index = sum2 + (sum-sum2) * (f+1)
  
default:
  title = "Triangle Inequality Average"
  helpfile = "dmj-pub\dmj-pub-uf-tia.htm"

  param apower
    caption = "Average Exponent"
    default = 1.0
    hint = "This skews the values averaged by raising them to \
            this power. Use 1.0 for the classic coloring."
  endparam
  param aflavor
    caption = "Average Flavor"
    default = 0
    enum = "normal" "reversed"
    hint = "Controls whether values are reversed before being \
            raised to a power. Has no effect if Average Exponent \
	    is 1.0."
  endparam
  param power
    caption = "Exponent"
    default = 2.0
    hint = "This should be set to match the exponent of the \
            formula you are using.  For Mandelbrot, this is 2."
  endparam
  param bailout
    caption = "Bailout"
    default = 1e20
    min = 1
    hint = "This should be set to match the bailout value in \
            the Formula tab.  Use a very high bailout!"
  endparam
}
// http://www.kerrymitchellart.com/tutorials/formulas2/uf2-2.htm
// http://formulas.ultrafractal.com/cgi/formuladb?view;file=lkm.ufm;type=.txt
comment { ; copyright Kerry Mitchell 07feb99

Triangle Inequality

The triangle inequality method is based on a simple characteristic of
complex numbers:  the magnitude of the sum of two complex numbers, |a+b|,
is strictly limited to a range determined by a and b:

|a+b| >= ||a| - |b||, and
|a+b| <= |a| + |b|,

where |z| is the square root of the sum of the squares of the
components, not the sum of the squares, as in Ultra Fractal.  The
extremes of this inequality are easily seen with a few examples.
If a=1 and b=2, then:

|a| = 1, |b| = 2;
||a| - |b|| = |1-2| = |-1| = 1;
|a| + |b| = 1+2 = 3;
|a+b| = |3| = 3;
1 <= 3 <= 3.

The upper bound occurs when both addends have the same polar angle.
The geometric interpretation of this is that the complex numbers add
up, and the length of the sum is simply the sum of the individual
lengths.

The lower bound occurs when the polar angles of the complex numbers
differ by 180 degrees; the two numbers are diametrically opposed.
Then, the length of the sum is the difference of the lengths.  For
example, if a=3i and b=-5i, then:

|a| = 3, |b| = 5;
||a| - |b|| = |3-5| = |-2| = 2;
|a| + |b| = 3 + 5 = 8;
|a+b| = |-2i| = 2;
2 <= 2 <= 8.

In general, the length of the sum is somewhere inbetween, and can be
thought of in terms of a triangle, which is how the inequality gets
its name.  If |a| is the length of one side of a triangle, and |b|
is the length of the second side, then |a+b| is the length of the
third side, and lies somewhere within the range shown above.

Back to fractals.  The two numbers of interest are z^n and c.  Given
z (the previous iterate) and c (the Mandelbrot or Julia parameter),
the range for the magnitude of the new iterate can then be determined.
With this range, the magnitude of the new iterate can be rescaled to
a fraction between 0 and 1 inclusive:

min = ||z_old| - |c||, max = |z_old| + |c|,
z_new = z_old * z_old + c
fraction = (|z_new| - min) / (max - min).

During the iterating, these fractions are average together.  After the
last iteration, this average fraction is stored in the real part of z,
and the actual fraction for the last iteration is stored in the imaginary
part of the z.  If the orbit diverges (bails out), then renormalization
techniques are used to color the outside pixels smoothly without iteration
bands.  This works best with large bailout values.  The large bailout
needs to be reduced with larger exponents, to prevent color gaps due to
overflow errors.

For best results, use the "basic" coloring method, with "real(z)" to show
the average triangulation fraction, or "imag(z)" to show the actual
fraction for the last iteration.

}

triangle-general-julia { ; Kerry Mitchell 05feb99
;
; z^n+c Julia set, colors by
; triangle inequality
;
init:
  zc=#pixel
  c=@julparam
  float rc=cabs(c)
  float rzc=0.0
  zn=(0.0,0.0)
  float rnz=0.0
  int iter=0
  bool done=false
  float logn=log(@nexp)
  float llbail=log(log(@bailout))+log(0.5)
  float count=0.0
  float count1=0.0
  float count2=0.0
  float countx=0.0
  float county=0.0
  float fac1=0.0
  float fac2=0.0
  float min=0.0
  float max=0.0
  float k=0.0
  float kfrac=0.0
loop:
  iter=iter+1
  if(@nexp==2.0)
    zn=sqr(zc)
    rnz=|zc|
  else
    zn=zc^@nexp
    rnz=cabs(zn)
  endif
  zc=zn+c
  min=cabs(rnz-rc)
  max=rnz+rc
  rzc=cabs(zc)
  county=(rzc-min)/(max-min)
  count=count+county
  countx=count/iter
  z=countx+flip(county)
  if(|zc|>@bailout)
    done=true
    count1=count/iter
    fac1=log(log(rzc))-llbail
    iter=iter+1
    if(@nexp==2.0)
      zn=sqr(zc)
      rnz=|zc|
    else
      zn=zc^@nexp
      rnz=cabs(zn)
    endif
    min=cabs(rnz-rc)
    max=rnz+rc
    zc=zn+c
    rzc=cabs(zc)
    county=(rzc-min)/(max-min)
    count=count+county
    count2=count/iter
    fac2=log(log(rzc))-llbail-logn
    k=exp((fac1+fac2)/2.0)
    kfrac=(k-1.0)/(@nexp-1.0)
    countx=kfrac*count1+(1.0-kfrac)*count2
    z=countx+flip(county)
  endif
bailout:
  done==false
default:
  title="Triangle General Julia"
  maxiter=100
  periodicity=0
  center=(0.0,0.0)
  magn=1.0
  angle=0
  param julparam
    caption="Julia parameter"
    default=(1.0,0.0)
  endparam
  param bailout
    caption="bailout value"
    default=1000000.0
    min=0.0
  endparam
  param nexp
    caption="exponent"
    default=2.0
    hint="z exponent, > 1.0"
    min=1.0
  endparam
switch:
  type="triangle-general-mandelbrot"
  bailout=bailout
  nexp=nexp
}

triangle-general-mandelbrot { ; Kerry Mitchell 05feb99
;
; z^n+c Mandelbrot set, colors by
; triangle inequality
;
init:
  c=#pixel
  zc=@manparam+c
  float rc=cabs(c)
  float rzc=0.0
  zn=(0.0,0.0)
  float rnz=0.0
  int iter=0
  bool done=false
  float logn=log(@nexp)
  float llbail=log(log(@bailout))+log(0.5)
  float count=0.5
  float count1=0.0
  float count2=0.0
  float countx=0.0
  float county=0.0
  float fac1=0.0
  float fac2=0.0
  float min=0.0
  float max=0.0
  float k=0.0
  float kfrac=0.0
loop:
  iter=iter+1
  if(@nexp==2.0)
    zn=sqr(zc)
    rnz=|zc|
  else
    zn=zc^@nexp
    rnz=cabs(zn)
  endif
  zc=zn+c
  min=cabs(rnz-rc)
  max=rnz+rc
  rzc=cabs(zc)
  county=(rzc-min)/(max-min)
  count=count+county
  countx=count/iter
  z=countx+flip(county)
  if(|zc|>@bailout)
    done=true
    count1=count/iter
    fac1=log(log(rzc))-llbail
    iter=iter+1
    if(@nexp==2.0)
      zn=sqr(zc)
      rnz=|zc|
    else
      zn=zc^@nexp
      rnz=cabs(zn)
    endif
    min=cabs(rnz-rc)
    max=rnz+rc
    zc=zn+c
    rzc=cabs(zc)
    county=(rzc-min)/(max-min)
    count=count+county
    count2=count/iter
    fac2=log(log(rzc))-llbail-logn
    k=exp((fac1+fac2)/2.0)
    kfrac=(k-1.0)/(@nexp-1.0)
    countx=kfrac*count1+(1.0-kfrac)*count2
    z=countx+flip(county)
  endif
bailout:
  done==false
default:
  title="Triangle General Mandelbrot"
  maxiter=100
  periodicity=0
  center=(0.0,0.0)
  magn=1.0
  angle=0
  param manparam
    caption="Mandelbrot start"
    default=(0.0,0.0)
    hint="use (0,0) for standard Mandelbrot"
  endparam
  param bailout
    caption="bailout value"
    default=1000000.0
    min=0.0
  endparam
  param nexp
    caption="exponent"
    default=2.0
    hint="z exponent, > 1.0"
    min=1.0
  endparam
switch:
  type="triangle-general-julia"
  julparam=pixel
  bailout=bailout
  nexp=nexp
}

from dmj.ucl:

comment {
  dmj-pub.ucl 2.1
  Coloring methods for Ultra Fractal 2
  by Damien M. Jones
  April 2, 2000

  For more information about this formula collection,
  please visit its home page:
  
      http://www.fractalus.com/ultrafractal/dmj-pub-uf.htm

  Many of these coloring algorithms are general-purpose tools
  which work with a variety of fractals. A few are more
  specialized. Huge portions of this compilation build upon
  the techniques explored by others.
}

dmj-Curvature {
;
; This formula averages curvature over the course
; of all iterations by averaging the difference in
; absolute value of angles between orbit steps. The
; technique was suggested by Prof. Javier Barrallo.
;
; Note that the results are often very similar to
; Kerry Mitchell's Triangle Inequality Average method,
; but are slightly more angular.
;
init:
  complex zold = (0,0)
  complex zold2 = (0,0)
  float a = 0.0
  float a2 = 0.0
  int i = 0

loop:
  a2 = a
  IF (i >= 2 && @aflavor != 2)			; zold and zold2 are valid
    a = a + abs(atan2((#z-zold)/(zold-zold2)))	; update average
  ENDIF
  i = i + 1					; count the iteration
  zold2 = zold					; save the orbit values
  zold = #z

final:
  IF (@aflavor == 0)
    float il = 1/log(@power)
    float lp = log(log(@bailout)/2.0)
    float f = il*lp - il*log(log(cabs(#z)))
    a = a / i
    a2 = a2 / (i-1)
    #index = (a2 + (a-a2) * (f+1)) / #pi
  
  ELSEIF (@aflavor == 1)
    #index = (a/i) / #pi + 1
    
  ELSE
    a = atan2((#z-zold)/(zold-zold2))		; update average
    #index =  a    / #pi + 1
  ENDIF

Visions of Chaos = VOC

edit
#version 400
// http://www.fractalforums.com/programming/triangle-inequality-average-coloring/
// code by Softology
uniform vec2 resolution;
uniform vec3 palette[256];
uniform double xmin;
uniform double xmax;
uniform double ymin;
uniform double ymax;
uniform double bailout;
uniform int maxiters;

double bailout_squared=double(bailout*bailout);
double magnitude,r1,r2,g1,g2,b1,b2,tweenval;
double realiters;
vec4 finalcol,col;
int superx,supery;
double stepx=(xmax-xmin)/resolution.x;
double stepy=(ymax-ymin)/resolution.y;
int colval,colval1,colval2;
dvec2 z,c;
//triangle inequality average coloring
double sum,sum2,ac,il,lp,az2,lowbound,f,index,tr,ti;
int mandelbrotPower;
double rval,gval,bval,rval1,gval1,bval1,rval2,gval2,bval2;

void main(void)
{
	sum=0;
	sum2=0;
	ac=0;
	il=0;
	lp=0;
	mandelbrotPower=2;

	finalcol=vec4(0,0,0,0);
			c.x = xmin+gl_FragCoord.x/resolution.x*(xmax-xmin);
			c.y = ymin+gl_FragCoord.y/resolution.y*(ymax-ymin);
			int i;
			z = dvec2(0.0,0.0);

				//triangle inequality average coloring
				sum = 0;
				sum2 = 0;
				ac = sqrt(c.x * c.x + c.y * c.y);
				il = 1.0 / log(mandelbrotPower);
				lp = log(float(log(float(bailout)) / mandelbrotPower));
				az2 = 0.0;
				lowbound = 0.0;
				f = 0.0;
				index = 0.0;

			for(i=0; i<maxiters; i++) 
			{
				//START OF FRACTAL FORMULA
				double x = (z.x * z.x - z.y * z.y) + c.x;
				double y = (z.y * z.x + z.x * z.y) + c.y;
				//END OF FRACTAL FORMULA
				
				magnitude=(x * x + y * y);
				if(magnitude>bailout_squared) break;
				z.x = x;
				z.y = y;

					//tia
					sum2=sum;
					if ((i!=0)&&(i!=maxiters-1)) {
						tr=z.x-c.x;
						ti=z.y-c.y;
						az2=sqrt(tr * tr + ti * ti);
						lowbound=abs(az2 - ac);
						sum+=((sqrt(z.x * z.x + z.y * z.y)-lowbound)/(az2+ac-lowbound));
					}

			}

			if (i==maxiters) {
				col=vec4(0.0,0.0,0.0,1.0);
			} else {
				//triangle inequality average
				sum=sum/i;
				sum2=sum2/(i-1.0);
				f=il*lp - il*log(log(float(length(z))));
				index=sum2+(sum-sum2)*(f+1.0);
				realiters=255*index;
				colval1= int(mod(realiters,255));
				colval2=int(mod((colval1+1),255));
				tweenval=fract(realiters);
				if (colval1<0) { colval1=colval1+255; }
				if (colval2<0) { colval2=colval2+255; }
				rval1 =palette[colval1].r;
				gval1 =palette[colval1].g;
				bval1 =palette[colval1].b;
				rval2 =palette[colval2].r;
				gval2 =palette[colval2].g;
				bval2 =palette[colval2].b;
				rval =rval1 +((rval2 - rval1)*tweenval);
				gval =gval1 +((gval2 - gval1)*tweenval);
				bval =bval1 +((bval2 - bval1)*tweenval);
				col=vec4(rval,gval,bval,1.0);
			}
	gl_FragColor = vec4(col);
}

Video

edit

References

edit

References

edit