<?xml version="1.0" standalone="no"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [

<!ENTITY stdlib SYSTEM "stdlib.xml">
<!ENTITY commands SYSTEM "commands.xml">
<!ENTITY tutorial001 SYSTEM "tutorial001.xml">
<!ENTITY tutorial002 SYSTEM "tutorial002.xml">
<!ENTITY tutorial003 SYSTEM "tutorial003.xml">

<!ENTITY gf4d "<application>Gnofract 4D</application>">
<!ENTITY fractint "<application>Fractint</application>">
<!ENTITY ultrafractal "<application>UltraFractal</application>">
<!ENTITY version "3.14.1">

]>
<article id="gnofract4d">
<articleinfo>
<author><firstname>Tim</firstname><surname>Whidbey</surname></author>
<date>1999-12-12</date>
<title>Gnofract 4D</title>
<subtitle><emphasis>For when 2D fractals just aren't weird enough</emphasis></subtitle>
</articleinfo>

<sect1 id="introduction">
<title>Introduction</title>

<epigraph>

<attribution>Francis Bacon</attribution>

<para>
There is no excellent beauty which hath not some strangeness in the
proportion.</para> 

</epigraph>

<para>&gf4d; is a program which draws complex mathematical
objects known as fractals, including the Mandelbrot and Julia sets and
many others. It allows you to treat a fractal which has more than one
parameter as a four-dimensional object and interactively view slices
of this object from arbitrary angles, giving rise to some very unusual
images.
</para>
 
<para>
This user's manual provides a tutorial introduction to &gf4d; and the
mathematical background behind it, information on how to use the
graphical interface, and reference material on the language used to
write fractal formulas.

</para>

</sect1>

<sect1 id="using">
<title>Using &gf4d;</title>
<para>

&gf4d;'s screen layout is deliberately simple. Most of the screen is
taken up by a viewport onto the fractal you're investigating. By
default, this is the Mandelbrot set. You can directly click on this to
zoom. The toolbar provides quick access to frequently used functions,
and more complex properties of the fractal are accessed through dialog
boxes brought up via the menu bar.
</para>

<para>
Initially, just play around - after all, generating fractals isn't
meant to be <emphasis>work</emphasis>. If you make a change you don't
like, just hit Undo.
</para>

<sect2 id="basics">
<title>Interacting with the Fractal</title> 

<para>
Each fractal is an infinitely complex image, which you can see a slice
of in the main window. By left-clicking on the window, you can zoom in
to view finer and finer details. Just click on an area you like to
view it more closely. If you click and drag with the left button, you can
draw a white box around an area. When you let go, you zoom in
so that the area inside that box fills the window. 
</para>

<para>
To zoom back out, click with the right button. You can also press
<keycap>Home</keycap> to return all parameters to the starting point
for this fractal, <keycap>Control</keycap>+<keycap>Home</keycap> to
reset the zoom only, or use <guibutton>Undo</guibutton> to go back one
step.  There isn't a click and drag feature for the right button.
</para>

<para>
Clicking with the middle button rotates the view by 90 degrees in the
<emphasis>xz</emphasis> and <emphasis>yw</emphasis> axes. If you're
currently looking at the Mandelbrot set, you'll get a Julia set, and
vice versa. If you're looking at something else, you'll get something
weird. Note that clicking this twice doesn't take you back to where
you started: the screen also gets recentered on the point you clicked,
so clicking twice will normally give you a perturbed, deformed-looking
Mandelbrot.
</para>

<para>
The cursor keys pan around the image. Hold down
<keycap>Control</keycap>+ <keycap>&lt;cursor&gt;</keycap> to move more
quickly. Hold down <keycap>Shift</keycap> +
<keycap>&lt;cursor&gt;</keycap> to move around in the other two
dimensions, mutating the image. You can recenter the image on a point
by left-clicking on that point while holding down
<keycap>Shift</keycap>.  </para>

<note><title>Non-4D formulas</title> <para> Some fractal formulas
(typically those originally written for Fractint or UltraFractal)
don't support full 4D operation. (&gf4d; determines this by whether
the formula uses the <varname>#zwpixel</varname> variable.) In this
case, the widgets for rotating in other dimensions, warping, and the
middle mouse button will be disabled.  </para> </note>

</sect2>

<sect2 id="files">
<title>Working with Files</title>

<para>

&gf4d; uses several different types of file. These have different
purposes as listed in the table below.

<informaltable>
<tgroup cols="3">

<thead><row>
<entry>File Type</entry>
<entry>Extensions</entry>
<entry>Description</entry>
</row></thead>

<tbody>
<row>
<entry>
Parameter File
</entry>
<entry><filename>.fct</filename></entry>
<entry>

A parameter file is a small text file which contains all the settings
required to produce a particular image, such as the position of the
viewer along the X axis and the coloring scheme used. The parameter
file lists the formula used, but doesn't contain the entire formula,
so if you invent a new formula and want to share parameter files which
use it, you need to distribute the formula file as well.

&fractint; uses <filename>.par</filename> files for
this purpose and &ultrafractal; uses <filename>.upr</filename>. 
Unfortunately &gf4d; can't read
those formats (yet).
</entry>
</row>
<row>
<entry>
Image File
</entry>
<entry>
<filename>.jpg</filename>,
<filename>.png</filename>
</entry>

<entry>
&gf4d; supports JPEG and PNG file formats for image
output. <emphasis>No information about the fractal parameters is
stored in the image file</emphasis>, so if you want to carry on
exploring from a particular point you need to save a parameter file as
well. &gf4d; can't load image files, only save them. Choose
<guimenu>File</guimenu> &gt; <guimenuitem>Save Image</guimenuitem> to
save an image.
I recommend
using PNG images for high quality output, and JPEGs only when image
size is important, because JPEGs introduce artifacts which blur the
fine details of your fractal.
</entry>

</row>

<row>
<entry>
Formula File
</entry>
<entry>
<filename>.frm</filename>,
<filename>.ufm</filename>
</entry>
<entry>

A formula file is a collection of formulas, each of which is a
description of the algorithm used to draw a particular kind of
fractal, expressed in a simple programming language (see <xref
linkend="formref"></xref> for language details). Both &gf4d; and &fractint;
use <filename>.frm</filename> as the extension, and
&ultrafractal; uses <filename>.ufm</filename>. In
general, any formula which works in &fractint; should work in &gf4d;
and any which works in &gf4d; should work in &ultrafractal;, but the
reverse is not true. 

</entry>
</row>

<row>
<entry>
Coloring Algorithm File
</entry>
<entry>
<filename>.cfrm</filename>,
<filename>.ucl</filename>
</entry>
<entry>

A coloring algorithm file is a collection of formulas used to assign
colors to a fractal. &gf4d; combines a coloring algorithm with a
formula to produce the final image (this approach is shared with
&ultrafractal; - &fractint; restricts you to built-in coloring
algorithms).  Coloring algorithms are written in the same language as
fractal formulas. &ultrafractal; uses the extension .ucl for its
coloring algorithm files. Some of these are compatible with &gf4d; but
so far not very many.
</entry>
</row>

<row>
<entry>
Gradient File
</entry>
<entry>
<filename>.map</filename>,
<filename>.ggr</filename>
<filename>.ugr</filename>
</entry>
<entry>

A gradient file is a list of colors which is used to translate the
purely numerical output of the formula into something pretty to look
at. Gradients are currently saved only inside the fractal itself, not
as separate files. The GIMP uses the extension .ggr for its gradient
files; &fractint; uses .map for its own, simpler files. &ultrafractal;
uses .ugr - these files contain multiple gradients.

</entry>
</row>

</tbody>
</tgroup>
</informaltable>
</para>

</sect2>

<sect2 id="tools">
<title>Tools</title>

<sect3 id="autozoom">
<title>Autozoom</title> 

<para> Autozoom automatically searches for interesting parts of the
fractal by zooming in repeatedly, each time choosing the quadrant of
the screen which has the largest number of different colors (with some
randomization as well). You can start it going, go off for a coffee,
and see what it's found when you return, or guide it by clicking on
parts you like as it goes. It'll stop when the image reaches the
minimum size, which is set by default to stop just before you get to
the limits of the precision &gf4d; offers.
</para>

</sect3>

<sect3 id="explorer">
<title>Explorer</title>

<para>
The <emphasis>Explorer</emphasis> helps you find neat-looking fractals
easily. It divides the screen into a large central section and smaller
"subfractals" which surround it. The central section is the main image
- you can click on this to zoom in, change the color, or perform any
operation you can normally. The other images around the edges are
"mutant" versions of the main image - they're formed by starting with
the base parameters and randomly changing them a bit. Whenever you
change the main image, you get a whole new set of mutants. If you like
a mutant more than the main picture, click on it to move it to the
middle - it then becomes the main picture and you get 12 new mutants
based on the new main image. When you're satisfied with the results,
click the Explorer button again to return to normal mode.  </para>

<para> The Shape and Color sliders on the toolbar determines how
different the mutants are from the standard image. If Shape's set to
100, they're almost unrecognizable - if it's 0, they're exactly the
same. Similarly if Color's 100, each mutant is a different color, and
0 keeps the colors all the same.  </para>

</sect3>

<sect3 id="browser">
<title>Formula Browser</title>
<para>

The <emphasis>Formula Browser</emphasis> allows you to look at all the
fractal formulas, coloring functions and gradients which are currently loaded
formula files. When you select a formula (from the Formula list in the
middle), the source window shows you the contents of that formula. You
can then use <guibutton>Apply</guibutton> to change the current
fractal to use that formula. This also resets the formula's parameters
to their defaults. Alternatively, <guibutton>OK</guibutton> applies
the formula and closes the window.  </para>

<para>
Tips: 
<itemizedlist>

<listitem><para> To load a new formula file, choose <guimenu>File</guimenu>
&gt; <guimenuitem>Open Formula File</guimenuitem>. </para></listitem>

<listitem><para> If you have changed a formula on disk, choose
<guibutton>Refresh</guibutton> to have &gf4d; re-read
it. </para></listitem>

<listitem><para> If the formula contains errors,
<guibutton>Apply</guibutton> and <guibutton>OK</guibutton> will be
disabled. Check the Messages window to see what the errors
are. </para></listitem>

</itemizedlist>
</para>
</sect3>

<sect3 id="director">
<title>Director</title>
<para>

The <emphasis>Director</emphasis> allows you to create fractal movies.
You first define keyframes (including base keyframes) which are stops
in video.  Then, for each of them, you define for how long they last
(<guilabel>duration</guilabel> - in frames), how long still image of
keyframe will stay in video (<guilabel>stopped for</guilabel>) and
interpolation type between several possibilities. When you hit
<guibutton>Render</guibutton> button, Director will render all frames
and put them in directory you selected and then it will try to create
video using <ulink
url="http://www.transcoding.org/"><emphasis>transcode</emphasis></ulink>
tool.  </para>

<para>
Tips:
<itemizedlist>

<listitem><para>
In order to end up with video file, not just a bunch of images, you need to have
<emphasis>transcode</emphasis> tool compiled with support for ImageMagick.
</para></listitem>

<listitem><para>
You can always save your animation configuration for later use.
</para></listitem>

<listitem><para>
You can always stop rendering images. As long as you use same animation setting again
(for example, saving them before starting rendering), Director will starts from where
it stopped last time.
</para></listitem>

</itemizedlist>
</para>
</sect3>

<sect3 id="randomizecolors">
<title>Randomize Colors</title>
<para>
Replaces the current gradient with a randomly-generated new one.
</para>
</sect3>

<sect3 id="painter">
<title>Painter</title>
<para>

The painter dialog allows you to change the colors of your fractal by
clicking on the place where you want the color to be different. First,
select the color you want in the color selector. Then click on the
image - the part of the gradient most responsible for the color of
that pixel will be updated with the color you chose. Toggle the
"painting" button off if you want to interact with the fractal while
the painter dialog is up.

</para>
</sect3>

</sect2>

<sect2 id="toolbar">
<title>Toolbar buttons</title>
<para>
On the left of the toolbar you can see a small preview window, which
updates as you change the angle or position buttons, to give you an
idea of what the fractal will look like when you release the button.
</para>

<para>
The first eight toolbar buttons correspond to the ten parameters which
define the view. The circular angle buttons, labelled
<emphasis>xy</emphasis> to <emphasis>zw</emphasis>, correspond to
rotation around the principal planes in four dimensions. They can
changed by dragging the dot around. When you let go, the fractal will
update. By the way, the <emphasis>zw</emphasis> angle does work, you
just can't see its effects until you rotate in some other dimensions
first.  </para>

<para>
The square position buttons, <emphasis>pan</emphasis> and
<emphasis>wrp</emphasis> (aka Warp), can be used to alter the view. The
<emphasis>pan</emphasis> button allows you to pan around the current
view. The <emphasis>wrp</emphasis> button allows you to move along the
other two axes, resulting in a mutated version of the current image.
Click inside one then drag the mouse, watching the preview window
update, then release the mouse when you like the results.  </para>

<para>The warp menu allows even formulas which weren't designed to be
used with &gf4d; to be used in 4D mode. If the current fractal has any
complex parameters, they're listed in this menu. If you select one,
that parameter's value is set to the value of the Z and W coordinates
for each pixel. Basically what this means is that the parameter you choose
becomes the fourth dimension. NB: If you set an explicit value for the parameter as
well, it'll be ignored.
</para>

<para>
The <emphasis>Deepen</emphasis> button allows you to increase the current iteration count
and tighten the periodicity checking, for those occasions when the
auto-deepening and/or auto-tolerance doesn't get it right. This will
generally convert some 'inside' pixels to outside and make the image
look better, at the cost of longer rendering time. The image size list should be
self-explanatory. If you want a size not listed here, use the
Preferences dialog. </para> <para> The <emphasis>Undo</emphasis> and
<emphasis>Redo</emphasis> buttons should be fairly obvious. You can
undo as many times as you like. Note that undo also affects parameters
such as color, not just position on screen.  Lastly, the
<emphasis>Explore</emphasis> button toggles Explorer Mode. See <xref
linkend="explorer"/>.</para>
  
</sect2>

<sect2 id="preferences">
<title>Changing Fractal Settings</title> 

<para> In &gf4d;, settings are divided into <emphasis>Fractal
Settings</emphasis>, <emphasis>Gradients</emphasis> and
<emphasis>Preferences</emphasis>. <emphasis>Fractal
Settings</emphasis> and <emphasis>Gradients</emphasis> are saved in the
fractal's .fct file - they are properties of the fractal itself. By
contrast, <emphasis> Preferences</emphasis> are your preferences for
&gf4d;'s general behavior and are saved in &gf4d;'s config file
(~/.gnofract4d), so they will still be active next time you
start &gf4d; </para>

<sect3 id="settingsdialog">
<title>Fractal Settings</title>
<para>

The <emphasis>Formula</emphasis> section allows you to choose the
formula used to calculate the fractal, and to set any parameters the
formula has. You can modify the formula by choosing <guibutton>Browse
</guibutton>, which invokes the Formula Browser. <emphasis>Max
Iterations</emphasis> sets the number of iterations a point will go
through before we give up and assume it's a member of the
Julibrot. The other parameters on this pane are different depending on
the fractal type.
</para>

<para>
The <emphasis>Outer</emphasis> page controls the function used to
decide what color to draw those points which aren't part of the
fractal set proper. Similarly, the <emphasis>Inner</emphasis> page
controls the function used for points which are part of the set.
</para> 

<para>
The <emphasis>Location</emphasis> entryboxes allow you to
change the coordinates of the screen center and the image size. 

The <emphasis>Angles</emphasis> entryboxes allows you to set the rotation
angles. Only values between 0 and 2 * pi are different; values outside
this range "wrap" to points inside that range.
</para>

<para>

The <emphasis>Transforms</emphasis> page allows you to control a list
of transformations applied to the image, and any parameters those transforms have.
</para>

<para>
The <emphasis>General</emphasis> page gives a few options which don't
fit anywhere else. <emphasis>Flip Y Axis</emphasis> causes Y to
increase top-to-bottom, rather than
bottom-to-top. <emphasis>Periodicity Checking</emphasis> is a method
to speed up generation of the fractal. Points inside the fractal
eventually settle into a loop, where they repeatedly jump around
between the same points (they become 'periodic'). By noticing this, we
can skip calculating the point any further. You will generally want to
disable this if you are coloring the inside of the fractal, since it
will look rather weird otherwise. <emphasis>Tolerance</emphasis> is
the distance between points which we'll accept as being 'the same' for
the purposes of periodicity detection. This is automatically adjusted
if the 'auto tolerance' setting in the preferences is enabled.

</para>

<para>

The <emphasis>Colors</emphasis> tab allows you to edit the list of
colors used to display your fractal. For more complex gradient
editing, you can also use the GIMP's gradient editor.

</para>
</sect3>

<sect3 id="prefsdialog">
<title>Preferences</title> 

<sect4 id="prefs_image">
<title>Image</title>

<para> <emphasis>Width</emphasis> and <emphasis>Height</emphasis> set
the size of the image in pixels. If <emphasis>Maintain Aspect
Ratio</emphasis> is checked when you change either the width or
height, the other automatically changes to keep the image the same
shape. If <emphasis>Auto Deepen</emphasis> is enabled, &gf4d; will try
to automatically guess how many iterations are required to display the
image correctly. Similarly, <emphasis>Auto Tolerance</emphasis>
adjusts the periodicity tolerance setting to try and calculate the
image quickly but correctly. <emphasis>Antialiasing</emphasis> makes
the image look smoother but takes extra time to do. The difference
between 'fast' and 'best' is that fast antialiasing doesn't bother to
recalculate points which are the same color as their neighbors. This
speeds things up a lot but can miss a few details sometimes. </para>

</sect4>

<sect4 id="prefs_compiler">
<title>Compiler</title>
<para>
&gf4d; needs a C compiler to be available at runtime in order to work
(it dynamically creates the code to compute a particular formula when
you select it). The <emphasis>Compiler</emphasis> page allows you to
specify a location for the compiler and options to pass to
it. <emphasis>If &gf4d; is working fine, generally I suggest you leave
those settings alone. However you <emphasis>may</emphasis> be able to
get noticeable performance gains by specifying the specific kind of
processor you have. For example, fairly modern AMD processors will
benefit by adding "-mathlon -msse2 -m3dnow" to the compiler flags.

</emphasis> The <emphasis>Formula Search
Path</emphasis> lists the directories where &gf4d; will look for
formulas when a parameter file is loaded.
</para> 
</sect4>

<sect4 id="prefs_general">
<title>General</title>
<para>

<emphasis>Number of threads</emphasis> sets how many calculation
threads to use. Generally, leave this at 1 unless you have a
hyper-threaded or multi-processor computer, in which case set it to 1
greater than the number of CPUs you have.
</para> 
</sect4>

<sect4 id="prefs_helpers">
<title>Helpers</title>
<para>

&gf4d; sometimes need to invoke a helper program. It'll try to use
your preferences from GConf if possible, and these fields are set to
be those defaults. However if that default is wrong somehow, you can
explicitly set it here.
</para> 
</sect4>

<sect4 id="prefs_flickr">
<title>Flickr</title>
<para>

&gf4d; can upload your images to the online image-sharing service
Flickr. This page handles your online identity.

</para> 
</sect4>

</sect3>

</sect2>

<sect2 id="hints">
<title>Hints</title>

<itemizedlist>

<listitem>
<para>If you zoom into a busy part of the fractal the image can look
"noisy". You can fix this by making the colors change more slowly - go
to the "Outer" tab and change the transfer function to 'sqrt' or 'log'
- or change "Density" to a number between 0 and 1 - a density of 0.1
makes the colors change 10 times more slowly.
</para>
</listitem>

<listitem>
<para>If you have an Inner coloring method other than zero, you may
see weird effects unless you disable periodicity checking.
</para>
</listitem>

</itemizedlist>

</sect2>
</sect1>

<sect1 id="cmdref">
<title>Command Reference</title>
<!-- pull in auto-generated list of keyboard and mouse commands -->
&commands;
</sect1>

<sect1 id="maths">
<title> About the maths</title>

<caution>
<title>Warning: Dubious mathematics ahead</title>
<para>I'm not a mathematician. You may find this discussion
insultingly oversimplified or just plain wrong.
</para>
</caution>

<sect2 id="mset" >
<title>The Mandelbrot Set</title> <para> The Mandelbrot may be
defined as the set of all complex numbers which, when you
repeatedly square them and add them again, never become infinite. (The
official definition of the set is somewhat different: it is the set of
points in the complex plane whose corresponding Julia sets are
connected. These end up being the same thing.)

We can tell that a number will eventually reach infinity if it ever
gets outside a circle of radius 2 around the origin. Unfortunately, we
can't tell in general that a point will <emphasis>never</emphasis>
become infinite, so we have to estimate by trying a large number of
times before giving up.
</para>

<para>
In &gf4d;, the formula is:
</para>

<programlisting>
Mandelbrot1 {
init:
    z = 0
loop:
    z = z^2 + c
bailout:
    |z| &lt; 4.0
}
</programlisting>

<para>
(|z| means the square of the magnitude of z). We calculate the loop
function repeatedly until the bailout condition is false or we've
performed the maximum number of iterations. At that point, if we
"bailed out", we know we're outside the set: otherwise we're
(probably) inside.
</para>

<para>
We do this repeatedly for each position on the screen, setting
<emphasis>c</emphasis> to a different value for each point. This gives
rise to the familiar Mandelbrot set:
</para>

<para>
<graphic align="center" format="PNG" fileref="figures/mandelbrot_standard.png"/>
</para>
<para>
All the points inside the set are (as is traditional) coloured
black. The points outside the set are different colours depending on
how long it takes them to escape from the set. These colours aren't
very mathematically significant, but they look nice.
</para>

<para>
So what happens if <emphasis>z</emphasis> is initially set to a
complex value other than zero? (Strictly speaking, you shouldn't do
this. Zero is important because it is the <emphasis>critical
value</emphasis> of z^2+c - other values are not mathematically
meaningful. However, as with most fractal programs, &gf4d; allows you
to draw anything which looks interesting, regardless of its
mathematical purity.)

Well, you get a rather odd-looking, deformed M-set.  This initial
value, which we'll call <emphasis>z0</emphasis>, is called the intial
perturbation, and sets which have a non-zero <emphasis>z0</emphasis>
are known as <emphasis>perturbed</emphasis> sets: 
</para>
<para>
<graphic align="center" format="PNG"
fileref="figures/mandelbrot_perturbed.png"/>

</para> </sect2>

<sect2 id="julia">
<title>The Julia Set</title>

<para>
The Julia set is actually drawn by the same procedure as the
Mandelbrot set. But instead of changing the value of
<emphasis>c</emphasis> for each pixel, we keep <emphasis>c</emphasis>
constant and change <emphasis>z0</emphasis>. There is a different
Julia set for each value of <emphasis>c</emphasis>; here's the one for
<emphasis>c</emphasis>=0.
</para>
<para>
<graphic align="center" format="PNG"
fileref="figures/julia_standard.png"/>

</para>

<para>
Boring, isn't it? That's because we're just squaring the value at each
iteration without adding anything to it. So any value which starts
with a magnitude less than 1 will shrink forever (and hence is a
member of the set). All other values will grow forever, and so we've
just discovered a rather inefficient way of drawing perfect circles.
If we use a different value of <emphasis>c</emphasis> we get something more
interesting: 
</para>
<para>
<graphic align="center" format="PNG"
fileref="figures/julia_perturbed.png"/>

</para>
</sect2>

<sect2 id="julibrot">
<title>The Julibrot</title> 
<para>

Here we come to the heart of the matter. I said above that both the
Julia and Mandelbrot sets are drawn with the <emphasis>same
function</emphasis>. 
<programlisting>
julibrot(z0,c) {
init:
    z = z0
loop:
    z = z^2 + c
bailout:
    |z| &lt; 4.0
}
</programlisting>

The Julibrot function has two complex parameters, or four real
ones. In &gf4d; I refer to the real parameters as x, y, z, and w:
these are c.re , c.im, z0.re and z0.im respectively.

The only difference is which points we choose to draw. To draw the
Mandelbrot set, we keep <emphasis>z0</emphasis> constant and change
<emphasis>c</emphasis> with each pixel. To draw the Julia set, we keep
<emphasis>c</emphasis> constant and change <emphasis>z0</emphasis>. If
you squint with your brain a bit, you can imagine both sets as
orthogonal "slices" through the same four-dimensional object. In
&gf4d; terms, the Mandelbrot set is the <emphasis>xy</emphasis>
plane, and the Julia set is the <emphasis>zw</emphasis> plane. We can
also look at other planes: here's an image of the
<emphasis>xw</emphasis> plane:
</para>
<para>
<graphic align="center" format="PNG"
fileref="figures/xw_plane.png"/>

</para>
</sect2>

<sect2 id="viewing">
<title>Viewing in Four Dimensions</title>
<para>
However, we can draw any 2D slice we like, not just those which are
parallel to the Julibrot axes. To do this we'll need to describe our
scene by four things. First, the (<emphasis>x,y,z,w</emphasis>)
coordinates of the center of the screen. Second, a vector for the
x-axis of the screen. This tells us how to change the parameters to
the Julibrot function as we proceed across the screen. Third, a vector
for the y-axis. Fourth and finally, the size of the image. For the
Mandelbrot set, our "default" view, the screen is centered at
[0,0,0,0], the x-vector is [1,0,0,0] and the y-vector is
[0,1,0,0]. The initial size is 4, because the whole Mandelbrot set
fits inside the 2x2 square. We can zoom into the set by changing
<emphasis>x</emphasis> and <emphasis>y</emphasis> and the zoom factor.
</para>
<para>
If we want to draw other slices, we need to rotate our view through
four dimensions. In 3D, we can rotate in 3 directions: around the
<emphasis>x</emphasis>, <emphasis>y</emphasis>, and
<emphasis>z</emphasis> axes. In 4D, we rotate around a <emphasis>
plane </emphasis> rather than a line, and we can rotate in 6
directions: around the <emphasis>xy, xz, xw, yz, yw</emphasis> and
<emphasis>zw</emphasis> planes. For example, if we rotate through 90
degrees in the xz and yw directions, our screen vectors become
[0,0,1,0] and [0,0,0,1]: in other words, the Julia set. If we rotate
only part of the way, we get a "hybrid" between the two sets, which
looks decidedly odd:
</para>
<para>
<graphic align="center" format="PNG" fileref="figures/hybrid.png"/>
</para>
<para>
In fact, we can rotate to any angle in each of the planes,
creating a whole world of bizarre pictures.
</para>

</sect2>

<sect2 id="hypercomplex">
<title>Hypercomplex Fractals and Quaternions</title> 

<para> There are other kinds of fractal which are commonly described
as "four-dimensional" - hypercomplex and quaternion-based
fractals. Hypercomplex numbers have four components (one real and
three imaginary) where complex numbers have two. Since the
hypercomplex mandelbrot has two hypercomplex parameters, in &gf4d;
terms it's actually an eight-dimensional object. &gf4d; allows you to
set four of these as part of the view - the other four have to be set
via parameters. &gf4d; doesn't support quaternions at present.</para>

</sect2>
</sect1>

<sect1 id="compiler">
<title>Writing Your Own Functions</title>

<para>
When you get tired of the fractal functions which come with Gnofract
4D, you can write your own, or take advantage of thousands of formulas
written by other fractal enthusiasts. Gnofract4D can load most fractal
formula files written for &fractint; (and some written for
&ultrafractal;). However the compiler is not 100%
backwards-compatible with &fractint;, so unfortunately some fractals
can't be loaded, or will display differently when they do. &gf4d;
also supports many constructs &fractint; doesn't, so you need to take
extra care when writing formulas if you want them to work in &fractint;
too.
</para>

<para>
Here are links to some online resources for formula files:
<itemizedlist>

<listitem><para> <ulink
url="http://home.att.net/~Paul.N.Lee/OrgForm.html">ORGFORM.ZIP</ulink>
A collection of about 25,000 &fractint; formula files by many authors,
originally compiled by George C. Martin and currently maintained by
Paul N. Lee. Indispensable. </para></listitem>

<listitem><para> <ulink
url="http://formulas.ultrafractal.com/">&ultrafractal; public formula
database</ulink> Many thousands of formulas by users of
&ultrafractal;. Most of these will work with &gf4d;. Let me know of
any issues, since I aim to improve compatibility further in future
releases. </para></listitem>

</itemizedlist>
</para>

<sect2 id="frm_tutorial">
<title>Writing Your First Formula</title>

<para>
This section steps you through the creation of a new fractal
formula. By the way, the formulas for each of these steps can also be
found in the file <filename>formulas/tutorial.frm</filename>.

<orderedlist numeration="arabic"> 

<listitem>
<para>
Create a new file called '<filename>example.frm</filename>' (the
extension is important - &gf4d; uses this to decide whether the file
is a formula or a coloring function).
</para>
</listitem>

<listitem>
<para>
Enter the following in <filename>example.frm</filename>.
&tutorial001;
</para>
</listitem>

<listitem>
<para>
Start &gf4d;, choose <guimenuitem>File | Open Formula
File</guimenuitem>, and open example.frm. You should see MyFormula in
the list of formulas to choose from. Select it and click Apply. You
should see an image like this:
</para>
<para>
<graphic format="PNG"
fileref="figures/tutorial001.png"/> 
</para>

<para>
A few things to note about the formula. It's divided into named
sections, marked with a colon: "init", "loop". and "bailout". The
compiler uses these to supply some of the standard scaffolding for a
fractal function so you don't have to. The "loop" statement is the
heart of the formula - this is the statement which is run repeatedly
and which defines the shape of your fractal.
</para>
</listitem>

<listitem>
<para>

At this point, the widgets for rotating the image in 4D will be
disabled, because your formula doesn't use any of the 4D
options. Let's turn those on. Edit your formula so it reads:
&tutorial002;
</para>

<para>
Then hit <guibutton>Refresh</guibutton> on the Formula Browser window. You 
should now find that all the options are enabled. This is because the image now depends on all 4 components of the 4D space, via #pixel and #zwpixel.
</para>
</listitem>

<listitem>
<para>
Next let's add some parameters to our function:
&tutorial003;
</para>

<para>
Hit <guibutton>Refresh</guibutton> again, then <guimenuitem>Edit |
Fractal Settings</guimenuitem> to show the formula settings. You
should two extra parameters in addition to the standard "Max
Iterations" option: <emphasis>myfunc</emphasis>, with a drop-down list
of functions, and <emphasis>fac</emphasis> (or Factor) with a
draggable 4-way widget and 2 edit boxes. If you set myfunc to
<emphasis>sqr</emphasis> and set factor to (-1,0.5) you should see:
</para>

<para>
<graphic format="PNG"
fileref="figures/tutorial002.png"/>
</para>

<para> 
Parameters like this are a quick way to add more options to your
fractal. Listing them in the "default" section is optional but
provides a way to pre-populate your formula with values that work
well. If you leave the default out &gf4d; will use "ident" for
functions and 0 for numeric ones.
</para>

</listitem>

</orderedlist> 
</para>
</sect2>

</sect1>

<sect1 id="formref">
<title>Formula Language Reference</title>

&stdlib;
</sect1>

<sect1 id="internals">
<title>&gf4d; Internals</title>
<para>

This section explains how &gf4d; is structured. You don't need to know
any of this to use the program, but it may come in handy if you want
to change it or contribute to its development (which you're heartily
encouraged to do).
</para>

<para>

&gf4d; is implemented primarily in Python, with some C++
extensions. Extensive use
is made of Python unittest framework to keep everything working - each
Python file <filename>foo.py</filename> is accompanied by
<filename>test_foo.py</filename>, which contains unit tests for that
file's features. 'test.py' for each folder runs all of the tests.
</para>

<sect2 id="layout">
<title>Source Code Layout</title>

<para>
The important directories in the source are:

<informaltable>
<tgroup cols="2">

<thead><row>
<entry>Directory</entry>
<entry>Contents</entry>
</row></thead>
<tbody>

<row>
<entry><para><filename>fract4d</filename></para></entry>

<entry> <para>This contains all the non-GUI-related, relatively
platform-independent parts of the code. This is in case it ever needs
to be ported to another environment (eg run on a server without a GUI
as part of a cluster). Most of the files here are parts of the
compiler (see below). The main class which represents a fractal is in
<filename>fractal.py</filename>. This holds references to the compiled
code, the formula and colorfunc definitions, the parameters and the
colormap. It also handles loading and saving information from a
<filename>.fct</filename> file, and provides
wrappers for some of the gnarlier C++ extension functions. </para>
</entry>

</row>

<row>
<entry><para><filename>fract4d/c</filename></para></entry>

<entry> <para>This contains the C++ extension code which is compiled
to produce <filename>fract4dc.so</filename>. This is divided into a
set of classes which communicate primaily via interfaces. The main
responsibility of this code is to call the 'pointFunc' (the function
which calculates a single pixel) once for each point on the
image. This code also does the bulk of the '4D' manipulation -
<filename>vectors.h</filename> contains code for 4-vectors and 4x4
matrix math. This library also handles multi-threaded calculations,
parcelling out the work to multiple MTFractWorkers via the queue in
<filename>threadpool.h</filename></para> </entry>

</row>

<row>
<entry><para><filename>fract4dgui</filename></para></entry>

<entry> <para>This contains the python code which implements the
GUI. It uses PyGTK as the GUI toolkit. The earliest PyGTK we support
is 1.99, which has some annoying incompatibilities with newer PyGTK's
like 2.4. I need to work out whether to ditch the older library
altogether or try to come up with some wrappers to hide the
differences. Basically there's one class per dialog or custom control,
and a few other for utility purposes. The central class is
<classname>gtkfractal</classname>, which wraps a
<classname>fractal</classname> and displays the results of the
calculation in a window. </para> </entry>

</row>

<row>
<entry><para><filename>fract4dgui/c</filename></para></entry>

<entry> <para>This contains the C code which implements the
fract4dguic.so extension. This only has one minimal function, to
obtain gconf settings. </para> </entry> </row>

</tbody>
</tgroup>
</informaltable>

</para>

</sect2>

<sect2 id="compiler_internals">
<title>Compiler</title> 

<para>The most complicated part of &gf4d; is the compiler. This takes
as input an UltraFractal or Fractint formula file, and produces C
code. We then invoke a C compiler (eg gcc) to produce a shared library
containing code to generate the fractal which we dynamically load.
</para>

<para>
The UltraFractal manual is the best current description of the formula
file format, though there are some UltraFractal features which are not
yet supported. You can download it from <ulink
url="http://www.ultrafractal.com/uf3-manual.zip">here</ulink>.
</para>

<para>
The implementation is based on the outline in <citetitle
pubwork="book">Modern Compiler Implementation in ML: basic
techniques</citetitle> (Appel 1997, Cambridge). It doesn't do any
optimization at this point, leaving that to the C compiler used as a
back-end. It would be worthwhile to do some simple optimization (eg
constant-folding, removing multiplication by 1.0) because the C
compiler refuses to do this to floating point numbers.</para>

<para>
Overall structure: The <ulink
url="http://www.dabeaz.com/ply/ply.html">PLY</ulink> package
is used to do lexing and SLR parsing - it's in
<filename>lex.py</filename> and
<filename>yacc.py</filename>. <filename>fractlexer.py</filename> and
<filename>fractparser.py</filename> are the lexer and parser
definitions, respectively. They produce as output an abstract syntax
tree (defined in the <classname>Absyn</classname> module). The
<classname>Translate</classname> module type-checks the code,
maintains the symbol table (<filename>symbol.py</filename>) and
converts it into an intermediate form (<filename>ir.py</filename>).
<classname>Canon</classname> performs several simplifying passes on
the IR to make it easier to deal with, then
<classname>codegen</classname> converts it into a linear sequence of
simple C instructions. <filename>stdlib.py</filename> contains the
'standard library' of mathematical functions, like cosh(z). It's at
this point that complex and hypercomplex variables are expanded out
into pairs of floating point numbers - the C code is oblivious to the
complex numbers. Finally we invoke the C compiler to convert to a
native code shared library.</para>

<para>
At runtime the different phases happen at different times. First, the
entire .frm file is lexed and parsed. Then when a particular formula
is selected, it's translated and syntax-checked. The actual code is
only generated just before the fractal is drawn. This phase is
repeated whenever the function parameters are changed (eg @fn1 is set
to 'cosh').
</para>

<para>
Probably the ugliest part of the code is the handling of
parameters. Numeric parameters like floats are passed in as an array,
and the C++ code and Python code need to collaborate to work out which
indices into this array correspond to which params- this is done by
sorting them into alphabetic order. In general this area is a bit of a
mess.</para>

</sect2>

<sect2 id="threading">
<title>Threading</title>

<para>
One of the weirder parts of the code is how we deal with
threading. Basically we want the calculation of the fractal to happen
on a different thread (or multiple threads for SMP) from the main UI,
so you can interrupt at any point. This is complicated by the fact
that Python only allows a single thread in the Global Interpreter
Lock, and that PyGTK is often compiled by Linux distribution vendors
without thread support, meaning this lock is not released when running
the GTK main loop.
</para>

<para>
The way out of this is that the additional threads live only in the
C++ code, where they are invisible to the Python code and GTK. When
<function>pycalc</function> is called with async=True, it spawns a
thread to do the calculation, which may in turn spawn more workers if
we want multiple threads. These all write to the image buffer and
report back what they're doing by writing messages into a pipe. This
pipe is added to the list of things the GTK main loop monitors, so
whenever a new message appears we get a callback into the gtkfractal
code, interleaved with the normal GTK events. We can interrupt a
calculation in progress by setting a var which the calculation threads
check frequently - they then abandon their work and quit.  </para>

<warning> <para> Multiple threads and C++ exceptions do not coexist
well, at least on some of the libstdc++'s that &gf4d; runs with. So the
C++ code can't throw exceptions or very odd things including crashes
will happen. </para> </warning>

</sect2>

</sect1>

<sect1 id="bugs">
<title>Bugs and Known Issues</title>

<sect2 id="reporting">

<title>Reporting Bugs</title> 

<para>
<emphasis>Please</emphasis> report any bugs you encounter, either by
mailing <ulink
url="mailto:catenary@users.sourceforge.net">
catenary@users.sourceforge.net</ulink> or by
using the <ulink
url="http://sourceforge.net/tracker/?func=add&amp;group_id=785&amp;atid=100785">
bug form</ulink> at SourceForge. I'll do my best to fix them.  </para>

</sect2>

<sect2 id="compat">
<title>Backwards Compatibility</title>

<para>
Version 2.x contains major architectural changes from version 1.x, so
unfortunately not all images generated by earlier versions will look
exactly the same or even load correctly. If you have a favorite image
which doesn't work any more, mail me the .fct file and I'll try and
convert it. I hope to fix most of these issues in future versions.
</para>
<para>
Specific known issues:
<itemizedlist>

<listitem> <para> Files generated by &gf4d; versions older than
1.4 can't be loaded. </para>
</listitem>

<listitem> <para> Only one colormap per file is supported (the outer
one). Inner colormaps are ignored. </para> </listitem>

</itemizedlist>

</para>

</sect2>
</sect1>

<sect1 id="about">
<title>About &gf4d;</title>
<para>

This is &gf4d; version &version;. You can find the most recent version of
&gf4d; from <ulink url="http://gnofract4d.sourceforge.net">
http://gnofract4d.sourceforge.net/</ulink>. 
</para>
<sect2 id="credits">
<title>Credits and copyright</title>

<para>
&gf4d; is Copyright 1999-2009 Tim Whidbey <ulink
url="mailto:catenary@users.sourceforge.net">(catenary@users.sourceforge.net)
</ulink>, and is distributed under the <emphasis>BSD
license</emphasis>.  See the file "COPYING" for details. 
</para>

<para>
&gf4d; was originally based on Gnofract, written by Aurelien Alleaume
<ulink url="mailto:manchot@club-internet.fr">(manchot@club-internet.fr)
</ulink>,
though none of the original code remains in the current version.
Gnofract could once be obtained from
<ulink url="http://www.multimania.com/mason/">
http://www.multimania.com/mason/</ulink> but this no longer appears to
work. 
</para>

<para>
Branko Kokanovic developed and contributed the animation
feature. Chris Le Sueur provided parts of the gradient editing
feature. Henryk Trappmann provided HSV gradient support. 
The man page was contributed by Aleksander Adamowski.</para>

<para>
The formula language which &gf4d; uses originated in &fractint; and
was substantially enhanced in &ultrafractal;. However the compiler
implementation does not share any code with those programs.
</para>

<para>
The &gf4d; distribution contains palette (.map) files by a number of
authors which were originally distributed with <ulink
url="http://spanky.triumf.ca/">&fractint;</ulink> under somewhat murky
licensing conditions. It also contains a copy of "standard.ucl",
originally distributed with <ulink
url="http://www.ultrafractal.com/">&ultrafractal;</ulink>, by kind
permission of Frederik Slijkerman, Damien Jones, and Kerry Mitchell.
"blatte1.ugr" and "blatte2.ugr" are included by kind permission of 
<ulink url="http://exoteric.roach.org/">'Blatte'</ulink>. The formulas
in Sterling2.frm are translations of formulas originally created by
Tad Boniecki for use with the SterlingWare 2 fractal program.
</para>


<para>
<filename>gmpy.c</filename> and <filename>gmpy.h</filename> are from
the GMPY package (http://gmpy.sf.net), and are distributed under the
LGPL license.  </para>

<para>
<filename>lex.py</filename> and <filename>yacc.py</filename> come from
the PLY package, and are distributed under the LGPL license. </para>

<para>
Some of the menu icons are taken or adapted from
the <ulink url="http://tango.freedesktop.org">Tango icon set</ulink>.
</para>

</sect2>

</sect1>

</article>

